| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878 |
- //////////////////////////////////////////////////////////////////////////////
- //
- // Create a process with a DLL (creatwth.cpp of detours.lib)
- //
- // Microsoft Research Detours Package, Version 2.1.
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- #include <windows.h>
- #include <stddef.h>
- #if (_MSC_VER < 1299)
- typedef DWORD DWORD_PTR;
- #endif
- #if (_MSC_VER < 1310)
- #else
- #include <strsafe.h>
- #endif
- //#define DETOUR_DEBUG 1
- #define DETOURS_INTERNAL
- #include "detours.h"
- #define IMPORT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
- #define BOUND_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]
- #define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
- #define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]
- //////////////////////////////////////////////////////////////////////////////
- //
- #ifndef _STRSAFE_H_INCLUDED_
- static inline HRESULT StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch)
- {
- HRESULT hr = S_OK;
- size_t cchMaxPrev = cchMax;
- if (cchMax > 2147483647)
- {
- return ERROR_INVALID_PARAMETER;
- }
- while (cchMax && (*psz != '\0'))
- {
- psz++;
- cchMax--;
- }
- if (cchMax == 0)
- {
- // the string is longer than cchMax
- hr = ERROR_INVALID_PARAMETER;
- }
- if (SUCCEEDED(hr) && pcch)
- {
- *pcch = cchMaxPrev - cchMax;
- }
- return hr;
- }
- static inline HRESULT StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc)
- {
- HRESULT hr = S_OK;
- if (cchDest == 0)
- {
- // can not null terminate a zero-byte dest buffer
- hr = ERROR_INVALID_PARAMETER;
- }
- else
- {
- while (cchDest && (*pszSrc != '\0'))
- {
- *pszDest++ = *pszSrc++;
- cchDest--;
- }
- if (cchDest == 0)
- {
- // we are going to truncate pszDest
- pszDest--;
- hr = ERROR_INVALID_PARAMETER;
- }
- *pszDest= '\0';
- }
- return hr;
- }
- static inline HRESULT StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc)
- {
- HRESULT hr;
- size_t cchDestCurrent;
- if (cchDest > 2147483647)
- {
- return ERROR_INVALID_PARAMETER;
- }
- hr = StringCchLengthA(pszDest, cchDest, &cchDestCurrent);
- if (SUCCEEDED(hr))
- {
- hr = StringCchCopyA(pszDest + cchDestCurrent,
- cchDest - cchDestCurrent,
- pszSrc);
- }
- return hr;
- }
- #endif
- //////////////////////////////////////////////////////////////////////////////
- //
- static WORD detour_sum_minus(WORD wSum, WORD wMinus)
- {
- wSum = (WORD)(wSum - ((wSum < wMinus) ? 1 : 0));
- wSum = (WORD)(wSum - wMinus);
- return wSum;
- }
- static WORD detour_sum_done(DWORD PartialSum)
- {
- // Fold final carry into a single word result and return the resultant value.
- return (WORD)(((PartialSum >> 16) + PartialSum) & 0xffff);
- }
- static WORD detour_sum_data(DWORD dwSum, PBYTE pbData, DWORD cbData)
- {
- while (cbData > 0) {
- dwSum += *((PWORD&)pbData)++;
- dwSum = (dwSum >> 16) + (dwSum & 0xffff);
- cbData -= sizeof(WORD);
- }
- return detour_sum_done(dwSum);
- }
- static WORD detour_sum_final(WORD wSum, PIMAGE_NT_HEADERS pinh)
- {
- DETOUR_TRACE((".... : %08x (value: %08x)\n", wSum, pinh->OptionalHeader.CheckSum));
- // Subtract the two checksum words in the optional header from the computed.
- wSum = detour_sum_minus(wSum, ((PWORD)(&pinh->OptionalHeader.CheckSum))[0]);
- wSum = detour_sum_minus(wSum, ((PWORD)(&pinh->OptionalHeader.CheckSum))[1]);
- return wSum;
- }
- static WORD ChkSumRange(WORD wSum, HANDLE hProcess, PBYTE pbBeg, PBYTE pbEnd)
- {
- BYTE rbPage[4096];
- while (pbBeg < pbEnd) {
- if (!ReadProcessMemory(hProcess, pbBeg, rbPage, sizeof(rbPage), NULL)) {
- DETOUR_TRACE(("ReadProcessMemory(idh) failed: %d\n", GetLastError()));
- break;
- }
- wSum = detour_sum_data(wSum, rbPage, sizeof(rbPage));
- pbBeg += sizeof(rbPage);
- }
- return wSum;
- }
- static WORD ComputeChkSum(HANDLE hProcess, PBYTE pbModule, PIMAGE_NT_HEADERS pinh)
- {
- // See LdrVerifyMappedImageMatchesChecksum.
- MEMORY_BASIC_INFORMATION mbi;
- ZeroMemory(&mbi, sizeof(mbi));
- WORD wSum = 0;
- for (PBYTE pbLast = pbModule;;
- pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
- if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) <= 0) {
- if (GetLastError() == ERROR_INVALID_PARAMETER) {
- break;
- }
- DETOUR_TRACE(("VirtualQueryEx(%08x) failed: %d\n",
- pbLast, GetLastError()));
- break;
- }
- if (mbi.AllocationBase != pbModule) {
- break;
- }
- wSum = ChkSumRange(wSum,
- hProcess,
- (PBYTE)mbi.BaseAddress,
- (PBYTE)mbi.BaseAddress + mbi.RegionSize);
- DETOUR_TRACE(("[%8p..%8p] : %04x\n",
- (PBYTE)mbi.BaseAddress,
- (PBYTE)mbi.BaseAddress + mbi.RegionSize,
- wSum));
- }
- return detour_sum_final(wSum, pinh);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Find a region of memory in which we can create a replacement import table.
- //
- static PBYTE FindAndAllocateNearBase(HANDLE hProcess, PBYTE pbBase, DWORD cbAlloc)
- {
- MEMORY_BASIC_INFORMATION mbi;
- ZeroMemory(&mbi, sizeof(mbi));
- for (PBYTE pbLast = pbBase;;
- pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
- if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) <= 0) {
- if (GetLastError() == ERROR_INVALID_PARAMETER) {
- break;
- }
- DETOUR_TRACE(("VirtualQueryEx(%08x) failed: %d\n",
- pbLast, GetLastError()));
- break;
- }
- // Skip uncommitted regions and guard pages.
- //
- if ((mbi.State != MEM_FREE)) {
- continue;
- }
- PBYTE pbAddress = (PBYTE)(((DWORD_PTR)mbi.BaseAddress + 0xffff) & ~(DWORD_PTR)0xffff);
- DETOUR_TRACE(("Free region %p..%p\n",
- mbi.BaseAddress,
- (PBYTE)mbi.BaseAddress + mbi.RegionSize));
- for (; pbAddress < (PBYTE)mbi.BaseAddress + mbi.RegionSize; pbAddress += 0x10000) {
- PBYTE pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc,
- MEM_RESERVE, PAGE_READWRITE);
- if (pbAlloc == NULL) {
- DETOUR_TRACE(("VirtualAllocEx(%p) failed: %d\n", pbAddress, GetLastError()));
- continue;
- }
- pbAlloc = (PBYTE)VirtualAllocEx(hProcess, pbAddress, cbAlloc,
- MEM_COMMIT, PAGE_READWRITE);
- if (pbAlloc == NULL) {
- DETOUR_TRACE(("VirtualAllocEx(%p) failed: %d\n", pbAddress, GetLastError()));
- continue;
- }
- DETOUR_TRACE(("[%p..%p] Allocated for import table.\n",
- pbAlloc, pbAlloc + cbAlloc));
- return pbAlloc;
- }
- }
- return NULL;
- }
- static inline DWORD PadToDword(DWORD dw)
- {
- return (dw + 3) & ~3u;
- }
- static inline DWORD PadToDwordPtr(DWORD dw)
- {
- return (dw + 7) & ~7u;
- }
- static BOOL IsExe(HANDLE hProcess, PBYTE pbModule)
- {
- IMAGE_DOS_HEADER idh;
- ZeroMemory(&idh, sizeof(idh));
- if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
- DETOUR_TRACE(("ReadProcessMemory(idh) failed: %d\n", GetLastError()));
- return FALSE;
- }
- if (idh.e_magic != IMAGE_DOS_SIGNATURE) {
- // DETOUR_TRACE((" No IMAGE_DOS_SIGNATURE\n"));
- return FALSE;
- }
- IMAGE_NT_HEADERS inh;
- ZeroMemory(&inh, sizeof(inh));
- if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
- DETOUR_TRACE(("ReadProcessMemory(inh) failed: %d\n", GetLastError()));
- return FALSE;
- }
- if (inh.Signature != IMAGE_NT_SIGNATURE) {
- DETOUR_TRACE((" No IMAGE_NT_SIGNATURE\n"));
- return FALSE;
- }
- if (inh.FileHeader.Characteristics & IMAGE_FILE_DLL) {
- DETOUR_TRACE((" Characteristics: %08x\n", inh.FileHeader.Characteristics));
- return FALSE;
- }
- return TRUE;
- }
- PVOID FindExe(HANDLE hProcess)
- {
- MEMORY_BASIC_INFORMATION mbi;
- ZeroMemory(&mbi, sizeof(mbi));
- // Find the next memory region that contains a mapped PE image.
- //
- for (PBYTE pbLast = (PBYTE)0x10000;;
- pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
- if (VirtualQueryEx(hProcess, (PVOID)pbLast, &mbi, sizeof(mbi)) <= 0) {
- if (GetLastError() == ERROR_INVALID_PARAMETER) {
- break;
- }
- DETOUR_TRACE(("VirtualQueryEx(%08x) failed: %d\n",
- pbLast, GetLastError()));
- break;
- }
- // Skip uncommitted regions and guard pages.
- //
- if ((mbi.State != MEM_COMMIT) || (mbi.Protect & PAGE_GUARD)) {
- continue;
- }
- DETOUR_TRACE(("%8p..%8p [%8p]\n",
- mbi.BaseAddress,
- (PBYTE)mbi.BaseAddress + mbi.RegionSize,
- mbi.AllocationBase));
- if (IsExe(hProcess, pbLast)) {
- #if DETOUR_DEBUG
- for (PBYTE pbNext = (PBYTE)mbi.BaseAddress + mbi.RegionSize;;
- pbNext = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
- if (VirtualQueryEx(hProcess, (PVOID)pbNext, &mbi, sizeof(mbi)) <= 0) {
- if (GetLastError() == ERROR_INVALID_PARAMETER) {
- break;
- }
- DETOUR_TRACE(("VirtualQueryEx(%08x) failed: %d\n",
- pbNext, GetLastError()));
- break;
- }
- // Skip uncommitted regions and guard pages.
- //
- if ((mbi.State != MEM_COMMIT) || (mbi.Protect & PAGE_GUARD)) {
- continue;
- }
- DETOUR_TRACE(("%8p..%8p [%8p]\n",
- mbi.BaseAddress,
- (PBYTE)mbi.BaseAddress + mbi.RegionSize,
- mbi.AllocationBase));
- IsExe(hProcess, pbNext);
- }
- #endif
- return pbLast;
- }
- }
- return NULL;
- }
- static BOOL UpdateImports(HANDLE hProcess, LPCSTR *plpDlls, DWORD nDlls)
- {
- BOOL fSucceeded = FALSE;
- BYTE * pbNew = NULL;
- DETOUR_EXE_RESTORE der;
- DWORD i;
- ZeroMemory(&der, sizeof(der));
- der.cb = sizeof(der);
- PBYTE pbModule = (PBYTE)FindExe(hProcess);
- IMAGE_DOS_HEADER idh;
- ZeroMemory(&idh, sizeof(idh));
- if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
- DETOUR_TRACE(("ReadProcessMemory(idh) failed: %d\n", GetLastError()));
- finish:
- if (pbNew != NULL) {
- delete[] pbNew;
- pbNew = NULL;
- }
- return fSucceeded;
- }
- CopyMemory(&der.idh, &idh, sizeof(idh));
- der.pidh = (PIMAGE_DOS_HEADER)pbModule;
- if (idh.e_magic != IMAGE_DOS_SIGNATURE) {
- goto finish;
- }
- IMAGE_NT_HEADERS inh;
- ZeroMemory(&inh, sizeof(inh));
- if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
- DETOUR_TRACE(("ReadProcessMemory(inh) failed: %d\n", GetLastError()));
- goto finish;
- }
- CopyMemory(&der.inh, &inh, sizeof(inh));
- der.pinh = (PIMAGE_NT_HEADERS)(pbModule + idh.e_lfanew);
- if (inh.Signature != IMAGE_NT_SIGNATURE) {
- goto finish;
- }
- if (inh.IMPORT_DIRECTORY.VirtualAddress == 0) {
- DETOUR_TRACE(("No IMAGE_DIRECTORY_ENTRY_IMPORT\n"));
- goto finish;
- }
- // Zero out the bound table so loader doesn't use it instead of our new table.
- inh.BOUND_DIRECTORY.VirtualAddress = 0;
- inh.BOUND_DIRECTORY.Size = 0;
- // Find the size of the mapped file.
- DWORD dwFileSize = 0;
- DWORD dwSec = idh.e_lfanew +
- FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) +
- inh.FileHeader.SizeOfOptionalHeader;
- for (i = 0; i < inh.FileHeader.NumberOfSections; i++) {
- IMAGE_SECTION_HEADER ish;
- ZeroMemory(&ish, sizeof(ish));
- if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish,
- sizeof(ish), NULL)) {
- DETOUR_TRACE(("ReadProcessMemory(inh) failed: %d\n", GetLastError()));
- goto finish;
- }
- DETOUR_TRACE(("ish[%d] : va=%p sr=%d\n", i, ish.VirtualAddress, ish.SizeOfRawData));
- // If the file didn't have an IAT_DIRECTORY, we create one...
- if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
- inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
- inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
- inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress;
- inh.IAT_DIRECTORY.Size = ish.SizeOfRawData;
- }
- // Find the end of the file...
- if (dwFileSize < ish.PointerToRawData + ish.SizeOfRawData) {
- dwFileSize = ish.PointerToRawData + ish.SizeOfRawData;
- }
- }
- DETOUR_TRACE(("dwFileSize = %08x\n", dwFileSize));
- // Find the current checksum.
- WORD wBefore = ComputeChkSum(hProcess, pbModule, &inh);
- DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wBefore, dwFileSize, wBefore + dwFileSize));
- DETOUR_TRACE((" Imports: %8p..%8p\n",
- (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
- (DWORD_PTR)pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
- inh.IMPORT_DIRECTORY.Size));
- DWORD obRem = sizeof(IMAGE_IMPORT_DESCRIPTOR) * nDlls;
- DWORD obTab = PadToDwordPtr(obRem + inh.IMPORT_DIRECTORY.Size);
- DWORD obDll = obTab + sizeof(DWORD_PTR) * 4 * nDlls;
- DWORD obStr = obDll;
- DWORD cbNew = obStr;
- DWORD n;
- for (n = 0; n < nDlls; n++) {
- cbNew += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
- }
- pbNew = new BYTE [cbNew];
- if (pbNew == NULL) {
- DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
- goto finish;
- }
- ZeroMemory(pbNew, cbNew);
- PBYTE pbBase = pbModule;
- PBYTE pbNext = pbBase
- + inh.OptionalHeader.BaseOfCode
- + inh.OptionalHeader.SizeOfCode
- + inh.OptionalHeader.SizeOfInitializedData
- + inh.OptionalHeader.SizeOfUninitializedData;
- if (pbBase < pbNext) {
- pbBase = pbNext;
- }
- DETOUR_TRACE(("pbBase = %p\n", pbBase));
- PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbBase, cbNew);
- if (pbNewIid == NULL) {
- DETOUR_TRACE(("FindAndAllocateNearBase failed.\n"));
- goto finish;
- }
- DWORD dwProtect = 0;
- der.impDirProt = 0;
- if (!VirtualProtectEx(hProcess,
- pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
- inh.IMPORT_DIRECTORY.Size, PAGE_EXECUTE_READWRITE, &dwProtect)) {
- DETOUR_TRACE(("VirtualProtextEx(import) write failed: %d\n", GetLastError()));
- goto finish;
- }
- DETOUR_TRACE(("IMPORT_DIRECTORY perms=%x\n", dwProtect));
- der.impDirProt = dwProtect;
- DWORD obBase = (DWORD)(pbNewIid - pbModule);
- if (!ReadProcessMemory(hProcess,
- pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
- pbNew + obRem,
- inh.IMPORT_DIRECTORY.Size, NULL)) {
- DETOUR_TRACE(("ReadProcessMemory(imports) failed: %d\n", GetLastError()));
- goto finish;
- }
- PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
- DWORD_PTR *pt;
- for (n = 0; n < nDlls; n++) {
- HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
- if (FAILED(hrRet))
- {
- DETOUR_TRACE(("StringCchCopyA failed: %d\n", GetLastError()));
- goto finish;
- }
- DWORD nOffset = obTab + (sizeof(DWORD_PTR) * (4 * n));
- piid[n].OriginalFirstThunk = obBase + nOffset;
- pt = ((DWORD_PTR*)(pbNew + nOffset));
- pt[0] = IMAGE_ORDINAL_FLAG + 1;
- pt[1] = 0;
- nOffset = obTab + (sizeof(DWORD_PTR) * ((4 * n) + 2));
- piid[n].FirstThunk = obBase + nOffset;
- pt = ((DWORD_PTR*)(pbNew + nOffset));
- pt[0] = IMAGE_ORDINAL_FLAG + 1;
- pt[1] = 0;
- piid[n].TimeDateStamp = 0;
- piid[n].ForwarderChain = 0;
- piid[n].Name = obBase + obStr;
- obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
- }
- for (i = 0; i < nDlls + (inh.IMPORT_DIRECTORY.Size / sizeof(*piid)); i++) {
- DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n",
- i,
- piid[i].OriginalFirstThunk,
- piid[i].TimeDateStamp,
- piid[i].ForwarderChain,
- piid[i].Name,
- piid[i].FirstThunk));
- if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) {
- break;
- }
- }
- if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
- DETOUR_TRACE(("WriteProcessMemory(iid) failed: %d\n", GetLastError()));
- goto finish;
- }
- DETOUR_TRACE(("obBase = %p..%p\n",
- inh.IMPORT_DIRECTORY.VirtualAddress,
- inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
- DETOUR_TRACE(("obBase = %p..%p\n", obBase, obBase + obStr));
- inh.IMPORT_DIRECTORY.VirtualAddress = obBase;
- inh.IMPORT_DIRECTORY.Size = cbNew;
- /////////////////////////////////////////////////// Update the CLR header.
- //
- if (inh.CLR_DIRECTORY.VirtualAddress != 0 &&
- inh.CLR_DIRECTORY.Size != 0) {
- DETOUR_CLR_HEADER clr;
- PBYTE pbClr = pbModule + inh.CLR_DIRECTORY.VirtualAddress;
- if (!ReadProcessMemory(hProcess, pbClr, &clr, sizeof(clr), NULL)) {
- DETOUR_TRACE(("ReadProcessMemory(clr) failed: %d\n", GetLastError()));
- goto finish;
- }
- der.pclrFlags = (PULONG)(pbClr + offsetof(DETOUR_CLR_HEADER, Flags));
- der.clrFlags = clr.Flags;
- clr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag.
- if (!VirtualProtectEx(hProcess, pbClr, sizeof(clr), PAGE_READWRITE, &dwProtect)) {
- DETOUR_TRACE(("VirtualProtextEx(clr) write failed: %d\n", GetLastError()));
- goto finish;
- }
- if (!WriteProcessMemory(hProcess, pbClr, &clr, sizeof(clr), NULL)) {
- DETOUR_TRACE(("WriteProcessMemory(clr) failed: %d\n", GetLastError()));
- goto finish;
- }
- if (!VirtualProtectEx(hProcess, pbClr, sizeof(clr), dwProtect, &dwProtect)) {
- DETOUR_TRACE(("VirtualProtextEx(clr) restore failed: %d\n", GetLastError()));
- goto finish;
- }
- }
- /////////////////////// Update the NT header for the import new directory.
- /////////////////////////////// Update the DOS header to fix the checksum.
- //
- if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
- PAGE_EXECUTE_READWRITE, &dwProtect)) {
- DETOUR_TRACE(("VirtualProtextEx(inh) write failed: %d\n", GetLastError()));
- goto finish;
- }
- idh.e_res[0] = 0;
- if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
- DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
- goto finish;
- }
- if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
- DETOUR_TRACE(("WriteProcessMemory(inh) failed: %d\n", GetLastError()));
- goto finish;
- }
- WORD wDuring = ComputeChkSum(hProcess, pbModule, &inh);
- DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wDuring, dwFileSize, wDuring + dwFileSize));
- idh.e_res[0] = detour_sum_minus(idh.e_res[0], detour_sum_minus(wDuring, wBefore));
- if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
- DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
- goto finish;
- }
- if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
- dwProtect, &dwProtect)) {
- DETOUR_TRACE(("VirtualProtextEx(idh) restore failed: %d\n", GetLastError()));
- goto finish;
- }
- WORD wAfter = ComputeChkSum(hProcess, pbModule, &inh);
- DETOUR_TRACE(("ChkSum: %04x + %08x => %08x\n", wAfter, dwFileSize, wAfter + dwFileSize));
- DETOUR_TRACE(("Before: %08x, After: %08x\n", wBefore + dwFileSize, wAfter + dwFileSize));
- if (wBefore != wAfter) {
- DETOUR_TRACE(("Restore of checksum failed %04x != %04x.\n", wBefore, wAfter));
- goto finish;
- }
- if (!DetourCopyPayloadToProcess(hProcess, DETOUR_EXE_RESTORE_GUID, &der, sizeof(der))) {
- DETOUR_TRACE(("DetourCopyPayloadToProcess failed: %d\n", GetLastError()));
- goto finish;
- }
- fSucceeded = TRUE;
- goto finish;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- BOOL WINAPI DetourCreateProcessWithDllA(LPCSTR lpApplicationName,
- __in_z LPSTR lpCommandLine,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- LPVOID lpEnvironment,
- LPCSTR lpCurrentDirectory,
- LPSTARTUPINFOA lpStartupInfo,
- LPPROCESS_INFORMATION lpProcessInformation,
- LPCSTR lpDetouredDllFullName,
- LPCSTR lpDllName,
- PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA)
- {
- DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED);
- PROCESS_INFORMATION pi;
- if (pfCreateProcessA == NULL) {
- pfCreateProcessA = CreateProcessA;
- }
- if (!pfCreateProcessA(lpApplicationName,
- lpCommandLine,
- lpProcessAttributes,
- lpThreadAttributes,
- bInheritHandles,
- dwMyCreationFlags,
- lpEnvironment,
- lpCurrentDirectory,
- lpStartupInfo,
- &pi)) {
- return FALSE;
- }
- LPCSTR rlpDlls[2];
- DWORD nDlls = 0;
- if (lpDetouredDllFullName != NULL) {
- rlpDlls[nDlls++] = lpDetouredDllFullName;
- }
- if (lpDllName != NULL) {
- rlpDlls[nDlls++] = lpDllName;
- }
- if (!UpdateImports(pi.hProcess, rlpDlls, nDlls)) {
- return FALSE;
- }
- if (lpProcessInformation) {
- CopyMemory(lpProcessInformation, &pi, sizeof(pi));
- }
- if (!(dwCreationFlags & CREATE_SUSPENDED)) {
- ResumeThread(pi.hThread);
- }
- return TRUE;
- }
- BOOL WINAPI DetourCreateProcessWithDllW(LPCWSTR lpApplicationName,
- __in_z LPWSTR lpCommandLine,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- LPVOID lpEnvironment,
- LPCWSTR lpCurrentDirectory,
- LPSTARTUPINFOW lpStartupInfo,
- LPPROCESS_INFORMATION lpProcessInformation,
- LPCSTR lpDetouredDllFullName,
- LPCSTR lpDllName,
- PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW)
- {
- DWORD dwMyCreationFlags = (dwCreationFlags | CREATE_SUSPENDED);
- PROCESS_INFORMATION pi;
- if (pfCreateProcessW == NULL) {
- pfCreateProcessW = CreateProcessW;
- }
- if (!pfCreateProcessW(lpApplicationName,
- lpCommandLine,
- lpProcessAttributes,
- lpThreadAttributes,
- bInheritHandles,
- dwMyCreationFlags,
- lpEnvironment,
- lpCurrentDirectory,
- lpStartupInfo,
- &pi)) {
- return FALSE;
- }
- LPCSTR rlpDlls[2];
- DWORD nDlls = 0;
- if (lpDetouredDllFullName != NULL) {
- rlpDlls[nDlls++] = lpDetouredDllFullName;
- }
- if (lpDllName != NULL) {
- rlpDlls[nDlls++] = lpDllName;
- }
- if (!UpdateImports(pi.hProcess, rlpDlls, nDlls)) {
- return FALSE;
- }
- if (lpProcessInformation) {
- CopyMemory(lpProcessInformation, &pi, sizeof(pi));
- }
- if (!(dwCreationFlags & CREATE_SUSPENDED)) {
- ResumeThread(pi.hThread);
- }
- return TRUE;
- }
- BOOL WINAPI DetourCopyPayloadToProcess(HANDLE hProcess,
- REFGUID rguid,
- PVOID pData,
- DWORD cbData)
- {
- DWORD cbTotal = (sizeof(IMAGE_DOS_HEADER) +
- sizeof(IMAGE_NT_HEADERS) +
- sizeof(IMAGE_SECTION_HEADER) +
- sizeof(DETOUR_SECTION_HEADER) +
- sizeof(DETOUR_SECTION_RECORD) +
- cbData);
- PBYTE pbBase = (PBYTE)VirtualAllocEx(hProcess, NULL, cbTotal,
- MEM_COMMIT, PAGE_READWRITE);
- if (pbBase == NULL) {
- DETOUR_TRACE(("VirtualAllocEx(%d) failed: %d\n", cbTotal, GetLastError()));
- return FALSE;
- }
- PBYTE pbTarget = pbBase;
- IMAGE_DOS_HEADER idh;
- IMAGE_NT_HEADERS inh;
- IMAGE_SECTION_HEADER ish;
- DETOUR_SECTION_HEADER dsh;
- DETOUR_SECTION_RECORD dsr;
- SIZE_T cbWrote = 0;
- ZeroMemory(&idh, sizeof(idh));
- idh.e_magic = IMAGE_DOS_SIGNATURE;
- idh.e_lfanew = sizeof(idh);
- if (!WriteProcessMemory(hProcess, pbTarget, &idh, sizeof(idh), &cbWrote) ||
- cbWrote != sizeof(idh)) {
- DETOUR_TRACE(("WriteProcessMemory(idh) failed: %d\n", GetLastError()));
- return FALSE;
- }
- pbTarget += sizeof(idh);
- ZeroMemory(&inh, sizeof(inh));
- inh.Signature = IMAGE_NT_SIGNATURE;
- inh.FileHeader.SizeOfOptionalHeader = sizeof(inh.OptionalHeader);
- inh.FileHeader.Characteristics = IMAGE_FILE_DLL;
- inh.FileHeader.NumberOfSections = 1;
- if (!WriteProcessMemory(hProcess, pbTarget, &inh, sizeof(inh), &cbWrote) ||
- cbWrote != sizeof(inh)) {
- return FALSE;
- }
- pbTarget += sizeof(inh);
- ZeroMemory(&ish, sizeof(ish));
- memcpy(ish.Name, ".detour", sizeof(ish.Name));
- ish.VirtualAddress = (DWORD)((pbTarget + sizeof(ish)) - pbBase);
- ish.SizeOfRawData = (sizeof(DETOUR_SECTION_HEADER) +
- sizeof(DETOUR_SECTION_RECORD) +
- cbData);
- if (!WriteProcessMemory(hProcess, pbTarget, &ish, sizeof(ish), &cbWrote) ||
- cbWrote != sizeof(ish)) {
- return FALSE;
- }
- pbTarget += sizeof(ish);
- ZeroMemory(&dsh, sizeof(dsh));
- dsh.cbHeaderSize = sizeof(dsh);
- dsh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE;
- dsh.nDataOffset = sizeof(DETOUR_SECTION_HEADER);
- dsh.cbDataSize = (sizeof(DETOUR_SECTION_HEADER) +
- sizeof(DETOUR_SECTION_RECORD) +
- cbData);
- if (!WriteProcessMemory(hProcess, pbTarget, &dsh, sizeof(dsh), &cbWrote) ||
- cbWrote != sizeof(dsh)) {
- return FALSE;
- }
- pbTarget += sizeof(dsh);
- ZeroMemory(&dsr, sizeof(dsr));
- dsr.cbBytes = cbData + sizeof(DETOUR_SECTION_RECORD);
- dsr.nReserved = 0;
- dsr.guid = rguid;
- if (!WriteProcessMemory(hProcess, pbTarget, &dsr, sizeof(dsr), &cbWrote) ||
- cbWrote != sizeof(dsr)) {
- return FALSE;
- }
- pbTarget += sizeof(dsr);
- if (!WriteProcessMemory(hProcess, pbTarget, pData, cbData, &cbWrote) ||
- cbWrote != cbData) {
- return FALSE;
- }
- pbTarget += cbData;
- DETOUR_TRACE(("Copied %d bytes into target process at %p\n",
- cbTotal, pbTarget - cbTotal));
- return TRUE;
- }
- //
- ///////////////////////////////////////////////////////////////// End of File.
|