mirror of
https://github.com/Detanup01/gbe_fork.git
synced 2024-12-25 01:44:15 +08:00
Update detours library to latest.
This commit is contained in:
parent
5495f36ed6
commit
c162ca79d5
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 <windows.h>
|
||||
#if (_MSC_VER < 1310)
|
||||
#else
|
||||
@ -36,8 +45,28 @@
|
||||
#pragma warning(disable:6102 6103) // /analyze warnings
|
||||
#endif
|
||||
#include <strsafe.h>
|
||||
#include <intsafe.h>
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#include <crtdbg.h>
|
||||
|
||||
// Allow Detours to cleanly compile with the MingW toolchain.
|
||||
//
|
||||
#ifdef __GNUC__
|
||||
#define __try
|
||||
#define __except(x) if (0)
|
||||
#include <strsafe.h>
|
||||
#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 <type_traits>
|
||||
|
||||
template<typename T>
|
||||
struct DetoursIsFunctionPointer : std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct DetoursIsFunctionPointer<T*> : std::is_function<typename std::remove_pointer<T>::type> {};
|
||||
|
||||
template<
|
||||
typename T,
|
||||
typename std::enable_if<DetoursIsFunctionPointer<T>::value, int>::type = 0>
|
||||
LONG DetourAttach(_Inout_ T *ppPointer,
|
||||
_In_ T pDetour) noexcept
|
||||
{
|
||||
return DetourAttach(
|
||||
reinterpret_cast<void**>(ppPointer),
|
||||
reinterpret_cast<void*>(pDetour));
|
||||
}
|
||||
|
||||
template<
|
||||
typename T,
|
||||
typename std::enable_if<DetoursIsFunctionPointer<T>::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<void**>(ppPointer),
|
||||
reinterpret_cast<void*>(pDetour),
|
||||
ppRealTrampoline,
|
||||
reinterpret_cast<void**>(ppRealTarget),
|
||||
reinterpret_cast<void**>(ppRealDetour));
|
||||
}
|
||||
|
||||
template<
|
||||
typename T,
|
||||
typename std::enable_if<DetoursIsFunctionPointer<T>::value, int>::type = 0>
|
||||
LONG DetourDetach(_Inout_ T *ppPointer,
|
||||
_In_ T pDetour) noexcept
|
||||
{
|
||||
return DetourDetach(
|
||||
reinterpret_cast<void**>(ppPointer),
|
||||
reinterpret_cast<void*>(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 <imagehlp.h>
|
||||
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
|
||||
|
1316
detours/disasm.cpp
1316
detours/disasm.cpp
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user