title: DLLMain The value of ESP was not properly saved across a function call
body: <p>When I try injecting the C++ dll into the process I end up getting the following error </p>
  
  <p>"Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function pointer declared with a different calling convention." </p>
  
  <p>I'm certain that the cause of the error is because of the DLLMain I very well could be wrong. </p>
  
  <pre><code>BOOL WINAPI DllMain (HMODULE hDll, DWORD dwReason, LPVOID lpReserved )
  {
      switch( dwReason )
      {
      case DLL_PROCESS_ATTACH:
          CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Inject, 0, 0, 0);
          break;
      }
      return TRUE;
  }
  </code></pre>
  
  <p>This is the inject function</p>
  
  <pre><code>VOID Inject() {
      QWORD time;
      DWORD id, pid;
      HANDLE hSs, hThread;
      HMODULE hMono;
      THREADENTRY32 t;
      FILETIME CreationTime, ExitTime, KernelTime, UserTime;
      CONTEXT context = { CONTEXT_CONTROL };
      // poll for mono
  
      while ((hMono = GetModuleHandle("mono.dll")) == NULL) Sleep(10);
  
  
      mono_security_get_mode = (DWORD (__cdecl *)(void))GetProcAddress(hMono, "mono_security_get_mode");
      mono_security_set_mode = (void (__cdecl *)(DWORD))GetProcAddress(hMono, "mono_security_set_mode");
      mono_domain_get = (PVOID (__cdecl *)(void))GetProcAddress(hMono, "mono_domain_get");
      mono_domain_assembly_open = (PVOID (__cdecl *)(PVOID,PCHAR))GetProcAddress(hMono, "mono_domain_assembly_open");
      mono_assembly_get_image = (PVOID (__cdecl *)(PVOID))GetProcAddress(hMono, "mono_assembly_get_image");
      mono_class_from_name = (PVOID (__cdecl *)(PVOID,PCHAR,PCHAR))GetProcAddress(hMono, "mono_class_from_name");
      mono_class_get_method_from_name = (PVOID (__cdecl *)(PVOID,PCHAR,DWORD))GetProcAddress(hMono, "mono_class_get_method_from_name");
      mono_runtime_invoke = (PVOID (__cdecl *)(PVOID,PVOID,PVOID *,PVOID))GetProcAddress(hMono, "mono_runtime_invoke");
  
  
      // mono executes with thread local data, get the main thread.
      id = NULL;
      pid = GetCurrentProcessId();
      hSs = CreateToolhelp32Snapshot(TH32CS_SNAPALL, pid);
  
      t.dwSize = sizeof(THREADENTRY32);
  
      if (hSs) {
          // set time to max value so we can find the oldest thread
          time = 0xFFFFFFFFFFFFFFFF;
          if (Thread32First(hSs, &amp;t)) {
              do {
                  if (t.th32OwnerProcessID == pid) {
                      hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, t.th32ThreadID);
                      if (hThread) {
                          if (GetThreadTimes(hThread, &amp;CreationTime, &amp;ExitTime, &amp;KernelTime, &amp;UserTime)) {
                              // nasty casting lol
                              if (time &gt; *(PQWORD)&amp;CreationTime) {
                                  time = *(PQWORD)&amp;CreationTime;
                                  id = t.th32ThreadID;
                              }
                          }
                          CloseHandle(hThread);
                      }
                  }
              } while (Thread32Next(hSs, &amp;t));
          }
      }
      else {
          Deject("Couldn't acquire the main thread.");
          return;
      }
  
      if (id) {
          // hijack the main thread and have it inject our c# code
          hThread = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, FALSE, id);
          if (hThread) {
              SuspendThread(hThread);
              if (GetThreadContext(hThread, &amp;context)) {
                  dwReturn = context.Eip;
                  context.Eip = (DWORD)MonoInject;
                  SetThreadContext(hThread, &amp;context);
              }
              ResumeThread(hThread);
              CloseHandle(hThread);
          }
          else {
              Deject("Couldn't hijack the main thread, BALLS!");
              return;
          }
      }
  }
  </code></pre>