From c162ca79d51988b8fc45c9c67a48365547530c83 Mon Sep 17 00:00:00 2001 From: Mr_Goldberg Date: Sun, 16 May 2021 21:04:54 -0400 Subject: [PATCH] Update detours library to latest. --- detours/creatwth.cpp | 410 +++++++++---- detours/detours.cpp | 71 ++- detours/detours.h | 128 +++- detours/disasm.cpp | 1316 +++++++++++++++++++++--------------------- detours/image.cpp | 15 +- detours/modules.cpp | 80 ++- detours/uimports.cc | 138 +++-- 7 files changed, 1294 insertions(+), 864 deletions(-) diff --git a/detours/creatwth.cpp b/detours/creatwth.cpp index d7bc08a..8230b83 100644 --- a/detours/creatwth.cpp +++ b/detours/creatwth.cpp @@ -29,32 +29,32 @@ const GUID DETOUR_EXE_HELPER_GUID = { /* ea0251b9-5cde-41b5-98d0-2af4a26b0fee */ ////////////////////////////////////////////////////////////////////////////// // -// Enumate through modules in the target process. +// Enumerate through modules in the target process. // -static BOOL WINAPI LoadNtHeaderFromProcess(HANDLE hProcess, - HMODULE hModule, - PIMAGE_NT_HEADERS32 pNtHeader) +static PVOID LoadNtHeaderFromProcess(_In_ HANDLE hProcess, + _In_ HMODULE hModule, + _Out_ PIMAGE_NT_HEADERS32 pNtHeader) { + ZeroMemory(pNtHeader, sizeof(*pNtHeader)); PBYTE pbModule = (PBYTE)hModule; if (pbModule == NULL) { SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + return NULL; } MEMORY_BASIC_INFORMATION mbi; ZeroMemory(&mbi, sizeof(mbi)); if (VirtualQueryEx(hProcess, hModule, &mbi, sizeof(mbi)) == 0) { - return FALSE; + return NULL; } IMAGE_DOS_HEADER idh; - if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n", pbModule, pbModule + sizeof(idh), GetLastError())); - return FALSE; + return NULL; } if (idh.e_magic != IMAGE_DOS_SIGNATURE || @@ -62,31 +62,37 @@ static BOOL WINAPI LoadNtHeaderFromProcess(HANDLE hProcess, (DWORD)idh.e_lfanew < sizeof(idh)) { SetLastError(ERROR_BAD_EXE_FORMAT); - return FALSE; + return NULL; } if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, pNtHeader, sizeof(*pNtHeader), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p:%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p:%p) failed: %lu\n", pbModule + idh.e_lfanew, pbModule + idh.e_lfanew + sizeof(*pNtHeader), pbModule, GetLastError())); - return FALSE; + return NULL; } if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { SetLastError(ERROR_BAD_EXE_FORMAT); - return FALSE; + return NULL; } - return TRUE; + return pbModule + idh.e_lfanew; } -static HMODULE WINAPI EnumerateModulesInProcess(HANDLE hProcess, - HMODULE hModuleLast, - PIMAGE_NT_HEADERS32 pNtHeader) +static HMODULE EnumerateModulesInProcess(_In_ HANDLE hProcess, + _In_opt_ HMODULE hModuleLast, + _Out_ PIMAGE_NT_HEADERS32 pNtHeader, + _Out_opt_ PVOID *pRemoteNtHeader) { + ZeroMemory(pNtHeader, sizeof(*pNtHeader)); + if (pRemoteNtHeader) { + *pRemoteNtHeader = NULL; + } + PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY; MEMORY_BASIC_INFORMATION mbi; @@ -118,13 +124,147 @@ static HMODULE WINAPI EnumerateModulesInProcess(HANDLE hProcess, continue; } - if (LoadNtHeaderFromProcess(hProcess, (HMODULE)pbLast, pNtHeader)) { + PVOID remoteHeader + = LoadNtHeaderFromProcess(hProcess, (HMODULE)pbLast, pNtHeader); + if (remoteHeader) { + if (pRemoteNtHeader) { + *pRemoteNtHeader = remoteHeader; + } + return (HMODULE)pbLast; } } return NULL; } +////////////////////////////////////////////////////////////////////////////// +// +// Find payloads in target process. +// + +static PVOID FindDetourSectionInRemoteModule(_In_ HANDLE hProcess, + _In_ HMODULE hModule, + _In_ const IMAGE_NT_HEADERS32 *pNtHeader, + _In_ PVOID pRemoteNtHeader) +{ + if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { + SetLastError(ERROR_EXE_MARKED_INVALID); + return NULL; + } + + PIMAGE_SECTION_HEADER pRemoteSectionHeaders + = (PIMAGE_SECTION_HEADER)((PBYTE)pRemoteNtHeader + + sizeof(pNtHeader->Signature) + + sizeof(pNtHeader->FileHeader) + + pNtHeader->FileHeader.SizeOfOptionalHeader); + + IMAGE_SECTION_HEADER header; + for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; ++n) { + if (!ReadProcessMemory(hProcess, pRemoteSectionHeaders + n, &header, sizeof(header), NULL)) { + DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n", + pRemoteSectionHeaders + n, + (PBYTE)(pRemoteSectionHeaders + n) + sizeof(header), + GetLastError())); + + return NULL; + } + + if (strcmp((PCHAR)header.Name, ".detour") == 0) { + if (header.VirtualAddress == 0 || + header.SizeOfRawData == 0) { + + break; + } + + SetLastError(NO_ERROR); + return (PBYTE)hModule + header.VirtualAddress; + } + } + + SetLastError(ERROR_EXE_MARKED_INVALID); + return NULL; +} + +static PVOID FindPayloadInRemoteDetourSection(_In_ HANDLE hProcess, + _In_ REFGUID rguid, + _Out_opt_ DWORD *pcbData, + _In_ PVOID pvRemoteDetoursSection) +{ + if (pcbData) { + *pcbData = 0; + } + + PBYTE pbData = (PBYTE)pvRemoteDetoursSection; + + DETOUR_SECTION_HEADER header; + if (!ReadProcessMemory(hProcess, pbData, &header, sizeof(header), NULL)) { + DETOUR_TRACE(("ReadProcessMemory(dsh@%p..%p) failed: %lu\n", + pbData, + pbData + sizeof(header), + GetLastError())); + return NULL; + } + + if (header.cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) || + header.nSignature != DETOUR_SECTION_HEADER_SIGNATURE) { + SetLastError(ERROR_EXE_MARKED_INVALID); + return NULL; + } + + if (header.nDataOffset == 0) { + header.nDataOffset = header.cbHeaderSize; + } + + for (PVOID pvSection = pbData + header.nDataOffset; pvSection < pbData + header.cbDataSize;) { + DETOUR_SECTION_RECORD section; + if (!ReadProcessMemory(hProcess, pvSection, §ion, sizeof(section), NULL)) { + DETOUR_TRACE(("ReadProcessMemory(dsr@%p..%p) failed: %lu\n", + pvSection, + (PBYTE)pvSection + sizeof(section), + GetLastError())); + return NULL; + } + + if (DetourAreSameGuid(section.guid, rguid)) { + if (pcbData) { + *pcbData = section.cbBytes - sizeof(section); + } + SetLastError(NO_ERROR); + return (DETOUR_SECTION_RECORD *)pvSection + 1; + } + + pvSection = (PBYTE)pvSection + section.cbBytes; + } + + return NULL; +} + +_Success_(return != NULL) +PVOID WINAPI DetourFindRemotePayload(_In_ HANDLE hProcess, + _In_ REFGUID rguid, + _Out_opt_ DWORD *pcbData) +{ + if (hProcess == NULL) { + SetLastError(ERROR_INVALID_HANDLE); + return NULL; + } + + IMAGE_NT_HEADERS32 header; + PVOID pvRemoteHeader; + for (HMODULE hMod = NULL; (hMod = EnumerateModulesInProcess(hProcess, hMod, &header, &pvRemoteHeader)) != NULL;) { + PVOID pvData = FindDetourSectionInRemoteModule(hProcess, hMod, &header, pvRemoteHeader); + if (pvData != NULL) { + pvData = FindPayloadInRemoteDetourSection(hProcess, rguid, pcbData, pvData); + if (pvData != NULL) { + return pvData; + } + } + } + + SetLastError(ERROR_MOD_NOT_FOUND); + return NULL; +} + ////////////////////////////////////////////////////////////////////////////// // // Find a region of memory in which we can create a replacement import table. @@ -142,7 +282,7 @@ static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBa if (GetLastError() == ERROR_INVALID_PARAMETER) { break; } - DETOUR_TRACE(("VirtualQueryEx(%p) failed: %d\n", + DETOUR_TRACE(("VirtualQueryEx(%p) failed: %lu\n", pbLast, GetLastError())); break; } @@ -187,7 +327,7 @@ static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBa PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (pbAlloc == NULL) { - DETOUR_TRACE(("VirtualAllocEx(%p) failed: %d\n", pbAddress, GetLastError())); + DETOUR_TRACE(("VirtualAllocEx(%p) failed: %lu\n", pbAddress, GetLastError())); continue; } #ifdef _WIN64 @@ -246,7 +386,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR der.pidh = (PBYTE)hModule; der.cbidh = sizeof(der.idh); if (!ReadProcessMemory(hProcess, der.pidh, &der.idh, sizeof(der.idh), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n", der.pidh, der.pidh + der.cbidh, GetLastError())); return FALSE; } @@ -257,7 +397,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR der.pinh = der.pidh + der.idh.e_lfanew; der.cbinh = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader); if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n", der.pinh, der.pinh + der.cbinh, GetLastError())); return FALSE; } @@ -272,7 +412,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR } if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n", der.pinh, der.pinh + der.cbinh, GetLastError())); return FALSE; } @@ -284,7 +424,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR if (der.inh32.CLR_DIRECTORY.VirtualAddress != 0 && der.inh32.CLR_DIRECTORY.Size != 0) { - DETOUR_TRACE(("CLR32.VirtAddr=%x, CLR.Size=%x\n", + DETOUR_TRACE(("CLR32.VirtAddr=%08lx, CLR.Size=%lu\n", der.inh32.CLR_DIRECTORY.VirtualAddress, der.inh32.CLR_DIRECTORY.Size)); @@ -295,7 +435,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR if (der.inh64.CLR_DIRECTORY.VirtualAddress != 0 && der.inh64.CLR_DIRECTORY.Size != 0) { - DETOUR_TRACE(("CLR64.VirtAddr=%x, CLR.Size=%x\n", + DETOUR_TRACE(("CLR64.VirtAddr=%08lx, CLR.Size=%lu\n", der.inh64.CLR_DIRECTORY.VirtualAddress, der.inh64.CLR_DIRECTORY.Size)); @@ -306,7 +446,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR if (der.pclr != 0) { der.cbclr = sizeof(der.clr); if (!ReadProcessMemory(hProcess, der.pclr, &der.clr, der.cbclr, NULL)) { - DETOUR_TRACE(("ReadProcessMemory(clr@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(clr@%p..%p) failed: %lu\n", der.pclr, der.pclr + der.cbclr, GetLastError())); return FALSE; } @@ -323,6 +463,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR #define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS32 #define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC #define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32 +#define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA32 #define UPDATE_IMPORTS_XX UpdateImports32 #define DETOURS_BITS_XX 32 #include "uimports.cc" @@ -339,6 +480,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR #define IMAGE_NT_HEADERS_XX IMAGE_NT_HEADERS64 #define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC #define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64 +#define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA64 #define UPDATE_IMPORTS_XX UpdateImports64 #define DETOURS_BITS_XX 64 #include "uimports.cc" @@ -374,7 +516,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, //////////////////////////////////////////////////////// Read old headers. // if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n", pbModule, pbModule + sizeof(idh), GetLastError())); return FALSE; } @@ -383,7 +525,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, PBYTE pnh = pbModule + idh.e_lfanew; if (!ReadProcessMemory(hProcess, pnh, &inh32, sizeof(inh32), NULL)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n", pnh, pnh + sizeof(inh32), GetLastError())); return FALSE; } @@ -398,7 +540,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, inh32.FileHeader.SizeOfOptionalHeader; ULONG cb = inh32.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); if (!ReadProcessMemory(hProcess, psects, §s, cb, NULL)) { - DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n", psects, psects + cb, GetLastError())); return FALSE; } @@ -455,7 +597,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, } if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) { - DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %d\n", + DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %lu\n", pnh, pnh + sizeof(inh64), GetLastError())); return FALSE; } @@ -466,7 +608,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, inh64.FileHeader.SizeOfOptionalHeader; cb = inh64.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); if (!WriteProcessMemory(hProcess, psects, §s, cb, NULL)) { - DETOUR_TRACE(("WriteProcessMemory(ish@%p..%p) failed: %d\n", + DETOUR_TRACE(("WriteProcessMemory(ish@%p..%p) failed: %lu\n", psects, psects + cb, GetLastError())); return FALSE; } @@ -478,12 +620,12 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, } // Remove the import table. - if (der.pclr != NULL && (der.clr.Flags & 1)) { + if (der.pclr != NULL && (der.clr.Flags & COMIMAGE_FLAGS_ILONLY)) { inh64.IMPORT_DIRECTORY.VirtualAddress = 0; inh64.IMPORT_DIRECTORY.Size = 0; if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) { - DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %d\n", + DETOUR_TRACE(("WriteProcessMemory(inh@%p..%p) failed: %lu\n", pnh, pnh + sizeof(inh64), GetLastError())); return FALSE; } @@ -499,6 +641,37 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine, } #endif // DETOURS_64BIT +typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); + +static BOOL IsWow64ProcessHelper(HANDLE hProcess, + PBOOL Wow64Process) +{ +#ifdef _X86_ + if (Wow64Process == NULL) { + return FALSE; + } + + // IsWow64Process is not available on all supported versions of Windows. + // + HMODULE hKernel32 = LoadLibraryW(L"KERNEL32.DLL"); + if (hKernel32 == NULL) { + DETOUR_TRACE(("LoadLibraryW failed: %lu\n", GetLastError())); + return FALSE; + } + + LPFN_ISWOW64PROCESS pfnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( + hKernel32, "IsWow64Process"); + + if (pfnIsWow64Process == NULL) { + DETOUR_TRACE(("GetProcAddress failed: %lu\n", GetLastError())); + return FALSE; + } + return pfnIsWow64Process(hProcess, Wow64Process); +#else + return IsWow64Process(hProcess, Wow64Process); +#endif +} + ////////////////////////////////////////////////////////////////////////////// // BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, @@ -507,18 +680,17 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, { // Find the next memory region that contains a mapped PE image. // - BOOL bHas64BitDll = FALSE; - BOOL bHas32BitExe = FALSE; BOOL bIs32BitProcess; + BOOL bIs64BitOS = FALSE; HMODULE hModule = NULL; HMODULE hLast = NULL; - DETOUR_TRACE(("DetourUpdateProcessWithDll(%p,dlls=%d)\n", hProcess, nDlls)); + DETOUR_TRACE(("DetourUpdateProcessWithDll(%p,dlls=%lu)\n", hProcess, nDlls)); for (;;) { IMAGE_NT_HEADERS32 inh; - if ((hLast = EnumerateModulesInProcess(hProcess, hLast, &inh)) == NULL) { + if ((hLast = EnumerateModulesInProcess(hProcess, hLast, &inh, NULL)) == NULL) { break; } @@ -527,20 +699,8 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) { hModule = hLast; - if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC - && inh.FileHeader.Machine != 0) { - - bHas32BitExe = TRUE; - } DETOUR_TRACE(("%p Found EXE\n", hLast)); } - else { - if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC - && inh.FileHeader.Machine != 0) { - - bHas64BitDll = TRUE; - } - } } if (hModule == NULL) { @@ -548,19 +708,37 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, return FALSE; } - if (!bHas32BitExe) { - bIs32BitProcess = FALSE; + // Determine if the target process is 32bit or 64bit. This is a two-stop process: + // + // 1. First, determine if we're running on a 64bit operating system. + // - If we're running 64bit code (i.e. _WIN64 is defined), this is trivially true. + // - If we're running 32bit code (i.e. _WIN64 is not defined), test if + // we're running under Wow64. If so, it implies that the operating system + // is 64bit. + // +#ifdef _WIN64 + bIs64BitOS = TRUE; +#else + if (!IsWow64ProcessHelper(GetCurrentProcess(), &bIs64BitOS)) { + return FALSE; } - else if (!bHas64BitDll) { - bIs32BitProcess = TRUE; - } - else { - if (!IsWow64Process(hProcess, &bIs32BitProcess)) { +#endif + + // 2. With the operating system bitness known, we can now consider the target process: + // - If we're running on a 64bit OS, the target process is 32bit in case + // it is running under Wow64. Otherwise, it's 64bit, running natively + // (without Wow64). + // - If we're running on a 32bit OS, the target process must be 32bit, too. + // + if (bIs64BitOS) { + if (!IsWow64ProcessHelper(hProcess, &bIs32BitProcess)) { return FALSE; } + } else { + bIs32BitProcess = TRUE; } - DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bHas32BitExe, bIs32BitProcess)); + DETOUR_TRACE((" 32BitProcess=%d\n", bIs32BitProcess)); return DetourUpdateProcessWithDllEx(hProcess, hModule, @@ -579,11 +757,11 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, // BOOL bIs32BitExe = FALSE; - DETOUR_TRACE(("DetourUpdateProcessWithDllEx(%p,%p,dlls=%d)\n", hProcess, hModule, nDlls)); + DETOUR_TRACE(("DetourUpdateProcessWithDllEx(%p,%p,dlls=%lu)\n", hProcess, hModule, nDlls)); IMAGE_NT_HEADERS32 inh; - if (hModule == NULL || LoadNtHeaderFromProcess(hProcess, hModule, &inh) == NULL) { + if (hModule == NULL || !LoadNtHeaderFromProcess(hProcess, hModule, &inh)) { SetLastError(ERROR_INVALID_OPERATION); return FALSE; } @@ -594,7 +772,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, bIs32BitExe = TRUE; } - DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bIs32BitExe, bIs32BitProcess)); + DETOUR_TRACE((" 32BitExe=%d\n", bIs32BitExe)); if (hModule == NULL) { SetLastError(ERROR_INVALID_OPERATION); @@ -613,8 +791,8 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, // Try to convert a neutral 32-bit managed binary to a 64-bit managed binary. if (bIs32BitExe && !bIs32BitProcess) { if (!der.pclr // Native binary - || (der.clr.Flags & 1) == 0 // Or mixed-mode MSIL - || (der.clr.Flags & 2) != 0) { // Or 32BIT Required MSIL + || (der.clr.Flags & COMIMAGE_FLAGS_ILONLY) == 0 // Or mixed-mode MSIL + || (der.clr.Flags & COMIMAGE_FLAGS_32BITREQUIRED) != 0) { // Or 32BIT Required MSIL SetLastError(ERROR_INVALID_HANDLE); return FALSE; @@ -677,30 +855,30 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, if (der.pclr != NULL) { DETOUR_CLR_HEADER clr; CopyMemory(&clr, &der.clr, sizeof(clr)); - clr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag. + clr.Flags &= ~COMIMAGE_FLAGS_ILONLY; // Clear the IL_ONLY flag. DWORD dwProtect; if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &dwProtect)) { - DETOUR_TRACE(("VirtualProtectEx(clr) write failed: %d\n", GetLastError())); + DETOUR_TRACE(("VirtualProtectEx(clr) write failed: %lu\n", GetLastError())); return FALSE; } if (!WriteProcessMemory(hProcess, der.pclr, &clr, sizeof(clr), NULL)) { - DETOUR_TRACE(("WriteProcessMemory(clr) failed: %d\n", GetLastError())); + DETOUR_TRACE(("WriteProcessMemory(clr) failed: %lu\n", GetLastError())); return FALSE; } if (!VirtualProtectEx(hProcess, der.pclr, sizeof(clr), dwProtect, &dwProtect)) { - DETOUR_TRACE(("VirtualProtectEx(clr) restore failed: %d\n", GetLastError())); + DETOUR_TRACE(("VirtualProtectEx(clr) restore failed: %lu\n", GetLastError())); return FALSE; } DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr)); #if DETOURS_64BIT - if (der.clr.Flags & 0x2) { // Is the 32BIT Required Flag set? + if (der.clr.Flags & COMIMAGE_FLAGS_32BITREQUIRED) { // Is the 32BIT Required Flag set? // X64 never gets here because the process appears as a WOW64 process. // However, on IA64, it doesn't appear to be a WOW process. - DETOUR_TRACE(("CLR Requires 32-bit\n", der.pclr, der.pclr + der.cbclr)); + DETOUR_TRACE(("CLR Requires 32-bit\n")); SetLastError(ERROR_INVALID_HANDLE); return FALSE; } @@ -710,7 +888,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, //////////////////////////////// Save the undo data to the target process. // if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) { - DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError())); + DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError())); return FALSE; } return TRUE; @@ -834,9 +1012,23 @@ BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, _In_ REFGUID rguid, - _In_reads_bytes_(cbData) PVOID pvData, + _In_reads_bytes_(cbData) LPCVOID pvData, _In_ DWORD cbData) { + return DetourCopyPayloadToProcessEx(hProcess, rguid, pvData, cbData) != NULL; +} + +_Success_(return != NULL) +PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess, + _In_ REFGUID rguid, + _In_reads_bytes_(cbData) LPCVOID pvData, + _In_ DWORD cbData) +{ + if (hProcess == NULL) { + SetLastError(ERROR_INVALID_HANDLE); + return NULL; + } + DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) + @@ -847,10 +1039,15 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal, MEM_COMMIT, PAGE_READWRITE); if (pbBase == NULL) { - DETOUR_TRACE(("VirtualAllocEx(%d) failed: %d\n", cbTotal, GetLastError())); - return FALSE; + DETOUR_TRACE(("VirtualAllocEx(%lu) failed: %lu\n", cbTotal, GetLastError())); + return NULL; } + // As you can see in the following code, + // the memory layout of the payload range "[pbBase, pbBase+cbTotal]" is a PE executable file, + // so DetourFreePayload can use "DetourGetContainingModule(Payload pointer)" to get the above "pbBase" pointer, + // pbBase: the memory block allocated by VirtualAllocEx will be released in DetourFreePayload by VirtualFree. + PBYTE pbTarget = pbBase; IMAGE_DOS_HEADER idh; IMAGE_NT_HEADERS inh; @@ -864,8 +1061,8 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, idh.e_lfanew = sizeof(idh); if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) || cbWrote != sizeof(idh)) { - DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); - return FALSE; + DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError())); + return NULL; } pbTarget += sizeof(idh); @@ -877,7 +1074,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, inh.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC; if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) || cbWrote != sizeof(inh)) { - return FALSE; + return NULL; } pbTarget += sizeof(inh); @@ -889,7 +1086,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, cbData); if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) || cbWrote != sizeof(ish)) { - return FALSE; + return NULL; } pbTarget += sizeof(ish); @@ -902,7 +1099,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, cbData); if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) || cbWrote != sizeof(dsh)) { - return FALSE; + return NULL; } pbTarget += sizeof(dsh); @@ -912,19 +1109,20 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, dsr.guid = rguid; if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) || cbWrote != sizeof(dsr)) { - return FALSE; + return NULL; } pbTarget += sizeof(dsr); if (!WriteProcessMemory(hProcess, pbTarget, pvData, cbData, &cbWrote) || cbWrote != cbData) { - return FALSE; + return NULL; } - pbTarget += cbData; - DETOUR_TRACE(("Copied %d byte payload into target process at %p\n", - cbTotal, pbTarget - cbTotal)); - return TRUE; + DETOUR_TRACE(("Copied %lu byte payload into target process at %p\n", + cbData, pbTarget)); + + SetLastError(NO_ERROR); + return pbTarget; } static BOOL s_fSearchedForHelper = FALSE; @@ -949,7 +1147,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, s_pHelper->pid); if (hProcess == NULL) { - DETOUR_TRACE(("OpenProcess(pid=%d) failed: %d\n", + DETOUR_TRACE(("OpenProcess(pid=%lu) failed: %lu\n", s_pHelper->pid, GetLastError())); Result = 9901; goto Cleanup; @@ -970,7 +1168,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, } if (!DetourUpdateProcessWithDll(hProcess, rlpDlls, s_pHelper->nDlls)) { - DETOUR_TRACE(("DetourUpdateProcessWithDll(pid=%d) failed: %d\n", + DETOUR_TRACE(("DetourUpdateProcessWithDll(pid=%lu) failed: %lu\n", s_pHelper->pid, GetLastError())); Result = 9903; goto Cleanup; @@ -983,6 +1181,15 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, rlpDlls = NULL; } + // Note: s_pHelper is allocated as part of injecting the payload in DetourCopyPayloadToProcess(..), + // it's a fake section and not data allocated by the system PE loader. + + // Delete the payload after execution to release the memory occupied by it + if (s_pHelper != NULL) { + DetourFreePayload(s_pHelper); + s_pHelper = NULL; + } + ExitProcess(Result); } @@ -1146,7 +1353,7 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, HRESULT hr; DWORD nLen = GetEnvironmentVariableA("WINDIR", szExe, ARRAYSIZE(szExe)); - DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%d,dlls=%d)\n", dwTargetPid, nDlls)); + DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%lu,dlls=%lu)\n", dwTargetPid, nDlls)); if (nDlls < 1 || nDlls > 4096) { SetLastError(ERROR_INVALID_PARAMETER); goto Cleanup; @@ -1172,8 +1379,10 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, goto Cleanup; } + //for East Asia languages and so on, like Chinese, print format with "%hs" can not work fine before user call _tsetlocale(LC_ALL,_T(".ACP")); + //so we can't use "%hs" in format string, because the dll that contain this code would inject to any process, even not call _tsetlocale(LC_ALL,_T(".ACP")) before hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand), - "rundll32.exe \"%hs\",#1", &helper->rDlls[0]); + "rundll32.exe \"%s\",#1", &helper->rDlls[0]); if (!SUCCEEDED(hr)) { goto Cleanup; } @@ -1189,7 +1398,7 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, if (!DetourCopyPayloadToProcess(pi.hProcess, DETOUR_EXE_HELPER_GUID, helper, helper->cb)) { - DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError())); + DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError())); TerminateProcess(pi.hProcess, ~0u); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); @@ -1206,13 +1415,13 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, CloseHandle(pi.hThread); if (dwResult != 0) { - DETOUR_TRACE(("Rundll32.exe failed: result=%d\n", dwResult)); + DETOUR_TRACE(("Rundll32.exe failed: result=%lu\n", dwResult)); goto Cleanup; } Result = TRUE; } else { - DETOUR_TRACE(("CreateProcess failed: %d\n", GetLastError())); + DETOUR_TRACE(("CreateProcess failed: %lu\n", GetLastError())); goto Cleanup; } @@ -1240,9 +1449,11 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, WCHAR szCommand[MAX_PATH]; PDETOUR_EXE_HELPER helper = NULL; HRESULT hr; + WCHAR szDllName[MAX_PATH]; + int cchWrittenWideChar; DWORD nLen = GetEnvironmentVariableW(L"WINDIR", szExe, ARRAYSIZE(szExe)); - DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%d,dlls=%d)\n", dwTargetPid, nDlls)); + DETOUR_TRACE(("DetourProcessViaHelperDlls(pid=%lu,dlls=%lu)\n", dwTargetPid, nDlls)); if (nDlls < 1 || nDlls > 4096) { SetLastError(ERROR_INVALID_PARAMETER); goto Cleanup; @@ -1268,8 +1479,15 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, goto Cleanup; } + //for East Asia languages and so on, like Chinese, print format with "%hs" can not work fine before user call _tsetlocale(LC_ALL,_T(".ACP")); + //so we can't use "%hs" in format string, because the dll that contain this code would inject to any process, even not call _tsetlocale(LC_ALL,_T(".ACP")) before + + cchWrittenWideChar = MultiByteToWideChar(CP_ACP, 0, &helper->rDlls[0], -1, szDllName, ARRAYSIZE(szDllName)); + if (cchWrittenWideChar >= ARRAYSIZE(szDllName) || cchWrittenWideChar <= 0) { + goto Cleanup; + } hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand), - L"rundll32.exe \"%hs\",#1", &helper->rDlls[0]); + L"rundll32.exe \"%s\",#1", szDllName); if (!SUCCEEDED(hr)) { goto Cleanup; } @@ -1285,15 +1503,13 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, if (!DetourCopyPayloadToProcess(pi.hProcess, DETOUR_EXE_HELPER_GUID, helper, helper->cb)) { - DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError())); + DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError())); TerminateProcess(pi.hProcess, ~0u); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); goto Cleanup; } - ResumeThread(pi.hThread); - ResumeThread(pi.hThread); WaitForSingleObject(pi.hProcess, INFINITE); @@ -1304,13 +1520,13 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, CloseHandle(pi.hThread); if (dwResult != 0) { - DETOUR_TRACE(("Rundll32.exe failed: result=%d\n", dwResult)); + DETOUR_TRACE(("Rundll32.exe failed: result=%lu\n", dwResult)); goto Cleanup; } Result = TRUE; } else { - DETOUR_TRACE(("CreateProcess failed: %d\n", GetLastError())); + DETOUR_TRACE(("CreateProcess failed: %lu\n", GetLastError())); goto Cleanup; } diff --git a/detours/detours.cpp b/detours/detours.cpp index b8f4688..1fb297d 100644 --- a/detours/detours.cpp +++ b/detours/detours.cpp @@ -18,6 +18,27 @@ #define NOTHROW +////////////////////////////////////////////////////////////////////////////// +// + +#ifdef _DEBUG +extern "C" IMAGE_DOS_HEADER __ImageBase; +int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg) +{ + int nRet = 0; + DWORD dwLastError = GetLastError(); + CHAR szModuleNameWithFunctionName[MAX_PATH * 2]; + szModuleNameWithFunctionName[0] = 0; + GetModuleFileNameA((HMODULE)&__ImageBase, szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName)); + StringCchCatNA(szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName), ",", ARRAYSIZE(szModuleNameWithFunctionName) - strlen(szModuleNameWithFunctionName) - 1); + StringCchCatNA(szModuleNameWithFunctionName, ARRAYSIZE(szModuleNameWithFunctionName), FunctionName, ARRAYSIZE(szModuleNameWithFunctionName) - strlen(szModuleNameWithFunctionName) - 1); + SetLastError(dwLastError); + nRet = _CrtDbgReport(reportType, filename, linenumber, szModuleNameWithFunctionName, msg); + SetLastError(dwLastError); + return nRet; +} +#endif// _DEBUG + ////////////////////////////////////////////////////////////////////////////// // struct _DETOUR_ALIGN @@ -186,7 +207,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode, // We have to place trampolines within +/- 2GB of code. ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); + DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi)); // And, within +/- 2GB of relative jmp targets. if (pbCode[0] == 0xe9) { // jmp +imm32 @@ -198,7 +219,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode, else { lo = detour_2gb_below((ULONG_PTR)pbNew); } - DETOUR_TRACE(("[%p..%p..%p] +imm32\n", lo, pbCode, hi)); + DETOUR_TRACE(("[%p..%p..%p] +imm32\n", (PVOID)lo, pbCode, (PVOID)hi)); } *ppLower = (PDETOUR_TRAMPOLINE)lo; @@ -399,7 +420,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode, // We have to place trampolines within +/- 2GB of code. ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); + DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi)); // And, within +/- 2GB of relative jmp vectors. if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] @@ -411,7 +432,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode, else { lo = detour_2gb_below((ULONG_PTR)pbNew); } - DETOUR_TRACE(("[%p..%p..%p] [+imm32]\n", lo, pbCode, hi)); + DETOUR_TRACE(("[%p..%p..%p] [+imm32]\n", (PVOID)lo, pbCode, (PVOID)hi)); } // And, within +/- 2GB of relative jmp targets. else if (pbCode[0] == 0xe9) { // jmp +imm32 @@ -423,7 +444,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode, else { lo = detour_2gb_below((ULONG_PTR)pbNew); } - DETOUR_TRACE(("[%p..%p..%p] +imm32\n", lo, pbCode, hi)); + DETOUR_TRACE(("[%p..%p..%p] +imm32\n", (PVOID)lo, pbCode, (PVOID)hi)); } *ppLower = (PDETOUR_TRAMPOLINE)lo; @@ -818,7 +839,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode, // We have to place trampolines within +/- 2GB of code. ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); + DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi)); *ppLower = (PDETOUR_TRAMPOLINE)lo; *ppUpper = (PDETOUR_TRAMPOLINE)hi; @@ -863,7 +884,7 @@ struct _DETOUR_TRAMPOLINE // An ARM64 instruction is 4 bytes long. // // The overwrite is always composed of 3 instructions (12 bytes) which perform an indirect jump - // using _DETOUR_TRAMPOLINE::pbDetour as the address holding the target location. + // using _DETOUR_TRAMPOLINE::pbDetour as the address holding the target location. // // Copied instructions can expand. // @@ -1124,7 +1145,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode, ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode); ULONG_PTR hi = detour_2gb_above((ULONG_PTR)pbCode); - DETOUR_TRACE(("[%p..%p..%p]\n", lo, pbCode, hi)); + DETOUR_TRACE(("[%p..%p..%p]\n", (PVOID)lo, pbCode, (PVOID)hi)); *ppLower = (PDETOUR_TRAMPOLINE)lo; *ppUpper = (PDETOUR_TRAMPOLINE)hi; @@ -1237,7 +1258,7 @@ static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi) break; } - DETOUR_TRACE((" Try %p => %p..%p %6x\n", + DETOUR_TRACE((" Try %p => %p..%p %6lx\n", pbTry, mbi.BaseAddress, (PBYTE)mbi.BaseAddress + mbi.RegionSize - 1, @@ -1252,6 +1273,9 @@ static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi) if (pv != NULL) { return pv; } + else if (GetLastError() == ERROR_DYNAMIC_CODE_BLOCKED) { + return NULL; + } pbTry += DETOUR_REGION_SIZE; } else { @@ -1284,7 +1308,7 @@ static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi) break; } - DETOUR_TRACE((" Try %p => %p..%p %6x\n", + DETOUR_TRACE((" Try %p => %p..%p %6lx\n", pbTry, mbi.BaseAddress, (PBYTE)mbi.BaseAddress + mbi.RegionSize - 1, @@ -1299,6 +1323,9 @@ static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi) if (pv != NULL) { return pv; } + else if (GetLastError() == ERROR_DYNAMIC_CODE_BLOCKED) { + return NULL; + } pbTry -= DETOUR_REGION_SIZE; } else { @@ -1698,7 +1725,7 @@ LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer) #endif // DETOURS_ARM } else { - DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbRestore=%d\n", + DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbRestore=%u\n", o->pTrampoline, o->pTrampoline->pbRemain, o->pTrampoline->pbDetour, @@ -1990,13 +2017,13 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, } if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { - DETOUR_TRACE(("transaction conflict with thread id=%d\n", s_nPendingThreadId)); + DETOUR_TRACE(("transaction conflict with thread id=%ld\n", s_nPendingThreadId)); return ERROR_INVALID_OPERATION; } // If any of the pending operations failed, then we don't need to do this. if (s_nPendingError != NO_ERROR) { - DETOUR_TRACE(("pending transaction error=%d\n", s_nPendingError)); + DETOUR_TRACE(("pending transaction error=%ld\n", s_nPendingError)); return s_nPendingError; } @@ -2177,7 +2204,7 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, pTrampoline->rAlign[n].obTrampoline == 0) { break; } - DETOUR_TRACE((" %d/%d", + DETOUR_TRACE((" %u/%u", pTrampoline->rAlign[n].obTarget, pTrampoline->rAlign[n].obTrampoline )); @@ -2545,4 +2572,20 @@ BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, pAddress, nSize, dwNewProtect, pdwOldProtect); } +BOOL WINAPI DetourAreSameGuid(_In_ REFGUID left, _In_ REFGUID right) +{ + return + left.Data1 == right.Data1 && + left.Data2 == right.Data2 && + left.Data3 == right.Data3 && + left.Data4[0] == right.Data4[0] && + left.Data4[1] == right.Data4[1] && + left.Data4[2] == right.Data4[2] && + left.Data4[3] == right.Data4[3] && + left.Data4[4] == right.Data4[4] && + left.Data4[5] == right.Data4[5] && + left.Data4[6] == right.Data4[6] && + left.Data4[7] == right.Data4[7]; +} + // End of File diff --git a/detours/detours.h b/detours/detours.h index 97595a2..3354d72 100644 --- a/detours/detours.h +++ b/detours/detours.h @@ -28,6 +28,15 @@ #pragma warning(disable:4091) // empty typedef #endif +// Suppress declspec(dllimport) for the sake of Detours +// users that provide kernel32 functionality themselves. +// This is ok in the mainstream case, it will just cost +// an extra instruction calling some functions, which +// LTCG optimizes away. +// +#define _KERNEL32_ 1 +#define _USER32_ 1 + #include #if (_MSC_VER < 1310) #else @@ -36,8 +45,28 @@ #pragma warning(disable:6102 6103) // /analyze warnings #endif #include +#include #pragma warning(pop) #endif +#include + +// Allow Detours to cleanly compile with the MingW toolchain. +// +#ifdef __GNUC__ +#define __try +#define __except(x) if (0) +#include +#endif + +// From winerror.h, as this error isn't found in some SDKs: +// +// MessageId: ERROR_DYNAMIC_CODE_BLOCKED +// +// MessageText: +// +// The operation was blocked as the process prohibits dynamic code generation. +// +#define ERROR_DYNAMIC_CODE_BLOCKED 1655L #endif // DETOURS_INTERNAL @@ -99,7 +128,7 @@ ////////////////////////////////////////////////////////////////////////////// // -#if (_MSC_VER < 1299) +#if (_MSC_VER < 1299) && !defined(__MINGW32__) typedef LONG LONG_PTR; typedef ULONG ULONG_PTR; #endif @@ -120,6 +149,7 @@ typedef ULONG ULONG_PTR; #undef _In_ #undef _In_bytecount_ #undef _In_count_ +#undef __in_ecount #undef _In_opt_ #undef _In_opt_bytecount_ #undef _In_opt_count_ @@ -176,6 +206,10 @@ typedef ULONG ULONG_PTR; #define _In_count_(x) #endif +#ifndef __in_ecount +#define __in_ecount(x) +#endif + #ifndef _In_opt_ #define _In_opt_ #endif @@ -581,16 +615,17 @@ _Readable_bytes_(*pcbData) _Success_(return != NULL) PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, _In_ REFGUID rguid, - _Out_ DWORD *pcbData); + _Out_opt_ DWORD *pcbData); _Writable_bytes_(*pcbData) _Readable_bytes_(*pcbData) _Success_(return != NULL) PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, - _Out_ DWORD * pcbData); + _Out_opt_ DWORD *pcbData); DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule); +BOOL WINAPI DetourFreePayload(_In_ PVOID pvData); ///////////////////////////////////////////////// Persistent Binary Functions. // @@ -629,6 +664,11 @@ BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary); /////////////////////////////////////////////////// Create Process & Load Dll. // +_Success_(return != NULL) +PVOID WINAPI DetourFindRemotePayload(_In_ HANDLE hProcess, + _In_ REFGUID rguid, + _Out_opt_ DWORD *pcbData); + typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)( _In_opt_ LPCSTR lpApplicationName, _Inout_opt_ LPSTR lpCommandLine, @@ -795,8 +835,14 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, _In_ REFGUID rguid, - _In_reads_bytes_(cbData) PVOID pvData, + _In_reads_bytes_(cbData) LPCVOID pvData, _In_ DWORD cbData); +_Success_(return != NULL) +PVOID WINAPI DetourCopyPayloadToProcessEx(_In_ HANDLE hProcess, + _In_ REFGUID rguid, + _In_reads_bytes_(cbData) LPCVOID pvData, + _In_ DWORD cbData); + BOOL WINAPI DetourRestoreAfterWith(VOID); BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, _In_ DWORD cbData); @@ -812,6 +858,60 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, } #endif // __cplusplus +/////////////////////////////////////////////////// Type-safe overloads for C++ +// +#if __cplusplus >= 201103L || _MSVC_LANG >= 201103L +#include + +template +struct DetoursIsFunctionPointer : std::false_type {}; + +template +struct DetoursIsFunctionPointer : std::is_function::type> {}; + +template< + typename T, + typename std::enable_if::value, int>::type = 0> +LONG DetourAttach(_Inout_ T *ppPointer, + _In_ T pDetour) noexcept +{ + return DetourAttach( + reinterpret_cast(ppPointer), + reinterpret_cast(pDetour)); +} + +template< + typename T, + typename std::enable_if::value, int>::type = 0> +LONG DetourAttachEx(_Inout_ T *ppPointer, + _In_ T pDetour, + _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, + _Out_opt_ T *ppRealTarget, + _Out_opt_ T *ppRealDetour) noexcept +{ + return DetourAttachEx( + reinterpret_cast(ppPointer), + reinterpret_cast(pDetour), + ppRealTrampoline, + reinterpret_cast(ppRealTarget), + reinterpret_cast(ppRealDetour)); +} + +template< + typename T, + typename std::enable_if::value, int>::type = 0> +LONG DetourDetach(_Inout_ T *ppPointer, + _In_ T pDetour) noexcept +{ + return DetourDetach( + reinterpret_cast(ppPointer), + reinterpret_cast(pDetour)); +} + +#endif // __cplusplus >= 201103L || _MSVC_LANG >= 201103L +// +////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////// Detours Internal Definitions. // #ifdef __cplusplus @@ -822,7 +922,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, ////////////////////////////////////////////////////////////////////////////// // -#if (_MSC_VER < 1299) +#if (_MSC_VER < 1299) && !defined(__GNUC__) #include typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; @@ -884,6 +984,21 @@ PDETOUR_SYM_INFO DetourLoadImageHlp(VOID); #endif #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 +#ifdef _DEBUG + +int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg); + +#define DETOUR_ASSERT_EXPR_WITH_FUNCTION(expr, msg) \ + (void) ((expr) || \ + (1 != Detour_AssertExprWithFunctionName(_CRT_ASSERT, __FILE__, __LINE__,__FUNCTION__, msg)) || \ + (_CrtDbgBreak(), 0)) + +#define DETOUR_ASSERT(expr) DETOUR_ASSERT_EXPR_WITH_FUNCTION((expr), #expr) + +#else// _DEBUG +#define DETOUR_ASSERT(expr) +#endif// _DEBUG + #ifndef DETOUR_TRACE #if DETOUR_DEBUG #define DETOUR_TRACE(x) printf x @@ -1090,6 +1205,9 @@ BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, _In_ SIZE_T nSize, _In_ DWORD dwNewProtect, _Out_ PDWORD pdwOldProtect); + +// Detours must depend only on kernel32.lib, so we cannot use IsEqualGUID +BOOL WINAPI DetourAreSameGuid(_In_ REFGUID left, _In_ REFGUID right); #ifdef __cplusplus } #endif // __cplusplus diff --git a/detours/disasm.cpp b/detours/disasm.cpp index ce666fb..6cd23b2 100644 --- a/detours/disasm.cpp +++ b/detours/disasm.cpp @@ -187,7 +187,6 @@ class CDetourDis struct COPYENTRY { // Many of these fields are often ignored. See ENTRY_DataIgnored. - ULONG nOpcode : 8; // Opcode (ignored) ULONG nFixedSize : 4; // Fixed size of opcode ULONG nFixedSize16 : 4; // Fixed size when 16 bit operand ULONG nModOffset : 4; // Offset to mod/rm byte (0=none) @@ -199,61 +198,60 @@ class CDetourDis protected: // These macros define common uses of nFixedSize, nFixedSize16, nModOffset, nRelOffset, nFlagBits, pfCopy. #define ENTRY_DataIgnored 0, 0, 0, 0, 0, -#define ENTRY_CopyBytes1 1, 1, 0, 0, 0, &CDetourDis::CopyBytes +#define ENTRY_CopyBytes1 { 1, 1, 0, 0, 0, &CDetourDis::CopyBytes } #ifdef DETOURS_X64 -#define ENTRY_CopyBytes1Address 9, 5, 0, 0, ADDRESS, &CDetourDis::CopyBytes +#define ENTRY_CopyBytes1Address { 9, 5, 0, 0, ADDRESS, &CDetourDis::CopyBytes } #else -#define ENTRY_CopyBytes1Address 5, 3, 0, 0, ADDRESS, &CDetourDis::CopyBytes +#define ENTRY_CopyBytes1Address { 5, 3, 0, 0, ADDRESS, &CDetourDis::CopyBytes } #endif -#define ENTRY_CopyBytes1Dynamic 1, 1, 0, 0, DYNAMIC, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes2 2, 2, 0, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes2Jump ENTRY_DataIgnored &CDetourDis::CopyBytesJump -#define ENTRY_CopyBytes2CantJump 2, 2, 0, 1, NOENLARGE, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes2Dynamic 2, 2, 0, 0, DYNAMIC, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes3 3, 3, 0, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes3Dynamic 3, 3, 0, 0, DYNAMIC, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes3Or5 5, 3, 0, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes3Or5Dynamic 5, 3, 0, 0, DYNAMIC, &CDetourDis::CopyBytes // x86 only +#define ENTRY_CopyBytes1Dynamic { 1, 1, 0, 0, DYNAMIC, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes2 { 2, 2, 0, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes2Jump { ENTRY_DataIgnored &CDetourDis::CopyBytesJump } +#define ENTRY_CopyBytes2CantJump { 2, 2, 0, 1, NOENLARGE, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes2Dynamic { 2, 2, 0, 0, DYNAMIC, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes3 { 3, 3, 0, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes3Dynamic { 3, 3, 0, 0, DYNAMIC, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes3Or5 { 5, 3, 0, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes3Or5Dynamic { 5, 3, 0, 0, DYNAMIC, &CDetourDis::CopyBytes }// x86 only #ifdef DETOURS_X64 -#define ENTRY_CopyBytes3Or5Rax 5, 3, 0, 0, RAX, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes3Or5Target 5, 5, 0, 1, 0, &CDetourDis::CopyBytes +#define ENTRY_CopyBytes3Or5Rax { 5, 3, 0, 0, RAX, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes3Or5Target { 5, 5, 0, 1, 0, &CDetourDis::CopyBytes } #else -#define ENTRY_CopyBytes3Or5Rax 5, 3, 0, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes3Or5Target 5, 3, 0, 1, 0, &CDetourDis::CopyBytes +#define ENTRY_CopyBytes3Or5Rax { 5, 3, 0, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes3Or5Target { 5, 3, 0, 1, 0, &CDetourDis::CopyBytes } #endif -#define ENTRY_CopyBytes4 4, 4, 0, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes5 5, 5, 0, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes5Or7Dynamic 7, 5, 0, 0, DYNAMIC, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes7 7, 7, 0, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes2Mod 2, 2, 1, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes2ModDynamic 2, 2, 1, 0, DYNAMIC, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes2Mod1 3, 3, 1, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes2ModOperand 6, 4, 1, 0, 0, &CDetourDis::CopyBytes -#define ENTRY_CopyBytes3Mod 3, 3, 2, 0, 0, &CDetourDis::CopyBytes // SSE3 0F 38 opcode modrm -#define ENTRY_CopyBytes3Mod1 4, 4, 2, 0, 0, &CDetourDis::CopyBytes // SSE3 0F 3A opcode modrm .. imm8 -#define ENTRY_CopyBytesPrefix ENTRY_DataIgnored &CDetourDis::CopyBytesPrefix -#define ENTRY_CopyBytesSegment ENTRY_DataIgnored &CDetourDis::CopyBytesSegment -#define ENTRY_CopyBytesRax ENTRY_DataIgnored &CDetourDis::CopyBytesRax -#define ENTRY_CopyF2 ENTRY_DataIgnored &CDetourDis::CopyF2 -#define ENTRY_CopyF3 ENTRY_DataIgnored &CDetourDis::CopyF3 // 32bit x86 only -#define ENTRY_Copy0F ENTRY_DataIgnored &CDetourDis::Copy0F -#define ENTRY_Copy0F78 ENTRY_DataIgnored &CDetourDis::Copy0F78 -#define ENTRY_Copy0F00 ENTRY_DataIgnored &CDetourDis::Copy0F00 // 32bit x86 only -#define ENTRY_Copy0FB8 ENTRY_DataIgnored &CDetourDis::Copy0FB8 // 32bit x86 only -#define ENTRY_Copy66 ENTRY_DataIgnored &CDetourDis::Copy66 -#define ENTRY_Copy67 ENTRY_DataIgnored &CDetourDis::Copy67 -#define ENTRY_CopyF6 ENTRY_DataIgnored &CDetourDis::CopyF6 -#define ENTRY_CopyF7 ENTRY_DataIgnored &CDetourDis::CopyF7 -#define ENTRY_CopyFF ENTRY_DataIgnored &CDetourDis::CopyFF -#define ENTRY_CopyVex2 ENTRY_DataIgnored &CDetourDis::CopyVex2 -#define ENTRY_CopyVex3 ENTRY_DataIgnored &CDetourDis::CopyVex3 -#define ENTRY_CopyEvex ENTRY_DataIgnored &CDetourDis::CopyEvex // 62, 3 byte payload, then normal with implied prefixes like vex -#define ENTRY_CopyXop ENTRY_DataIgnored &CDetourDis::CopyXop // 0x8F ... POP /0 or AMD XOP -#define ENTRY_CopyBytesXop 5, 5, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm -#define ENTRY_CopyBytesXop1 6, 6, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm ... imm8 -#define ENTRY_CopyBytesXop4 9, 9, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm ... imm32 -#define ENTRY_Invalid ENTRY_DataIgnored &CDetourDis::Invalid -#define ENTRY_End ENTRY_DataIgnored NULL +#define ENTRY_CopyBytes4 { 4, 4, 0, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes5 { 5, 5, 0, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes5Or7Dynamic { 7, 5, 0, 0, DYNAMIC, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes7 { 7, 7, 0, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes2Mod { 2, 2, 1, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes2ModDynamic { 2, 2, 1, 0, DYNAMIC, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes2Mod1 { 3, 3, 1, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes2ModOperand { 6, 4, 1, 0, 0, &CDetourDis::CopyBytes } +#define ENTRY_CopyBytes3Mod { 3, 3, 2, 0, 0, &CDetourDis::CopyBytes } // SSE3 0F 38 opcode modrm +#define ENTRY_CopyBytes3Mod1 { 4, 4, 2, 0, 0, &CDetourDis::CopyBytes } // SSE3 0F 3A opcode modrm .. imm8 +#define ENTRY_CopyBytesPrefix { ENTRY_DataIgnored &CDetourDis::CopyBytesPrefix } +#define ENTRY_CopyBytesSegment { ENTRY_DataIgnored &CDetourDis::CopyBytesSegment } +#define ENTRY_CopyBytesRax { ENTRY_DataIgnored &CDetourDis::CopyBytesRax } +#define ENTRY_CopyF2 { ENTRY_DataIgnored &CDetourDis::CopyF2 } +#define ENTRY_CopyF3 { ENTRY_DataIgnored &CDetourDis::CopyF3 } // 32bit x86 only +#define ENTRY_Copy0F { ENTRY_DataIgnored &CDetourDis::Copy0F } +#define ENTRY_Copy0F78 { ENTRY_DataIgnored &CDetourDis::Copy0F78 } +#define ENTRY_Copy0F00 { ENTRY_DataIgnored &CDetourDis::Copy0F00 } // 32bit x86 only +#define ENTRY_Copy0FB8 { ENTRY_DataIgnored &CDetourDis::Copy0FB8 } // 32bit x86 only +#define ENTRY_Copy66 { ENTRY_DataIgnored &CDetourDis::Copy66 } +#define ENTRY_Copy67 { ENTRY_DataIgnored &CDetourDis::Copy67 } +#define ENTRY_CopyF6 { ENTRY_DataIgnored &CDetourDis::CopyF6 } +#define ENTRY_CopyF7 { ENTRY_DataIgnored &CDetourDis::CopyF7 } +#define ENTRY_CopyFF { ENTRY_DataIgnored &CDetourDis::CopyFF } +#define ENTRY_CopyVex2 { ENTRY_DataIgnored &CDetourDis::CopyVex2 } +#define ENTRY_CopyVex3 { ENTRY_DataIgnored &CDetourDis::CopyVex3 } +#define ENTRY_CopyEvex { ENTRY_DataIgnored &CDetourDis::CopyEvex } // 62, 3 byte payload, then normal with implied prefixes like vex +#define ENTRY_CopyXop { ENTRY_DataIgnored &CDetourDis::CopyXop } // 0x8F ... POP /0 or AMD XOP +#define ENTRY_CopyBytesXop { 5, 5, 4, 0, 0, &CDetourDis::CopyBytes } // 0x8F xop1 xop2 opcode modrm +#define ENTRY_CopyBytesXop1 { 6, 6, 4, 0, 0, &CDetourDis::CopyBytes } // 0x8F xop1 xop2 opcode modrm ... imm8 +#define ENTRY_CopyBytesXop4 { 9, 9, 4, 0, 0, &CDetourDis::CopyBytes } // 0x8F xop1 xop2 opcode modrm ... imm32 +#define ENTRY_Invalid { ENTRY_DataIgnored &CDetourDis::Invalid } PBYTE CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); PBYTE CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); @@ -286,8 +284,8 @@ class CDetourDis PBYTE CopyXop(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); protected: - static const COPYENTRY s_rceCopyTable[257]; - static const COPYENTRY s_rceCopyTable0F[257]; + static const COPYENTRY s_rceCopyTable[]; + static const COPYENTRY s_rceCopyTable0F[]; static const BYTE s_rbModRm[256]; static PBYTE s_pbModuleBeg; static PBYTE s_pbModuleEnd; @@ -325,16 +323,15 @@ PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, /////////////////////////////////////////////////////////// Disassembler Code. // -CDetourDis::CDetourDis(_Out_opt_ PBYTE *ppbTarget, _Out_opt_ LONG *plExtra) +CDetourDis::CDetourDis(_Out_opt_ PBYTE *ppbTarget, _Out_opt_ LONG *plExtra) : + m_bOperandOverride(FALSE), + m_bAddressOverride(FALSE), + m_bRaxOverride(FALSE), + m_bF2(FALSE), + m_bF3(FALSE), + m_bVex(FALSE), + m_bEvex(FALSE) { - m_bOperandOverride = FALSE; - m_bAddressOverride = FALSE; - m_bRaxOverride = FALSE; - m_bF2 = FALSE; - m_bF3 = FALSE; - m_bVex = FALSE; - m_bEvex = FALSE; - m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget; m_plExtra = plExtra ? plExtra : &m_lScratchExtra; @@ -597,8 +594,8 @@ PBYTE CDetourDis::Copy0F78(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc) { // vmread, 66/extrq, F2/insertq - static const COPYENTRY vmread = { 0x78, ENTRY_CopyBytes2Mod }; - static const COPYENTRY extrq_insertq = { 0x78, ENTRY_CopyBytes4 }; + static const COPYENTRY vmread = /* 78 */ ENTRY_CopyBytes2Mod; + static const COPYENTRY extrq_insertq = /* 78 */ ENTRY_CopyBytes4; ASSERT(!(m_bF2 && m_bOperandOverride)); @@ -616,8 +613,8 @@ PBYTE CDetourDis::Copy0F00(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc) // jmpe is 32bit x86 only // Notice that the sizes are the same either way, but jmpe is marked as "dynamic". - static const COPYENTRY other = { 0xB8, ENTRY_CopyBytes2Mod }; // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6 invalid/7 - static const COPYENTRY jmpe = { 0xB8, ENTRY_CopyBytes2ModDynamic }; // jmpe/6 x86-on-IA64 syscalls + static const COPYENTRY other = /* B8 */ ENTRY_CopyBytes2Mod; // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6 invalid/7 + static const COPYENTRY jmpe = /* B8 */ ENTRY_CopyBytes2ModDynamic; // jmpe/6 x86-on-IA64 syscalls REFCOPYENTRY const pEntry = (((6 << 3) == ((7 << 3) & pbSrc[1])) ? &jmpe : &other); return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc); @@ -627,8 +624,8 @@ PBYTE CDetourDis::Copy0FB8(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc) { // jmpe is 32bit x86 only - static const COPYENTRY popcnt = { 0xB8, ENTRY_CopyBytes2Mod }; - static const COPYENTRY jmpe = { 0xB8, ENTRY_CopyBytes3Or5Dynamic }; // jmpe x86-on-IA64 syscalls + static const COPYENTRY popcnt = /* B8 */ ENTRY_CopyBytes2Mod; + static const COPYENTRY jmpe = /* B8 */ ENTRY_CopyBytes3Or5Dynamic; // jmpe x86-on-IA64 syscalls REFCOPYENTRY const pEntry = m_bF3 ? &popcnt : &jmpe; return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc); } @@ -663,7 +660,7 @@ PBYTE CDetourDis::CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) // TEST BYTE /0 if (0x00 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 0 - static const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod1 }; + static const COPYENTRY ce = /* f6 */ ENTRY_CopyBytes2Mod1; return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); } // DIV /6 @@ -673,7 +670,7 @@ PBYTE CDetourDis::CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) // NEG /3 // NOT /2 - static const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod }; + static const COPYENTRY ce = /* f6 */ ENTRY_CopyBytes2Mod; return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); } @@ -683,7 +680,7 @@ PBYTE CDetourDis::CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) // TEST WORD /0 if (0x00 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 0 - static const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2ModOperand }; + static const COPYENTRY ce = /* f7 */ ENTRY_CopyBytes2ModOperand; return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); } @@ -693,7 +690,7 @@ PBYTE CDetourDis::CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) // MUL /4 // NEG /3 // NOT /2 - static const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2Mod }; + static const COPYENTRY ce = /* f7 */ ENTRY_CopyBytes2Mod; return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); } @@ -708,7 +705,7 @@ PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) // invalid/7 (void)pEntry; - static const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod }; + static const COPYENTRY ce = /* ff */ ENTRY_CopyBytes2Mod; PBYTE pbOut = (this->*ce.pfCopy)(&ce, pbDst, pbSrc); BYTE const b1 = pbSrc[1]; @@ -752,9 +749,9 @@ PBYTE CDetourDis::CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p) // m is first instead of last in the hopes of pbDst/pbSrc being // passed along efficiently in the registers they were already in. { - static const COPYENTRY ceF38 = { 0x38, ENTRY_CopyBytes2Mod }; - static const COPYENTRY ceF3A = { 0x3A, ENTRY_CopyBytes2Mod1 }; - static const COPYENTRY ceInvalid = { 0xC4, ENTRY_Invalid }; + static const COPYENTRY ceF38 = /* 38 */ ENTRY_CopyBytes2Mod; + static const COPYENTRY ceF3A = /* 3A */ ENTRY_CopyBytes2Mod1; + static const COPYENTRY ceInvalid = /* C4 */ ENTRY_Invalid; switch (p & 3) { case 0: break; @@ -788,7 +785,7 @@ PBYTE CDetourDis::CopyVex3(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc) // 3 byte VEX prefix 0xC4 { #ifdef DETOURS_X86 - const static COPYENTRY ceLES = { 0xC4, ENTRY_CopyBytes2Mod }; + const static COPYENTRY ceLES = /* C4 */ ENTRY_CopyBytes2Mod; if ((pbSrc[1] & 0xC0) != 0xC0) { REFCOPYENTRY pEntry = &ceLES; return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc); @@ -833,7 +830,7 @@ PBYTE CDetourDis::CopyVex2(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc) // 2 byte VEX prefix 0xC5 { #ifdef DETOURS_X86 - const static COPYENTRY ceLDS = { 0xC5, ENTRY_CopyBytes2Mod }; + const static COPYENTRY ceLDS = /* C5 */ ENTRY_CopyBytes2Mod; if ((pbSrc[1] & 0xC0) != 0xC0) { REFCOPYENTRY pEntry = &ceLDS; return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc); @@ -854,13 +851,13 @@ PBYTE CDetourDis::CopyEvex(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc) BYTE const p0 = pbSrc[1]; #ifdef DETOURS_X86 - const static COPYENTRY ceBound = { 0x62, ENTRY_CopyBytes2Mod }; + const static COPYENTRY ceBound = /* 62 */ ENTRY_CopyBytes2Mod; if ((p0 & 0xC0) != 0xC0) { return CopyBytes(&ceBound, pbDst, pbSrc); } #endif - static const COPYENTRY ceInvalid = { 0x62, ENTRY_Invalid }; + static const COPYENTRY ceInvalid = /* 62 */ ENTRY_Invalid; if ((p0 & 0x0C) != 0) return Invalid(&ceInvalid, pbDst, pbSrc); @@ -893,10 +890,10 @@ mmmmm only otherwise defined for 8, 9, A. pp is like VEX but only instructions with 0 are defined */ { - const static COPYENTRY cePop = { 0x8F, ENTRY_CopyBytes2Mod }; - const static COPYENTRY ceXop = { 0x8F, ENTRY_CopyBytesXop }; - const static COPYENTRY ceXop1 = { 0x8F, ENTRY_CopyBytesXop1 }; - const static COPYENTRY ceXop4 = { 0x8F, ENTRY_CopyBytesXop4 }; + const static COPYENTRY cePop = /* 8F */ ENTRY_CopyBytes2Mod; + const static COPYENTRY ceXop = /* 8F */ ENTRY_CopyBytesXop; + const static COPYENTRY ceXop1 = /* 8F */ ENTRY_CopyBytesXop1; + const static COPYENTRY ceXop4 = /* 8F */ ENTRY_CopyBytesXop4; BYTE const m = (BYTE)(pbSrc[1] & 0x1F); ASSERT(m <= 10); @@ -956,544 +953,543 @@ const BYTE CDetourDis::s_rbModRm[256] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 // Fx }; -const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[257] = +const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[] = { - { 0x00, ENTRY_CopyBytes2Mod }, // ADD /r - { 0x01, ENTRY_CopyBytes2Mod }, // ADD /r - { 0x02, ENTRY_CopyBytes2Mod }, // ADD /r - { 0x03, ENTRY_CopyBytes2Mod }, // ADD /r - { 0x04, ENTRY_CopyBytes2 }, // ADD ib - { 0x05, ENTRY_CopyBytes3Or5 }, // ADD iw + /* 00 */ ENTRY_CopyBytes2Mod, // ADD /r + /* 01 */ ENTRY_CopyBytes2Mod, // ADD /r + /* 02 */ ENTRY_CopyBytes2Mod, // ADD /r + /* 03 */ ENTRY_CopyBytes2Mod, // ADD /r + /* 04 */ ENTRY_CopyBytes2, // ADD ib + /* 05 */ ENTRY_CopyBytes3Or5, // ADD iw #ifdef DETOURS_X64 - { 0x06, ENTRY_Invalid }, // Invalid - { 0x07, ENTRY_Invalid }, // Invalid + /* 06 */ ENTRY_Invalid, // Invalid + /* 07 */ ENTRY_Invalid, // Invalid #else - { 0x06, ENTRY_CopyBytes1 }, // PUSH - { 0x07, ENTRY_CopyBytes1 }, // POP + /* 06 */ ENTRY_CopyBytes1, // PUSH + /* 07 */ ENTRY_CopyBytes1, // POP #endif - { 0x08, ENTRY_CopyBytes2Mod }, // OR /r - { 0x09, ENTRY_CopyBytes2Mod }, // OR /r - { 0x0A, ENTRY_CopyBytes2Mod }, // OR /r - { 0x0B, ENTRY_CopyBytes2Mod }, // OR /r - { 0x0C, ENTRY_CopyBytes2 }, // OR ib - { 0x0D, ENTRY_CopyBytes3Or5 }, // OR iw + /* 08 */ ENTRY_CopyBytes2Mod, // OR /r + /* 09 */ ENTRY_CopyBytes2Mod, // OR /r + /* 0A */ ENTRY_CopyBytes2Mod, // OR /r + /* 0B */ ENTRY_CopyBytes2Mod, // OR /r + /* 0C */ ENTRY_CopyBytes2, // OR ib + /* 0D */ ENTRY_CopyBytes3Or5, // OR iw #ifdef DETOURS_X64 - { 0x0E, ENTRY_Invalid }, // Invalid + /* 0E */ ENTRY_Invalid, // Invalid #else - { 0x0E, ENTRY_CopyBytes1 }, // PUSH + /* 0E */ ENTRY_CopyBytes1, // PUSH #endif - { 0x0F, ENTRY_Copy0F }, // Extension Ops - { 0x10, ENTRY_CopyBytes2Mod }, // ADC /r - { 0x11, ENTRY_CopyBytes2Mod }, // ADC /r - { 0x12, ENTRY_CopyBytes2Mod }, // ADC /r - { 0x13, ENTRY_CopyBytes2Mod }, // ADC /r - { 0x14, ENTRY_CopyBytes2 }, // ADC ib - { 0x15, ENTRY_CopyBytes3Or5 }, // ADC id + /* 0F */ ENTRY_Copy0F, // Extension Ops + /* 10 */ ENTRY_CopyBytes2Mod, // ADC /r + /* 11 */ ENTRY_CopyBytes2Mod, // ADC /r + /* 12 */ ENTRY_CopyBytes2Mod, // ADC /r + /* 13 */ ENTRY_CopyBytes2Mod, // ADC /r + /* 14 */ ENTRY_CopyBytes2, // ADC ib + /* 15 */ ENTRY_CopyBytes3Or5, // ADC id #ifdef DETOURS_X64 - { 0x16, ENTRY_Invalid }, // Invalid - { 0x17, ENTRY_Invalid }, // Invalid + /* 16 */ ENTRY_Invalid, // Invalid + /* 17 */ ENTRY_Invalid, // Invalid #else - { 0x16, ENTRY_CopyBytes1 }, // PUSH - { 0x17, ENTRY_CopyBytes1 }, // POP + /* 16 */ ENTRY_CopyBytes1, // PUSH + /* 17 */ ENTRY_CopyBytes1, // POP #endif - { 0x18, ENTRY_CopyBytes2Mod }, // SBB /r - { 0x19, ENTRY_CopyBytes2Mod }, // SBB /r - { 0x1A, ENTRY_CopyBytes2Mod }, // SBB /r - { 0x1B, ENTRY_CopyBytes2Mod }, // SBB /r - { 0x1C, ENTRY_CopyBytes2 }, // SBB ib - { 0x1D, ENTRY_CopyBytes3Or5 }, // SBB id + /* 18 */ ENTRY_CopyBytes2Mod, // SBB /r + /* 19 */ ENTRY_CopyBytes2Mod, // SBB /r + /* 1A */ ENTRY_CopyBytes2Mod, // SBB /r + /* 1B */ ENTRY_CopyBytes2Mod, // SBB /r + /* 1C */ ENTRY_CopyBytes2, // SBB ib + /* 1D */ ENTRY_CopyBytes3Or5, // SBB id #ifdef DETOURS_X64 - { 0x1E, ENTRY_Invalid }, // Invalid - { 0x1F, ENTRY_Invalid }, // Invalid + /* 1E */ ENTRY_Invalid, // Invalid + /* 1F */ ENTRY_Invalid, // Invalid #else - { 0x1E, ENTRY_CopyBytes1 }, // PUSH - { 0x1F, ENTRY_CopyBytes1 }, // POP + /* 1E */ ENTRY_CopyBytes1, // PUSH + /* 1F */ ENTRY_CopyBytes1, // POP #endif - { 0x20, ENTRY_CopyBytes2Mod }, // AND /r - { 0x21, ENTRY_CopyBytes2Mod }, // AND /r - { 0x22, ENTRY_CopyBytes2Mod }, // AND /r - { 0x23, ENTRY_CopyBytes2Mod }, // AND /r - { 0x24, ENTRY_CopyBytes2 }, // AND ib - { 0x25, ENTRY_CopyBytes3Or5 }, // AND id - { 0x26, ENTRY_CopyBytesSegment }, // ES prefix + /* 20 */ ENTRY_CopyBytes2Mod, // AND /r + /* 21 */ ENTRY_CopyBytes2Mod, // AND /r + /* 22 */ ENTRY_CopyBytes2Mod, // AND /r + /* 23 */ ENTRY_CopyBytes2Mod, // AND /r + /* 24 */ ENTRY_CopyBytes2, // AND ib + /* 25 */ ENTRY_CopyBytes3Or5, // AND id + /* 26 */ ENTRY_CopyBytesSegment, // ES prefix #ifdef DETOURS_X64 - { 0x27, ENTRY_Invalid }, // Invalid + /* 27 */ ENTRY_Invalid, // Invalid #else - { 0x27, ENTRY_CopyBytes1 }, // DAA + /* 27 */ ENTRY_CopyBytes1, // DAA #endif - { 0x28, ENTRY_CopyBytes2Mod }, // SUB /r - { 0x29, ENTRY_CopyBytes2Mod }, // SUB /r - { 0x2A, ENTRY_CopyBytes2Mod }, // SUB /r - { 0x2B, ENTRY_CopyBytes2Mod }, // SUB /r - { 0x2C, ENTRY_CopyBytes2 }, // SUB ib - { 0x2D, ENTRY_CopyBytes3Or5 }, // SUB id - { 0x2E, ENTRY_CopyBytesSegment }, // CS prefix + /* 28 */ ENTRY_CopyBytes2Mod, // SUB /r + /* 29 */ ENTRY_CopyBytes2Mod, // SUB /r + /* 2A */ ENTRY_CopyBytes2Mod, // SUB /r + /* 2B */ ENTRY_CopyBytes2Mod, // SUB /r + /* 2C */ ENTRY_CopyBytes2, // SUB ib + /* 2D */ ENTRY_CopyBytes3Or5, // SUB id + /* 2E */ ENTRY_CopyBytesSegment, // CS prefix #ifdef DETOURS_X64 - { 0x2F, ENTRY_Invalid }, // Invalid + /* 2F */ ENTRY_Invalid, // Invalid #else - { 0x2F, ENTRY_CopyBytes1 }, // DAS + /* 2F */ ENTRY_CopyBytes1, // DAS #endif - { 0x30, ENTRY_CopyBytes2Mod }, // XOR /r - { 0x31, ENTRY_CopyBytes2Mod }, // XOR /r - { 0x32, ENTRY_CopyBytes2Mod }, // XOR /r - { 0x33, ENTRY_CopyBytes2Mod }, // XOR /r - { 0x34, ENTRY_CopyBytes2 }, // XOR ib - { 0x35, ENTRY_CopyBytes3Or5 }, // XOR id - { 0x36, ENTRY_CopyBytesSegment }, // SS prefix + /* 30 */ ENTRY_CopyBytes2Mod, // XOR /r + /* 31 */ ENTRY_CopyBytes2Mod, // XOR /r + /* 32 */ ENTRY_CopyBytes2Mod, // XOR /r + /* 33 */ ENTRY_CopyBytes2Mod, // XOR /r + /* 34 */ ENTRY_CopyBytes2, // XOR ib + /* 35 */ ENTRY_CopyBytes3Or5, // XOR id + /* 36 */ ENTRY_CopyBytesSegment, // SS prefix #ifdef DETOURS_X64 - { 0x37, ENTRY_Invalid }, // Invalid + /* 37 */ ENTRY_Invalid, // Invalid #else - { 0x37, ENTRY_CopyBytes1 }, // AAA + /* 37 */ ENTRY_CopyBytes1, // AAA #endif - { 0x38, ENTRY_CopyBytes2Mod }, // CMP /r - { 0x39, ENTRY_CopyBytes2Mod }, // CMP /r - { 0x3A, ENTRY_CopyBytes2Mod }, // CMP /r - { 0x3B, ENTRY_CopyBytes2Mod }, // CMP /r - { 0x3C, ENTRY_CopyBytes2 }, // CMP ib - { 0x3D, ENTRY_CopyBytes3Or5 }, // CMP id - { 0x3E, ENTRY_CopyBytesSegment }, // DS prefix + /* 38 */ ENTRY_CopyBytes2Mod, // CMP /r + /* 39 */ ENTRY_CopyBytes2Mod, // CMP /r + /* 3A */ ENTRY_CopyBytes2Mod, // CMP /r + /* 3B */ ENTRY_CopyBytes2Mod, // CMP /r + /* 3C */ ENTRY_CopyBytes2, // CMP ib + /* 3D */ ENTRY_CopyBytes3Or5, // CMP id + /* 3E */ ENTRY_CopyBytesSegment, // DS prefix #ifdef DETOURS_X64 - { 0x3F, ENTRY_Invalid }, // Invalid + /* 3F */ ENTRY_Invalid, // Invalid #else - { 0x3F, ENTRY_CopyBytes1 }, // AAS + /* 3F */ ENTRY_CopyBytes1, // AAS #endif #ifdef DETOURS_X64 // For Rax Prefix - { 0x40, ENTRY_CopyBytesRax }, // Rax - { 0x41, ENTRY_CopyBytesRax }, // Rax - { 0x42, ENTRY_CopyBytesRax }, // Rax - { 0x43, ENTRY_CopyBytesRax }, // Rax - { 0x44, ENTRY_CopyBytesRax }, // Rax - { 0x45, ENTRY_CopyBytesRax }, // Rax - { 0x46, ENTRY_CopyBytesRax }, // Rax - { 0x47, ENTRY_CopyBytesRax }, // Rax - { 0x48, ENTRY_CopyBytesRax }, // Rax - { 0x49, ENTRY_CopyBytesRax }, // Rax - { 0x4A, ENTRY_CopyBytesRax }, // Rax - { 0x4B, ENTRY_CopyBytesRax }, // Rax - { 0x4C, ENTRY_CopyBytesRax }, // Rax - { 0x4D, ENTRY_CopyBytesRax }, // Rax - { 0x4E, ENTRY_CopyBytesRax }, // Rax - { 0x4F, ENTRY_CopyBytesRax }, // Rax + /* 40 */ ENTRY_CopyBytesRax, // Rax + /* 41 */ ENTRY_CopyBytesRax, // Rax + /* 42 */ ENTRY_CopyBytesRax, // Rax + /* 43 */ ENTRY_CopyBytesRax, // Rax + /* 44 */ ENTRY_CopyBytesRax, // Rax + /* 45 */ ENTRY_CopyBytesRax, // Rax + /* 46 */ ENTRY_CopyBytesRax, // Rax + /* 47 */ ENTRY_CopyBytesRax, // Rax + /* 48 */ ENTRY_CopyBytesRax, // Rax + /* 49 */ ENTRY_CopyBytesRax, // Rax + /* 4A */ ENTRY_CopyBytesRax, // Rax + /* 4B */ ENTRY_CopyBytesRax, // Rax + /* 4C */ ENTRY_CopyBytesRax, // Rax + /* 4D */ ENTRY_CopyBytesRax, // Rax + /* 4E */ ENTRY_CopyBytesRax, // Rax + /* 4F */ ENTRY_CopyBytesRax, // Rax #else - { 0x40, ENTRY_CopyBytes1 }, // INC - { 0x41, ENTRY_CopyBytes1 }, // INC - { 0x42, ENTRY_CopyBytes1 }, // INC - { 0x43, ENTRY_CopyBytes1 }, // INC - { 0x44, ENTRY_CopyBytes1 }, // INC - { 0x45, ENTRY_CopyBytes1 }, // INC - { 0x46, ENTRY_CopyBytes1 }, // INC - { 0x47, ENTRY_CopyBytes1 }, // INC - { 0x48, ENTRY_CopyBytes1 }, // DEC - { 0x49, ENTRY_CopyBytes1 }, // DEC - { 0x4A, ENTRY_CopyBytes1 }, // DEC - { 0x4B, ENTRY_CopyBytes1 }, // DEC - { 0x4C, ENTRY_CopyBytes1 }, // DEC - { 0x4D, ENTRY_CopyBytes1 }, // DEC - { 0x4E, ENTRY_CopyBytes1 }, // DEC - { 0x4F, ENTRY_CopyBytes1 }, // DEC + /* 40 */ ENTRY_CopyBytes1, // INC + /* 41 */ ENTRY_CopyBytes1, // INC + /* 42 */ ENTRY_CopyBytes1, // INC + /* 43 */ ENTRY_CopyBytes1, // INC + /* 44 */ ENTRY_CopyBytes1, // INC + /* 45 */ ENTRY_CopyBytes1, // INC + /* 46 */ ENTRY_CopyBytes1, // INC + /* 47 */ ENTRY_CopyBytes1, // INC + /* 48 */ ENTRY_CopyBytes1, // DEC + /* 49 */ ENTRY_CopyBytes1, // DEC + /* 4A */ ENTRY_CopyBytes1, // DEC + /* 4B */ ENTRY_CopyBytes1, // DEC + /* 4C */ ENTRY_CopyBytes1, // DEC + /* 4D */ ENTRY_CopyBytes1, // DEC + /* 4E */ ENTRY_CopyBytes1, // DEC + /* 4F */ ENTRY_CopyBytes1, // DEC #endif - { 0x50, ENTRY_CopyBytes1 }, // PUSH - { 0x51, ENTRY_CopyBytes1 }, // PUSH - { 0x52, ENTRY_CopyBytes1 }, // PUSH - { 0x53, ENTRY_CopyBytes1 }, // PUSH - { 0x54, ENTRY_CopyBytes1 }, // PUSH - { 0x55, ENTRY_CopyBytes1 }, // PUSH - { 0x56, ENTRY_CopyBytes1 }, // PUSH - { 0x57, ENTRY_CopyBytes1 }, // PUSH - { 0x58, ENTRY_CopyBytes1 }, // POP - { 0x59, ENTRY_CopyBytes1 }, // POP - { 0x5A, ENTRY_CopyBytes1 }, // POP - { 0x5B, ENTRY_CopyBytes1 }, // POP - { 0x5C, ENTRY_CopyBytes1 }, // POP - { 0x5D, ENTRY_CopyBytes1 }, // POP - { 0x5E, ENTRY_CopyBytes1 }, // POP - { 0x5F, ENTRY_CopyBytes1 }, // POP + /* 50 */ ENTRY_CopyBytes1, // PUSH + /* 51 */ ENTRY_CopyBytes1, // PUSH + /* 52 */ ENTRY_CopyBytes1, // PUSH + /* 53 */ ENTRY_CopyBytes1, // PUSH + /* 54 */ ENTRY_CopyBytes1, // PUSH + /* 55 */ ENTRY_CopyBytes1, // PUSH + /* 56 */ ENTRY_CopyBytes1, // PUSH + /* 57 */ ENTRY_CopyBytes1, // PUSH + /* 58 */ ENTRY_CopyBytes1, // POP + /* 59 */ ENTRY_CopyBytes1, // POP + /* 5A */ ENTRY_CopyBytes1, // POP + /* 5B */ ENTRY_CopyBytes1, // POP + /* 5C */ ENTRY_CopyBytes1, // POP + /* 5D */ ENTRY_CopyBytes1, // POP + /* 5E */ ENTRY_CopyBytes1, // POP + /* 5F */ ENTRY_CopyBytes1, // POP #ifdef DETOURS_X64 - { 0x60, ENTRY_Invalid }, // Invalid - { 0x61, ENTRY_Invalid }, // Invalid - { 0x62, ENTRY_CopyEvex }, // EVEX / AVX512 + /* 60 */ ENTRY_Invalid, // Invalid + /* 61 */ ENTRY_Invalid, // Invalid + /* 62 */ ENTRY_CopyEvex, // EVEX / AVX512 #else - { 0x60, ENTRY_CopyBytes1 }, // PUSHAD - { 0x61, ENTRY_CopyBytes1 }, // POPAD - { 0x62, ENTRY_CopyEvex }, // BOUND /r and EVEX / AVX512 + /* 60 */ ENTRY_CopyBytes1, // PUSHAD + /* 61 */ ENTRY_CopyBytes1, // POPAD + /* 62 */ ENTRY_CopyEvex, // BOUND /r and EVEX / AVX512 #endif - { 0x63, ENTRY_CopyBytes2Mod }, // 32bit ARPL /r, 64bit MOVSXD - { 0x64, ENTRY_CopyBytesSegment }, // FS prefix - { 0x65, ENTRY_CopyBytesSegment }, // GS prefix - { 0x66, ENTRY_Copy66 }, // Operand Prefix - { 0x67, ENTRY_Copy67 }, // Address Prefix - { 0x68, ENTRY_CopyBytes3Or5 }, // PUSH - { 0x69, ENTRY_CopyBytes2ModOperand }, // IMUL /r iz - { 0x6A, ENTRY_CopyBytes2 }, // PUSH - { 0x6B, ENTRY_CopyBytes2Mod1 }, // IMUL /r ib - { 0x6C, ENTRY_CopyBytes1 }, // INS - { 0x6D, ENTRY_CopyBytes1 }, // INS - { 0x6E, ENTRY_CopyBytes1 }, // OUTS/OUTSB - { 0x6F, ENTRY_CopyBytes1 }, // OUTS/OUTSW - { 0x70, ENTRY_CopyBytes2Jump }, // JO // 0f80 - { 0x71, ENTRY_CopyBytes2Jump }, // JNO // 0f81 - { 0x72, ENTRY_CopyBytes2Jump }, // JB/JC/JNAE // 0f82 - { 0x73, ENTRY_CopyBytes2Jump }, // JAE/JNB/JNC // 0f83 - { 0x74, ENTRY_CopyBytes2Jump }, // JE/JZ // 0f84 - { 0x75, ENTRY_CopyBytes2Jump }, // JNE/JNZ // 0f85 - { 0x76, ENTRY_CopyBytes2Jump }, // JBE/JNA // 0f86 - { 0x77, ENTRY_CopyBytes2Jump }, // JA/JNBE // 0f87 - { 0x78, ENTRY_CopyBytes2Jump }, // JS // 0f88 - { 0x79, ENTRY_CopyBytes2Jump }, // JNS // 0f89 - { 0x7A, ENTRY_CopyBytes2Jump }, // JP/JPE // 0f8a - { 0x7B, ENTRY_CopyBytes2Jump }, // JNP/JPO // 0f8b - { 0x7C, ENTRY_CopyBytes2Jump }, // JL/JNGE // 0f8c - { 0x7D, ENTRY_CopyBytes2Jump }, // JGE/JNL // 0f8d - { 0x7E, ENTRY_CopyBytes2Jump }, // JLE/JNG // 0f8e - { 0x7F, ENTRY_CopyBytes2Jump }, // JG/JNLE // 0f8f - { 0x80, ENTRY_CopyBytes2Mod1 }, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 byte reg, immediate byte - { 0x81, ENTRY_CopyBytes2ModOperand }, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 byte reg, immediate word or dword + /* 63 */ ENTRY_CopyBytes2Mod, // 32bit ARPL /r, 64bit MOVSXD + /* 64 */ ENTRY_CopyBytesSegment, // FS prefix + /* 65 */ ENTRY_CopyBytesSegment, // GS prefix + /* 66 */ ENTRY_Copy66, // Operand Prefix + /* 67 */ ENTRY_Copy67, // Address Prefix + /* 68 */ ENTRY_CopyBytes3Or5, // PUSH + /* 69 */ ENTRY_CopyBytes2ModOperand, // IMUL /r iz + /* 6A */ ENTRY_CopyBytes2, // PUSH + /* 6B */ ENTRY_CopyBytes2Mod1, // IMUL /r ib + /* 6C */ ENTRY_CopyBytes1, // INS + /* 6D */ ENTRY_CopyBytes1, // INS + /* 6E */ ENTRY_CopyBytes1, // OUTS/OUTSB + /* 6F */ ENTRY_CopyBytes1, // OUTS/OUTSW + /* 70 */ ENTRY_CopyBytes2Jump, // JO // 0f80 + /* 71 */ ENTRY_CopyBytes2Jump, // JNO // 0f81 + /* 72 */ ENTRY_CopyBytes2Jump, // JB/JC/JNAE // 0f82 + /* 73 */ ENTRY_CopyBytes2Jump, // JAE/JNB/JNC // 0f83 + /* 74 */ ENTRY_CopyBytes2Jump, // JE/JZ // 0f84 + /* 75 */ ENTRY_CopyBytes2Jump, // JNE/JNZ // 0f85 + /* 76 */ ENTRY_CopyBytes2Jump, // JBE/JNA // 0f86 + /* 77 */ ENTRY_CopyBytes2Jump, // JA/JNBE // 0f87 + /* 78 */ ENTRY_CopyBytes2Jump, // JS // 0f88 + /* 79 */ ENTRY_CopyBytes2Jump, // JNS // 0f89 + /* 7A */ ENTRY_CopyBytes2Jump, // JP/JPE // 0f8a + /* 7B */ ENTRY_CopyBytes2Jump, // JNP/JPO // 0f8b + /* 7C */ ENTRY_CopyBytes2Jump, // JL/JNGE // 0f8c + /* 7D */ ENTRY_CopyBytes2Jump, // JGE/JNL // 0f8d + /* 7E */ ENTRY_CopyBytes2Jump, // JLE/JNG // 0f8e + /* 7F */ ENTRY_CopyBytes2Jump, // JG/JNLE // 0f8f + /* 80 */ ENTRY_CopyBytes2Mod1, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 byte reg, immediate byte + /* 81 */ ENTRY_CopyBytes2ModOperand, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 byte reg, immediate word or dword #ifdef DETOURS_X64 - { 0x82, ENTRY_Invalid }, // Invalid + /* 82 */ ENTRY_Invalid, // Invalid #else - { 0x82, ENTRY_CopyBytes2Mod1 }, // MOV al,x + /* 82 */ ENTRY_CopyBytes2Mod1, // MOV al,x #endif - { 0x83, ENTRY_CopyBytes2Mod1 }, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 reg, immediate byte - { 0x84, ENTRY_CopyBytes2Mod }, // TEST /r - { 0x85, ENTRY_CopyBytes2Mod }, // TEST /r - { 0x86, ENTRY_CopyBytes2Mod }, // XCHG /r @todo - { 0x87, ENTRY_CopyBytes2Mod }, // XCHG /r @todo - { 0x88, ENTRY_CopyBytes2Mod }, // MOV /r - { 0x89, ENTRY_CopyBytes2Mod }, // MOV /r - { 0x8A, ENTRY_CopyBytes2Mod }, // MOV /r - { 0x8B, ENTRY_CopyBytes2Mod }, // MOV /r - { 0x8C, ENTRY_CopyBytes2Mod }, // MOV /r - { 0x8D, ENTRY_CopyBytes2Mod }, // LEA /r - { 0x8E, ENTRY_CopyBytes2Mod }, // MOV /r - { 0x8F, ENTRY_CopyXop }, // POP /0 or AMD XOP - { 0x90, ENTRY_CopyBytes1 }, // NOP - { 0x91, ENTRY_CopyBytes1 }, // XCHG - { 0x92, ENTRY_CopyBytes1 }, // XCHG - { 0x93, ENTRY_CopyBytes1 }, // XCHG - { 0x94, ENTRY_CopyBytes1 }, // XCHG - { 0x95, ENTRY_CopyBytes1 }, // XCHG - { 0x96, ENTRY_CopyBytes1 }, // XCHG - { 0x97, ENTRY_CopyBytes1 }, // XCHG - { 0x98, ENTRY_CopyBytes1 }, // CWDE - { 0x99, ENTRY_CopyBytes1 }, // CDQ + /* 83 */ ENTRY_CopyBytes2Mod1, // ADD/0 OR/1 ADC/2 SBB/3 AND/4 SUB/5 XOR/6 CMP/7 reg, immediate byte + /* 84 */ ENTRY_CopyBytes2Mod, // TEST /r + /* 85 */ ENTRY_CopyBytes2Mod, // TEST /r + /* 86 */ ENTRY_CopyBytes2Mod, // XCHG /r @todo + /* 87 */ ENTRY_CopyBytes2Mod, // XCHG /r @todo + /* 88 */ ENTRY_CopyBytes2Mod, // MOV /r + /* 89 */ ENTRY_CopyBytes2Mod, // MOV /r + /* 8A */ ENTRY_CopyBytes2Mod, // MOV /r + /* 8B */ ENTRY_CopyBytes2Mod, // MOV /r + /* 8C */ ENTRY_CopyBytes2Mod, // MOV /r + /* 8D */ ENTRY_CopyBytes2Mod, // LEA /r + /* 8E */ ENTRY_CopyBytes2Mod, // MOV /r + /* 8F */ ENTRY_CopyXop, // POP /0 or AMD XOP + /* 90 */ ENTRY_CopyBytes1, // NOP + /* 91 */ ENTRY_CopyBytes1, // XCHG + /* 92 */ ENTRY_CopyBytes1, // XCHG + /* 93 */ ENTRY_CopyBytes1, // XCHG + /* 94 */ ENTRY_CopyBytes1, // XCHG + /* 95 */ ENTRY_CopyBytes1, // XCHG + /* 96 */ ENTRY_CopyBytes1, // XCHG + /* 97 */ ENTRY_CopyBytes1, // XCHG + /* 98 */ ENTRY_CopyBytes1, // CWDE + /* 99 */ ENTRY_CopyBytes1, // CDQ #ifdef DETOURS_X64 - { 0x9A, ENTRY_Invalid }, // Invalid + /* 9A */ ENTRY_Invalid, // Invalid #else - { 0x9A, ENTRY_CopyBytes5Or7Dynamic }, // CALL cp + /* 9A */ ENTRY_CopyBytes5Or7Dynamic, // CALL cp #endif - { 0x9B, ENTRY_CopyBytes1 }, // WAIT/FWAIT - { 0x9C, ENTRY_CopyBytes1 }, // PUSHFD - { 0x9D, ENTRY_CopyBytes1 }, // POPFD - { 0x9E, ENTRY_CopyBytes1 }, // SAHF - { 0x9F, ENTRY_CopyBytes1 }, // LAHF - { 0xA0, ENTRY_CopyBytes1Address }, // MOV - { 0xA1, ENTRY_CopyBytes1Address }, // MOV - { 0xA2, ENTRY_CopyBytes1Address }, // MOV - { 0xA3, ENTRY_CopyBytes1Address }, // MOV - { 0xA4, ENTRY_CopyBytes1 }, // MOVS - { 0xA5, ENTRY_CopyBytes1 }, // MOVS/MOVSD - { 0xA6, ENTRY_CopyBytes1 }, // CMPS/CMPSB - { 0xA7, ENTRY_CopyBytes1 }, // CMPS/CMPSW - { 0xA8, ENTRY_CopyBytes2 }, // TEST - { 0xA9, ENTRY_CopyBytes3Or5 }, // TEST - { 0xAA, ENTRY_CopyBytes1 }, // STOS/STOSB - { 0xAB, ENTRY_CopyBytes1 }, // STOS/STOSW - { 0xAC, ENTRY_CopyBytes1 }, // LODS/LODSB - { 0xAD, ENTRY_CopyBytes1 }, // LODS/LODSW - { 0xAE, ENTRY_CopyBytes1 }, // SCAS/SCASB - { 0xAF, ENTRY_CopyBytes1 }, // SCAS/SCASD - { 0xB0, ENTRY_CopyBytes2 }, // MOV B0+rb - { 0xB1, ENTRY_CopyBytes2 }, // MOV B0+rb - { 0xB2, ENTRY_CopyBytes2 }, // MOV B0+rb - { 0xB3, ENTRY_CopyBytes2 }, // MOV B0+rb - { 0xB4, ENTRY_CopyBytes2 }, // MOV B0+rb - { 0xB5, ENTRY_CopyBytes2 }, // MOV B0+rb - { 0xB6, ENTRY_CopyBytes2 }, // MOV B0+rb - { 0xB7, ENTRY_CopyBytes2 }, // MOV B0+rb - { 0xB8, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb - { 0xB9, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb - { 0xBA, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb - { 0xBB, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb - { 0xBC, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb - { 0xBD, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb - { 0xBE, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb - { 0xBF, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb - { 0xC0, ENTRY_CopyBytes2Mod1 }, // RCL/2 ib, etc. - { 0xC1, ENTRY_CopyBytes2Mod1 }, // RCL/2 ib, etc. - { 0xC2, ENTRY_CopyBytes3 }, // RET - { 0xC3, ENTRY_CopyBytes1 }, // RET - { 0xC4, ENTRY_CopyVex3 }, // LES, VEX 3-byte opcodes. - { 0xC5, ENTRY_CopyVex2 }, // LDS, VEX 2-byte opcodes. - { 0xC6, ENTRY_CopyBytes2Mod1 }, // MOV - { 0xC7, ENTRY_CopyBytes2ModOperand }, // MOV/0 XBEGIN/7 - { 0xC8, ENTRY_CopyBytes4 }, // ENTER - { 0xC9, ENTRY_CopyBytes1 }, // LEAVE - { 0xCA, ENTRY_CopyBytes3Dynamic }, // RET - { 0xCB, ENTRY_CopyBytes1Dynamic }, // RET - { 0xCC, ENTRY_CopyBytes1Dynamic }, // INT 3 - { 0xCD, ENTRY_CopyBytes2Dynamic }, // INT ib + /* 9B */ ENTRY_CopyBytes1, // WAIT/FWAIT + /* 9C */ ENTRY_CopyBytes1, // PUSHFD + /* 9D */ ENTRY_CopyBytes1, // POPFD + /* 9E */ ENTRY_CopyBytes1, // SAHF + /* 9F */ ENTRY_CopyBytes1, // LAHF + /* A0 */ ENTRY_CopyBytes1Address, // MOV + /* A1 */ ENTRY_CopyBytes1Address, // MOV + /* A2 */ ENTRY_CopyBytes1Address, // MOV + /* A3 */ ENTRY_CopyBytes1Address, // MOV + /* A4 */ ENTRY_CopyBytes1, // MOVS + /* A5 */ ENTRY_CopyBytes1, // MOVS/MOVSD + /* A6 */ ENTRY_CopyBytes1, // CMPS/CMPSB + /* A7 */ ENTRY_CopyBytes1, // CMPS/CMPSW + /* A8 */ ENTRY_CopyBytes2, // TEST + /* A9 */ ENTRY_CopyBytes3Or5, // TEST + /* AA */ ENTRY_CopyBytes1, // STOS/STOSB + /* AB */ ENTRY_CopyBytes1, // STOS/STOSW + /* AC */ ENTRY_CopyBytes1, // LODS/LODSB + /* AD */ ENTRY_CopyBytes1, // LODS/LODSW + /* AE */ ENTRY_CopyBytes1, // SCAS/SCASB + /* AF */ ENTRY_CopyBytes1, // SCAS/SCASD + /* B0 */ ENTRY_CopyBytes2, // MOV B0+rb + /* B1 */ ENTRY_CopyBytes2, // MOV B0+rb + /* B2 */ ENTRY_CopyBytes2, // MOV B0+rb + /* B3 */ ENTRY_CopyBytes2, // MOV B0+rb + /* B4 */ ENTRY_CopyBytes2, // MOV B0+rb + /* B5 */ ENTRY_CopyBytes2, // MOV B0+rb + /* B6 */ ENTRY_CopyBytes2, // MOV B0+rb + /* B7 */ ENTRY_CopyBytes2, // MOV B0+rb + /* B8 */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb + /* B9 */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb + /* BA */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb + /* BB */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb + /* BC */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb + /* BD */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb + /* BE */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb + /* BF */ ENTRY_CopyBytes3Or5Rax, // MOV B8+rb + /* C0 */ ENTRY_CopyBytes2Mod1, // RCL/2 ib, etc. + /* C1 */ ENTRY_CopyBytes2Mod1, // RCL/2 ib, etc. + /* C2 */ ENTRY_CopyBytes3, // RET + /* C3 */ ENTRY_CopyBytes1, // RET + /* C4 */ ENTRY_CopyVex3, // LES, VEX 3-byte opcodes. + /* C5 */ ENTRY_CopyVex2, // LDS, VEX 2-byte opcodes. + /* C6 */ ENTRY_CopyBytes2Mod1, // MOV + /* C7 */ ENTRY_CopyBytes2ModOperand, // MOV/0 XBEGIN/7 + /* C8 */ ENTRY_CopyBytes4, // ENTER + /* C9 */ ENTRY_CopyBytes1, // LEAVE + /* CA */ ENTRY_CopyBytes3Dynamic, // RET + /* CB */ ENTRY_CopyBytes1Dynamic, // RET + /* CC */ ENTRY_CopyBytes1Dynamic, // INT 3 + /* CD */ ENTRY_CopyBytes2Dynamic, // INT ib #ifdef DETOURS_X64 - { 0xCE, ENTRY_Invalid }, // Invalid + /* CE */ ENTRY_Invalid, // Invalid #else - { 0xCE, ENTRY_CopyBytes1Dynamic }, // INTO + /* CE */ ENTRY_CopyBytes1Dynamic, // INTO #endif - { 0xCF, ENTRY_CopyBytes1Dynamic }, // IRET - { 0xD0, ENTRY_CopyBytes2Mod }, // RCL/2, etc. - { 0xD1, ENTRY_CopyBytes2Mod }, // RCL/2, etc. - { 0xD2, ENTRY_CopyBytes2Mod }, // RCL/2, etc. - { 0xD3, ENTRY_CopyBytes2Mod }, // RCL/2, etc. + /* CF */ ENTRY_CopyBytes1Dynamic, // IRET + /* D0 */ ENTRY_CopyBytes2Mod, // RCL/2, etc. + /* D1 */ ENTRY_CopyBytes2Mod, // RCL/2, etc. + /* D2 */ ENTRY_CopyBytes2Mod, // RCL/2, etc. + /* D3 */ ENTRY_CopyBytes2Mod, // RCL/2, etc. #ifdef DETOURS_X64 - { 0xD4, ENTRY_Invalid }, // Invalid - { 0xD5, ENTRY_Invalid }, // Invalid + /* D4 */ ENTRY_Invalid, // Invalid + /* D5 */ ENTRY_Invalid, // Invalid #else - { 0xD4, ENTRY_CopyBytes2 }, // AAM - { 0xD5, ENTRY_CopyBytes2 }, // AAD + /* D4 */ ENTRY_CopyBytes2, // AAM + /* D5 */ ENTRY_CopyBytes2, // AAD #endif - { 0xD6, ENTRY_Invalid }, // Invalid - { 0xD7, ENTRY_CopyBytes1 }, // XLAT/XLATB - { 0xD8, ENTRY_CopyBytes2Mod }, // FADD, etc. - { 0xD9, ENTRY_CopyBytes2Mod }, // F2XM1, etc. - { 0xDA, ENTRY_CopyBytes2Mod }, // FLADD, etc. - { 0xDB, ENTRY_CopyBytes2Mod }, // FCLEX, etc. - { 0xDC, ENTRY_CopyBytes2Mod }, // FADD/0, etc. - { 0xDD, ENTRY_CopyBytes2Mod }, // FFREE, etc. - { 0xDE, ENTRY_CopyBytes2Mod }, // FADDP, etc. - { 0xDF, ENTRY_CopyBytes2Mod }, // FBLD/4, etc. - { 0xE0, ENTRY_CopyBytes2CantJump }, // LOOPNE cb - { 0xE1, ENTRY_CopyBytes2CantJump }, // LOOPE cb - { 0xE2, ENTRY_CopyBytes2CantJump }, // LOOP cb - { 0xE3, ENTRY_CopyBytes2CantJump }, // JCXZ/JECXZ - { 0xE4, ENTRY_CopyBytes2 }, // IN ib - { 0xE5, ENTRY_CopyBytes2 }, // IN id - { 0xE6, ENTRY_CopyBytes2 }, // OUT ib - { 0xE7, ENTRY_CopyBytes2 }, // OUT ib - { 0xE8, ENTRY_CopyBytes3Or5Target }, // CALL cd - { 0xE9, ENTRY_CopyBytes3Or5Target }, // JMP cd + /* D6 */ ENTRY_Invalid, // Invalid + /* D7 */ ENTRY_CopyBytes1, // XLAT/XLATB + /* D8 */ ENTRY_CopyBytes2Mod, // FADD, etc. + /* D9 */ ENTRY_CopyBytes2Mod, // F2XM1, etc. + /* DA */ ENTRY_CopyBytes2Mod, // FLADD, etc. + /* DB */ ENTRY_CopyBytes2Mod, // FCLEX, etc. + /* DC */ ENTRY_CopyBytes2Mod, // FADD/0, etc. + /* DD */ ENTRY_CopyBytes2Mod, // FFREE, etc. + /* DE */ ENTRY_CopyBytes2Mod, // FADDP, etc. + /* DF */ ENTRY_CopyBytes2Mod, // FBLD/4, etc. + /* E0 */ ENTRY_CopyBytes2CantJump, // LOOPNE cb + /* E1 */ ENTRY_CopyBytes2CantJump, // LOOPE cb + /* E2 */ ENTRY_CopyBytes2CantJump, // LOOP cb + /* E3 */ ENTRY_CopyBytes2CantJump, // JCXZ/JECXZ + /* E4 */ ENTRY_CopyBytes2, // IN ib + /* E5 */ ENTRY_CopyBytes2, // IN id + /* E6 */ ENTRY_CopyBytes2, // OUT ib + /* E7 */ ENTRY_CopyBytes2, // OUT ib + /* E8 */ ENTRY_CopyBytes3Or5Target, // CALL cd + /* E9 */ ENTRY_CopyBytes3Or5Target, // JMP cd #ifdef DETOURS_X64 - { 0xEA, ENTRY_Invalid }, // Invalid + /* EA */ ENTRY_Invalid, // Invalid #else - { 0xEA, ENTRY_CopyBytes5Or7Dynamic }, // JMP cp + /* EA */ ENTRY_CopyBytes5Or7Dynamic, // JMP cp #endif - { 0xEB, ENTRY_CopyBytes2Jump }, // JMP cb - { 0xEC, ENTRY_CopyBytes1 }, // IN ib - { 0xED, ENTRY_CopyBytes1 }, // IN id - { 0xEE, ENTRY_CopyBytes1 }, // OUT - { 0xEF, ENTRY_CopyBytes1 }, // OUT - { 0xF0, ENTRY_CopyBytesPrefix }, // LOCK prefix - { 0xF1, ENTRY_CopyBytes1Dynamic }, // INT1 / ICEBP somewhat documented by AMD, not by Intel - { 0xF2, ENTRY_CopyF2 }, // REPNE prefix + /* EB */ ENTRY_CopyBytes2Jump, // JMP cb + /* EC */ ENTRY_CopyBytes1, // IN ib + /* ED */ ENTRY_CopyBytes1, // IN id + /* EE */ ENTRY_CopyBytes1, // OUT + /* EF */ ENTRY_CopyBytes1, // OUT + /* F0 */ ENTRY_CopyBytesPrefix, // LOCK prefix + /* F1 */ ENTRY_CopyBytes1Dynamic, // INT1 / ICEBP somewhat documented by AMD, not by Intel + /* F2 */ ENTRY_CopyF2, // REPNE prefix //#ifdef DETOURS_X86 - { 0xF3, ENTRY_CopyF3 }, // REPE prefix + /* F3 */ ENTRY_CopyF3, // REPE prefix //#else // This does presently suffice for AMD64 but it requires tracing // through a bunch of code to verify and seems not worth maintaining. -// { 0xF3, ENTRY_CopyBytesPrefix }, // REPE prefix +// /* F3 */ ENTRY_CopyBytesPrefix, // REPE prefix //#endif - { 0xF4, ENTRY_CopyBytes1 }, // HLT - { 0xF5, ENTRY_CopyBytes1 }, // CMC - { 0xF6, ENTRY_CopyF6 }, // TEST/0, DIV/6 - { 0xF7, ENTRY_CopyF7 }, // TEST/0, DIV/6 - { 0xF8, ENTRY_CopyBytes1 }, // CLC - { 0xF9, ENTRY_CopyBytes1 }, // STC - { 0xFA, ENTRY_CopyBytes1 }, // CLI - { 0xFB, ENTRY_CopyBytes1 }, // STI - { 0xFC, ENTRY_CopyBytes1 }, // CLD - { 0xFD, ENTRY_CopyBytes1 }, // STD - { 0xFE, ENTRY_CopyBytes2Mod }, // DEC/1,INC/0 - { 0xFF, ENTRY_CopyFF }, // CALL/2 - { 0, ENTRY_End }, + /* F4 */ ENTRY_CopyBytes1, // HLT + /* F5 */ ENTRY_CopyBytes1, // CMC + /* F6 */ ENTRY_CopyF6, // TEST/0, DIV/6 + /* F7 */ ENTRY_CopyF7, // TEST/0, DIV/6 + /* F8 */ ENTRY_CopyBytes1, // CLC + /* F9 */ ENTRY_CopyBytes1, // STC + /* FA */ ENTRY_CopyBytes1, // CLI + /* FB */ ENTRY_CopyBytes1, // STI + /* FC */ ENTRY_CopyBytes1, // CLD + /* FD */ ENTRY_CopyBytes1, // STD + /* FE */ ENTRY_CopyBytes2Mod, // DEC/1,INC/0 + /* FF */ ENTRY_CopyFF, // CALL/2 }; -const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable0F[257] = +const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable0F[] = { #ifdef DETOURS_X86 - { 0x00, ENTRY_Copy0F00 }, // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6/dynamic invalid/7 + /* 00 */ ENTRY_Copy0F00, // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6/dynamic invalid/7 #else - { 0x00, ENTRY_CopyBytes2Mod }, // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6/dynamic invalid/7 + /* 00 */ ENTRY_CopyBytes2Mod, // sldt/0 str/1 lldt/2 ltr/3 err/4 verw/5 jmpe/6/dynamic invalid/7 #endif - { 0x01, ENTRY_CopyBytes2Mod }, // INVLPG/7, etc. - { 0x02, ENTRY_CopyBytes2Mod }, // LAR/r - { 0x03, ENTRY_CopyBytes2Mod }, // LSL/r - { 0x04, ENTRY_Invalid }, // _04 - { 0x05, ENTRY_CopyBytes1 }, // SYSCALL - { 0x06, ENTRY_CopyBytes1 }, // CLTS - { 0x07, ENTRY_CopyBytes1 }, // SYSRET - { 0x08, ENTRY_CopyBytes1 }, // INVD - { 0x09, ENTRY_CopyBytes1 }, // WBINVD - { 0x0A, ENTRY_Invalid }, // _0A - { 0x0B, ENTRY_CopyBytes1 }, // UD2 - { 0x0C, ENTRY_Invalid }, // _0C - { 0x0D, ENTRY_CopyBytes2Mod }, // PREFETCH - { 0x0E, ENTRY_CopyBytes1 }, // FEMMS (3DNow -- not in Intel documentation) - { 0x0F, ENTRY_CopyBytes2Mod1 }, // 3DNow Opcodes - { 0x10, ENTRY_CopyBytes2Mod }, // MOVSS MOVUPD MOVSD - { 0x11, ENTRY_CopyBytes2Mod }, // MOVSS MOVUPD MOVSD - { 0x12, ENTRY_CopyBytes2Mod }, // MOVLPD - { 0x13, ENTRY_CopyBytes2Mod }, // MOVLPD - { 0x14, ENTRY_CopyBytes2Mod }, // UNPCKLPD - { 0x15, ENTRY_CopyBytes2Mod }, // UNPCKHPD - { 0x16, ENTRY_CopyBytes2Mod }, // MOVHPD - { 0x17, ENTRY_CopyBytes2Mod }, // MOVHPD - { 0x18, ENTRY_CopyBytes2Mod }, // PREFETCHINTA... - { 0x19, ENTRY_CopyBytes2Mod }, // NOP/r multi byte nop, not documented by Intel, documented by AMD - { 0x1A, ENTRY_CopyBytes2Mod }, // NOP/r multi byte nop, not documented by Intel, documented by AMD - { 0x1B, ENTRY_CopyBytes2Mod }, // NOP/r multi byte nop, not documented by Intel, documented by AMD - { 0x1C, ENTRY_CopyBytes2Mod }, // NOP/r multi byte nop, not documented by Intel, documented by AMD - { 0x1D, ENTRY_CopyBytes2Mod }, // NOP/r multi byte nop, not documented by Intel, documented by AMD - { 0x1E, ENTRY_CopyBytes2Mod }, // NOP/r multi byte nop, not documented by Intel, documented by AMD - { 0x1F, ENTRY_CopyBytes2Mod }, // NOP/r multi byte nop - { 0x20, ENTRY_CopyBytes2Mod }, // MOV/r - { 0x21, ENTRY_CopyBytes2Mod }, // MOV/r - { 0x22, ENTRY_CopyBytes2Mod }, // MOV/r - { 0x23, ENTRY_CopyBytes2Mod }, // MOV/r + /* 01 */ ENTRY_CopyBytes2Mod, // INVLPG/7, etc. + /* 02 */ ENTRY_CopyBytes2Mod, // LAR/r + /* 03 */ ENTRY_CopyBytes2Mod, // LSL/r + /* 04 */ ENTRY_Invalid, // _04 + /* 05 */ ENTRY_CopyBytes1, // SYSCALL + /* 06 */ ENTRY_CopyBytes1, // CLTS + /* 07 */ ENTRY_CopyBytes1, // SYSRET + /* 08 */ ENTRY_CopyBytes1, // INVD + /* 09 */ ENTRY_CopyBytes1, // WBINVD + /* 0A */ ENTRY_Invalid, // _0A + /* 0B */ ENTRY_CopyBytes1, // UD2 + /* 0C */ ENTRY_Invalid, // _0C + /* 0D */ ENTRY_CopyBytes2Mod, // PREFETCH + /* 0E */ ENTRY_CopyBytes1, // FEMMS (3DNow -- not in Intel documentation) + /* 0F */ ENTRY_CopyBytes2Mod1, // 3DNow Opcodes + /* 10 */ ENTRY_CopyBytes2Mod, // MOVSS MOVUPD MOVSD + /* 11 */ ENTRY_CopyBytes2Mod, // MOVSS MOVUPD MOVSD + /* 12 */ ENTRY_CopyBytes2Mod, // MOVLPD + /* 13 */ ENTRY_CopyBytes2Mod, // MOVLPD + /* 14 */ ENTRY_CopyBytes2Mod, // UNPCKLPD + /* 15 */ ENTRY_CopyBytes2Mod, // UNPCKHPD + /* 16 */ ENTRY_CopyBytes2Mod, // MOVHPD + /* 17 */ ENTRY_CopyBytes2Mod, // MOVHPD + /* 18 */ ENTRY_CopyBytes2Mod, // PREFETCHINTA... + /* 19 */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD + /* 1A */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD + /* 1B */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD + /* 1C */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD + /* 1D */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD + /* 1E */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop, not documented by Intel, documented by AMD + /* 1F */ ENTRY_CopyBytes2Mod, // NOP/r multi byte nop + /* 20 */ ENTRY_CopyBytes2Mod, // MOV/r + /* 21 */ ENTRY_CopyBytes2Mod, // MOV/r + /* 22 */ ENTRY_CopyBytes2Mod, // MOV/r + /* 23 */ ENTRY_CopyBytes2Mod, // MOV/r #ifdef DETOURS_X64 - { 0x24, ENTRY_Invalid }, // _24 + /* 24 */ ENTRY_Invalid, // _24 #else - { 0x24, ENTRY_CopyBytes2Mod }, // MOV/r,TR TR is test register on 80386 and 80486, removed in Pentium + /* 24 */ ENTRY_CopyBytes2Mod, // MOV/r,TR TR is test register on 80386 and 80486, removed in Pentium #endif - { 0x25, ENTRY_Invalid }, // _25 + /* 25 */ ENTRY_Invalid, // _25 #ifdef DETOURS_X64 - { 0x26, ENTRY_Invalid }, // _26 + /* 26 */ ENTRY_Invalid, // _26 #else - { 0x26, ENTRY_CopyBytes2Mod }, // MOV TR/r TR is test register on 80386 and 80486, removed in Pentium + /* 26 */ ENTRY_CopyBytes2Mod, // MOV TR/r TR is test register on 80386 and 80486, removed in Pentium #endif - { 0x27, ENTRY_Invalid }, // _27 - { 0x28, ENTRY_CopyBytes2Mod }, // MOVAPS MOVAPD - { 0x29, ENTRY_CopyBytes2Mod }, // MOVAPS MOVAPD - { 0x2A, ENTRY_CopyBytes2Mod }, // CVPI2PS & - { 0x2B, ENTRY_CopyBytes2Mod }, // MOVNTPS MOVNTPD - { 0x2C, ENTRY_CopyBytes2Mod }, // CVTTPS2PI & - { 0x2D, ENTRY_CopyBytes2Mod }, // CVTPS2PI & - { 0x2E, ENTRY_CopyBytes2Mod }, // UCOMISS UCOMISD - { 0x2F, ENTRY_CopyBytes2Mod }, // COMISS COMISD - { 0x30, ENTRY_CopyBytes1 }, // WRMSR - { 0x31, ENTRY_CopyBytes1 }, // RDTSC - { 0x32, ENTRY_CopyBytes1 }, // RDMSR - { 0x33, ENTRY_CopyBytes1 }, // RDPMC - { 0x34, ENTRY_CopyBytes1 }, // SYSENTER - { 0x35, ENTRY_CopyBytes1 }, // SYSEXIT - { 0x36, ENTRY_Invalid }, // _36 - { 0x37, ENTRY_CopyBytes1 }, // GETSEC - { 0x38, ENTRY_CopyBytes3Mod }, // SSE3 Opcodes - { 0x39, ENTRY_Invalid }, // _39 - { 0x3A, ENTRY_CopyBytes3Mod1 }, // SSE3 Opcodes - { 0x3B, ENTRY_Invalid }, // _3B - { 0x3C, ENTRY_Invalid }, // _3C - { 0x3D, ENTRY_Invalid }, // _3D - { 0x3E, ENTRY_Invalid }, // _3E - { 0x3F, ENTRY_Invalid }, // _3F - { 0x40, ENTRY_CopyBytes2Mod }, // CMOVO (0F 40) - { 0x41, ENTRY_CopyBytes2Mod }, // CMOVNO (0F 41) - { 0x42, ENTRY_CopyBytes2Mod }, // CMOVB & CMOVNE (0F 42) - { 0x43, ENTRY_CopyBytes2Mod }, // CMOVAE & CMOVNB (0F 43) - { 0x44, ENTRY_CopyBytes2Mod }, // CMOVE & CMOVZ (0F 44) - { 0x45, ENTRY_CopyBytes2Mod }, // CMOVNE & CMOVNZ (0F 45) - { 0x46, ENTRY_CopyBytes2Mod }, // CMOVBE & CMOVNA (0F 46) - { 0x47, ENTRY_CopyBytes2Mod }, // CMOVA & CMOVNBE (0F 47) - { 0x48, ENTRY_CopyBytes2Mod }, // CMOVS (0F 48) - { 0x49, ENTRY_CopyBytes2Mod }, // CMOVNS (0F 49) - { 0x4A, ENTRY_CopyBytes2Mod }, // CMOVP & CMOVPE (0F 4A) - { 0x4B, ENTRY_CopyBytes2Mod }, // CMOVNP & CMOVPO (0F 4B) - { 0x4C, ENTRY_CopyBytes2Mod }, // CMOVL & CMOVNGE (0F 4C) - { 0x4D, ENTRY_CopyBytes2Mod }, // CMOVGE & CMOVNL (0F 4D) - { 0x4E, ENTRY_CopyBytes2Mod }, // CMOVLE & CMOVNG (0F 4E) - { 0x4F, ENTRY_CopyBytes2Mod }, // CMOVG & CMOVNLE (0F 4F) - { 0x50, ENTRY_CopyBytes2Mod }, // MOVMSKPD MOVMSKPD - { 0x51, ENTRY_CopyBytes2Mod }, // SQRTPS & - { 0x52, ENTRY_CopyBytes2Mod }, // RSQRTTS RSQRTPS - { 0x53, ENTRY_CopyBytes2Mod }, // RCPPS RCPSS - { 0x54, ENTRY_CopyBytes2Mod }, // ANDPS ANDPD - { 0x55, ENTRY_CopyBytes2Mod }, // ANDNPS ANDNPD - { 0x56, ENTRY_CopyBytes2Mod }, // ORPS ORPD - { 0x57, ENTRY_CopyBytes2Mod }, // XORPS XORPD - { 0x58, ENTRY_CopyBytes2Mod }, // ADDPS & - { 0x59, ENTRY_CopyBytes2Mod }, // MULPS & - { 0x5A, ENTRY_CopyBytes2Mod }, // CVTPS2PD & - { 0x5B, ENTRY_CopyBytes2Mod }, // CVTDQ2PS & - { 0x5C, ENTRY_CopyBytes2Mod }, // SUBPS & - { 0x5D, ENTRY_CopyBytes2Mod }, // MINPS & - { 0x5E, ENTRY_CopyBytes2Mod }, // DIVPS & - { 0x5F, ENTRY_CopyBytes2Mod }, // MASPS & - { 0x60, ENTRY_CopyBytes2Mod }, // PUNPCKLBW/r - { 0x61, ENTRY_CopyBytes2Mod }, // PUNPCKLWD/r - { 0x62, ENTRY_CopyBytes2Mod }, // PUNPCKLWD/r - { 0x63, ENTRY_CopyBytes2Mod }, // PACKSSWB/r - { 0x64, ENTRY_CopyBytes2Mod }, // PCMPGTB/r - { 0x65, ENTRY_CopyBytes2Mod }, // PCMPGTW/r - { 0x66, ENTRY_CopyBytes2Mod }, // PCMPGTD/r - { 0x67, ENTRY_CopyBytes2Mod }, // PACKUSWB/r - { 0x68, ENTRY_CopyBytes2Mod }, // PUNPCKHBW/r - { 0x69, ENTRY_CopyBytes2Mod }, // PUNPCKHWD/r - { 0x6A, ENTRY_CopyBytes2Mod }, // PUNPCKHDQ/r - { 0x6B, ENTRY_CopyBytes2Mod }, // PACKSSDW/r - { 0x6C, ENTRY_CopyBytes2Mod }, // PUNPCKLQDQ - { 0x6D, ENTRY_CopyBytes2Mod }, // PUNPCKHQDQ - { 0x6E, ENTRY_CopyBytes2Mod }, // MOVD/r - { 0x6F, ENTRY_CopyBytes2Mod }, // MOV/r - { 0x70, ENTRY_CopyBytes2Mod1 }, // PSHUFW/r ib - { 0x71, ENTRY_CopyBytes2Mod1 }, // PSLLW/6 ib,PSRAW/4 ib,PSRLW/2 ib - { 0x72, ENTRY_CopyBytes2Mod1 }, // PSLLD/6 ib,PSRAD/4 ib,PSRLD/2 ib - { 0x73, ENTRY_CopyBytes2Mod1 }, // PSLLQ/6 ib,PSRLQ/2 ib - { 0x74, ENTRY_CopyBytes2Mod }, // PCMPEQB/r - { 0x75, ENTRY_CopyBytes2Mod }, // PCMPEQW/r - { 0x76, ENTRY_CopyBytes2Mod }, // PCMPEQD/r - { 0x77, ENTRY_CopyBytes1 }, // EMMS + /* 27 */ ENTRY_Invalid, // _27 + /* 28 */ ENTRY_CopyBytes2Mod, // MOVAPS MOVAPD + /* 29 */ ENTRY_CopyBytes2Mod, // MOVAPS MOVAPD + /* 2A */ ENTRY_CopyBytes2Mod, // CVPI2PS & + /* 2B */ ENTRY_CopyBytes2Mod, // MOVNTPS MOVNTPD + /* 2C */ ENTRY_CopyBytes2Mod, // CVTTPS2PI & + /* 2D */ ENTRY_CopyBytes2Mod, // CVTPS2PI & + /* 2E */ ENTRY_CopyBytes2Mod, // UCOMISS UCOMISD + /* 2F */ ENTRY_CopyBytes2Mod, // COMISS COMISD + /* 30 */ ENTRY_CopyBytes1, // WRMSR + /* 31 */ ENTRY_CopyBytes1, // RDTSC + /* 32 */ ENTRY_CopyBytes1, // RDMSR + /* 33 */ ENTRY_CopyBytes1, // RDPMC + /* 34 */ ENTRY_CopyBytes1, // SYSENTER + /* 35 */ ENTRY_CopyBytes1, // SYSEXIT + /* 36 */ ENTRY_Invalid, // _36 + /* 37 */ ENTRY_CopyBytes1, // GETSEC + /* 38 */ ENTRY_CopyBytes3Mod, // SSE3 Opcodes + /* 39 */ ENTRY_Invalid, // _39 + /* 3A */ ENTRY_CopyBytes3Mod1, // SSE3 Opcodes + /* 3B */ ENTRY_Invalid, // _3B + /* 3C */ ENTRY_Invalid, // _3C + /* 3D */ ENTRY_Invalid, // _3D + /* 3E */ ENTRY_Invalid, // _3E + /* 3F */ ENTRY_Invalid, // _3F + /* 40 */ ENTRY_CopyBytes2Mod, // CMOVO (0F 40) + /* 41 */ ENTRY_CopyBytes2Mod, // CMOVNO (0F 41) + /* 42 */ ENTRY_CopyBytes2Mod, // CMOVB & CMOVNE (0F 42) + /* 43 */ ENTRY_CopyBytes2Mod, // CMOVAE & CMOVNB (0F 43) + /* 44 */ ENTRY_CopyBytes2Mod, // CMOVE & CMOVZ (0F 44) + /* 45 */ ENTRY_CopyBytes2Mod, // CMOVNE & CMOVNZ (0F 45) + /* 46 */ ENTRY_CopyBytes2Mod, // CMOVBE & CMOVNA (0F 46) + /* 47 */ ENTRY_CopyBytes2Mod, // CMOVA & CMOVNBE (0F 47) + /* 48 */ ENTRY_CopyBytes2Mod, // CMOVS (0F 48) + /* 49 */ ENTRY_CopyBytes2Mod, // CMOVNS (0F 49) + /* 4A */ ENTRY_CopyBytes2Mod, // CMOVP & CMOVPE (0F 4A) + /* 4B */ ENTRY_CopyBytes2Mod, // CMOVNP & CMOVPO (0F 4B) + /* 4C */ ENTRY_CopyBytes2Mod, // CMOVL & CMOVNGE (0F 4C) + /* 4D */ ENTRY_CopyBytes2Mod, // CMOVGE & CMOVNL (0F 4D) + /* 4E */ ENTRY_CopyBytes2Mod, // CMOVLE & CMOVNG (0F 4E) + /* 4F */ ENTRY_CopyBytes2Mod, // CMOVG & CMOVNLE (0F 4F) + /* 50 */ ENTRY_CopyBytes2Mod, // MOVMSKPD MOVMSKPD + /* 51 */ ENTRY_CopyBytes2Mod, // SQRTPS & + /* 52 */ ENTRY_CopyBytes2Mod, // RSQRTTS RSQRTPS + /* 53 */ ENTRY_CopyBytes2Mod, // RCPPS RCPSS + /* 54 */ ENTRY_CopyBytes2Mod, // ANDPS ANDPD + /* 55 */ ENTRY_CopyBytes2Mod, // ANDNPS ANDNPD + /* 56 */ ENTRY_CopyBytes2Mod, // ORPS ORPD + /* 57 */ ENTRY_CopyBytes2Mod, // XORPS XORPD + /* 58 */ ENTRY_CopyBytes2Mod, // ADDPS & + /* 59 */ ENTRY_CopyBytes2Mod, // MULPS & + /* 5A */ ENTRY_CopyBytes2Mod, // CVTPS2PD & + /* 5B */ ENTRY_CopyBytes2Mod, // CVTDQ2PS & + /* 5C */ ENTRY_CopyBytes2Mod, // SUBPS & + /* 5D */ ENTRY_CopyBytes2Mod, // MINPS & + /* 5E */ ENTRY_CopyBytes2Mod, // DIVPS & + /* 5F */ ENTRY_CopyBytes2Mod, // MASPS & + /* 60 */ ENTRY_CopyBytes2Mod, // PUNPCKLBW/r + /* 61 */ ENTRY_CopyBytes2Mod, // PUNPCKLWD/r + /* 62 */ ENTRY_CopyBytes2Mod, // PUNPCKLWD/r + /* 63 */ ENTRY_CopyBytes2Mod, // PACKSSWB/r + /* 64 */ ENTRY_CopyBytes2Mod, // PCMPGTB/r + /* 65 */ ENTRY_CopyBytes2Mod, // PCMPGTW/r + /* 66 */ ENTRY_CopyBytes2Mod, // PCMPGTD/r + /* 67 */ ENTRY_CopyBytes2Mod, // PACKUSWB/r + /* 68 */ ENTRY_CopyBytes2Mod, // PUNPCKHBW/r + /* 69 */ ENTRY_CopyBytes2Mod, // PUNPCKHWD/r + /* 6A */ ENTRY_CopyBytes2Mod, // PUNPCKHDQ/r + /* 6B */ ENTRY_CopyBytes2Mod, // PACKSSDW/r + /* 6C */ ENTRY_CopyBytes2Mod, // PUNPCKLQDQ + /* 6D */ ENTRY_CopyBytes2Mod, // PUNPCKHQDQ + /* 6E */ ENTRY_CopyBytes2Mod, // MOVD/r + /* 6F */ ENTRY_CopyBytes2Mod, // MOV/r + /* 70 */ ENTRY_CopyBytes2Mod1, // PSHUFW/r ib + /* 71 */ ENTRY_CopyBytes2Mod1, // PSLLW/6 ib,PSRAW/4 ib,PSRLW/2 ib + /* 72 */ ENTRY_CopyBytes2Mod1, // PSLLD/6 ib,PSRAD/4 ib,PSRLD/2 ib + /* 73 */ ENTRY_CopyBytes2Mod1, // PSLLQ/6 ib,PSRLQ/2 ib + /* 74 */ ENTRY_CopyBytes2Mod, // PCMPEQB/r + /* 75 */ ENTRY_CopyBytes2Mod, // PCMPEQW/r + /* 76 */ ENTRY_CopyBytes2Mod, // PCMPEQD/r + /* 77 */ ENTRY_CopyBytes1, // EMMS // extrq/insertq require mode=3 and are followed by two immediate bytes - { 0x78, ENTRY_Copy0F78 }, // VMREAD/r, 66/EXTRQ/r/ib/ib, F2/INSERTQ/r/ib/ib + /* 78 */ ENTRY_Copy0F78, // VMREAD/r, 66/EXTRQ/r/ib/ib, F2/INSERTQ/r/ib/ib // extrq/insertq require mod=3, therefore ENTRY_CopyBytes2, but it ends up the same - { 0x79, ENTRY_CopyBytes2Mod }, // VMWRITE/r, 66/EXTRQ/r, F2/INSERTQ/r - { 0x7A, ENTRY_Invalid }, // _7A - { 0x7B, ENTRY_Invalid }, // _7B - { 0x7C, ENTRY_CopyBytes2Mod }, // HADDPS - { 0x7D, ENTRY_CopyBytes2Mod }, // HSUBPS - { 0x7E, ENTRY_CopyBytes2Mod }, // MOVD/r - { 0x7F, ENTRY_CopyBytes2Mod }, // MOV/r - { 0x80, ENTRY_CopyBytes3Or5Target }, // JO - { 0x81, ENTRY_CopyBytes3Or5Target }, // JNO - { 0x82, ENTRY_CopyBytes3Or5Target }, // JB,JC,JNAE - { 0x83, ENTRY_CopyBytes3Or5Target }, // JAE,JNB,JNC - { 0x84, ENTRY_CopyBytes3Or5Target }, // JE,JZ,JZ - { 0x85, ENTRY_CopyBytes3Or5Target }, // JNE,JNZ - { 0x86, ENTRY_CopyBytes3Or5Target }, // JBE,JNA - { 0x87, ENTRY_CopyBytes3Or5Target }, // JA,JNBE - { 0x88, ENTRY_CopyBytes3Or5Target }, // JS - { 0x89, ENTRY_CopyBytes3Or5Target }, // JNS - { 0x8A, ENTRY_CopyBytes3Or5Target }, // JP,JPE - { 0x8B, ENTRY_CopyBytes3Or5Target }, // JNP,JPO - { 0x8C, ENTRY_CopyBytes3Or5Target }, // JL,NGE - { 0x8D, ENTRY_CopyBytes3Or5Target }, // JGE,JNL - { 0x8E, ENTRY_CopyBytes3Or5Target }, // JLE,JNG - { 0x8F, ENTRY_CopyBytes3Or5Target }, // JG,JNLE - { 0x90, ENTRY_CopyBytes2Mod }, // CMOVO (0F 40) - { 0x91, ENTRY_CopyBytes2Mod }, // CMOVNO (0F 41) - { 0x92, ENTRY_CopyBytes2Mod }, // CMOVB & CMOVC & CMOVNAE (0F 42) - { 0x93, ENTRY_CopyBytes2Mod }, // CMOVAE & CMOVNB & CMOVNC (0F 43) - { 0x94, ENTRY_CopyBytes2Mod }, // CMOVE & CMOVZ (0F 44) - { 0x95, ENTRY_CopyBytes2Mod }, // CMOVNE & CMOVNZ (0F 45) - { 0x96, ENTRY_CopyBytes2Mod }, // CMOVBE & CMOVNA (0F 46) - { 0x97, ENTRY_CopyBytes2Mod }, // CMOVA & CMOVNBE (0F 47) - { 0x98, ENTRY_CopyBytes2Mod }, // CMOVS (0F 48) - { 0x99, ENTRY_CopyBytes2Mod }, // CMOVNS (0F 49) - { 0x9A, ENTRY_CopyBytes2Mod }, // CMOVP & CMOVPE (0F 4A) - { 0x9B, ENTRY_CopyBytes2Mod }, // CMOVNP & CMOVPO (0F 4B) - { 0x9C, ENTRY_CopyBytes2Mod }, // CMOVL & CMOVNGE (0F 4C) - { 0x9D, ENTRY_CopyBytes2Mod }, // CMOVGE & CMOVNL (0F 4D) - { 0x9E, ENTRY_CopyBytes2Mod }, // CMOVLE & CMOVNG (0F 4E) - { 0x9F, ENTRY_CopyBytes2Mod }, // CMOVG & CMOVNLE (0F 4F) - { 0xA0, ENTRY_CopyBytes1 }, // PUSH - { 0xA1, ENTRY_CopyBytes1 }, // POP - { 0xA2, ENTRY_CopyBytes1 }, // CPUID - { 0xA3, ENTRY_CopyBytes2Mod }, // BT (0F A3) - { 0xA4, ENTRY_CopyBytes2Mod1 }, // SHLD - { 0xA5, ENTRY_CopyBytes2Mod }, // SHLD - { 0xA6, ENTRY_CopyBytes2Mod }, // XBTS - { 0xA7, ENTRY_CopyBytes2Mod }, // IBTS - { 0xA8, ENTRY_CopyBytes1 }, // PUSH - { 0xA9, ENTRY_CopyBytes1 }, // POP - { 0xAA, ENTRY_CopyBytes1 }, // RSM - { 0xAB, ENTRY_CopyBytes2Mod }, // BTS (0F AB) - { 0xAC, ENTRY_CopyBytes2Mod1 }, // SHRD - { 0xAD, ENTRY_CopyBytes2Mod }, // SHRD + /* 79 */ ENTRY_CopyBytes2Mod, // VMWRITE/r, 66/EXTRQ/r, F2/INSERTQ/r + /* 7A */ ENTRY_Invalid, // _7A + /* 7B */ ENTRY_Invalid, // _7B + /* 7C */ ENTRY_CopyBytes2Mod, // HADDPS + /* 7D */ ENTRY_CopyBytes2Mod, // HSUBPS + /* 7E */ ENTRY_CopyBytes2Mod, // MOVD/r + /* 7F */ ENTRY_CopyBytes2Mod, // MOV/r + /* 80 */ ENTRY_CopyBytes3Or5Target, // JO + /* 81 */ ENTRY_CopyBytes3Or5Target, // JNO + /* 82 */ ENTRY_CopyBytes3Or5Target, // JB,JC,JNAE + /* 83 */ ENTRY_CopyBytes3Or5Target, // JAE,JNB,JNC + /* 84 */ ENTRY_CopyBytes3Or5Target, // JE,JZ,JZ + /* 85 */ ENTRY_CopyBytes3Or5Target, // JNE,JNZ + /* 86 */ ENTRY_CopyBytes3Or5Target, // JBE,JNA + /* 87 */ ENTRY_CopyBytes3Or5Target, // JA,JNBE + /* 88 */ ENTRY_CopyBytes3Or5Target, // JS + /* 89 */ ENTRY_CopyBytes3Or5Target, // JNS + /* 8A */ ENTRY_CopyBytes3Or5Target, // JP,JPE + /* 8B */ ENTRY_CopyBytes3Or5Target, // JNP,JPO + /* 8C */ ENTRY_CopyBytes3Or5Target, // JL,NGE + /* 8D */ ENTRY_CopyBytes3Or5Target, // JGE,JNL + /* 8E */ ENTRY_CopyBytes3Or5Target, // JLE,JNG + /* 8F */ ENTRY_CopyBytes3Or5Target, // JG,JNLE + /* 90 */ ENTRY_CopyBytes2Mod, // CMOVO (0F 40) + /* 91 */ ENTRY_CopyBytes2Mod, // CMOVNO (0F 41) + /* 92 */ ENTRY_CopyBytes2Mod, // CMOVB & CMOVC & CMOVNAE (0F 42) + /* 93 */ ENTRY_CopyBytes2Mod, // CMOVAE & CMOVNB & CMOVNC (0F 43) + /* 94 */ ENTRY_CopyBytes2Mod, // CMOVE & CMOVZ (0F 44) + /* 95 */ ENTRY_CopyBytes2Mod, // CMOVNE & CMOVNZ (0F 45) + /* 96 */ ENTRY_CopyBytes2Mod, // CMOVBE & CMOVNA (0F 46) + /* 97 */ ENTRY_CopyBytes2Mod, // CMOVA & CMOVNBE (0F 47) + /* 98 */ ENTRY_CopyBytes2Mod, // CMOVS (0F 48) + /* 99 */ ENTRY_CopyBytes2Mod, // CMOVNS (0F 49) + /* 9A */ ENTRY_CopyBytes2Mod, // CMOVP & CMOVPE (0F 4A) + /* 9B */ ENTRY_CopyBytes2Mod, // CMOVNP & CMOVPO (0F 4B) + /* 9C */ ENTRY_CopyBytes2Mod, // CMOVL & CMOVNGE (0F 4C) + /* 9D */ ENTRY_CopyBytes2Mod, // CMOVGE & CMOVNL (0F 4D) + /* 9E */ ENTRY_CopyBytes2Mod, // CMOVLE & CMOVNG (0F 4E) + /* 9F */ ENTRY_CopyBytes2Mod, // CMOVG & CMOVNLE (0F 4F) + /* A0 */ ENTRY_CopyBytes1, // PUSH + /* A1 */ ENTRY_CopyBytes1, // POP + /* A2 */ ENTRY_CopyBytes1, // CPUID + /* A3 */ ENTRY_CopyBytes2Mod, // BT (0F A3) + /* A4 */ ENTRY_CopyBytes2Mod1, // SHLD + /* A5 */ ENTRY_CopyBytes2Mod, // SHLD + /* A6 */ ENTRY_CopyBytes2Mod, // XBTS + /* A7 */ ENTRY_CopyBytes2Mod, // IBTS + /* A8 */ ENTRY_CopyBytes1, // PUSH + /* A9 */ ENTRY_CopyBytes1, // POP + /* AA */ ENTRY_CopyBytes1, // RSM + /* AB */ ENTRY_CopyBytes2Mod, // BTS (0F AB) + /* AC */ ENTRY_CopyBytes2Mod1, // SHRD + /* AD */ ENTRY_CopyBytes2Mod, // SHRD // 0F AE mod76=mem mod543=0 fxsave // 0F AE mod76=mem mod543=1 fxrstor @@ -1510,124 +1506,98 @@ const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable0F[257] = // F3 0F AE mod76=11b mod543=1 rdgsbase // F3 0F AE mod76=11b mod543=2 wrfsbase // F3 0F AE mod76=11b mod543=3 wrgsbase - { 0xAE, ENTRY_CopyBytes2Mod }, // fxsave fxrstor ldmxcsr stmxcsr xsave xrstor saveopt clflush lfence mfence sfence rdfsbase rdgsbase wrfsbase wrgsbase - { 0xAF, ENTRY_CopyBytes2Mod }, // IMUL (0F AF) - { 0xB0, ENTRY_CopyBytes2Mod }, // CMPXCHG (0F B0) - { 0xB1, ENTRY_CopyBytes2Mod }, // CMPXCHG (0F B1) - { 0xB2, ENTRY_CopyBytes2Mod }, // LSS/r - { 0xB3, ENTRY_CopyBytes2Mod }, // BTR (0F B3) - { 0xB4, ENTRY_CopyBytes2Mod }, // LFS/r - { 0xB5, ENTRY_CopyBytes2Mod }, // LGS/r - { 0xB6, ENTRY_CopyBytes2Mod }, // MOVZX/r - { 0xB7, ENTRY_CopyBytes2Mod }, // MOVZX/r + /* AE */ ENTRY_CopyBytes2Mod, // fxsave fxrstor ldmxcsr stmxcsr xsave xrstor saveopt clflush lfence mfence sfence rdfsbase rdgsbase wrfsbase wrgsbase + /* AF */ ENTRY_CopyBytes2Mod, // IMUL (0F AF) + /* B0 */ ENTRY_CopyBytes2Mod, // CMPXCHG (0F B0) + /* B1 */ ENTRY_CopyBytes2Mod, // CMPXCHG (0F B1) + /* B2 */ ENTRY_CopyBytes2Mod, // LSS/r + /* B3 */ ENTRY_CopyBytes2Mod, // BTR (0F B3) + /* B4 */ ENTRY_CopyBytes2Mod, // LFS/r + /* B5 */ ENTRY_CopyBytes2Mod, // LGS/r + /* B6 */ ENTRY_CopyBytes2Mod, // MOVZX/r + /* B7 */ ENTRY_CopyBytes2Mod, // MOVZX/r #ifdef DETOURS_X86 - { 0xB8, ENTRY_Copy0FB8 }, // jmpe f3/popcnt + /* B8 */ ENTRY_Copy0FB8, // jmpe f3/popcnt #else - { 0xB8, ENTRY_CopyBytes2Mod }, // f3/popcnt + /* B8 */ ENTRY_CopyBytes2Mod, // f3/popcnt #endif - { 0xB9, ENTRY_Invalid }, // _B9 - { 0xBA, ENTRY_CopyBytes2Mod1 }, // BT & BTC & BTR & BTS (0F BA) - { 0xBB, ENTRY_CopyBytes2Mod }, // BTC (0F BB) - { 0xBC, ENTRY_CopyBytes2Mod }, // BSF (0F BC) - { 0xBD, ENTRY_CopyBytes2Mod }, // BSR (0F BD) - { 0xBE, ENTRY_CopyBytes2Mod }, // MOVSX/r - { 0xBF, ENTRY_CopyBytes2Mod }, // MOVSX/r - { 0xC0, ENTRY_CopyBytes2Mod }, // XADD/r - { 0xC1, ENTRY_CopyBytes2Mod }, // XADD/r - { 0xC2, ENTRY_CopyBytes2Mod1 }, // CMPPS & - { 0xC3, ENTRY_CopyBytes2Mod }, // MOVNTI - { 0xC4, ENTRY_CopyBytes2Mod1 }, // PINSRW /r ib - { 0xC5, ENTRY_CopyBytes2Mod1 }, // PEXTRW /r ib - { 0xC6, ENTRY_CopyBytes2Mod1 }, // SHUFPS & SHUFPD - { 0xC7, ENTRY_CopyBytes2Mod }, // CMPXCHG8B (0F C7) - { 0xC8, ENTRY_CopyBytes1 }, // BSWAP 0F C8 + rd - { 0xC9, ENTRY_CopyBytes1 }, // BSWAP 0F C8 + rd - { 0xCA, ENTRY_CopyBytes1 }, // BSWAP 0F C8 + rd - { 0xCB, ENTRY_CopyBytes1 }, // CVTPD2PI BSWAP 0F C8 + rd - { 0xCC, ENTRY_CopyBytes1 }, // BSWAP 0F C8 + rd - { 0xCD, ENTRY_CopyBytes1 }, // BSWAP 0F C8 + rd - { 0xCE, ENTRY_CopyBytes1 }, // BSWAP 0F C8 + rd - { 0xCF, ENTRY_CopyBytes1 }, // BSWAP 0F C8 + rd - { 0xD0, ENTRY_CopyBytes2Mod }, // ADDSUBPS (untestd) - { 0xD1, ENTRY_CopyBytes2Mod }, // PSRLW/r - { 0xD2, ENTRY_CopyBytes2Mod }, // PSRLD/r - { 0xD3, ENTRY_CopyBytes2Mod }, // PSRLQ/r - { 0xD4, ENTRY_CopyBytes2Mod }, // PADDQ - { 0xD5, ENTRY_CopyBytes2Mod }, // PMULLW/r - { 0xD6, ENTRY_CopyBytes2Mod }, // MOVDQ2Q / MOVQ2DQ - { 0xD7, ENTRY_CopyBytes2Mod }, // PMOVMSKB/r - { 0xD8, ENTRY_CopyBytes2Mod }, // PSUBUSB/r - { 0xD9, ENTRY_CopyBytes2Mod }, // PSUBUSW/r - { 0xDA, ENTRY_CopyBytes2Mod }, // PMINUB/r - { 0xDB, ENTRY_CopyBytes2Mod }, // PAND/r - { 0xDC, ENTRY_CopyBytes2Mod }, // PADDUSB/r - { 0xDD, ENTRY_CopyBytes2Mod }, // PADDUSW/r - { 0xDE, ENTRY_CopyBytes2Mod }, // PMAXUB/r - { 0xDF, ENTRY_CopyBytes2Mod }, // PANDN/r - { 0xE0, ENTRY_CopyBytes2Mod }, // PAVGB - { 0xE1, ENTRY_CopyBytes2Mod }, // PSRAW/r - { 0xE2, ENTRY_CopyBytes2Mod }, // PSRAD/r - { 0xE3, ENTRY_CopyBytes2Mod }, // PAVGW - { 0xE4, ENTRY_CopyBytes2Mod }, // PMULHUW/r - { 0xE5, ENTRY_CopyBytes2Mod }, // PMULHW/r - { 0xE6, ENTRY_CopyBytes2Mod }, // CTDQ2PD & - { 0xE7, ENTRY_CopyBytes2Mod }, // MOVNTQ - { 0xE8, ENTRY_CopyBytes2Mod }, // PSUBB/r - { 0xE9, ENTRY_CopyBytes2Mod }, // PSUBW/r - { 0xEA, ENTRY_CopyBytes2Mod }, // PMINSW/r - { 0xEB, ENTRY_CopyBytes2Mod }, // POR/r - { 0xEC, ENTRY_CopyBytes2Mod }, // PADDSB/r - { 0xED, ENTRY_CopyBytes2Mod }, // PADDSW/r - { 0xEE, ENTRY_CopyBytes2Mod }, // PMAXSW /r - { 0xEF, ENTRY_CopyBytes2Mod }, // PXOR/r - { 0xF0, ENTRY_CopyBytes2Mod }, // LDDQU - { 0xF1, ENTRY_CopyBytes2Mod }, // PSLLW/r - { 0xF2, ENTRY_CopyBytes2Mod }, // PSLLD/r - { 0xF3, ENTRY_CopyBytes2Mod }, // PSLLQ/r - { 0xF4, ENTRY_CopyBytes2Mod }, // PMULUDQ/r - { 0xF5, ENTRY_CopyBytes2Mod }, // PMADDWD/r - { 0xF6, ENTRY_CopyBytes2Mod }, // PSADBW/r - { 0xF7, ENTRY_CopyBytes2Mod }, // MASKMOVQ - { 0xF8, ENTRY_CopyBytes2Mod }, // PSUBB/r - { 0xF9, ENTRY_CopyBytes2Mod }, // PSUBW/r - { 0xFA, ENTRY_CopyBytes2Mod }, // PSUBD/r - { 0xFB, ENTRY_CopyBytes2Mod }, // FSUBQ/r - { 0xFC, ENTRY_CopyBytes2Mod }, // PADDB/r - { 0xFD, ENTRY_CopyBytes2Mod }, // PADDW/r - { 0xFE, ENTRY_CopyBytes2Mod }, // PADDD/r - { 0xFF, ENTRY_Invalid }, // _FF - { 0, ENTRY_End }, + /* B9 */ ENTRY_Invalid, // _B9 + /* BA */ ENTRY_CopyBytes2Mod1, // BT & BTC & BTR & BTS (0F BA) + /* BB */ ENTRY_CopyBytes2Mod, // BTC (0F BB) + /* BC */ ENTRY_CopyBytes2Mod, // BSF (0F BC) + /* BD */ ENTRY_CopyBytes2Mod, // BSR (0F BD) + /* BE */ ENTRY_CopyBytes2Mod, // MOVSX/r + /* BF */ ENTRY_CopyBytes2Mod, // MOVSX/r + /* C0 */ ENTRY_CopyBytes2Mod, // XADD/r + /* C1 */ ENTRY_CopyBytes2Mod, // XADD/r + /* C2 */ ENTRY_CopyBytes2Mod1, // CMPPS & + /* C3 */ ENTRY_CopyBytes2Mod, // MOVNTI + /* C4 */ ENTRY_CopyBytes2Mod1, // PINSRW /r ib + /* C5 */ ENTRY_CopyBytes2Mod1, // PEXTRW /r ib + /* C6 */ ENTRY_CopyBytes2Mod1, // SHUFPS & SHUFPD + /* C7 */ ENTRY_CopyBytes2Mod, // CMPXCHG8B (0F C7) + /* C8 */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd + /* C9 */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd + /* CA */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd + /* CB */ ENTRY_CopyBytes1, // CVTPD2PI BSWAP 0F C8 + rd + /* CC */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd + /* CD */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd + /* CE */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd + /* CF */ ENTRY_CopyBytes1, // BSWAP 0F C8 + rd + /* D0 */ ENTRY_CopyBytes2Mod, // ADDSUBPS (untestd) + /* D1 */ ENTRY_CopyBytes2Mod, // PSRLW/r + /* D2 */ ENTRY_CopyBytes2Mod, // PSRLD/r + /* D3 */ ENTRY_CopyBytes2Mod, // PSRLQ/r + /* D4 */ ENTRY_CopyBytes2Mod, // PADDQ + /* D5 */ ENTRY_CopyBytes2Mod, // PMULLW/r + /* D6 */ ENTRY_CopyBytes2Mod, // MOVDQ2Q / MOVQ2DQ + /* D7 */ ENTRY_CopyBytes2Mod, // PMOVMSKB/r + /* D8 */ ENTRY_CopyBytes2Mod, // PSUBUSB/r + /* D9 */ ENTRY_CopyBytes2Mod, // PSUBUSW/r + /* DA */ ENTRY_CopyBytes2Mod, // PMINUB/r + /* DB */ ENTRY_CopyBytes2Mod, // PAND/r + /* DC */ ENTRY_CopyBytes2Mod, // PADDUSB/r + /* DD */ ENTRY_CopyBytes2Mod, // PADDUSW/r + /* DE */ ENTRY_CopyBytes2Mod, // PMAXUB/r + /* DF */ ENTRY_CopyBytes2Mod, // PANDN/r + /* E0 */ ENTRY_CopyBytes2Mod , // PAVGB + /* E1 */ ENTRY_CopyBytes2Mod, // PSRAW/r + /* E2 */ ENTRY_CopyBytes2Mod, // PSRAD/r + /* E3 */ ENTRY_CopyBytes2Mod, // PAVGW + /* E4 */ ENTRY_CopyBytes2Mod, // PMULHUW/r + /* E5 */ ENTRY_CopyBytes2Mod, // PMULHW/r + /* E6 */ ENTRY_CopyBytes2Mod, // CTDQ2PD & + /* E7 */ ENTRY_CopyBytes2Mod, // MOVNTQ + /* E8 */ ENTRY_CopyBytes2Mod, // PSUBB/r + /* E9 */ ENTRY_CopyBytes2Mod, // PSUBW/r + /* EA */ ENTRY_CopyBytes2Mod, // PMINSW/r + /* EB */ ENTRY_CopyBytes2Mod, // POR/r + /* EC */ ENTRY_CopyBytes2Mod, // PADDSB/r + /* ED */ ENTRY_CopyBytes2Mod, // PADDSW/r + /* EE */ ENTRY_CopyBytes2Mod, // PMAXSW /r + /* EF */ ENTRY_CopyBytes2Mod, // PXOR/r + /* F0 */ ENTRY_CopyBytes2Mod, // LDDQU + /* F1 */ ENTRY_CopyBytes2Mod, // PSLLW/r + /* F2 */ ENTRY_CopyBytes2Mod, // PSLLD/r + /* F3 */ ENTRY_CopyBytes2Mod, // PSLLQ/r + /* F4 */ ENTRY_CopyBytes2Mod, // PMULUDQ/r + /* F5 */ ENTRY_CopyBytes2Mod, // PMADDWD/r + /* F6 */ ENTRY_CopyBytes2Mod, // PSADBW/r + /* F7 */ ENTRY_CopyBytes2Mod, // MASKMOVQ + /* F8 */ ENTRY_CopyBytes2Mod, // PSUBB/r + /* F9 */ ENTRY_CopyBytes2Mod, // PSUBW/r + /* FA */ ENTRY_CopyBytes2Mod, // PSUBD/r + /* FB */ ENTRY_CopyBytes2Mod, // FSUBQ/r + /* FC */ ENTRY_CopyBytes2Mod, // PADDB/r + /* FD */ ENTRY_CopyBytes2Mod, // PADDW/r + /* FE */ ENTRY_CopyBytes2Mod, // PADDD/r + /* FF */ ENTRY_Invalid, // _FF }; BOOL CDetourDis::SanityCheckSystem() { - ULONG n = 0; - for (; n < 256; n++) { - REFCOPYENTRY pEntry = &s_rceCopyTable[n]; - - if (n != pEntry->nOpcode) { - ASSERT(n == pEntry->nOpcode); - return FALSE; - } - } - if (s_rceCopyTable[256].pfCopy != NULL) { - ASSERT(!"Missing end marker."); - return FALSE; - } - - for (n = 0; n < 256; n++) { - REFCOPYENTRY pEntry = &s_rceCopyTable0F[n]; - - if (n != pEntry->nOpcode) { - ASSERT(n == pEntry->nOpcode); - return FALSE; - } - } - if (s_rceCopyTable0F[256].pfCopy != NULL) { - ASSERT(!"Missing end marker."); - return FALSE; - } - + C_ASSERT(ARRAYSIZE(CDetourDis::s_rceCopyTable) == 256); + C_ASSERT(ARRAYSIZE(CDetourDis::s_rceCopyTable0F) == 256); return TRUE; } #endif // defined(DETOURS_X64) || defined(DETOURS_X86) @@ -3557,11 +3527,11 @@ BYTE CDetourDis::BeginCopy32(BYTE* pSource, BYTE* pDest) /////////////////////////////////////////////////////////// Disassembler Code. // -CDetourDis::CDetourDis() +CDetourDis::CDetourDis() : + m_pbTarget((PBYTE)DETOUR_INSTRUCTION_TARGET_NONE), + m_pbPool(NULL), + m_lExtra(0) { - m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_NONE; - m_pbPool = NULL; - m_lExtra = 0; } PBYTE CDetourDis::CopyInstruction(PBYTE pDst, @@ -3962,9 +3932,9 @@ BYTE CDetourDis::PureCopy32(BYTE* pSource, BYTE* pDest) /////////////////////////////////////////////////////////// Disassembler Code. // -CDetourDis::CDetourDis() +CDetourDis::CDetourDis() : + m_pbTarget((PBYTE)DETOUR_INSTRUCTION_TARGET_NONE) { - m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_NONE; } PBYTE CDetourDis::CopyInstruction(PBYTE pDst, diff --git a/detours/image.cpp b/detours/image.cpp index 4fa31a7..10b17a0 100644 --- a/detours/image.cpp +++ b/detours/image.cpp @@ -146,6 +146,8 @@ protected: DWORD m_cbAlloc; }; +class CImageImportName; + class CImageImportFile { friend class CImage; @@ -534,18 +536,7 @@ PBYTE CImageData::Find(REFGUID rguid, DWORD *pcbData) continue; } - if (pRecord->guid.Data1 == rguid.Data1 && - pRecord->guid.Data2 == rguid.Data2 && - pRecord->guid.Data3 == rguid.Data3 && - pRecord->guid.Data4[0] == rguid.Data4[0] && - pRecord->guid.Data4[1] == rguid.Data4[1] && - pRecord->guid.Data4[2] == rguid.Data4[2] && - pRecord->guid.Data4[3] == rguid.Data4[3] && - pRecord->guid.Data4[4] == rguid.Data4[4] && - pRecord->guid.Data4[5] == rguid.Data4[5] && - pRecord->guid.Data4[6] == rguid.Data4[6] && - pRecord->guid.Data4[7] == rguid.Data4[7]) { - + if (DetourAreSameGuid(pRecord->guid, rguid)) { *pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD); return (PBYTE)(pRecord + 1); } diff --git a/detours/modules.cpp b/detours/modules.cpp index ade78c9..52fc2cf 100644 --- a/detours/modules.cpp +++ b/detours/modules.cpp @@ -23,8 +23,8 @@ ////////////////////////////////////////////////////////////////////////////// // const GUID DETOUR_EXE_RESTORE_GUID = { - 0x2ed7a3ff, 0x3339, 0x4a8d, - { 0x80, 0x5c, 0xd4, 0x98, 0x15, 0x3f, 0xc2, 0x8f }}; + 0xbda26f34, 0xbc82, 0x4829, + { 0x9e, 0x64, 0x74, 0x2c, 0x4, 0xc8, 0x4f, 0xa0 } }; ////////////////////////////////////////////////////////////////////////////// // @@ -142,6 +142,11 @@ PDETOUR_SYM_INFO DetourLoadImageHlp(VOID) PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, _In_ LPCSTR pszFunction) { + if (pszFunction == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + /////////////////////////////////////////////// First, try GetProcAddress. // #pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.") @@ -160,7 +165,7 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction)); PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp(); if (pSymInfo == NULL) { - DETOUR_TRACE(("DetourLoadImageHlp failed: %d\n", + DETOUR_TRACE(("DetourLoadImageHlp failed: %lu\n", GetLastError())); return NULL; } @@ -169,7 +174,7 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, (PCHAR)pszModule, NULL, (DWORD64)hModule, 0) == 0) { if (ERROR_SUCCESS != GetLastError()) { - DETOUR_TRACE(("SymLoadModule64(%p) failed: %d\n", + DETOUR_TRACE(("SymLoadModule64(%p) failed: %lu\n", pSymInfo->hProcess, GetLastError())); return NULL; } @@ -181,24 +186,24 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, ZeroMemory(&modinfo, sizeof(modinfo)); modinfo.SizeOfStruct = sizeof(modinfo); if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) { - DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %d\n", + DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %lu\n", pSymInfo->hProcess, hModule, GetLastError())); return NULL; } hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName); if (FAILED(hrRet)) { - DETOUR_TRACE(("StringCchCopyA failed: %08x\n", hrRet)); + DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet)); return NULL; } hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!"); if (FAILED(hrRet)) { - DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet)); + DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet)); return NULL; } hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction); if (FAILED(hrRet)) { - DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet)); + DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet)); return NULL; } @@ -215,7 +220,7 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, #endif if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) { - DETOUR_TRACE(("SymFromName(%hs) failed: %d\n", szFullName, GetLastError())); + DETOUR_TRACE(("SymFromName(%hs) failed: %lu\n", szFullName, GetLastError())); return NULL; } @@ -277,6 +282,7 @@ HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast) continue; } + SetLastError(NO_ERROR); return (HMODULE)pDosHeader; } #pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.") @@ -340,7 +346,7 @@ PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule) } SetLastError(NO_ERROR); - return GetProcAddress(hClr, "_CorExeMain"); + return (PVOID)GetProcAddress(hClr, "_CorExeMain"); } SetLastError(NO_ERROR); @@ -456,6 +462,11 @@ BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, _In_opt_ PVOID pContext, _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport) { + if (pfExport == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; if (hModule == NULL) { pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL); @@ -658,6 +669,11 @@ BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc) { + if (pfImportFile == NULL || pfImportFunc == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc }; return DetourEnumerateImportsEx(hModule, @@ -761,7 +777,7 @@ _Readable_bytes_(*pcbData) _Success_(return != NULL) PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, _In_ REFGUID rguid, - _Out_ DWORD *pcbData) + _Out_opt_ DWORD *pcbData) { PBYTE pbData = NULL; if (pcbData) { @@ -789,23 +805,12 @@ PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, for (pbData = pbBeg; pbData < pbEnd;) { DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData; - if (pSection->guid.Data1 == rguid.Data1 && - pSection->guid.Data2 == rguid.Data2 && - pSection->guid.Data3 == rguid.Data3 && - pSection->guid.Data4[0] == rguid.Data4[0] && - pSection->guid.Data4[1] == rguid.Data4[1] && - pSection->guid.Data4[2] == rguid.Data4[2] && - pSection->guid.Data4[3] == rguid.Data4[3] && - pSection->guid.Data4[4] == rguid.Data4[4] && - pSection->guid.Data4[5] == rguid.Data4[5] && - pSection->guid.Data4[6] == rguid.Data4[6] && - pSection->guid.Data4[7] == rguid.Data4[7]) { - + if (DetourAreSameGuid(pSection->guid, rguid)) { if (pcbData) { *pcbData = pSection->cbBytes - sizeof(*pSection); - SetLastError(NO_ERROR); - return (PBYTE)(pSection + 1); } + SetLastError(NO_ERROR); + return (PBYTE)(pSection + 1); } pbData = (PBYTE)pSection + pSection->cbBytes; @@ -824,7 +829,7 @@ _Writable_bytes_(*pcbData) _Readable_bytes_(*pcbData) _Success_(return != NULL) PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, - _Out_ DWORD * pcbData) + _Out_opt_ DWORD *pcbData) { for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) { PVOID pvData; @@ -838,6 +843,24 @@ PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, return NULL; } +BOOL WINAPI DetourFreePayload(_In_ PVOID pvData) +{ + BOOL fSucceeded = FALSE; + + // If you have any doubts about the following code, please refer to the comments in DetourCopyPayloadToProcess. + HMODULE hModule = DetourGetContainingModule(pvData); + DETOUR_ASSERT(hModule != NULL); + if (hModule != NULL) { + fSucceeded = VirtualFree(hModule, 0, MEM_RELEASE); + DETOUR_ASSERT(fSucceeded); + if (fSucceeded) { + hModule = NULL; + } + } + + return fSucceeded; +} + BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, _In_ DWORD cbData) { @@ -884,6 +907,11 @@ BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, } VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore); } + // Delete the payload after successful recovery to prevent repeated restore + if (fSucceeded) { + DetourFreePayload(pder); + pder = NULL; + } return fSucceeded; } diff --git a/detours/uimports.cc b/detours/uimports.cc index 1e8cbd7..ed43d65 100644 --- a/detours/uimports.cc +++ b/detours/uimports.cc @@ -35,7 +35,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead) || cbRead < sizeof(idh)) { - DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n", pbModule, pbModule + sizeof(idh), GetLastError())); finish: @@ -51,7 +51,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead) || cbRead < sizeof(inh)) { - DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n", pbModule + idh.e_lfanew, pbModule + idh.e_lfanew + sizeof(inh), GetLastError())); @@ -82,16 +82,21 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, sizeof(ish), &cbRead) || cbRead < sizeof(ish)) { - DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %d\n", + DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n", pbModule + dwSec + sizeof(ish) * i, pbModule + dwSec + sizeof(ish) * (i + 1), GetLastError())); goto finish; } - DETOUR_TRACE(("ish[%d] : va=%08x sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData)); - - // If the file didn't have an IAT_DIRECTORY, we assign it... + DETOUR_TRACE(("ish[%lu] : va=%08lx sr=%lu\n", i, ish.VirtualAddress, ish.SizeOfRawData)); + + // If the linker didn't suggest an IAT in the data directories, the + // loader will look for the section of the import directory to be used + // for this instead. Since we put out new IMPORT_DIRECTORY outside any + // section boundary, the loader will not find it. So we provide one + // explicitly to avoid the search. + // if (inh.IAT_DIRECTORY.VirtualAddress == 0 && inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress && inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) { @@ -101,25 +106,78 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, } } + if (inh.IMPORT_DIRECTORY.VirtualAddress != 0 && inh.IMPORT_DIRECTORY.Size == 0) { + + // Don't worry about changing the PE file, + // because the load information of the original PE header has been saved and will be restored. + // The change here is just for the following code to work normally + + PIMAGE_IMPORT_DESCRIPTOR pImageImport = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule + inh.IMPORT_DIRECTORY.VirtualAddress); + + do { + IMAGE_IMPORT_DESCRIPTOR ImageImport; + if (!ReadProcessMemory(hProcess, pImageImport, &ImageImport, sizeof(ImageImport), NULL)) { + DETOUR_TRACE(("ReadProcessMemory failed: %lu\n", GetLastError())); + goto finish; + } + inh.IMPORT_DIRECTORY.Size += sizeof(IMAGE_IMPORT_DESCRIPTOR); + if (!ImageImport.Name) { + break; + } + ++pImageImport; + } while (TRUE); + + DWORD dwLastError = GetLastError(); + OutputDebugString(TEXT("[This PE file has an import table, but the import table size is marked as 0. This is an error.") + TEXT("If it is not repaired, the launched program will not work properly, Detours has automatically repaired its import table size for you! ! !]\r\n")); + if (GetLastError() != dwLastError) { + SetLastError(dwLastError); + } + } + DETOUR_TRACE((" Imports: %p..%p\n", - (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, - (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress + + pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, + pbModule + inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size)); + // Calculate new import directory size. Note that since inh is from another + // process, inh could have been corrupted. We need to protect against + // integer overflow in allocation calculations. DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR); - DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls; - DWORD obOld = obRem + sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls; + DWORD obRem; + if (DWordMult(sizeof(IMAGE_IMPORT_DESCRIPTOR), nDlls, &obRem) != S_OK) { + DETOUR_TRACE(("too many new DLLs.\n")); + goto finish; + } + DWORD obOld; + if (DWordAdd(obRem, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls, &obOld) != S_OK) { + DETOUR_TRACE(("DLL entries overflow.\n")); + goto finish; + } DWORD obTab = PadToDwordPtr(obOld); - DWORD obDll = obTab + sizeof(DWORD_XX) * 4 * nDlls; + // Check for integer overflow. + if (obTab < obOld) { + DETOUR_TRACE(("DLL entries padding overflow.\n")); + goto finish; + } + DWORD stSize; + if (DWordMult(sizeof(DWORD_XX) * 4, nDlls, &stSize) != S_OK) { + DETOUR_TRACE(("String table overflow.\n")); + goto finish; + } + DWORD obDll; + if (DWordAdd(obTab, stSize, &obDll) != S_OK) { + DETOUR_TRACE(("Import table size overflow\n")); + goto finish; + } DWORD obStr = obDll; cbNew = obStr; for (n = 0; n < nDlls; n++) { - cbNew += PadToDword((DWORD)strlen(plpDlls[n]) + 1); + if (DWordAdd(cbNew, PadToDword((DWORD)strlen(plpDlls[n]) + 1), &cbNew) != S_OK) { + DETOUR_TRACE(("Overflow adding string table entry\n")); + goto finish; + } } - - _Analysis_assume_(cbNew > - sizeof(IMAGE_IMPORT_DESCRIPTOR) * (nDlls + nOldDlls) - + sizeof(DWORD_XX) * 4 * nDlls); pbNew = new BYTE [cbNew]; if (pbNew == NULL) { DETOUR_TRACE(("new BYTE [cbNew] failed.\n")); @@ -145,14 +203,14 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, } PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew; - DWORD_XX *pt; + IMAGE_THUNK_DATAXX *pt = NULL; DWORD obBase = (DWORD)(pbNewIid - pbModule); DWORD dwProtect = 0; if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) { // Read the old import directory if it exists. - DETOUR_TRACE(("IMPORT_DIRECTORY perms=%x\n", dwProtect)); + DETOUR_TRACE(("IMPORT_DIRECTORY perms=%lx\n", dwProtect)); if (!ReadProcessMemory(hProcess, pbModule + inh.IMPORT_DIRECTORY.VirtualAddress, @@ -160,7 +218,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead) || cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) { - DETOUR_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError())); + DETOUR_TRACE(("ReadProcessMemory(imports) failed: %lu\n", GetLastError())); goto finish; } } @@ -168,7 +226,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, for (n = 0; n < nDlls; n++) { HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]); if (FAILED(hrRet)) { - DETOUR_TRACE(("StringCchCopyA failed: %d\n", GetLastError())); + DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet)); goto finish; } @@ -177,21 +235,24 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, cbNew - obStr, DETOURS_STRINGIFY(DETOURS_BITS_XX)); if (FAILED(hrRet)) { - DETOUR_TRACE(("ReplaceOptionalSizeA failed: %d\n", GetLastError())); + DETOUR_TRACE(("ReplaceOptionalSizeA failed: %08lx\n", hrRet)); goto finish; } - DWORD nOffset = obTab + (sizeof(DWORD_XX) * (4 * n)); + DWORD nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * (4 * n)); piid[n].OriginalFirstThunk = obBase + nOffset; - pt = ((DWORD_XX*)(pbNew + nOffset)); - pt[0] = IMAGE_ORDINAL_FLAG_XX + 1; - pt[1] = 0; + + // We need 2 thunks for the import table and 2 thunks for the IAT. + // One for an ordinal import and one to mark the end of the list. + pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset)); + pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1; + pt[1].u1.Ordinal = 0; - nOffset = obTab + (sizeof(DWORD_XX) * ((4 * n) + 2)); + nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * ((4 * n) + 2)); piid[n].FirstThunk = obBase + nOffset; - pt = ((DWORD_XX*)(pbNew + nOffset)); - pt[0] = IMAGE_ORDINAL_FLAG_XX + 1; - pt[1] = 0; + pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset)); + pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1; + pt[1].u1.Ordinal = 0; piid[n].TimeDateStamp = 0; piid[n].ForwarderChain = 0; piid[n].Name = obBase + obStr; @@ -216,16 +277,19 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, #endif if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) { - DETOUR_TRACE(("WriteProcessMemory(iid) failed: %d\n", GetLastError())); + DETOUR_TRACE(("WriteProcessMemory(iid) failed: %lu\n", GetLastError())); goto finish; } - DETOUR_TRACE(("obBaseBef = %08x..%08x\n", + DETOUR_TRACE(("obBaseBef = %08lx..%08lx\n", inh.IMPORT_DIRECTORY.VirtualAddress, inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size)); - DETOUR_TRACE(("obBaseAft = %08x..%08x\n", obBase, obBase + obStr)); + DETOUR_TRACE(("obBaseAft = %08lx..%08lx\n", obBase, obBase + obStr)); - // If the file doesn't have an IAT_DIRECTORY, we create it... + // In this case the file didn't have an import directory in first place, + // so we couldn't fix the missing IAT above. We still need to explicitly + // provide an IAT to prevent to loader from looking for one. + // if (inh.IAT_DIRECTORY.VirtualAddress == 0) { inh.IAT_DIRECTORY.VirtualAddress = obBase; inh.IAT_DIRECTORY.Size = cbNew; @@ -238,20 +302,20 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, // if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, PAGE_EXECUTE_READWRITE, &dwProtect)) { - DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %d\n", GetLastError())); + DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %lu\n", GetLastError())); goto finish; } inh.OptionalHeader.CheckSum = 0; if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) { - DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError())); + DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError())); goto finish; } DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh))); if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) { - DETOUR_TRACE(("WriteProcessMemory(inh) failed: %d\n", GetLastError())); + DETOUR_TRACE(("WriteProcessMemory(inh) failed: %lu\n", GetLastError())); goto finish; } DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n", @@ -260,7 +324,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess, if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders, dwProtect, &dwProtect)) { - DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %d\n", GetLastError())); + DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %lu\n", GetLastError())); goto finish; }