title: Windows Kernel Driver: ZwAllocateVirtualMemory causing thread to terminate
body: <p>I'm trying to write an APC dll injection driver, I've found <a href="https://www.rohitab.com/discuss/topic/40737-inject-dll-from-kernel-mode/" rel="nofollow noreferrer">this</a> example and thought to modify it to my needs.</p>
  
  <p>I use <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nc-ntddk-pcreate_process_notify_routine_ex" rel="nofollow noreferrer">PcreateProcessNotifyRoutineEx</a> to obtain the ProcessId for specific applications I targeting, in this case, "iexplore.exe" and then use <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nc-ntddk-pload_image_notify_routine" rel="nofollow noreferrer">PloadImageNotifyRoutine</a> to check if ntdll.dll is already loaded and initialized (from <a href="https://stackoverflow.com/a/50304959/4917303">this recommendation</a>), and if ntdll.dll is loaded, I call "my" InjectDLL function.</p>
  
  <p>This is the PloadImageNotifyRoutine function that is calling InjectDll:</p>
  
  <pre><code>VOID PloadImageNotifyRoutine(
      _In_ PUNICODE_STRING FullImageName,
      _In_ HANDLE ProcessId,
      _In_ PIMAGE_INFO ImageInfo
  )
  {
      PEPROCESS Process = NULL;
      PETHREAD Thread = NULL;
      PCHAR pTeb = nullptr;
      DWORD ArbitraryUserPointer = 0;
      PCHAR pszProcessNameA = nullptr;
  
      pTeb = (PCHAR)__readfsdword(0x18);
      ArbitraryUserPointer = *(DWORD*)(pTeb + 0x014);
  
      // If ArbitraryUserPointer points to kernel32.dll it means ntdll.dll is done loading.
      if (FALSE == IsStringEndWith((wchar_t*)ArbitraryUserPointer, L"\\kernel32.dll"))
      {
          return;
      }
  
      if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &amp;Process)))
      {
          return;
      }
  
      pszProcessNameA = (PCHAR)PsGetProcessImageFileName(Process);
      if (FALSE == StringNCompare(pszProcessNameA, "iexplore.exe", GetStringLength("iexplore.exe")))
      {
          return;
      }
  
      Thread = KeGetCurrentThread();
      InjectDll(MODULE_PATH, Process, Thread);
      ObDereferenceObject(Process);
  }
  </code></pre>
  
  <p>And this is the InjectDll function:</p>
  
  <pre><code>BOOLEAN InjectDll(PWCHAR pModulePath, PEPROCESS Process, PETHREAD Thread)
  {
      PKINJECT mem;
      ULONG size;
  
      mem = NULL;
      size = 4096;
  
      if (!NT_SUCCESS(ZwAllocateVirtualMemory(NtCurrentProcess(), (PVOID*)&amp;mem, 0, &amp;size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)))
      {
          return FALSE;
      }
  
      //more code ...
  }
  </code></pre>
  
  <p>I removed here some checks so it would be more clear.</p>
  
  <p>I tried to debug it a little, but it seems like <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-ntallocatevirtualmemory" rel="nofollow noreferrer">ZwAllocateVirtualMemory</a> is trying to allocate memory, failing at some point and terminate the thread.</p>
  
  <p>After it calls ExAllocatePoolWithTag it starting to free memory, unmapping sections and terminate the thread (&lt;= calls I saw at the stack while debugging - didn't really trace each call, but looked at it in general view).</p>
  
  <p>The stack before the thread get terminated:</p>
  
  <pre><code>nt!ExAllocatePoolWithTag+0x195
  nt!NtAllocateVirtualMemory+0x1066
  nt!KiSystemServicePostCall
  nt!ZwAllocateVirtualMemory+0x11
  kernel_apc_dll_injector!InjectDll+0x54
  kernel_apc_dll_injector!PloadImageNotifyRoutine+0x2b0
  nt!PsCallImageNotifyRoutines+0x62
  </code></pre>
  
  <p>The process is still visible from task manager, but its Memory is 92k and has no CPU usage, probably because it didn't "cleaned up" properly.</p>
  
  <p>I don't know if my analysis is right, and maybe it even unnecessary for this problem.</p>