mirror of
https://gitlab.com/Mr_Goldberg/goldberg_emulator.git
synced 2024-11-23 12:28:07 +01:00
Update detours library to latest.
This commit is contained in:
parent
5495f36ed6
commit
c162ca79d5
7 changed files with 1294 additions and 864 deletions
|
@ -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,
|
static PVOID LoadNtHeaderFromProcess(_In_ HANDLE hProcess,
|
||||||
HMODULE hModule,
|
_In_ HMODULE hModule,
|
||||||
PIMAGE_NT_HEADERS32 pNtHeader)
|
_Out_ PIMAGE_NT_HEADERS32 pNtHeader)
|
||||||
{
|
{
|
||||||
|
ZeroMemory(pNtHeader, sizeof(*pNtHeader));
|
||||||
PBYTE pbModule = (PBYTE)hModule;
|
PBYTE pbModule = (PBYTE)hModule;
|
||||||
|
|
||||||
if (pbModule == NULL) {
|
if (pbModule == NULL) {
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
ZeroMemory(&mbi, sizeof(mbi));
|
ZeroMemory(&mbi, sizeof(mbi));
|
||||||
|
|
||||||
if (VirtualQueryEx(hProcess, hModule, &mbi, sizeof(mbi)) == 0) {
|
if (VirtualQueryEx(hProcess, hModule, &mbi, sizeof(mbi)) == 0) {
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMAGE_DOS_HEADER idh;
|
IMAGE_DOS_HEADER idh;
|
||||||
|
|
||||||
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
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()));
|
pbModule, pbModule + sizeof(idh), GetLastError()));
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idh.e_magic != IMAGE_DOS_SIGNATURE ||
|
if (idh.e_magic != IMAGE_DOS_SIGNATURE ||
|
||||||
|
@ -62,31 +62,37 @@ static BOOL WINAPI LoadNtHeaderFromProcess(HANDLE hProcess,
|
||||||
(DWORD)idh.e_lfanew < sizeof(idh)) {
|
(DWORD)idh.e_lfanew < sizeof(idh)) {
|
||||||
|
|
||||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew,
|
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew,
|
||||||
pNtHeader, sizeof(*pNtHeader), NULL)) {
|
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,
|
||||||
pbModule + idh.e_lfanew + sizeof(*pNtHeader),
|
pbModule + idh.e_lfanew + sizeof(*pNtHeader),
|
||||||
pbModule,
|
pbModule,
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
SetLastError(ERROR_BAD_EXE_FORMAT);
|
SetLastError(ERROR_BAD_EXE_FORMAT);
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return pbModule + idh.e_lfanew;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HMODULE WINAPI EnumerateModulesInProcess(HANDLE hProcess,
|
static HMODULE EnumerateModulesInProcess(_In_ HANDLE hProcess,
|
||||||
HMODULE hModuleLast,
|
_In_opt_ HMODULE hModuleLast,
|
||||||
PIMAGE_NT_HEADERS32 pNtHeader)
|
_Out_ PIMAGE_NT_HEADERS32 pNtHeader,
|
||||||
|
_Out_opt_ PVOID *pRemoteNtHeader)
|
||||||
{
|
{
|
||||||
|
ZeroMemory(pNtHeader, sizeof(*pNtHeader));
|
||||||
|
if (pRemoteNtHeader) {
|
||||||
|
*pRemoteNtHeader = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
|
PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
@ -118,13 +124,147 @@ static HMODULE WINAPI EnumerateModulesInProcess(HANDLE hProcess,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LoadNtHeaderFromProcess(hProcess, (HMODULE)pbLast, pNtHeader)) {
|
PVOID remoteHeader
|
||||||
|
= LoadNtHeaderFromProcess(hProcess, (HMODULE)pbLast, pNtHeader);
|
||||||
|
if (remoteHeader) {
|
||||||
|
if (pRemoteNtHeader) {
|
||||||
|
*pRemoteNtHeader = remoteHeader;
|
||||||
|
}
|
||||||
|
|
||||||
return (HMODULE)pbLast;
|
return (HMODULE)pbLast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
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.
|
// 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) {
|
if (GetLastError() == ERROR_INVALID_PARAMETER) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("VirtualQueryEx(%p) failed: %d\n",
|
DETOUR_TRACE(("VirtualQueryEx(%p) failed: %lu\n",
|
||||||
pbLast, GetLastError()));
|
pbLast, GetLastError()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +327,7 @@ static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbModule, PBYTE pbBa
|
||||||
PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc,
|
PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc,
|
||||||
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||||
if (pbAlloc == NULL) {
|
if (pbAlloc == NULL) {
|
||||||
DETOUR_TRACE(("VirtualAllocEx(%p) failed: %d\n", pbAddress, GetLastError()));
|
DETOUR_TRACE(("VirtualAllocEx(%p) failed: %lu\n", pbAddress, GetLastError()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
@ -246,7 +386,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
der.pidh = (PBYTE)hModule;
|
der.pidh = (PBYTE)hModule;
|
||||||
der.cbidh = sizeof(der.idh);
|
der.cbidh = sizeof(der.idh);
|
||||||
if (!ReadProcessMemory(hProcess, der.pidh, &der.idh, sizeof(der.idh), NULL)) {
|
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()));
|
der.pidh, der.pidh + der.cbidh, GetLastError()));
|
||||||
return FALSE;
|
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.pinh = der.pidh + der.idh.e_lfanew;
|
||||||
der.cbinh = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader);
|
der.cbinh = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader);
|
||||||
if (!ReadProcessMemory(hProcess, der.pinh, &der.inh, der.cbinh, NULL)) {
|
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()));
|
der.pinh, der.pinh + der.cbinh, GetLastError()));
|
||||||
return FALSE;
|
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)) {
|
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()));
|
der.pinh, der.pinh + der.cbinh, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -284,7 +424,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
if (der.inh32.CLR_DIRECTORY.VirtualAddress != 0 &&
|
if (der.inh32.CLR_DIRECTORY.VirtualAddress != 0 &&
|
||||||
der.inh32.CLR_DIRECTORY.Size != 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.VirtualAddress,
|
||||||
der.inh32.CLR_DIRECTORY.Size));
|
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 &&
|
if (der.inh64.CLR_DIRECTORY.VirtualAddress != 0 &&
|
||||||
der.inh64.CLR_DIRECTORY.Size != 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.VirtualAddress,
|
||||||
der.inh64.CLR_DIRECTORY.Size));
|
der.inh64.CLR_DIRECTORY.Size));
|
||||||
|
|
||||||
|
@ -306,7 +446,7 @@ static BOOL RecordExeRestore(HANDLE hProcess, HMODULE hModule, DETOUR_EXE_RESTOR
|
||||||
if (der.pclr != 0) {
|
if (der.pclr != 0) {
|
||||||
der.cbclr = sizeof(der.clr);
|
der.cbclr = sizeof(der.clr);
|
||||||
if (!ReadProcessMemory(hProcess, der.pclr, &der.clr, der.cbclr, NULL)) {
|
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()));
|
der.pclr, der.pclr + der.cbclr, GetLastError()));
|
||||||
return FALSE;
|
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_HEADERS_XX IMAGE_NT_HEADERS32
|
||||||
#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
||||||
#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32
|
#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG32
|
||||||
|
#define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA32
|
||||||
#define UPDATE_IMPORTS_XX UpdateImports32
|
#define UPDATE_IMPORTS_XX UpdateImports32
|
||||||
#define DETOURS_BITS_XX 32
|
#define DETOURS_BITS_XX 32
|
||||||
#include "uimports.cc"
|
#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_HEADERS_XX IMAGE_NT_HEADERS64
|
||||||
#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC
|
#define IMAGE_NT_OPTIONAL_HDR_MAGIC_XX IMAGE_NT_OPTIONAL_HDR64_MAGIC
|
||||||
#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64
|
#define IMAGE_ORDINAL_FLAG_XX IMAGE_ORDINAL_FLAG64
|
||||||
|
#define IMAGE_THUNK_DATAXX IMAGE_THUNK_DATA64
|
||||||
#define UPDATE_IMPORTS_XX UpdateImports64
|
#define UPDATE_IMPORTS_XX UpdateImports64
|
||||||
#define DETOURS_BITS_XX 64
|
#define DETOURS_BITS_XX 64
|
||||||
#include "uimports.cc"
|
#include "uimports.cc"
|
||||||
|
@ -374,7 +516,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
//////////////////////////////////////////////////////// Read old headers.
|
//////////////////////////////////////////////////////// Read old headers.
|
||||||
//
|
//
|
||||||
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
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()));
|
pbModule, pbModule + sizeof(idh), GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -383,7 +525,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
|
|
||||||
PBYTE pnh = pbModule + idh.e_lfanew;
|
PBYTE pnh = pbModule + idh.e_lfanew;
|
||||||
if (!ReadProcessMemory(hProcess, pnh, &inh32, sizeof(inh32), NULL)) {
|
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()));
|
pnh, pnh + sizeof(inh32), GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -398,7 +540,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
inh32.FileHeader.SizeOfOptionalHeader;
|
inh32.FileHeader.SizeOfOptionalHeader;
|
||||||
ULONG cb = inh32.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
ULONG cb = inh32.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
||||||
if (!ReadProcessMemory(hProcess, psects, §s, cb, NULL)) {
|
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()));
|
psects, psects + cb, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -455,7 +597,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) {
|
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()));
|
pnh, pnh + sizeof(inh64), GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -466,7 +608,7 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
inh64.FileHeader.SizeOfOptionalHeader;
|
inh64.FileHeader.SizeOfOptionalHeader;
|
||||||
cb = inh64.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
cb = inh64.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
||||||
if (!WriteProcessMemory(hProcess, psects, §s, cb, NULL)) {
|
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()));
|
psects, psects + cb, GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -478,12 +620,12 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the import table.
|
// 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.VirtualAddress = 0;
|
||||||
inh64.IMPORT_DIRECTORY.Size = 0;
|
inh64.IMPORT_DIRECTORY.Size = 0;
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pnh, &inh64, sizeof(inh64), NULL)) {
|
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()));
|
pnh, pnh + sizeof(inh64), GetLastError()));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -499,6 +641,37 @@ static BOOL UpdateFrom32To64(HANDLE hProcess, HMODULE hModule, WORD machine,
|
||||||
}
|
}
|
||||||
#endif // DETOURS_64BIT
|
#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,
|
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.
|
// Find the next memory region that contains a mapped PE image.
|
||||||
//
|
//
|
||||||
BOOL bHas64BitDll = FALSE;
|
|
||||||
BOOL bHas32BitExe = FALSE;
|
|
||||||
BOOL bIs32BitProcess;
|
BOOL bIs32BitProcess;
|
||||||
|
BOOL bIs64BitOS = FALSE;
|
||||||
HMODULE hModule = NULL;
|
HMODULE hModule = NULL;
|
||||||
HMODULE hLast = NULL;
|
HMODULE hLast = NULL;
|
||||||
|
|
||||||
DETOUR_TRACE(("DetourUpdateProcessWithDll(%p,dlls=%d)\n", hProcess, nDlls));
|
DETOUR_TRACE(("DetourUpdateProcessWithDll(%p,dlls=%lu)\n", hProcess, nDlls));
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
IMAGE_NT_HEADERS32 inh;
|
IMAGE_NT_HEADERS32 inh;
|
||||||
|
|
||||||
if ((hLast = EnumerateModulesInProcess(hProcess, hLast, &inh)) == NULL) {
|
if ((hLast = EnumerateModulesInProcess(hProcess, hLast, &inh, NULL)) == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,20 +699,8 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
|
||||||
|
|
||||||
if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
|
if ((inh.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
|
||||||
hModule = hLast;
|
hModule = hLast;
|
||||||
if (inh.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
|
||||||
&& inh.FileHeader.Machine != 0) {
|
|
||||||
|
|
||||||
bHas32BitExe = TRUE;
|
|
||||||
}
|
|
||||||
DETOUR_TRACE(("%p Found EXE\n", hLast));
|
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) {
|
if (hModule == NULL) {
|
||||||
|
@ -548,19 +708,37 @@ BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bHas32BitExe) {
|
// Determine if the target process is 32bit or 64bit. This is a two-stop process:
|
||||||
bIs32BitProcess = FALSE;
|
//
|
||||||
|
// 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) {
|
#endif
|
||||||
bIs32BitProcess = TRUE;
|
|
||||||
}
|
// 2. With the operating system bitness known, we can now consider the target process:
|
||||||
else {
|
// - If we're running on a 64bit OS, the target process is 32bit in case
|
||||||
if (!IsWow64Process(hProcess, &bIs32BitProcess)) {
|
// 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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
bIs32BitProcess = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bHas32BitExe, bIs32BitProcess));
|
DETOUR_TRACE((" 32BitProcess=%d\n", bIs32BitProcess));
|
||||||
|
|
||||||
return DetourUpdateProcessWithDllEx(hProcess,
|
return DetourUpdateProcessWithDllEx(hProcess,
|
||||||
hModule,
|
hModule,
|
||||||
|
@ -579,11 +757,11 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
//
|
//
|
||||||
BOOL bIs32BitExe = FALSE;
|
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;
|
IMAGE_NT_HEADERS32 inh;
|
||||||
|
|
||||||
if (hModule == NULL || LoadNtHeaderFromProcess(hProcess, hModule, &inh) == NULL) {
|
if (hModule == NULL || !LoadNtHeaderFromProcess(hProcess, hModule, &inh)) {
|
||||||
SetLastError(ERROR_INVALID_OPERATION);
|
SetLastError(ERROR_INVALID_OPERATION);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -594,7 +772,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
bIs32BitExe = TRUE;
|
bIs32BitExe = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE((" 32BitExe=%d 32BitProcess\n", bIs32BitExe, bIs32BitProcess));
|
DETOUR_TRACE((" 32BitExe=%d\n", bIs32BitExe));
|
||||||
|
|
||||||
if (hModule == NULL) {
|
if (hModule == NULL) {
|
||||||
SetLastError(ERROR_INVALID_OPERATION);
|
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.
|
// Try to convert a neutral 32-bit managed binary to a 64-bit managed binary.
|
||||||
if (bIs32BitExe && !bIs32BitProcess) {
|
if (bIs32BitExe && !bIs32BitProcess) {
|
||||||
if (!der.pclr // Native binary
|
if (!der.pclr // Native binary
|
||||||
|| (der.clr.Flags & 1) == 0 // Or mixed-mode MSIL
|
|| (der.clr.Flags & COMIMAGE_FLAGS_ILONLY) == 0 // Or mixed-mode MSIL
|
||||||
|| (der.clr.Flags & 2) != 0) { // Or 32BIT Required MSIL
|
|| (der.clr.Flags & COMIMAGE_FLAGS_32BITREQUIRED) != 0) { // Or 32BIT Required MSIL
|
||||||
|
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -677,30 +855,30 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
if (der.pclr != NULL) {
|
if (der.pclr != NULL) {
|
||||||
DETOUR_CLR_HEADER clr;
|
DETOUR_CLR_HEADER clr;
|
||||||
CopyMemory(&clr, &der.clr, sizeof(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;
|
DWORD dwProtect;
|
||||||
if (!DetourVirtualProtectSameExecuteEx(hProcess, der.pclr, sizeof(clr), PAGE_READWRITE, &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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, der.pclr, &clr, sizeof(clr), NULL)) {
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!VirtualProtectEx(hProcess, der.pclr, sizeof(clr), dwProtect, &dwProtect)) {
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr));
|
DETOUR_TRACE(("CLR: %p..%p\n", der.pclr, der.pclr + der.cbclr));
|
||||||
|
|
||||||
#if DETOURS_64BIT
|
#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.
|
// X64 never gets here because the process appears as a WOW64 process.
|
||||||
// However, on IA64, it doesn't appear to be a WOW 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);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -710,7 +888,7 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
//////////////////////////////// Save the undo data to the target process.
|
//////////////////////////////// Save the undo data to the target process.
|
||||||
//
|
//
|
||||||
if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) {
|
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 FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -834,9 +1012,23 @@ BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName,
|
||||||
|
|
||||||
BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
_In_ REFGUID rguid,
|
_In_ REFGUID rguid,
|
||||||
_In_reads_bytes_(cbData) PVOID pvData,
|
_In_reads_bytes_(cbData) LPCVOID pvData,
|
||||||
_In_ DWORD cbData)
|
_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) +
|
DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) +
|
||||||
sizeof(IMAGE_NT_HEADERS) +
|
sizeof(IMAGE_NT_HEADERS) +
|
||||||
sizeof(IMAGE_SECTION_HEADER) +
|
sizeof(IMAGE_SECTION_HEADER) +
|
||||||
|
@ -847,10 +1039,15 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal,
|
PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal,
|
||||||
MEM_COMMIT, PAGE_READWRITE);
|
MEM_COMMIT, PAGE_READWRITE);
|
||||||
if (pbBase == NULL) {
|
if (pbBase == NULL) {
|
||||||
DETOUR_TRACE(("VirtualAllocEx(%d) failed: %d\n", cbTotal, GetLastError()));
|
DETOUR_TRACE(("VirtualAllocEx(%lu) failed: %lu\n", cbTotal, GetLastError()));
|
||||||
return FALSE;
|
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;
|
PBYTE pbTarget = pbBase;
|
||||||
IMAGE_DOS_HEADER idh;
|
IMAGE_DOS_HEADER idh;
|
||||||
IMAGE_NT_HEADERS inh;
|
IMAGE_NT_HEADERS inh;
|
||||||
|
@ -864,8 +1061,8 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
idh.e_lfanew = sizeof(idh);
|
idh.e_lfanew = sizeof(idh);
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) ||
|
||||||
cbWrote != sizeof(idh)) {
|
cbWrote != sizeof(idh)) {
|
||||||
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError()));
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(idh);
|
pbTarget += sizeof(idh);
|
||||||
|
|
||||||
|
@ -877,7 +1074,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
inh.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
|
inh.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) ||
|
||||||
cbWrote != sizeof(inh)) {
|
cbWrote != sizeof(inh)) {
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(inh);
|
pbTarget += sizeof(inh);
|
||||||
|
|
||||||
|
@ -889,7 +1086,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
cbData);
|
cbData);
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) ||
|
||||||
cbWrote != sizeof(ish)) {
|
cbWrote != sizeof(ish)) {
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(ish);
|
pbTarget += sizeof(ish);
|
||||||
|
|
||||||
|
@ -902,7 +1099,7 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
cbData);
|
cbData);
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) ||
|
||||||
cbWrote != sizeof(dsh)) {
|
cbWrote != sizeof(dsh)) {
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(dsh);
|
pbTarget += sizeof(dsh);
|
||||||
|
|
||||||
|
@ -912,19 +1109,20 @@ BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
dsr.guid = rguid;
|
dsr.guid = rguid;
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) ||
|
||||||
cbWrote != sizeof(dsr)) {
|
cbWrote != sizeof(dsr)) {
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
pbTarget += sizeof(dsr);
|
pbTarget += sizeof(dsr);
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pbTarget, pvData, cbData, &cbWrote) ||
|
if (!WriteProcessMemory(hProcess, pbTarget, pvData, cbData, &cbWrote) ||
|
||||||
cbWrote != cbData) {
|
cbWrote != cbData) {
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
pbTarget += cbData;
|
|
||||||
|
|
||||||
DETOUR_TRACE(("Copied %d byte payload into target process at %p\n",
|
DETOUR_TRACE(("Copied %lu byte payload into target process at %p\n",
|
||||||
cbTotal, pbTarget - cbTotal));
|
cbData, pbTarget));
|
||||||
return TRUE;
|
|
||||||
|
SetLastError(NO_ERROR);
|
||||||
|
return pbTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL s_fSearchedForHelper = FALSE;
|
static BOOL s_fSearchedForHelper = FALSE;
|
||||||
|
@ -949,7 +1147,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
|
|
||||||
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, s_pHelper->pid);
|
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, s_pHelper->pid);
|
||||||
if (hProcess == NULL) {
|
if (hProcess == NULL) {
|
||||||
DETOUR_TRACE(("OpenProcess(pid=%d) failed: %d\n",
|
DETOUR_TRACE(("OpenProcess(pid=%lu) failed: %lu\n",
|
||||||
s_pHelper->pid, GetLastError()));
|
s_pHelper->pid, GetLastError()));
|
||||||
Result = 9901;
|
Result = 9901;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -970,7 +1168,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DetourUpdateProcessWithDll(hProcess, rlpDlls, s_pHelper->nDlls)) {
|
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()));
|
s_pHelper->pid, GetLastError()));
|
||||||
Result = 9903;
|
Result = 9903;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -983,6 +1181,15 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
rlpDlls = NULL;
|
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);
|
ExitProcess(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1146,7 +1353,7 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
DWORD nLen = GetEnvironmentVariableA("WINDIR", szExe, ARRAYSIZE(szExe));
|
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) {
|
if (nDlls < 1 || nDlls > 4096) {
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -1172,8 +1379,10 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
|
||||||
goto Cleanup;
|
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),
|
hr = StringCchPrintfA(szCommand, ARRAYSIZE(szCommand),
|
||||||
"rundll32.exe \"%hs\",#1", &helper->rDlls[0]);
|
"rundll32.exe \"%s\",#1", &helper->rDlls[0]);
|
||||||
if (!SUCCEEDED(hr)) {
|
if (!SUCCEEDED(hr)) {
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
@ -1189,7 +1398,7 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
|
||||||
if (!DetourCopyPayloadToProcess(pi.hProcess,
|
if (!DetourCopyPayloadToProcess(pi.hProcess,
|
||||||
DETOUR_EXE_HELPER_GUID,
|
DETOUR_EXE_HELPER_GUID,
|
||||||
helper, helper->cb)) {
|
helper, helper->cb)) {
|
||||||
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError()));
|
||||||
TerminateProcess(pi.hProcess, ~0u);
|
TerminateProcess(pi.hProcess, ~0u);
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
@ -1206,13 +1415,13 @@ BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
|
||||||
if (dwResult != 0) {
|
if (dwResult != 0) {
|
||||||
DETOUR_TRACE(("Rundll32.exe failed: result=%d\n", dwResult));
|
DETOUR_TRACE(("Rundll32.exe failed: result=%lu\n", dwResult));
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
Result = TRUE;
|
Result = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DETOUR_TRACE(("CreateProcess failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("CreateProcess failed: %lu\n", GetLastError()));
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1240,9 +1449,11 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
|
||||||
WCHAR szCommand[MAX_PATH];
|
WCHAR szCommand[MAX_PATH];
|
||||||
PDETOUR_EXE_HELPER helper = NULL;
|
PDETOUR_EXE_HELPER helper = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
WCHAR szDllName[MAX_PATH];
|
||||||
|
int cchWrittenWideChar;
|
||||||
DWORD nLen = GetEnvironmentVariableW(L"WINDIR", szExe, ARRAYSIZE(szExe));
|
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) {
|
if (nDlls < 1 || nDlls > 4096) {
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
@ -1268,8 +1479,15 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
|
||||||
goto Cleanup;
|
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),
|
hr = StringCchPrintfW(szCommand, ARRAYSIZE(szCommand),
|
||||||
L"rundll32.exe \"%hs\",#1", &helper->rDlls[0]);
|
L"rundll32.exe \"%s\",#1", szDllName);
|
||||||
if (!SUCCEEDED(hr)) {
|
if (!SUCCEEDED(hr)) {
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
@ -1285,15 +1503,13 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
|
||||||
if (!DetourCopyPayloadToProcess(pi.hProcess,
|
if (!DetourCopyPayloadToProcess(pi.hProcess,
|
||||||
DETOUR_EXE_HELPER_GUID,
|
DETOUR_EXE_HELPER_GUID,
|
||||||
helper, helper->cb)) {
|
helper, helper->cb)) {
|
||||||
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %lu\n", GetLastError()));
|
||||||
TerminateProcess(pi.hProcess, ~0u);
|
TerminateProcess(pi.hProcess, ~0u);
|
||||||
CloseHandle(pi.hProcess);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResumeThread(pi.hThread);
|
|
||||||
|
|
||||||
ResumeThread(pi.hThread);
|
ResumeThread(pi.hThread);
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
@ -1304,13 +1520,13 @@ BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
|
||||||
if (dwResult != 0) {
|
if (dwResult != 0) {
|
||||||
DETOUR_TRACE(("Rundll32.exe failed: result=%d\n", dwResult));
|
DETOUR_TRACE(("Rundll32.exe failed: result=%lu\n", dwResult));
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
Result = TRUE;
|
Result = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DETOUR_TRACE(("CreateProcess failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("CreateProcess failed: %lu\n", GetLastError()));
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,27 @@
|
||||||
|
|
||||||
#define NOTHROW
|
#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
|
struct _DETOUR_ALIGN
|
||||||
|
@ -186,7 +207,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
// We have to place trampolines within +/- 2GB of code.
|
// We have to place trampolines within +/- 2GB of code.
|
||||||
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
||||||
ULONG_PTR hi = detour_2gb_above((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.
|
// And, within +/- 2GB of relative jmp targets.
|
||||||
if (pbCode[0] == 0xe9) { // jmp +imm32
|
if (pbCode[0] == 0xe9) { // jmp +imm32
|
||||||
|
@ -198,7 +219,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
else {
|
else {
|
||||||
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
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;
|
*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.
|
// We have to place trampolines within +/- 2GB of code.
|
||||||
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
||||||
ULONG_PTR hi = detour_2gb_above((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.
|
// And, within +/- 2GB of relative jmp vectors.
|
||||||
if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
|
if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
|
||||||
|
@ -411,7 +432,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
else {
|
else {
|
||||||
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
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.
|
// And, within +/- 2GB of relative jmp targets.
|
||||||
else if (pbCode[0] == 0xe9) { // jmp +imm32
|
else if (pbCode[0] == 0xe9) { // jmp +imm32
|
||||||
|
@ -423,7 +444,7 @@ inline void detour_find_jmp_bounds(PBYTE pbCode,
|
||||||
else {
|
else {
|
||||||
lo = detour_2gb_below((ULONG_PTR)pbNew);
|
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;
|
*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.
|
// We have to place trampolines within +/- 2GB of code.
|
||||||
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
ULONG_PTR lo = detour_2gb_below((ULONG_PTR)pbCode);
|
||||||
ULONG_PTR hi = detour_2gb_above((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;
|
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
||||||
*ppUpper = (PDETOUR_TRAMPOLINE)hi;
|
*ppUpper = (PDETOUR_TRAMPOLINE)hi;
|
||||||
|
@ -863,7 +884,7 @@ struct _DETOUR_TRAMPOLINE
|
||||||
// An ARM64 instruction is 4 bytes long.
|
// An ARM64 instruction is 4 bytes long.
|
||||||
//
|
//
|
||||||
// The overwrite is always composed of 3 instructions (12 bytes) which perform an indirect jump
|
// 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.
|
// 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 lo = detour_2gb_below((ULONG_PTR)pbCode);
|
||||||
ULONG_PTR hi = detour_2gb_above((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;
|
*ppLower = (PDETOUR_TRAMPOLINE)lo;
|
||||||
*ppUpper = (PDETOUR_TRAMPOLINE)hi;
|
*ppUpper = (PDETOUR_TRAMPOLINE)hi;
|
||||||
|
@ -1237,7 +1258,7 @@ static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE((" Try %p => %p..%p %6x\n",
|
DETOUR_TRACE((" Try %p => %p..%p %6lx\n",
|
||||||
pbTry,
|
pbTry,
|
||||||
mbi.BaseAddress,
|
mbi.BaseAddress,
|
||||||
(PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
|
(PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
|
||||||
|
@ -1252,6 +1273,9 @@ static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi)
|
||||||
if (pv != NULL) {
|
if (pv != NULL) {
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
|
else if (GetLastError() == ERROR_DYNAMIC_CODE_BLOCKED) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pbTry += DETOUR_REGION_SIZE;
|
pbTry += DETOUR_REGION_SIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1284,7 +1308,7 @@ static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE((" Try %p => %p..%p %6x\n",
|
DETOUR_TRACE((" Try %p => %p..%p %6lx\n",
|
||||||
pbTry,
|
pbTry,
|
||||||
mbi.BaseAddress,
|
mbi.BaseAddress,
|
||||||
(PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
|
(PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
|
||||||
|
@ -1299,6 +1323,9 @@ static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi)
|
||||||
if (pv != NULL) {
|
if (pv != NULL) {
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
|
else if (GetLastError() == ERROR_DYNAMIC_CODE_BLOCKED) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pbTry -= DETOUR_REGION_SIZE;
|
pbTry -= DETOUR_REGION_SIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1698,7 +1725,7 @@ LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer)
|
||||||
#endif // DETOURS_ARM
|
#endif // DETOURS_ARM
|
||||||
}
|
}
|
||||||
else {
|
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,
|
||||||
o->pTrampoline->pbRemain,
|
o->pTrampoline->pbRemain,
|
||||||
o->pTrampoline->pbDetour,
|
o->pTrampoline->pbDetour,
|
||||||
|
@ -1990,13 +2017,13 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
|
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;
|
return ERROR_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any of the pending operations failed, then we don't need to do this.
|
// If any of the pending operations failed, then we don't need to do this.
|
||||||
if (s_nPendingError != NO_ERROR) {
|
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;
|
return s_nPendingError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2177,7 +2204,7 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
|
||||||
pTrampoline->rAlign[n].obTrampoline == 0) {
|
pTrampoline->rAlign[n].obTrampoline == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE((" %d/%d",
|
DETOUR_TRACE((" %u/%u",
|
||||||
pTrampoline->rAlign[n].obTarget,
|
pTrampoline->rAlign[n].obTarget,
|
||||||
pTrampoline->rAlign[n].obTrampoline
|
pTrampoline->rAlign[n].obTrampoline
|
||||||
));
|
));
|
||||||
|
@ -2545,4 +2572,20 @@ BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress,
|
||||||
pAddress, nSize, dwNewProtect, pdwOldProtect);
|
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
|
// End of File
|
||||||
|
|
|
@ -28,6 +28,15 @@
|
||||||
#pragma warning(disable:4091) // empty typedef
|
#pragma warning(disable:4091) // empty typedef
|
||||||
#endif
|
#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>
|
#include <windows.h>
|
||||||
#if (_MSC_VER < 1310)
|
#if (_MSC_VER < 1310)
|
||||||
#else
|
#else
|
||||||
|
@ -36,8 +45,28 @@
|
||||||
#pragma warning(disable:6102 6103) // /analyze warnings
|
#pragma warning(disable:6102 6103) // /analyze warnings
|
||||||
#endif
|
#endif
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
#include <intsafe.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#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
|
#endif // DETOURS_INTERNAL
|
||||||
|
|
||||||
|
@ -99,7 +128,7 @@
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
||||||
#if (_MSC_VER < 1299)
|
#if (_MSC_VER < 1299) && !defined(__MINGW32__)
|
||||||
typedef LONG LONG_PTR;
|
typedef LONG LONG_PTR;
|
||||||
typedef ULONG ULONG_PTR;
|
typedef ULONG ULONG_PTR;
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,6 +149,7 @@ typedef ULONG ULONG_PTR;
|
||||||
#undef _In_
|
#undef _In_
|
||||||
#undef _In_bytecount_
|
#undef _In_bytecount_
|
||||||
#undef _In_count_
|
#undef _In_count_
|
||||||
|
#undef __in_ecount
|
||||||
#undef _In_opt_
|
#undef _In_opt_
|
||||||
#undef _In_opt_bytecount_
|
#undef _In_opt_bytecount_
|
||||||
#undef _In_opt_count_
|
#undef _In_opt_count_
|
||||||
|
@ -176,6 +206,10 @@ typedef ULONG ULONG_PTR;
|
||||||
#define _In_count_(x)
|
#define _In_count_(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __in_ecount
|
||||||
|
#define __in_ecount(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _In_opt_
|
#ifndef _In_opt_
|
||||||
#define _In_opt_
|
#define _In_opt_
|
||||||
#endif
|
#endif
|
||||||
|
@ -581,16 +615,17 @@ _Readable_bytes_(*pcbData)
|
||||||
_Success_(return != NULL)
|
_Success_(return != NULL)
|
||||||
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
||||||
_In_ REFGUID rguid,
|
_In_ REFGUID rguid,
|
||||||
_Out_ DWORD *pcbData);
|
_Out_opt_ DWORD *pcbData);
|
||||||
|
|
||||||
_Writable_bytes_(*pcbData)
|
_Writable_bytes_(*pcbData)
|
||||||
_Readable_bytes_(*pcbData)
|
_Readable_bytes_(*pcbData)
|
||||||
_Success_(return != NULL)
|
_Success_(return != NULL)
|
||||||
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
||||||
_Out_ DWORD * pcbData);
|
_Out_opt_ DWORD *pcbData);
|
||||||
|
|
||||||
DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule);
|
DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule);
|
||||||
|
|
||||||
|
BOOL WINAPI DetourFreePayload(_In_ PVOID pvData);
|
||||||
///////////////////////////////////////////////// Persistent Binary Functions.
|
///////////////////////////////////////////////// Persistent Binary Functions.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -629,6 +664,11 @@ BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary);
|
||||||
|
|
||||||
/////////////////////////////////////////////////// Create Process & Load Dll.
|
/////////////////////////////////////////////////// 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)(
|
typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)(
|
||||||
_In_opt_ LPCSTR lpApplicationName,
|
_In_opt_ LPCSTR lpApplicationName,
|
||||||
_Inout_opt_ LPSTR lpCommandLine,
|
_Inout_opt_ LPSTR lpCommandLine,
|
||||||
|
@ -795,8 +835,14 @@ BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
|
||||||
|
|
||||||
BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
|
||||||
_In_ REFGUID rguid,
|
_In_ REFGUID rguid,
|
||||||
_In_reads_bytes_(cbData) PVOID pvData,
|
_In_reads_bytes_(cbData) LPCVOID pvData,
|
||||||
_In_ DWORD cbData);
|
_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 DetourRestoreAfterWith(VOID);
|
||||||
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
||||||
_In_ DWORD cbData);
|
_In_ DWORD cbData);
|
||||||
|
@ -812,6 +858,60 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
}
|
}
|
||||||
#endif // __cplusplus
|
#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.
|
//////////////////////////////////////////////// Detours Internal Definitions.
|
||||||
//
|
//
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -822,7 +922,7 @@ VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
#if (_MSC_VER < 1299)
|
#if (_MSC_VER < 1299) && !defined(__GNUC__)
|
||||||
#include <imagehlp.h>
|
#include <imagehlp.h>
|
||||||
typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64;
|
typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64;
|
||||||
typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64;
|
typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64;
|
||||||
|
@ -884,6 +984,21 @@ PDETOUR_SYM_INFO DetourLoadImageHlp(VOID);
|
||||||
#endif
|
#endif
|
||||||
#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
|
#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
|
#ifndef DETOUR_TRACE
|
||||||
#if DETOUR_DEBUG
|
#if DETOUR_DEBUG
|
||||||
#define DETOUR_TRACE(x) printf x
|
#define DETOUR_TRACE(x) printf x
|
||||||
|
@ -1090,6 +1205,9 @@ BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress,
|
||||||
_In_ SIZE_T nSize,
|
_In_ SIZE_T nSize,
|
||||||
_In_ DWORD dwNewProtect,
|
_In_ DWORD dwNewProtect,
|
||||||
_Out_ PDWORD pdwOldProtect);
|
_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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif // __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;
|
DWORD m_cbAlloc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CImageImportName;
|
||||||
|
|
||||||
class CImageImportFile
|
class CImageImportFile
|
||||||
{
|
{
|
||||||
friend class CImage;
|
friend class CImage;
|
||||||
|
@ -534,18 +536,7 @@ PBYTE CImageData::Find(REFGUID rguid, DWORD *pcbData)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pRecord->guid.Data1 == rguid.Data1 &&
|
if (DetourAreSameGuid(pRecord->guid, rguid)) {
|
||||||
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]) {
|
|
||||||
|
|
||||||
*pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD);
|
*pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD);
|
||||||
return (PBYTE)(pRecord + 1);
|
return (PBYTE)(pRecord + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
const GUID DETOUR_EXE_RESTORE_GUID = {
|
const GUID DETOUR_EXE_RESTORE_GUID = {
|
||||||
0x2ed7a3ff, 0x3339, 0x4a8d,
|
0xbda26f34, 0xbc82, 0x4829,
|
||||||
{ 0x80, 0x5c, 0xd4, 0x98, 0x15, 0x3f, 0xc2, 0x8f }};
|
{ 0x9e, 0x64, 0x74, 0x2c, 0x4, 0xc8, 0x4f, 0xa0 } };
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -142,6 +142,11 @@ PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
|
||||||
PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
_In_ LPCSTR pszFunction)
|
_In_ LPCSTR pszFunction)
|
||||||
{
|
{
|
||||||
|
if (pszFunction == NULL) {
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////// First, try GetProcAddress.
|
/////////////////////////////////////////////// First, try GetProcAddress.
|
||||||
//
|
//
|
||||||
#pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.")
|
#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));
|
DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction));
|
||||||
PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
|
PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
|
||||||
if (pSymInfo == NULL) {
|
if (pSymInfo == NULL) {
|
||||||
DETOUR_TRACE(("DetourLoadImageHlp failed: %d\n",
|
DETOUR_TRACE(("DetourLoadImageHlp failed: %lu\n",
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +174,7 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
(PCHAR)pszModule, NULL,
|
(PCHAR)pszModule, NULL,
|
||||||
(DWORD64)hModule, 0) == 0) {
|
(DWORD64)hModule, 0) == 0) {
|
||||||
if (ERROR_SUCCESS != GetLastError()) {
|
if (ERROR_SUCCESS != GetLastError()) {
|
||||||
DETOUR_TRACE(("SymLoadModule64(%p) failed: %d\n",
|
DETOUR_TRACE(("SymLoadModule64(%p) failed: %lu\n",
|
||||||
pSymInfo->hProcess, GetLastError()));
|
pSymInfo->hProcess, GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -181,24 +186,24 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
ZeroMemory(&modinfo, sizeof(modinfo));
|
ZeroMemory(&modinfo, sizeof(modinfo));
|
||||||
modinfo.SizeOfStruct = sizeof(modinfo);
|
modinfo.SizeOfStruct = sizeof(modinfo);
|
||||||
if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &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()));
|
pSymInfo->hProcess, hModule, GetLastError()));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
|
hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("StringCchCopyA failed: %08x\n", hrRet));
|
DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
|
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
|
DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
|
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
|
DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +220,7 @@ PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +282,7 @@ HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetLastError(NO_ERROR);
|
||||||
return (HMODULE)pDosHeader;
|
return (HMODULE)pDosHeader;
|
||||||
}
|
}
|
||||||
#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.")
|
#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);
|
SetLastError(NO_ERROR);
|
||||||
return GetProcAddress(hClr, "_CorExeMain");
|
return (PVOID)GetProcAddress(hClr, "_CorExeMain");
|
||||||
}
|
}
|
||||||
|
|
||||||
SetLastError(NO_ERROR);
|
SetLastError(NO_ERROR);
|
||||||
|
@ -456,6 +462,11 @@ BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule,
|
||||||
_In_opt_ PVOID pContext,
|
_In_opt_ PVOID pContext,
|
||||||
_In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
|
_In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
|
||||||
{
|
{
|
||||||
|
if (pfExport == NULL) {
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
||||||
if (hModule == NULL) {
|
if (hModule == NULL) {
|
||||||
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(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_FILE_CALLBACK pfImportFile,
|
||||||
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
|
_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 };
|
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc };
|
||||||
|
|
||||||
return DetourEnumerateImportsEx(hModule,
|
return DetourEnumerateImportsEx(hModule,
|
||||||
|
@ -761,7 +777,7 @@ _Readable_bytes_(*pcbData)
|
||||||
_Success_(return != NULL)
|
_Success_(return != NULL)
|
||||||
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
||||||
_In_ REFGUID rguid,
|
_In_ REFGUID rguid,
|
||||||
_Out_ DWORD *pcbData)
|
_Out_opt_ DWORD *pcbData)
|
||||||
{
|
{
|
||||||
PBYTE pbData = NULL;
|
PBYTE pbData = NULL;
|
||||||
if (pcbData) {
|
if (pcbData) {
|
||||||
|
@ -789,23 +805,12 @@ PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
|
||||||
for (pbData = pbBeg; pbData < pbEnd;) {
|
for (pbData = pbBeg; pbData < pbEnd;) {
|
||||||
DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
|
DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
|
||||||
|
|
||||||
if (pSection->guid.Data1 == rguid.Data1 &&
|
if (DetourAreSameGuid(pSection->guid, rguid)) {
|
||||||
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 (pcbData) {
|
if (pcbData) {
|
||||||
*pcbData = pSection->cbBytes - sizeof(*pSection);
|
*pcbData = pSection->cbBytes - sizeof(*pSection);
|
||||||
SetLastError(NO_ERROR);
|
|
||||||
return (PBYTE)(pSection + 1);
|
|
||||||
}
|
}
|
||||||
|
SetLastError(NO_ERROR);
|
||||||
|
return (PBYTE)(pSection + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pbData = (PBYTE)pSection + pSection->cbBytes;
|
pbData = (PBYTE)pSection + pSection->cbBytes;
|
||||||
|
@ -824,7 +829,7 @@ _Writable_bytes_(*pcbData)
|
||||||
_Readable_bytes_(*pcbData)
|
_Readable_bytes_(*pcbData)
|
||||||
_Success_(return != NULL)
|
_Success_(return != NULL)
|
||||||
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
||||||
_Out_ DWORD * pcbData)
|
_Out_opt_ DWORD *pcbData)
|
||||||
{
|
{
|
||||||
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
|
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
|
||||||
PVOID pvData;
|
PVOID pvData;
|
||||||
|
@ -838,6 +843,24 @@ PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
|
||||||
return NULL;
|
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,
|
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
||||||
_In_ DWORD cbData)
|
_In_ DWORD cbData)
|
||||||
{
|
{
|
||||||
|
@ -884,6 +907,11 @@ BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
|
||||||
}
|
}
|
||||||
VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
|
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;
|
return fSucceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead)
|
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead)
|
||||||
|| cbRead < sizeof(idh)) {
|
|| 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()));
|
pbModule, pbModule + sizeof(idh), GetLastError()));
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
|
@ -51,7 +51,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
|
|
||||||
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead)
|
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead)
|
||||||
|| cbRead < sizeof(inh)) {
|
|| 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,
|
||||||
pbModule + idh.e_lfanew + sizeof(inh),
|
pbModule + idh.e_lfanew + sizeof(inh),
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
|
@ -82,16 +82,21 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
sizeof(ish), &cbRead)
|
sizeof(ish), &cbRead)
|
||||||
|| cbRead < sizeof(ish)) {
|
|| 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,
|
||||||
pbModule + dwSec + sizeof(ish) * (i + 1),
|
pbModule + dwSec + sizeof(ish) * (i + 1),
|
||||||
GetLastError()));
|
GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_TRACE(("ish[%d] : va=%08x sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData));
|
DETOUR_TRACE(("ish[%lu] : va=%08lx sr=%lu\n", i, ish.VirtualAddress, ish.SizeOfRawData));
|
||||||
|
|
||||||
// If the file didn't have an IAT_DIRECTORY, we assign it...
|
// 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 &&
|
if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
|
||||||
inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
|
inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
|
||||||
inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
|
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",
|
DETOUR_TRACE((" Imports: %p..%p\n",
|
||||||
(DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
||||||
(DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
|
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
|
||||||
inh.IMPORT_DIRECTORY.Size));
|
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 nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
|
||||||
DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls;
|
DWORD obRem;
|
||||||
DWORD obOld = obRem + sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls;
|
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 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;
|
DWORD obStr = obDll;
|
||||||
cbNew = obStr;
|
cbNew = obStr;
|
||||||
for (n = 0; n < nDlls; n++) {
|
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];
|
pbNew = new BYTE [cbNew];
|
||||||
if (pbNew == NULL) {
|
if (pbNew == NULL) {
|
||||||
DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
|
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;
|
PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
|
||||||
DWORD_XX *pt;
|
IMAGE_THUNK_DATAXX *pt = NULL;
|
||||||
|
|
||||||
DWORD obBase = (DWORD)(pbNewIid - pbModule);
|
DWORD obBase = (DWORD)(pbNewIid - pbModule);
|
||||||
DWORD dwProtect = 0;
|
DWORD dwProtect = 0;
|
||||||
|
|
||||||
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) {
|
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) {
|
||||||
// Read the old import directory if it exists.
|
// 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,
|
if (!ReadProcessMemory(hProcess,
|
||||||
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
|
||||||
|
@ -160,7 +218,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead)
|
nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead)
|
||||||
|| cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
|
|| cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
|
||||||
|
|
||||||
DETOUR_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("ReadProcessMemory(imports) failed: %lu\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +226,7 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
for (n = 0; n < nDlls; n++) {
|
for (n = 0; n < nDlls; n++) {
|
||||||
HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
|
HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("StringCchCopyA failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,21 +235,24 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
cbNew - obStr,
|
cbNew - obStr,
|
||||||
DETOURS_STRINGIFY(DETOURS_BITS_XX));
|
DETOURS_STRINGIFY(DETOURS_BITS_XX));
|
||||||
if (FAILED(hrRet)) {
|
if (FAILED(hrRet)) {
|
||||||
DETOUR_TRACE(("ReplaceOptionalSizeA failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("ReplaceOptionalSizeA failed: %08lx\n", hrRet));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD nOffset = obTab + (sizeof(DWORD_XX) * (4 * n));
|
DWORD nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * (4 * n));
|
||||||
piid[n].OriginalFirstThunk = obBase + nOffset;
|
piid[n].OriginalFirstThunk = obBase + nOffset;
|
||||||
pt = ((DWORD_XX*)(pbNew + nOffset));
|
|
||||||
pt[0] = IMAGE_ORDINAL_FLAG_XX + 1;
|
// We need 2 thunks for the import table and 2 thunks for the IAT.
|
||||||
pt[1] = 0;
|
// 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;
|
piid[n].FirstThunk = obBase + nOffset;
|
||||||
pt = ((DWORD_XX*)(pbNew + nOffset));
|
pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
|
||||||
pt[0] = IMAGE_ORDINAL_FLAG_XX + 1;
|
pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
|
||||||
pt[1] = 0;
|
pt[1].u1.Ordinal = 0;
|
||||||
piid[n].TimeDateStamp = 0;
|
piid[n].TimeDateStamp = 0;
|
||||||
piid[n].ForwarderChain = 0;
|
piid[n].ForwarderChain = 0;
|
||||||
piid[n].Name = obBase + obStr;
|
piid[n].Name = obBase + obStr;
|
||||||
|
@ -216,16 +277,19 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
|
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;
|
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.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
|
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) {
|
if (inh.IAT_DIRECTORY.VirtualAddress == 0) {
|
||||||
inh.IAT_DIRECTORY.VirtualAddress = obBase;
|
inh.IAT_DIRECTORY.VirtualAddress = obBase;
|
||||||
inh.IAT_DIRECTORY.Size = cbNew;
|
inh.IAT_DIRECTORY.Size = cbNew;
|
||||||
|
@ -238,20 +302,20 @@ static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
|
||||||
//
|
//
|
||||||
if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
||||||
PAGE_EXECUTE_READWRITE, &dwProtect)) {
|
PAGE_EXECUTE_READWRITE, &dwProtect)) {
|
||||||
DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %lu\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
inh.OptionalHeader.CheckSum = 0;
|
inh.OptionalHeader.CheckSum = 0;
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
|
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;
|
goto finish;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh)));
|
DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh)));
|
||||||
|
|
||||||
if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
|
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;
|
goto finish;
|
||||||
}
|
}
|
||||||
DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n",
|
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,
|
if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
|
||||||
dwProtect, &dwProtect)) {
|
dwProtect, &dwProtect)) {
|
||||||
DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %d\n", GetLastError()));
|
DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %lu\n", GetLastError()));
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue