DWORD64 Wow64Local::LoadLibrary64( const wchar_t* path ) { _UNICODE_STRING_T<DWORD64> upath = {0}; DWORD64 hModule = 0; DWORD64 pfnLdrLoad = (DWORD64)GetProcAddress64(getNTDLL64(), "LdrLoadDll"); upath.Length = (WORD)wcslen(path) * sizeof(wchar_t); upath.MaximumLength = (WORD)upath.Length; upath.Buffer = (DWORD64)path; X64Call(pfnLdrLoad, 4, (DWORD64)NULL, (DWORD64)0, (DWORD64)&upath, (DWORD64)&hModule); return hModule; };
extern "C" SIZE_T __cdecl VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength) { static DWORD64 ntqvm = 0; if (0 == ntqvm) { ntqvm = GetProcAddress64(getNTDLL64(), "NtQueryVirtualMemory"); if (0 == ntqvm) return 0; } DWORD64 ret = 0; DWORD64 status = X64Call(ntqvm, 6, (DWORD64)hProcess, lpAddress, (DWORD64)0, (DWORD64)lpBuffer, (DWORD64)dwLength, (DWORD64)&ret); if (STATUS_SUCCESS != status) SetLastErrorFromX64Call(status); return (SIZE_T)ret; }
DWORD64 getLdrGetProcedureAddress() { DWORD64 modBase = getNTDLL64(); if (0 == modBase) return 0; IMAGE_DOS_HEADER idh; getMem64(&idh, modBase, sizeof(idh)); IMAGE_NT_HEADERS64 inh; getMem64(&inh, modBase + idh.e_lfanew, sizeof(IMAGE_NT_HEADERS64)); IMAGE_DATA_DIRECTORY& idd = inh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (0 == idd.VirtualAddress) return 0; IMAGE_EXPORT_DIRECTORY ied; getMem64(&ied, modBase + idd.VirtualAddress, sizeof(ied)); DWORD* rvaTable = (DWORD*)malloc(sizeof(DWORD)*ied.NumberOfFunctions); if (nullptr == rvaTable) return 0; WATCH(rvaTable); getMem64(rvaTable, modBase + ied.AddressOfFunctions, sizeof(DWORD)*ied.NumberOfFunctions); WORD* ordTable = (WORD*)malloc(sizeof(WORD)*ied.NumberOfFunctions); if (nullptr == ordTable) return 0; WATCH(ordTable); getMem64(ordTable, modBase + ied.AddressOfNameOrdinals, sizeof(WORD)*ied.NumberOfFunctions); DWORD* nameTable = (DWORD*)malloc(sizeof(DWORD)*ied.NumberOfNames); if (nullptr == nameTable) return 0; WATCH(nameTable); getMem64(nameTable, modBase + ied.AddressOfNames, sizeof(DWORD)*ied.NumberOfNames); // lazy search, there is no need to use binsearch for just one function for (DWORD i = 0; i < ied.NumberOfFunctions; i++) { if (!cmpMem64("LdrGetProcedureAddress", modBase + nameTable[i], sizeof("LdrGetProcedureAddress"))) continue; else return modBase + rvaTable[ordTable[i]]; } return 0; }
extern "C" BOOL __cdecl SetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext) { static DWORD64 stc = 0; if (0 == stc) { stc = GetProcAddress64(getNTDLL64(), "NtSetContextThread"); if (0 == stc) return 0; } DWORD64 ret = X64Call(stc, 2, (DWORD64)hThread, (DWORD64)lpContext); if (STATUS_SUCCESS != ret) { SetLastErrorFromX64Call(ret); return FALSE; } else return TRUE; }
extern "C" BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect) { static DWORD64 ntpvm = 0; if (0 == ntpvm) { ntpvm = GetProcAddress64(getNTDLL64(), "NtProtectVirtualMemory"); if (0 == ntpvm) return 0; } DWORD64 tmpAddr = lpAddress; DWORD64 tmpSize = dwSize; DWORD64 ret = X64Call(ntpvm, 5, (DWORD64)hProcess, (DWORD64)&tmpAddr, (DWORD64)&tmpSize, (DWORD64)flNewProtect, (DWORD64)lpflOldProtect); if (STATUS_SUCCESS != ret) { SetLastErrorFromX64Call(ret); return FALSE; } else return TRUE; }
extern "C" BOOL __cdecl VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType) { static DWORD64 ntfvm = 0; if (0 == ntfvm) { ntfvm = GetProcAddress64(getNTDLL64(), "NtFreeVirtualMemory"); if (0 == ntfvm) return 0; } DWORD64 tmpAddr = lpAddress; DWORD64 tmpSize = dwSize; DWORD64 ret = X64Call(ntfvm, 4, (DWORD64)hProcess, (DWORD64)&tmpAddr, (DWORD64)&tmpSize, (DWORD64)dwFreeType); if (STATUS_SUCCESS != ret) { SetLastErrorFromX64Call(ret); return FALSE; } else return TRUE; }
extern "C" DWORD64 __cdecl VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) { static DWORD64 ntavm = 0; if (0 == ntavm) { ntavm = GetProcAddress64(getNTDLL64(), "NtAllocateVirtualMemory"); if (0 == ntavm) return 0; } DWORD64 tmpAddr = lpAddress; DWORD64 tmpSize = dwSize; DWORD64 ret = X64Call(ntavm, 6, (DWORD64)hProcess, (DWORD64)&tmpAddr, (DWORD64)0, (DWORD64)&tmpSize, (DWORD64)flAllocationType, (DWORD64)flProtect); if (STATUS_SUCCESS != ret) { SetLastErrorFromX64Call(ret); return FALSE; } else return tmpAddr; }
extern "C" BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten) { static DWORD64 nrvm = 0; if (0 == nrvm) { nrvm = GetProcAddress64(getNTDLL64(), "NtWriteVirtualMemory"); if (0 == nrvm) return 0; } DWORD64 numOfBytes = lpNumberOfBytesWritten ? *lpNumberOfBytesWritten : 0; DWORD64 ret = X64Call(nrvm, 5, (DWORD64)hProcess, lpBaseAddress, (DWORD64)lpBuffer, (DWORD64)nSize, (DWORD64)&numOfBytes); if (STATUS_SUCCESS != ret) { SetLastErrorFromX64Call(ret); return FALSE; } else { if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = (SIZE_T)numOfBytes; return TRUE; } }
DWORD64 Wow64Local::getLdrGetProcedureAddress() { DWORD ntSize = 0; DWORD64 modBase = getNTDLL64(&ntSize); if(modBase == 0 || ntSize == 0) return 0; std::unique_ptr<uint8_t[]> buf(new uint8_t[ntSize]()); memcpy64((DWORD64)buf.get(), modBase, ntSize); IMAGE_NT_HEADERS64* inh = (IMAGE_NT_HEADERS64*)(buf.get() + ((IMAGE_DOS_HEADER*)buf.get())->e_lfanew); IMAGE_DATA_DIRECTORY& idd = inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (0 == idd.VirtualAddress) return 0; IMAGE_EXPORT_DIRECTORY* ied = (IMAGE_EXPORT_DIRECTORY*)(buf.get() + idd.VirtualAddress); DWORD* rvaTable = (DWORD*)(buf.get() + ied->AddressOfFunctions); WORD* ordTable = (WORD*) (buf.get() + ied->AddressOfNameOrdinals); DWORD* nameTable = (DWORD*)(buf.get() + ied->AddressOfNames); //lazy search, there is no need to use binsearch for just one function for (DWORD i = 0; i < ied->NumberOfFunctions; i++) { if (strcmp((char*)buf.get() + nameTable[i], "LdrGetProcedureAddress")) continue; else { return (DWORD64)(modBase + rvaTable[ordTable[i]]); } } return 0; }