DWORD64 WoW64dm::LoadLibrary64( const wchar_t* path ) { BOOL isWOW = FALSE; IsWow64Process(_hProcess, &isWOW); // Inject into x64 if(isWOW == FALSE) { DWORD64 memptr = 0; VirtualAllocEx64(memptr, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(memptr != 0) { DWORD size = 0; DWORD64 hKernel32 = GetModuleHandle64(L"Kernel32.dll", &size); DWORD64 pLoadLib = GetProcAddress64(hKernel32, size, "LoadLibraryW"); if(pLoadLib != 0 && WriteProcessMemory64(memptr, (LPVOID)path, (wcslen(path) + 1)*sizeof(wchar_t), 0) == STATUS_SUCCESS) { DWORD64 status = 0; if(CreateRemoteThread64(pLoadLib, memptr, status, true) != FALSE && status == STATUS_SUCCESS) { VirtualFreeEx64(memptr, 0x1000, MEM_RELEASE); return status; } } VirtualFreeEx64(memptr, 0x1000, MEM_FREE); } return FALSE; } // Inject into WOW64 else { return LoadLibraryRemoteWOW64(path); } }
// runs position independent code in remote process BOOL inject (DWORD dwId, LPVOID pPIC, SIZE_T dwCode, LPVOID lpParam, SIZE_T dwParam, DWORD dbg) { HANDLE hProc, hThread; BOOL bStatus=FALSE, bRemoteWow64, bLocalWow64; LPVOID pCode=NULL, pData=NULL; SIZE_T written; DWORD old, idx, ec; pCreateRemoteThread64 CreateRemoteThread64=NULL; // try open the process printf(" [ opening process id %lu\n", dwId); hProc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, dwId); if (hProc != NULL) { // allocate memory there printf(" [ allocating %lu bytes of RW memory in process for code\n", dwCode); pCode=VirtualAllocEx (hProc, 0, dwCode, MEM_COMMIT, PAGE_READWRITE); if (pCode != NULL) { // write the code printf(" [ writing %lu bytes of code to 0x%p\n", dwCode, pCode); bStatus=WriteProcessMemory (hProc, pCode, pPIC, dwCode, &written); if (bStatus) { printf(" [ changing memory attributes to RX\n"); // change the protection to read/execute only VirtualProtectEx (hProc, pCode, dwCode, PAGE_EXECUTE_READ, &old); // is there a parameter required for PIC? if (lpParam != NULL) { printf(" [ allocating %lu bytes of RW memory in process for parameter\n", dwParam); pData=VirtualAllocEx (hProc, 0, dwParam+1, MEM_COMMIT, PAGE_READWRITE); if (pData != NULL) { printf(" [ writing %lu bytes of data to 0x%p\n", dwParam, pData); bStatus=WriteProcessMemory (hProc, pData, lpParam, dwParam, &written); if (!bStatus) { printf (" [ warning: unable to allocate write parameters to process..."); } } } IsWow64Process (GetCurrentProcess(), &bLocalWow64); IsWow64Process (hProc, &bRemoteWow64); printf(" [ remote process is %s-bit\n", bRemoteWow64 ? "32" : "64"); if (dbg) { printf(" [ attach debugger now or set breakpoint on %p\n", pCode); printf(" [ press any key to continue . . .\n"); fgetc (stdin); } printf(" [ creating thread\n"); // if remote process is not wow64 but I am, // make switch to 64-bit for thread creation. if (!bRemoteWow64 && bLocalWow64) { hThread=NULL; //DebugBreak (); CreateRemoteThread64=(pCreateRemoteThread64) init_func(CreateThreadPIC, CreateThreadPIC_SIZE); CreateRemoteThread64 (hProc, NULL, 0, (LPTHREAD_START_ROUTINE)pCode, pData, 0, 0, &hThread); } else { hThread=CreateRemoteThread (hProc, NULL, 0, (LPTHREAD_START_ROUTINE)pCode, pData, 0, 0); } if (hThread != NULL) { printf (" [ waiting for thread %lx to terminate\n", (DWORD)hThread); idx=WaitForSingleObject (hThread, INFINITE); if (idx!=0) { xstrerror ("WaitForSingleObject"); } ec=0; if (GetExitCodeThread(hThread, &ec)) { printf (" [ exit code was %lu (%08lX)", ec, ec); } CloseHandle (hThread); } else { xstrerror ("CreateRemoteThread"); } } if (idx==0) { VirtualFreeEx (hProc, pCode, 0, MEM_RELEASE); if (pData!=NULL) { VirtualFreeEx (hProc, pData, 0, MEM_RELEASE); } } } else { xstrerror ("VirtualFreeEx()"); } CloseHandle (hProc); } else { xstrerror ("OpenProcess (%lu)", dwId); } if (CreateRemoteThread64!=NULL) free_func(CreateRemoteThread64); return bStatus; }
/* Memory layout. Function additionally writes Activation Context pointer into TEB for RtlQueryInformationActivationContext. ------------------------------------------------------------------------------------ | Return handle | UNICODE_STRING | dll path | padding | executable code | ------------------------------------------------------------------------------------ */ DWORD64 WoW64dm::LoadLibraryRemoteWOW64( const wchar_t* path ) { DWORD64 memptr = 0; int idx = 0; _UNICODE_STRING_T<DWORD64> upath = {0}; VirtualAllocEx64(memptr, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if(memptr != 0) { DWORD size = 0; DWORD64 hNtdll = GetModuleHandle64(L"ntdll.dll", &size); DWORD64 pfnLdrLoadDll = GetProcAddress64(hNtdll, size, "LdrLoadDll"); upath.Length = wcslen(path) * sizeof(wchar_t); upath.MaximumLength = upath.Length; upath.Buffer = memptr + 0x100; DWORD64 codeAddr = memptr + 0xA00; uint8_t code[] = { // Enter x64 mode 0x6A, 0x33, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x83, 0x04, 0x24, 0x05, 0xCB, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x30, 0x00, 0x00, 0x00, // mov rax, gs:[30] 0x48, 0xBA, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, // movabs rdx, memptr + 0x700 0x48, 0x89, 0x90, 0xC8, 0x02, 0x00, 0x00, // mov QWORD PTR [rax + 0x2c8],rdx 0x48, 0x89, 0xE5, // mov rbp, rsp 0x48, 0x83, 0xE4, 0xF0, // and rsp, 0xfffffffffffffff0 0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x30 0x48, 0x31, 0xC9, // xor rcx, rcx 0x48, 0x31, 0xD2, // xor rdx, rdx 0x49, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, // movabs r8, &upath 0x49, 0xB9, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, // movabs r9, &memptr 0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0xEF, 0xBE, 0xAD, 0xDE, // movabs rax, LdrLoadDll //0xCC, 0xFF, 0xD0, // call rax 0x48, 0x89, 0xEC, // mov rsp, rbp // Leave x64 mode 0xE8, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x44, 0x24, 0x04, 0x23, 0x00, 0x00, 0x00, 0x83, 0x04, 0x24, 0x0D, 0xCB, 0xC2, 0x04, 0x00 // retn 0x4 }; DWORD64 patch[] = { memptr + 0x700, memptr + 0x10, memptr, pfnLdrLoadDll }; // Patch immediate memory values for(uint8_t* ptr = code; ptr < (code + sizeof(code) - 8); ptr++) { if(*(DWORD64*)ptr == (DWORD64)0xDEADBEEFDEADBEEF) { *(DWORD64*)ptr = patch[idx]; idx++; } } if(WriteProcessMemory64(memptr + 0x10, &upath, sizeof(upath), 0) == STATUS_SUCCESS && WriteProcessMemory64(upath.Buffer, (LPVOID)path, upath.Length + sizeof(wchar_t), 0) == STATUS_SUCCESS && WriteProcessMemory64(codeAddr, code, sizeof(code), 0) == STATUS_SUCCESS) { DWORD64 status = 0; if(CreateRemoteThread64(codeAddr, 0, status, true) != FALSE && (status & 0xFFFFFFFF) == STATUS_SUCCESS) { DWORD64 module = 0; ReadProcessMemory64(memptr, &module, sizeof(module), 0); VirtualFreeEx64(memptr, 0x1000, MEM_RELEASE); return module; } } VirtualFreeEx64(memptr, 0x1000, MEM_FREE); } return 0; }