tishion / mmLoader

A library for loading dll module bypassing windows PE loader from memory (x86/x64)

Home Page:http://tishion.github.io/mmLoader/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bad behavior on static std::string

kyle-go opened this issue · comments

commented

modify the project demo-module

std::string
get_str() {
  return "hello string";
}
// This is an example of an exported function.
__declspec(dllexport) BOOL _stdcall demoFunction(unsigned char *buffer, unsigned int size) {
  OutputDebugStringA("demoFunction1 in\n");
  printf("demoFunction1 in\n");
  static std::string the_string = get_str(); // crash on windows xp
  if (!the_string.empty()) {
    printf(the_string.c_str());
    OutputDebugStringA(the_string.c_str());
  } else {
	  // bad behavior on windows 7 and later.  string is always  emtpy
    OutputDebugStringA("the the_string is empty().\n");
    printf("the the_string is empty().\n");
  }
  OutputDebugStringA("demoFunction2 after static std::string\n");
  printf("demoFunction2 after static std::string\n");

  if (!buffer)
    return FALSE;

  char *p = "{f56fee02-16d1-44a3-b191-4d7535f92ca5}";
  memcpy_s(buffer, size, p, strlen(p));
  return TRUE;
}

THE LINE: static std::string the_string = get_str(); will crash on windows xp.
and on windows 7 and later, the string is always empty;
Any idea?

btw: I test it with project "demo-mmloader-shellcode" with x86.

it should be caused by the C++ runtime library.
Just load your module with normal LoadLibrary and see whether it can work or not.

commented

it should be caused by the C++ runtime library.
Just load your module with normal LoadLibrary and see whether it can work or not.

I TESTED, If load the module by LoadLibrary API, everything is OK.

confirmed this is cuased by the uninitialization of scoped static variable, will look into it and try to solve.

After some investigation, here the detailed information about this problem are as follows.

First, in this scenario there is a local static variable in this target dll module. For local static variable MSVC compiler before vs 2015 will not guarantee the thread-safe of the initialization, so if you use MSVC < VS 2015, there will be no any problem with mmloader.

But since VS 2015, it makes sure all the local static variable are initialized thread-safely, this is called /Zc:threadSafeInit (Thread-safe Local Static Initialization). MS implemented this feature by using the TLS technology and more specifically is it uses static TLS in dynamic module. This feature is only supported on Windows Vista (KB). If you try to consume the dll module by calling LoadLibrary on windows below Vista, it will crash (this also applies to mmloader).

On windows Vista or above, LoadLibrary can process it correctly, but mmloader currently doesn't support TLS, and I need to evaluate whether to add support it or not (it needs to insert the module into the loader module list, thus the module will become unhidden to this process and other monitor tools).

In short if you want to walk around this problem:
if you compile the module with VS below 2015, and run mmload with it on any supported windows version, no problems
if you compile the module with VS 2015 or above, eliminate all static local variable usage in your code or add compiler flag: /Zc:threadSafeInit- (you need to ensure the thread-safety of the initialization of all these variables).

commented

Good job, thanks.