Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/byakugan/detours/image.cpp
Views: 11779
//////////////////////////////////////////////////////////////////////////////1//2// Image manipulation functions (image.cpp of detours.lib)3//4// Microsoft Research Detours Package, Version 2.1.5//6// Copyright (c) Microsoft Corporation. All rights reserved.7//8// Used for for payloads, byways, and imports.9//1011#include <windows.h>12#if (_MSC_VER < 1310)13#else14#include <strsafe.h>15#endif1617#if (_MSC_VER < 1299)18#pragma warning(disable: 4710)19#else20#endif2122//#define DETOUR_DEBUG 123#define DETOURS_INTERNAL2425#include "detours.h"2627namespace Detour28{29//////////////////////////////////////////////////////////////////////////////30//31#ifndef _STRSAFE_H_INCLUDED_32static inline HRESULT StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch)33{34HRESULT hr = S_OK;35size_t cchMaxPrev = cchMax;3637if (cchMax > 2147483647)38{39return ERROR_INVALID_PARAMETER;40}4142while (cchMax && (*psz != '\0'))43{44psz++;45cchMax--;46}4748if (cchMax == 0)49{50// the string is longer than cchMax51hr = ERROR_INVALID_PARAMETER;52}5354if (SUCCEEDED(hr) && pcch)55{56*pcch = cchMaxPrev - cchMax;57}5859return hr;60}616263static inline HRESULT StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc)64{65HRESULT hr = S_OK;6667if (cchDest == 0)68{69// can not null terminate a zero-byte dest buffer70hr = ERROR_INVALID_PARAMETER;71}72else73{74while (cchDest && (*pszSrc != '\0'))75{76*pszDest++ = *pszSrc++;77cchDest--;78}7980if (cchDest == 0)81{82// we are going to truncate pszDest83pszDest--;84hr = ERROR_INVALID_PARAMETER;85}8687*pszDest= '\0';88}8990return hr;91}9293static inline HRESULT StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc)94{95HRESULT hr;96size_t cchDestCurrent;9798if (cchDest > 2147483647)99{100return ERROR_INVALID_PARAMETER;101}102103hr = StringCchLengthA(pszDest, cchDest, &cchDestCurrent);104105if (SUCCEEDED(hr))106{107hr = StringCchCopyA(pszDest + cchDestCurrent,108cchDest - cchDestCurrent,109pszSrc);110}111112return hr;113}114115#endif116117///////////////////////////////////////////////////////////////////////////////118//119class CImageData120{121friend class CImage;122123public:124CImageData(PBYTE pbData, DWORD cbData);125~CImageData();126127PBYTE Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator);128PBYTE Find(REFGUID rguid, DWORD *pcbData);129PBYTE Set(REFGUID rguid, PBYTE pbData, DWORD cbData);130131BOOL Delete(REFGUID rguid);132BOOL Purge();133134BOOL IsEmpty() { return m_cbData == 0; }135BOOL IsValid();136137protected:138BOOL SizeTo(DWORD cbData);139140protected:141PBYTE m_pbData;142DWORD m_cbData;143DWORD m_cbAlloc;144};145146class CImageImportFile147{148friend class CImage;149friend class CImageImportName;150151public:152CImageImportFile();153~CImageImportFile();154155public:156CImageImportFile * m_pNextFile;157BOOL m_fByway;158159CImageImportName * m_pImportNames;160DWORD m_nImportNames;161162DWORD m_rvaOriginalFirstThunk;163DWORD m_rvaFirstThunk;164165DWORD m_nForwarderChain;166PCHAR m_pszOrig;167PCHAR m_pszName;168};169170class CImageImportName171{172friend class CImage;173friend class CImageImportFile;174175public:176CImageImportName();177~CImageImportName();178179public:180WORD m_nHint;181ULONG m_nOrig;182ULONG m_nOrdinal;183PCHAR m_pszOrig;184PCHAR m_pszName;185};186187class CImage188{189friend class CImageThunks;190friend class CImageChars;191friend class CImageImportFile;192friend class CImageImportName;193194public:195CImage();196~CImage();197198static CImage * IsValid(PDETOUR_BINARY pBinary);199200public: // File Functions201BOOL Read(HANDLE hFile);202BOOL Write(HANDLE hFile);203BOOL Close();204205public: // Manipulation Functions206PBYTE DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator);207PBYTE DataFind(REFGUID rguid, DWORD *pcbData);208PBYTE DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData);209BOOL DataDelete(REFGUID rguid);210BOOL DataPurge();211212BOOL EditImports(PVOID pContext,213PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,214PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,215PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,216PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback);217218protected:219BOOL WriteFile(HANDLE hFile,220LPCVOID lpBuffer,221DWORD nNumberOfBytesToWrite,222LPDWORD lpNumberOfBytesWritten);223BOOL CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData);224BOOL ZeroFileData(HANDLE hFile, DWORD cbData);225BOOL AlignFileData(HANDLE hFile);226227BOOL SizeOutputBuffer(DWORD cbData);228PBYTE AllocateOutput(DWORD cbData, DWORD *pnVirtAddr);229230PVOID RvaToVa(ULONG_PTR nRva);231DWORD RvaToFileOffset(DWORD nRva);232233DWORD FileAlign(DWORD nAddr);234DWORD SectionAlign(DWORD nAddr);235236BOOL CheckImportsNeeded(DWORD *pnTables,237DWORD *pnThunks,238DWORD *pnChars);239240CImageImportFile * NewByway(__in_z PCHAR pszName);241242private:243DWORD m_dwValidSignature;244CImageData * m_pImageData; // Read & Write245246HANDLE m_hMap; // Read & Write247PBYTE m_pMap; // Read & Write248249DWORD m_nNextFileAddr; // Write250DWORD m_nNextVirtAddr; // Write251252IMAGE_DOS_HEADER m_DosHeader; // Read & Write253IMAGE_NT_HEADERS m_NtHeader; // Read & Write254IMAGE_SECTION_HEADER m_SectionHeaders[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];255256DWORD m_nPrePE;257DWORD m_cbPrePE;258DWORD m_cbPostPE;259260DWORD m_nPeOffset;261DWORD m_nSectionsOffset;262DWORD m_nExtraOffset;263DWORD m_nFileSize;264265DWORD m_nOutputVirtAddr;266DWORD m_nOutputVirtSize;267DWORD m_nOutputFileAddr;268269PBYTE m_pbOutputBuffer;270DWORD m_cbOutputBuffer;271272CImageImportFile * m_pImportFiles;273DWORD m_nImportFiles;274275BOOL m_fHadDetourSection;276277private:278enum {279DETOUR_IMAGE_VALID_SIGNATURE = 0xfedcba01, // "Dtr\0"280};281};282283//////////////////////////////////////////////////////////////////////////////284//285static BYTE s_rbDosCode[0x10] = {2860x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD,2870x21,0xB8,0x01,0x4C,0xCD,0x21,'*','*'288};289290static inline DWORD Max(DWORD a, DWORD b)291{292return a > b ? a : b;293}294295static inline DWORD Align(DWORD a, DWORD size)296{297size--;298return (a + size) & ~size;299}300301static inline DWORD QuadAlign(DWORD a)302{303return Align(a, 8);304}305306static PCHAR DuplicateString(__in_z PCHAR pszIn)307{308if (pszIn) {309UINT nIn = (UINT)strlen(pszIn);310PCHAR pszOut = new CHAR [nIn + 1];311if (pszOut == NULL) {312SetLastError(ERROR_OUTOFMEMORY);313}314else {315CopyMemory(pszOut, pszIn, nIn + 1);316}317return pszOut;318}319return NULL;320}321322static PCHAR ReplaceString(__deref_out PCHAR *ppsz, __in_z PCHAR pszIn)323{324if (ppsz == NULL) {325return NULL;326}327328UINT nIn;329if (*ppsz != NULL) {330if (strcmp(*ppsz, pszIn) == 0) {331return *ppsz;332}333nIn = (UINT)strlen(pszIn);334335if (strlen(*ppsz) == nIn) {336CopyMemory(*ppsz, pszIn, nIn + 1);337return *ppsz;338}339else {340delete[] *ppsz;341*ppsz = NULL;342}343}344else {345nIn = (UINT)strlen(pszIn);346}347348*ppsz = new CHAR [nIn + 1];349if (*ppsz == NULL) {350SetLastError(ERROR_OUTOFMEMORY);351}352else {353CopyMemory(*ppsz, pszIn, nIn + 1);354}355return *ppsz;356}357358//////////////////////////////////////////////////////////////////////////////359//360CImageImportFile::CImageImportFile()361{362m_pNextFile = NULL;363m_fByway = FALSE;364365m_pImportNames = NULL;366m_nImportNames = 0;367368m_rvaOriginalFirstThunk = 0;369m_rvaFirstThunk = 0;370371m_nForwarderChain = (UINT)0;372m_pszName = NULL;373m_pszOrig = NULL;374}375376CImageImportFile::~CImageImportFile()377{378if (m_pNextFile) {379delete m_pNextFile;380m_pNextFile = NULL;381}382if (m_pImportNames) {383delete[] m_pImportNames;384m_pImportNames = NULL;385m_nImportNames = 0;386}387if (m_pszName) {388delete[] m_pszName;389m_pszName = NULL;390}391if (m_pszOrig) {392delete[] m_pszOrig;393m_pszOrig = NULL;394}395}396397CImageImportName::CImageImportName()398{399m_nOrig = 0;400m_nOrdinal = 0;401m_nHint = 0;402m_pszName = NULL;403m_pszOrig = NULL;404}405406CImageImportName::~CImageImportName()407{408if (m_pszName) {409delete[] m_pszName;410m_pszName = NULL;411}412if (m_pszOrig) {413delete[] m_pszOrig;414m_pszOrig = NULL;415}416}417418//////////////////////////////////////////////////////////////////////////////419//420CImageData::CImageData(PBYTE pbData, DWORD cbData)421{422m_pbData = pbData;423m_cbData = cbData;424m_cbAlloc = 0;425}426427CImageData::~CImageData()428{429IsValid();430431if (m_cbAlloc == 0) {432m_pbData = NULL;433}434if (m_pbData) {435delete[] m_pbData;436m_pbData = NULL;437}438m_cbData = 0;439m_cbAlloc = 0;440}441442BOOL CImageData::SizeTo(DWORD cbData)443{444IsValid();445446if (cbData <= m_cbAlloc) {447return TRUE;448}449450PBYTE pbNew = new BYTE [cbData];451if (pbNew == NULL) {452SetLastError(ERROR_OUTOFMEMORY);453return FALSE;454}455456if (m_pbData) {457CopyMemory(pbNew, m_pbData, m_cbData);458if (m_cbAlloc > 0) {459delete[] m_pbData;460}461m_pbData = NULL;462}463m_pbData = pbNew;464m_cbAlloc = cbData;465466IsValid();467468return TRUE;469}470471BOOL CImageData::Purge()472{473m_cbData = 0;474475IsValid();476477return TRUE;478}479480BOOL CImageData::IsValid()481{482if (m_pbData == NULL) {483return TRUE;484}485486PBYTE pbBeg = m_pbData;487PBYTE pbEnd = m_pbData + m_cbData;488489for (PBYTE pbIter = pbBeg; pbIter < pbEnd;) {490PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)pbIter;491492if (pRecord->cbBytes < sizeof(DETOUR_SECTION_RECORD)) {493return FALSE;494}495if (pRecord->nReserved != 0) {496return FALSE;497}498499pbIter += pRecord->cbBytes;500}501return TRUE;502}503504PBYTE CImageData::Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator)505{506IsValid();507508if (pnIterator == NULL ||509m_cbData < *pnIterator + sizeof(DETOUR_SECTION_RECORD)) {510511if (pcbData) {512*pcbData = 0;513}514if (pGuid) {515ZeroMemory(pGuid, sizeof(*pGuid));516}517return NULL;518}519520PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + *pnIterator);521522if (pGuid) {523*pGuid = pRecord->guid;524}525if (pcbData) {526*pcbData = pRecord->cbBytes - sizeof(DETOUR_SECTION_RECORD);527}528*pnIterator = (LONG)(((PBYTE)pRecord - m_pbData) + pRecord->cbBytes);529530return (PBYTE)(pRecord + 1);531}532533PBYTE CImageData::Find(REFGUID rguid, DWORD *pcbData)534{535IsValid();536537DWORD cbBytes = sizeof(DETOUR_SECTION_RECORD);538for (DWORD nOffset = 0; nOffset < m_cbData; nOffset += cbBytes) {539PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + nOffset);540541cbBytes = pRecord->cbBytes;542if (cbBytes > m_cbData) {543break;544}545if (cbBytes < sizeof(DETOUR_SECTION_RECORD)) {546continue;547}548549if (pRecord->guid.Data1 == rguid.Data1 &&550pRecord->guid.Data2 == rguid.Data2 &&551pRecord->guid.Data3 == rguid.Data3 &&552pRecord->guid.Data4[0] == rguid.Data4[0] &&553pRecord->guid.Data4[1] == rguid.Data4[1] &&554pRecord->guid.Data4[2] == rguid.Data4[2] &&555pRecord->guid.Data4[3] == rguid.Data4[3] &&556pRecord->guid.Data4[4] == rguid.Data4[4] &&557pRecord->guid.Data4[5] == rguid.Data4[5] &&558pRecord->guid.Data4[6] == rguid.Data4[6] &&559pRecord->guid.Data4[7] == rguid.Data4[7]) {560561*pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD);562return (PBYTE)(pRecord + 1);563}564}565566if (pcbData) {567*pcbData = 0;568}569return NULL;570}571572BOOL CImageData::Delete(REFGUID rguid)573{574IsValid();575576PBYTE pbFound = NULL;577DWORD cbFound = 0;578579pbFound = Find(rguid, &cbFound);580if (pbFound == NULL) {581SetLastError(ERROR_MOD_NOT_FOUND);582return FALSE;583}584585pbFound -= sizeof(DETOUR_SECTION_RECORD);586cbFound += sizeof(DETOUR_SECTION_RECORD);587588PBYTE pbRestData = pbFound + cbFound;589DWORD cbRestData = m_cbData - (LONG)(pbRestData - m_pbData);590591if (cbRestData) {592MoveMemory(pbFound, pbRestData, cbRestData);593}594m_cbData -= cbFound;595596IsValid();597return TRUE;598}599600PBYTE CImageData::Set(REFGUID rguid, PBYTE pbData, DWORD cbData)601{602IsValid();603Delete(rguid);604605DWORD cbAlloc = QuadAlign(cbData);606607if (!SizeTo(m_cbData + cbAlloc + sizeof(DETOUR_SECTION_RECORD))) {608return NULL;609}610611PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + m_cbData);612pRecord->cbBytes = cbAlloc + sizeof(DETOUR_SECTION_RECORD);613pRecord->nReserved = 0;614pRecord->guid = rguid;615616PBYTE pbDest = (PBYTE)(pRecord + 1);617if (pbData) {618CopyMemory(pbDest, pbData, cbData);619if (cbData < cbAlloc) {620ZeroMemory(pbDest + cbData, cbAlloc - cbData);621}622}623else {624if (cbAlloc > 0) {625ZeroMemory(pbDest, cbAlloc);626}627}628629m_cbData += cbAlloc + sizeof(DETOUR_SECTION_RECORD);630631IsValid();632return pbDest;633}634635//////////////////////////////////////////////////////////////////////////////636//637class CImageThunks638{639private:640CImage * m_pImage;641PIMAGE_THUNK_DATA m_pThunks;642DWORD m_nThunks;643DWORD m_nThunksMax;644DWORD m_nThunkVirtAddr;645646public:647CImageThunks(CImage *pImage, DWORD nThunksMax, DWORD *pnAddr)648{649m_pImage = pImage;650m_nThunks = 0;651m_nThunksMax = nThunksMax;652m_pThunks = (PIMAGE_THUNK_DATA)653m_pImage->AllocateOutput(sizeof(IMAGE_THUNK_DATA) * nThunksMax,654&m_nThunkVirtAddr);655*pnAddr = m_nThunkVirtAddr;656}657658PIMAGE_THUNK_DATA Current(DWORD *pnVirtAddr)659{660if (m_nThunksMax > 1) {661*pnVirtAddr = m_nThunkVirtAddr;662return m_pThunks;663}664*pnVirtAddr = 0;665return NULL;666}667668PIMAGE_THUNK_DATA Allocate(ULONG_PTR nData, DWORD *pnVirtAddr)669{670if (m_nThunks < m_nThunksMax) {671*pnVirtAddr = m_nThunkVirtAddr;672673m_nThunks++;674m_nThunkVirtAddr += sizeof(IMAGE_THUNK_DATA);675m_pThunks->u1.Ordinal = nData;676return m_pThunks++;677}678*pnVirtAddr = 0;679return NULL;680}681682DWORD Size()683{684return m_nThunksMax * sizeof(IMAGE_THUNK_DATA);685}686};687688//////////////////////////////////////////////////////////////////////////////689//690class CImageChars691{692private:693CImage * m_pImage;694PCHAR m_pChars;695DWORD m_nChars;696DWORD m_nCharsMax;697DWORD m_nCharVirtAddr;698699public:700CImageChars(CImage *pImage, DWORD nCharsMax, DWORD *pnAddr)701{702m_pImage = pImage;703m_nChars = 0;704m_nCharsMax = nCharsMax;705m_pChars = (PCHAR)m_pImage->AllocateOutput(nCharsMax, &m_nCharVirtAddr);706*pnAddr = m_nCharVirtAddr;707}708709PCHAR Allocate(__in_z PCHAR pszString, DWORD *pnVirtAddr)710{711DWORD nLen = (DWORD)strlen(pszString) + 1;712nLen += (nLen & 1);713714if (m_nChars + nLen > m_nCharsMax) {715*pnVirtAddr = 0;716return NULL;717}718719*pnVirtAddr = m_nCharVirtAddr;720HRESULT hrRet = StringCchCopyA(m_pChars,m_nCharsMax, pszString);721722if (FAILED(hrRet)) {723return NULL;724}725726pszString = m_pChars;727728m_pChars += nLen;729m_nChars += nLen;730m_nCharVirtAddr += nLen;731732return pszString;733}734735PCHAR Allocate(PCHAR pszString, DWORD nHint, DWORD *pnVirtAddr)736{737DWORD nLen = (DWORD)strlen(pszString) + 1 + sizeof(USHORT);738nLen += (nLen & 1);739740if (m_nChars + nLen > m_nCharsMax) {741*pnVirtAddr = 0;742return NULL;743}744745*pnVirtAddr = m_nCharVirtAddr;746*(USHORT *)m_pChars = (USHORT)nHint;747748HRESULT hrRet = StringCchCopyA(m_pChars + sizeof(USHORT), m_nCharsMax, pszString);749if (FAILED(hrRet)) {750return NULL;751}752753pszString = m_pChars + sizeof(USHORT);754755m_pChars += nLen;756m_nChars += nLen;757m_nCharVirtAddr += nLen;758759return pszString;760}761762DWORD Size()763{764return m_nChars;765}766};767768//////////////////////////////////////////////////////////////////////////////769//770CImage * CImage::IsValid(PDETOUR_BINARY pBinary)771{772if (pBinary) {773CImage *pImage = (CImage *)pBinary;774775if (pImage->m_dwValidSignature == DETOUR_IMAGE_VALID_SIGNATURE) {776return pImage;777}778}779SetLastError(ERROR_INVALID_HANDLE);780return NULL;781}782783CImage::CImage()784{785m_dwValidSignature = (DWORD)DETOUR_IMAGE_VALID_SIGNATURE;786787m_hMap = NULL;788m_pMap = NULL;789790m_nPeOffset = 0;791m_nSectionsOffset = 0;792793m_pbOutputBuffer = NULL;794m_cbOutputBuffer = 0;795796m_pImageData = NULL;797798m_pImportFiles = NULL;799m_nImportFiles = 0;800801m_fHadDetourSection = FALSE;802}803804CImage::~CImage()805{806Close();807m_dwValidSignature = 0;808}809810BOOL CImage::Close()811{812if (m_pImportFiles) {813delete m_pImportFiles;814m_pImportFiles = NULL;815m_nImportFiles = 0;816}817818if (m_pImageData) {819delete m_pImageData;820m_pImageData = NULL;821}822823if (m_pMap != NULL) {824UnmapViewOfFile(m_pMap);825m_pMap = NULL;826}827828if (m_hMap) {829CloseHandle(m_hMap);830m_hMap = NULL;831}832833if (m_pbOutputBuffer) {834delete[] m_pbOutputBuffer;835m_pbOutputBuffer = NULL;836m_cbOutputBuffer = 0;837}838return TRUE;839}840841//////////////////////////////////////////////////////////////////////////////842//843PBYTE CImage::DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator)844{845if (m_pImageData == NULL) {846return NULL;847}848return m_pImageData->Enumerate(pGuid, pcbData, pnIterator);849}850851PBYTE CImage::DataFind(REFGUID rguid, DWORD *pcbData)852{853if (m_pImageData == NULL) {854return NULL;855}856return m_pImageData->Find(rguid, pcbData);857}858859PBYTE CImage::DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData)860{861if (m_pImageData == NULL) {862return NULL;863}864return m_pImageData->Set(rguid, pbData, cbData);865}866867BOOL CImage::DataDelete(REFGUID rguid)868{869if (m_pImageData == NULL) {870return FALSE;871}872return m_pImageData->Delete(rguid);873}874875BOOL CImage::DataPurge()876{877if (m_pImageData == NULL) {878return TRUE;879}880return m_pImageData->Purge();881}882883//////////////////////////////////////////////////////////////////////////////884//885BOOL CImage::SizeOutputBuffer(DWORD cbData)886{887if (m_cbOutputBuffer < cbData) {888if (cbData < 1024) {//65536889cbData = 1024;890}891cbData = FileAlign(cbData);892893PBYTE pOutput = new BYTE [cbData];894if (pOutput == NULL) {895SetLastError(ERROR_OUTOFMEMORY);896return FALSE;897}898899if (m_pbOutputBuffer) {900CopyMemory(pOutput, m_pbOutputBuffer, m_cbOutputBuffer);901902delete[] m_pbOutputBuffer;903m_pbOutputBuffer = NULL;904}905906ZeroMemory(pOutput + m_cbOutputBuffer, cbData - m_cbOutputBuffer),907908m_pbOutputBuffer = pOutput;909m_cbOutputBuffer = cbData;910}911return TRUE;912}913914PBYTE CImage::AllocateOutput(DWORD cbData, DWORD *pnVirtAddr)915{916cbData = QuadAlign(cbData);917918PBYTE pbData = m_pbOutputBuffer + m_nOutputVirtSize;919920*pnVirtAddr = m_nOutputVirtAddr + m_nOutputVirtSize;921m_nOutputVirtSize += cbData;922923if (m_nOutputVirtSize > m_cbOutputBuffer) {924SetLastError(ERROR_OUTOFMEMORY);925return NULL;926}927928ZeroMemory(pbData, cbData);929930return pbData;931}932933//////////////////////////////////////////////////////////////////////////////934//935DWORD CImage::FileAlign(DWORD nAddr)936{937return Align(nAddr, m_NtHeader.OptionalHeader.FileAlignment);938}939940DWORD CImage::SectionAlign(DWORD nAddr)941{942return Align(nAddr, m_NtHeader.OptionalHeader.SectionAlignment);943}944945//////////////////////////////////////////////////////////////////////////////946//947PVOID CImage::RvaToVa(ULONG_PTR nRva)948{949if (nRva == 0) {950return NULL;951}952953for (DWORD n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {954DWORD vaStart = m_SectionHeaders[n].VirtualAddress;955DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;956957if (nRva >= vaStart && nRva < vaEnd) {958return (PBYTE)m_pMap959+ m_SectionHeaders[n].PointerToRawData960+ nRva - m_SectionHeaders[n].VirtualAddress;961}962}963return NULL;964}965966DWORD CImage::RvaToFileOffset(DWORD nRva)967{968DWORD n;969for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {970DWORD vaStart = m_SectionHeaders[n].VirtualAddress;971DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;972973if (nRva >= vaStart && nRva < vaEnd) {974return m_SectionHeaders[n].PointerToRawData975+ nRva - m_SectionHeaders[n].VirtualAddress;976}977}978return 0;979}980981//////////////////////////////////////////////////////////////////////////////982//983BOOL CImage::WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,984LPDWORD lpNumberOfBytesWritten)985{986return ::WriteFile(hFile,987lpBuffer,988nNumberOfBytesToWrite,989lpNumberOfBytesWritten,990NULL);991}992993994BOOL CImage::CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData)995{996DWORD cbDone = 0;997return WriteFile(hFile, m_pMap + nOldPos, cbData, &cbDone);998}9991000BOOL CImage::ZeroFileData(HANDLE hFile, DWORD cbData)1001{1002if (!SizeOutputBuffer(4096)) {1003return FALSE;1004}10051006ZeroMemory(m_pbOutputBuffer, 4096);10071008for (DWORD cbLeft = cbData; cbLeft > 0;) {1009DWORD cbStep = cbLeft > sizeof(m_pbOutputBuffer)1010? sizeof(m_pbOutputBuffer) : cbLeft;1011DWORD cbDone = 0;10121013if (!WriteFile(hFile, m_pbOutputBuffer, cbStep, &cbDone)) {1014return FALSE;1015}1016if (cbDone == 0) {1017break;1018}10191020cbLeft -= cbDone;1021}1022return TRUE;1023}10241025BOOL CImage::AlignFileData(HANDLE hFile)1026{1027DWORD nLastFileAddr = m_nNextFileAddr;10281029m_nNextFileAddr = FileAlign(m_nNextFileAddr);1030m_nNextVirtAddr = SectionAlign(m_nNextVirtAddr);10311032if (hFile != INVALID_HANDLE_VALUE) {1033if (m_nNextFileAddr > nLastFileAddr) {1034if (SetFilePointer(hFile, nLastFileAddr, NULL, FILE_BEGIN) == ~0u) {1035return FALSE;1036}1037return ZeroFileData(hFile, m_nNextFileAddr - nLastFileAddr);1038}1039}1040return TRUE;1041}10421043BOOL CImage::Read(HANDLE hFile)1044{1045DWORD n;1046PBYTE pbData = NULL;1047DWORD cbData = 0;10481049if (hFile == INVALID_HANDLE_VALUE) {1050SetLastError(ERROR_INVALID_HANDLE);1051return FALSE;1052}10531054///////////////////////////////////////////////////////// Create mapping.1055//1056m_nFileSize = GetFileSize(hFile, NULL);1057if (m_nFileSize == (DWORD)-1) {1058return FALSE;1059}10601061m_hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);1062if (m_hMap == NULL) {1063return FALSE;1064}10651066m_pMap = (PBYTE)MapViewOfFile(m_hMap, FILE_MAP_READ, 0, 0, 0);1067if (m_pMap == NULL) {1068return FALSE;1069}10701071////////////////////////////////////////////////////// Process DOS Header.1072//1073PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)m_pMap;1074if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {1075SetLastError(ERROR_BAD_EXE_FORMAT);1076return FALSE;1077}1078m_nPeOffset = pDosHeader->e_lfanew;1079m_nPrePE = 0;1080m_cbPrePE = QuadAlign(pDosHeader->e_lfanew);10811082CopyMemory(&m_DosHeader, m_pMap + m_nPrePE, sizeof(m_DosHeader));10831084/////////////////////////////////////////////////////// Process PE Header.1085//1086CopyMemory(&m_NtHeader, m_pMap + m_nPeOffset, sizeof(m_NtHeader));1087if (m_NtHeader.Signature != IMAGE_NT_SIGNATURE) {1088SetLastError(ERROR_INVALID_EXE_SIGNATURE);1089return FALSE;1090}1091if (m_NtHeader.FileHeader.SizeOfOptionalHeader == 0) {1092SetLastError(ERROR_EXE_MARKED_INVALID);1093return FALSE;1094}1095m_nSectionsOffset = m_nPeOffset1096+ sizeof(m_NtHeader.Signature)1097+ sizeof(m_NtHeader.FileHeader)1098+ m_NtHeader.FileHeader.SizeOfOptionalHeader;10991100///////////////////////////////////////////////// Process Section Headers.1101//1102if (m_NtHeader.FileHeader.NumberOfSections > (sizeof(m_SectionHeaders) /1103sizeof(m_SectionHeaders[0]))) {1104SetLastError(ERROR_EXE_MARKED_INVALID);1105return FALSE;1106}1107CopyMemory(&m_SectionHeaders,1108m_pMap + m_nSectionsOffset,1109sizeof(m_SectionHeaders[0]) * m_NtHeader.FileHeader.NumberOfSections);11101111/////////////////////////////////////////////////// Parse .detour Section.1112//1113DWORD rvaOriginalImageDirectory = 0;1114DWORD rvaDetourBeg = 0;1115DWORD rvaDetourEnd = 0;11161117for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {1118if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) {1119DETOUR_SECTION_HEADER dh;1120CopyMemory(&dh,1121m_pMap + m_SectionHeaders[n].PointerToRawData,1122sizeof(dh));11231124rvaOriginalImageDirectory = dh.nOriginalImportVirtualAddress;1125if (dh.cbPrePE != 0) {1126m_nPrePE = m_SectionHeaders[n].PointerToRawData + sizeof(dh);1127m_cbPrePE = dh.cbPrePE;1128}1129rvaDetourBeg = m_SectionHeaders[n].VirtualAddress;1130rvaDetourEnd = rvaDetourBeg + m_SectionHeaders[n].SizeOfRawData;1131}1132}11331134//////////////////////////////////////////////////////// Get Import Table.1135//1136DWORD rvaImageDirectory = m_NtHeader.OptionalHeader1137.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;1138PIMAGE_IMPORT_DESCRIPTOR iidp1139= (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaImageDirectory);1140PIMAGE_IMPORT_DESCRIPTOR oidp1141= (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaOriginalImageDirectory);11421143if (oidp == NULL) {1144oidp = iidp;1145}1146if (iidp == NULL || oidp == NULL) {1147SetLastError(ERROR_EXE_MARKED_INVALID);1148return FALSE;1149}11501151DWORD nFiles = 0;1152for (; iidp[nFiles].OriginalFirstThunk != 0; nFiles++) {1153}11541155CImageImportFile **ppLastFile = &m_pImportFiles;1156m_pImportFiles = NULL;11571158for (n = 0; n < nFiles; n++, iidp++) {1159ULONG_PTR rvaName = iidp->Name;1160PCHAR pszName = (PCHAR)RvaToVa(rvaName);1161if (pszName == NULL) {1162SetLastError(ERROR_EXE_MARKED_INVALID);1163goto fail;1164}11651166CImageImportFile *pImportFile = new CImageImportFile;1167if (pImportFile == NULL) {1168SetLastError(ERROR_OUTOFMEMORY);1169goto fail;1170}11711172*ppLastFile = pImportFile;1173ppLastFile = &pImportFile->m_pNextFile;1174m_nImportFiles++;11751176pImportFile->m_pszName = DuplicateString(pszName);1177if (pImportFile->m_pszName == NULL) {1178goto fail;1179}11801181pImportFile->m_rvaOriginalFirstThunk = iidp->OriginalFirstThunk;1182pImportFile->m_rvaFirstThunk = iidp->FirstThunk;1183pImportFile->m_nForwarderChain = iidp->ForwarderChain;1184pImportFile->m_pImportNames = NULL;1185pImportFile->m_nImportNames = 0;1186pImportFile->m_fByway = FALSE;11871188if ((ULONG)iidp->FirstThunk >= rvaDetourBeg &&1189(ULONG)iidp->FirstThunk < rvaDetourEnd) {11901191pImportFile->m_pszOrig = NULL;1192pImportFile->m_fByway = TRUE;1193continue;1194}11951196rvaName = oidp->Name;1197pszName = (PCHAR)RvaToVa(rvaName);1198if (pszName == NULL) {1199SetLastError(ERROR_EXE_MARKED_INVALID);1200goto fail;1201}1202pImportFile->m_pszOrig = DuplicateString(pszName);1203if (pImportFile->m_pszOrig == NULL) {1204goto fail;1205}12061207DWORD rvaThunk = iidp->OriginalFirstThunk;1208PIMAGE_THUNK_DATA pAddrThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk);1209rvaThunk = oidp->OriginalFirstThunk;1210PIMAGE_THUNK_DATA pLookThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk);12111212DWORD nNames = 0;1213if (pAddrThunk) {1214for (; pAddrThunk[nNames].u1.Ordinal; nNames++) {1215}1216}12171218if (pAddrThunk && nNames) {1219pImportFile->m_nImportNames = nNames;1220pImportFile->m_pImportNames = new CImageImportName [nNames];1221if (pImportFile->m_pImportNames == NULL) {1222SetLastError(ERROR_OUTOFMEMORY);1223goto fail;1224}12251226CImageImportName *pImportName = &pImportFile->m_pImportNames[0];12271228for (DWORD f = 0; f < nNames; f++, pImportName++) {1229pImportName->m_nOrig = 0;1230pImportName->m_nOrdinal = 0;1231pImportName->m_nHint = 0;1232pImportName->m_pszName = NULL;1233pImportName->m_pszOrig = NULL;12341235rvaName = pAddrThunk[f].u1.Ordinal;1236if (rvaName & IMAGE_ORDINAL_FLAG) {1237pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName);1238pImportName->m_nOrdinal = pImportName->m_nOrig;1239}1240else {1241PIMAGE_IMPORT_BY_NAME pName1242= (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName);1243if (pName) {1244pImportName->m_nHint = pName->Hint;1245pImportName->m_pszName = DuplicateString((PCHAR)pName->Name);1246if (pImportName->m_pszName == NULL) {1247goto fail;1248}1249}12501251rvaName = pLookThunk[f].u1.Ordinal;1252if (rvaName & IMAGE_ORDINAL_FLAG) {1253pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName);1254pImportName->m_nOrdinal = (ULONG)IMAGE_ORDINAL(rvaName);1255}1256else {1257pName = (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName);1258if (pName) {1259pImportName->m_pszOrig1260= DuplicateString((PCHAR)pName->Name);1261if (pImportName->m_pszOrig == NULL) {1262goto fail;1263}1264}1265}1266}1267}1268}1269oidp++;1270}12711272////////////////////////////////////////////////////////// Parse Sections.1273//1274m_nExtraOffset = 0;1275for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {1276m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData +1277m_SectionHeaders[n].SizeOfRawData,1278m_nExtraOffset);12791280if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) {1281DETOUR_SECTION_HEADER dh;1282CopyMemory(&dh,1283m_pMap + m_SectionHeaders[n].PointerToRawData,1284sizeof(dh));12851286if (dh.nDataOffset == 0) {1287dh.nDataOffset = dh.cbHeaderSize;1288}12891290cbData = dh.cbDataSize - dh.nDataOffset;1291pbData = (m_pMap +1292m_SectionHeaders[n].PointerToRawData +1293dh.nDataOffset);12941295m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData +1296m_SectionHeaders[n].SizeOfRawData,1297m_nExtraOffset);12981299m_NtHeader.FileHeader.NumberOfSections--;13001301m_NtHeader.OptionalHeader1302.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress1303= dh.nOriginalImportVirtualAddress;1304m_NtHeader.OptionalHeader1305.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size1306= dh.nOriginalImportSize;13071308m_NtHeader.OptionalHeader1309.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress1310= dh.nOriginalBoundImportVirtualAddress;1311m_NtHeader.OptionalHeader1312.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size1313= dh.nOriginalBoundImportSize;13141315m_NtHeader.OptionalHeader1316.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress1317= dh.nOriginalIatVirtualAddress;1318m_NtHeader.OptionalHeader1319.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size1320= dh.nOriginalIatSize;13211322m_NtHeader.OptionalHeader.CheckSum = 0;1323m_NtHeader.OptionalHeader.SizeOfImage1324= dh.nOriginalSizeOfImage;13251326m_fHadDetourSection = TRUE;1327}1328}13291330m_pImageData = new CImageData(pbData, cbData);1331if (m_pImageData == NULL) {1332SetLastError(ERROR_OUTOFMEMORY);1333}1334return TRUE;13351336fail:1337return FALSE;1338}13391340static inline BOOL strneq(__in_z PCHAR pszOne, __in_z PCHAR pszTwo)1341{1342if (pszOne == pszTwo) {1343return FALSE;1344}1345if (!pszOne || !pszTwo) {1346return TRUE;1347}1348return (strcmp(pszOne, pszTwo) != 0);1349}13501351BOOL CImage::CheckImportsNeeded(DWORD *pnTables, DWORD *pnThunks, DWORD *pnChars)1352{1353DWORD nTables = 0;1354DWORD nThunks = 0;1355DWORD nChars = 0;1356BOOL fNeedDetourSection = FALSE;13571358for (CImageImportFile *pImportFile = m_pImportFiles;1359pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) {13601361nChars += (int)strlen(pImportFile->m_pszName) + 1;1362nChars += nChars & 1;13631364if (pImportFile->m_fByway) {1365fNeedDetourSection = TRUE;1366nThunks++;1367}1368else {1369if (!fNeedDetourSection &&1370strneq(pImportFile->m_pszName, pImportFile->m_pszOrig)) {13711372fNeedDetourSection = TRUE;1373}1374for (DWORD n = 0; n < pImportFile->m_nImportNames; n++) {1375CImageImportName *pImportName = &pImportFile->m_pImportNames[n];13761377if (!fNeedDetourSection &&1378strneq(pImportName->m_pszName, pImportName->m_pszOrig)) {13791380fNeedDetourSection = TRUE;1381}13821383if (pImportName->m_pszName) {1384nChars += sizeof(WORD); // Hint1385nChars += (int)strlen(pImportName->m_pszName) + 1;1386nChars += nChars & 1;1387}1388nThunks++;1389}1390}1391nThunks++;1392nTables++;1393}1394nTables++;13951396*pnTables = nTables;1397*pnThunks = nThunks;1398*pnChars = nChars;13991400return fNeedDetourSection;1401}14021403//////////////////////////////////////////////////////////////////////////////1404//1405CImageImportFile * CImage::NewByway(__in_z PCHAR pszName)1406{1407CImageImportFile *pImportFile = new CImageImportFile;1408if (pImportFile == NULL) {1409SetLastError(ERROR_OUTOFMEMORY);1410goto fail;1411}14121413pImportFile->m_pNextFile = NULL;1414pImportFile->m_fByway = TRUE;14151416pImportFile->m_pszName = DuplicateString(pszName);1417if (pImportFile->m_pszName == NULL) {1418goto fail;1419}14201421pImportFile->m_rvaOriginalFirstThunk = 0;1422pImportFile->m_rvaFirstThunk = 0;1423pImportFile->m_nForwarderChain = (UINT)0;1424pImportFile->m_pImportNames = NULL;1425pImportFile->m_nImportNames = 0;14261427m_nImportFiles++;1428return pImportFile;14291430fail:1431if (pImportFile) {1432delete pImportFile;1433pImportFile = NULL;1434}1435return NULL;1436}14371438BOOL CImage::EditImports(PVOID pContext,1439PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,1440PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,1441PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,1442PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback)1443{1444CImageImportFile *pImportFile = NULL;1445CImageImportFile **ppLastFile = &m_pImportFiles;14461447SetLastError(ERROR_CALL_NOT_IMPLEMENTED);14481449while ((pImportFile = *ppLastFile) != NULL) {14501451if (pfBywayCallback) {1452PCHAR pszFile = NULL;1453if (!(*pfBywayCallback)(pContext, pszFile, &pszFile)) {1454goto fail;1455}14561457if (pszFile) {1458// Insert a new Byway.1459CImageImportFile *pByway = NewByway(pszFile);1460if (pByway == NULL) {1461return FALSE;1462}14631464pByway->m_pNextFile = pImportFile;1465*ppLastFile = pByway;1466ppLastFile = &pByway->m_pNextFile;1467continue; // Retry after Byway.1468}1469}14701471if (pImportFile->m_fByway) {1472if (pfBywayCallback) {1473PCHAR pszFile = pImportFile->m_pszName;14741475if (!(*pfBywayCallback)(pContext, pszFile, &pszFile)) {1476goto fail;1477}14781479if (pszFile) { // Replace? Byway1480if (ReplaceString(&pImportFile->m_pszName, pszFile) == NULL) {1481goto fail;1482}1483}1484else { // Delete Byway1485*ppLastFile = pImportFile->m_pNextFile;1486pImportFile->m_pNextFile = NULL;1487delete pImportFile;1488pImportFile = *ppLastFile;1489m_nImportFiles--;1490continue; // Retry after delete.1491}1492}1493}1494else {1495if (pfFileCallback) {1496PCHAR pszFile = pImportFile->m_pszName;14971498if (!(*pfFileCallback)(pContext, pImportFile->m_pszOrig,1499pszFile, &pszFile)) {1500goto fail;1501}15021503if (pszFile != NULL) {1504if (ReplaceString(&pImportFile->m_pszName, pszFile) == NULL) {1505goto fail;1506}1507}1508}15091510if (pfSymbolCallback) {1511for (DWORD n = 0; n < pImportFile->m_nImportNames; n++) {1512CImageImportName *pImportName = &pImportFile->m_pImportNames[n];15131514PCHAR pszName = pImportName->m_pszName;1515ULONG nOrdinal = pImportName->m_nOrdinal;1516if (!(*pfSymbolCallback)(pContext,1517pImportName->m_nOrig,1518nOrdinal,1519&nOrdinal,1520pImportName->m_pszOrig,1521pszName,1522&pszName)) {1523goto fail;1524}15251526if (pszName != NULL) {1527pImportName->m_nOrdinal = 0;1528if (ReplaceString(&pImportName->m_pszName, pszName) == NULL) {1529goto fail;1530}1531}1532else if (nOrdinal != 0) {1533pImportName->m_nOrdinal = nOrdinal;15341535if (pImportName->m_pszName != NULL) {1536delete[] pImportName->m_pszName;1537pImportName->m_pszName = NULL;1538}1539}1540}1541}1542}15431544ppLastFile = &pImportFile->m_pNextFile;1545pImportFile = pImportFile->m_pNextFile;1546}15471548for (;;) {1549if (pfBywayCallback) {1550PCHAR pszFile = NULL;1551if (!(*pfBywayCallback)(pContext, NULL, &pszFile)) {1552goto fail;1553}1554if (pszFile) {1555// Insert a new Byway.1556CImageImportFile *pByway = NewByway(pszFile);1557if (pByway == NULL) {1558return FALSE;1559}15601561pByway->m_pNextFile = pImportFile;1562*ppLastFile = pByway;1563ppLastFile = &pByway->m_pNextFile;1564continue; // Retry after Byway.1565}1566}1567break;1568}15691570if (pfCommitCallback) {1571if (!(*pfCommitCallback)(pContext)) {1572goto fail;1573}1574}15751576SetLastError(NO_ERROR);1577return TRUE;15781579fail:1580return FALSE;1581}15821583BOOL CImage::Write(HANDLE hFile)1584{1585DWORD cbDone;15861587if (hFile == INVALID_HANDLE_VALUE) {1588SetLastError(ERROR_INVALID_HANDLE);1589return FALSE;1590}15911592m_nNextFileAddr = 0;1593m_nNextVirtAddr = 0;15941595DWORD nTables = 0;1596DWORD nThunks = 0;1597DWORD nChars = 0;1598BOOL fNeedDetourSection = CheckImportsNeeded(&nTables, &nThunks, &nChars);15991600//////////////////////////////////////////////////////////// Copy Headers.1601//1602if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {1603return FALSE;1604}1605if (!CopyFileData(hFile, 0, m_NtHeader.OptionalHeader.SizeOfHeaders)) {1606return FALSE;1607}16081609if (fNeedDetourSection || !m_pImageData->IsEmpty()) {1610// Replace the file's DOS header with our own.1611m_nPeOffset = sizeof(m_DosHeader) + sizeof(s_rbDosCode);1612m_nSectionsOffset = m_nPeOffset1613+ sizeof(m_NtHeader.Signature)1614+ sizeof(m_NtHeader.FileHeader)1615+ m_NtHeader.FileHeader.SizeOfOptionalHeader;1616m_DosHeader.e_lfanew = m_nPeOffset;16171618if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {1619return FALSE;1620}1621if (!WriteFile(hFile, &m_DosHeader, sizeof(m_DosHeader), &cbDone)) {1622return FALSE;1623}1624if (!WriteFile(hFile, &s_rbDosCode, sizeof(s_rbDosCode), &cbDone)) {1625return FALSE;1626}1627}1628else {1629// Restore the file's original DOS header.1630if (m_nPrePE != 0) {1631m_nPeOffset = m_cbPrePE;1632m_nSectionsOffset = m_nPeOffset1633+ sizeof(m_NtHeader.Signature)1634+ sizeof(m_NtHeader.FileHeader)1635+ m_NtHeader.FileHeader.SizeOfOptionalHeader;1636m_DosHeader.e_lfanew = m_nPeOffset;163716381639if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {1640return FALSE;1641}1642if (!CopyFileData(hFile, m_nPrePE, m_cbPrePE)) {1643return FALSE;1644}1645}1646}16471648m_nNextFileAddr = m_NtHeader.OptionalHeader.SizeOfHeaders;1649m_nNextVirtAddr = 0;1650if (!AlignFileData(hFile)) {1651return FALSE;1652}16531654/////////////////////////////////////////////////////////// Copy Sections.1655//1656DWORD n = 0;1657for (; n < m_NtHeader.FileHeader.NumberOfSections; n++) {1658if (m_SectionHeaders[n].SizeOfRawData) {1659if (SetFilePointer(hFile,1660m_SectionHeaders[n].PointerToRawData,1661NULL, FILE_BEGIN) == ~0u) {1662return FALSE;1663}1664if (!CopyFileData(hFile,1665m_SectionHeaders[n].PointerToRawData,1666m_SectionHeaders[n].SizeOfRawData)) {1667return FALSE;1668}1669}1670m_nNextFileAddr = Max(m_SectionHeaders[n].PointerToRawData +1671m_SectionHeaders[n].SizeOfRawData,1672m_nNextFileAddr);1673m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress +1674m_SectionHeaders[n].Misc.VirtualSize,1675m_nNextVirtAddr);1676m_nExtraOffset = Max(m_nNextFileAddr, m_nExtraOffset);16771678if (!AlignFileData(hFile)) {1679return FALSE;1680}1681}16821683if (fNeedDetourSection || !m_pImageData->IsEmpty()) {1684////////////////////////////////////////////// Insert .detour Section.1685//1686DWORD nSection = m_NtHeader.FileHeader.NumberOfSections++;1687DETOUR_SECTION_HEADER dh;16881689ZeroMemory(&dh, sizeof(dh));1690ZeroMemory(&m_SectionHeaders[nSection], sizeof(m_SectionHeaders[nSection]));16911692dh.cbHeaderSize = sizeof(DETOUR_SECTION_HEADER);1693dh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE;16941695dh.nOriginalImportVirtualAddress = m_NtHeader.OptionalHeader1696.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;1697dh.nOriginalImportSize = m_NtHeader.OptionalHeader1698.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;16991700dh.nOriginalBoundImportVirtualAddress1701= m_NtHeader.OptionalHeader1702.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;1703dh.nOriginalBoundImportSize = m_NtHeader.OptionalHeader1704.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size;17051706dh.nOriginalIatVirtualAddress = m_NtHeader.OptionalHeader1707.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;1708dh.nOriginalIatSize = m_NtHeader.OptionalHeader1709.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;17101711dh.nOriginalSizeOfImage = m_NtHeader.OptionalHeader.SizeOfImage;17121713DWORD clrAddr = m_NtHeader.OptionalHeader1714.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;1715DWORD clrSize = m_NtHeader.OptionalHeader1716.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;1717if (clrAddr && clrSize) {1718PDETOUR_CLR_HEADER pHdr = (PDETOUR_CLR_HEADER)RvaToVa(clrAddr);1719if (pHdr != NULL) {1720DETOUR_CLR_HEADER hdr;1721hdr = *pHdr;17221723dh.nOriginalClrFlags = hdr.Flags;1724}1725}17261727HRESULT hrRet = StringCchCopyA((PCHAR)m_SectionHeaders[nSection].Name, IMAGE_SIZEOF_SHORT_NAME , ".detour");1728if (FAILED(hrRet))1729return FALSE;17301731m_SectionHeaders[nSection].Characteristics1732= IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;17331734m_nOutputVirtAddr = m_nNextVirtAddr;1735m_nOutputVirtSize = 0;1736m_nOutputFileAddr = m_nNextFileAddr;17371738dh.nDataOffset = 0; // pbData1739dh.cbDataSize = m_pImageData->m_cbData;1740dh.cbPrePE = m_cbPrePE;17411742//////////////////////////////////////////////////////////////////////////1743//17441745DWORD rvaImportTable = 0;1746DWORD rvaLookupTable = 0;1747DWORD rvaBoundTable = 0;1748DWORD rvaNameTable = 0;1749DWORD nImportTableSize = nTables * sizeof(IMAGE_IMPORT_DESCRIPTOR);17501751if (!SizeOutputBuffer(QuadAlign(sizeof(dh))1752+ m_cbPrePE1753+ QuadAlign(m_pImageData->m_cbData)1754+ QuadAlign(sizeof(IMAGE_THUNK_DATA) * nThunks)1755+ QuadAlign(sizeof(IMAGE_THUNK_DATA) * nThunks)1756+ QuadAlign(nChars)1757+ QuadAlign(nImportTableSize))) {1758return FALSE;1759}17601761DWORD vaHead = 0;1762PBYTE pbHead = NULL;1763DWORD vaPrePE = 0;1764PBYTE pbPrePE = NULL;1765DWORD vaData = 0;1766PBYTE pbData = NULL;17671768if ((pbHead = AllocateOutput(sizeof(dh), &vaHead)) == NULL) {1769return FALSE;1770}17711772if ((pbPrePE = AllocateOutput(m_cbPrePE, &vaPrePE)) == NULL) {1773return FALSE;1774}17751776CImageThunks lookupTable(this, nThunks, &rvaLookupTable);1777CImageThunks boundTable(this, nThunks, &rvaBoundTable);1778CImageChars nameTable(this, nChars, &rvaNameTable);17791780if ((pbData = AllocateOutput(m_pImageData->m_cbData, &vaData)) == NULL) {1781return FALSE;1782}17831784dh.nDataOffset = vaData - vaHead;1785dh.cbDataSize = dh.nDataOffset + m_pImageData->m_cbData;1786CopyMemory(pbHead, &dh, sizeof(dh));1787CopyMemory(pbPrePE, m_pMap + m_nPrePE, m_cbPrePE);1788CopyMemory(pbData, m_pImageData->m_pbData, m_pImageData->m_cbData);17891790PIMAGE_IMPORT_DESCRIPTOR piidDst = (PIMAGE_IMPORT_DESCRIPTOR)1791AllocateOutput(nImportTableSize, &rvaImportTable);1792if (piidDst == NULL) {1793return FALSE;1794}17951796//////////////////////////////////////////////// Step Through Imports.1797//1798for (CImageImportFile *pImportFile = m_pImportFiles;1799pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) {18001801ZeroMemory(piidDst, sizeof(piidDst));1802nameTable.Allocate(pImportFile->m_pszName, (DWORD *)&piidDst->Name);1803piidDst->TimeDateStamp = 0;1804piidDst->ForwarderChain = pImportFile->m_nForwarderChain;18051806if (pImportFile->m_fByway) {1807ULONG rvaIgnored;18081809lookupTable.Allocate(IMAGE_ORDINAL_FLAG+1,1810(DWORD *)&piidDst->OriginalFirstThunk);1811boundTable.Allocate(IMAGE_ORDINAL_FLAG+1,1812(DWORD *)&piidDst->FirstThunk);18131814lookupTable.Allocate(0, &rvaIgnored);1815boundTable.Allocate(0, &rvaIgnored);1816}1817else {1818ULONG rvaIgnored;18191820piidDst->FirstThunk = (ULONG)pImportFile->m_rvaFirstThunk;1821lookupTable.Current((DWORD *)&piidDst->OriginalFirstThunk);18221823for (n = 0; n < pImportFile->m_nImportNames; n++) {1824CImageImportName *pImportName = &pImportFile->m_pImportNames[n];18251826if (pImportName->m_pszName) {1827ULONG nDstName = 0;18281829nameTable.Allocate(pImportName->m_pszName,1830pImportName->m_nHint,1831&nDstName);1832lookupTable.Allocate(nDstName, &rvaIgnored);1833}1834else {1835lookupTable.Allocate(IMAGE_ORDINAL_FLAG + pImportName->m_nOrdinal,1836&rvaIgnored);1837}1838}1839lookupTable.Allocate(0, &rvaIgnored);1840}1841piidDst++;1842}1843ZeroMemory(piidDst, sizeof(piidDst));18441845//////////////////////////////////////////////////////////////////////////1846//1847m_nNextVirtAddr += m_nOutputVirtSize;1848m_nNextFileAddr += FileAlign(m_nOutputVirtSize);18491850if (!AlignFileData(hFile)) {1851return FALSE;1852}18531854//////////////////////////////////////////////////////////////////////////1855//1856m_SectionHeaders[nSection].VirtualAddress = m_nOutputVirtAddr;1857m_SectionHeaders[nSection].Misc.VirtualSize = m_nOutputVirtSize;1858m_SectionHeaders[nSection].PointerToRawData = m_nOutputFileAddr;1859m_SectionHeaders[nSection].SizeOfRawData = FileAlign(m_nOutputVirtSize);18601861m_NtHeader.OptionalHeader1862.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress1863= rvaImportTable;1864m_NtHeader.OptionalHeader1865.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size1866= nImportTableSize;18671868m_NtHeader.OptionalHeader1869.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;1870m_NtHeader.OptionalHeader1871.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;18721873//////////////////////////////////////////////////////////////////////////1874//1875if (SetFilePointer(hFile, m_SectionHeaders[nSection].PointerToRawData,1876NULL, FILE_BEGIN) == ~0u) {1877return FALSE;1878}1879if (!WriteFile(hFile, m_pbOutputBuffer, m_SectionHeaders[nSection].SizeOfRawData,1880&cbDone)) {1881return FALSE;1882}1883}18841885///////////////////////////////////////////////////// Adjust Extra Data.1886//1887LONG nExtraAdjust = m_nNextFileAddr - m_nExtraOffset;1888for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {1889if (m_SectionHeaders[n].PointerToRawData > m_nExtraOffset) {1890m_SectionHeaders[n].PointerToRawData += nExtraAdjust;1891}1892if (m_SectionHeaders[n].PointerToRelocations > m_nExtraOffset) {1893m_SectionHeaders[n].PointerToRelocations += nExtraAdjust;1894}1895if (m_SectionHeaders[n].PointerToLinenumbers > m_nExtraOffset) {1896m_SectionHeaders[n].PointerToLinenumbers += nExtraAdjust;1897}1898}1899if (m_NtHeader.FileHeader.PointerToSymbolTable > m_nExtraOffset) {1900m_NtHeader.FileHeader.PointerToSymbolTable += nExtraAdjust;1901}19021903m_NtHeader.OptionalHeader.CheckSum = 0;1904m_NtHeader.OptionalHeader.SizeOfImage = m_nNextVirtAddr;19051906////////////////////////////////////////////////// Adjust Debug Directory.1907//1908DWORD debugAddr = m_NtHeader.OptionalHeader1909.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;1910DWORD debugSize = m_NtHeader.OptionalHeader1911.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;1912if (debugAddr && debugSize) {1913DWORD nFileOffset = RvaToFileOffset(debugAddr);1914if (SetFilePointer(hFile, nFileOffset, NULL, FILE_BEGIN) == ~0u) {1915return FALSE;1916}19171918PIMAGE_DEBUG_DIRECTORY pDir = (PIMAGE_DEBUG_DIRECTORY)RvaToVa(debugAddr);1919if (pDir == NULL) {1920return FALSE;1921}19221923DWORD nEntries = debugSize / sizeof(*pDir);1924for (n = 0; n < nEntries; n++) {1925IMAGE_DEBUG_DIRECTORY dir = pDir[n];19261927if (dir.PointerToRawData > m_nExtraOffset) {1928dir.PointerToRawData += nExtraAdjust;1929}1930if (!WriteFile(hFile, &dir, sizeof(dir), &cbDone)) {1931return FALSE;1932}1933}1934}19351936/////////////////////////////////////////////////////// Adjust CLR Header.1937//1938DWORD clrAddr = m_NtHeader.OptionalHeader1939.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;1940DWORD clrSize = m_NtHeader.OptionalHeader1941.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;1942if (clrAddr && clrSize && fNeedDetourSection) {1943DWORD nFileOffset = RvaToFileOffset(clrAddr);1944if (SetFilePointer(hFile, nFileOffset, NULL, FILE_BEGIN) == ~0u) {1945return FALSE;1946}19471948PDETOUR_CLR_HEADER pHdr = (PDETOUR_CLR_HEADER)RvaToVa(clrAddr);1949if (pHdr == NULL) {1950return FALSE;1951}19521953DETOUR_CLR_HEADER hdr;1954hdr = *pHdr;1955hdr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag.19561957if (!WriteFile(hFile, &hdr, sizeof(hdr), &cbDone)) {1958return FALSE;1959}1960}19611962///////////////////////////////////////////////// Copy Left-over Data.1963//1964if (m_nFileSize > m_nExtraOffset) {1965if (SetFilePointer(hFile, m_nNextFileAddr, NULL, FILE_BEGIN) == ~0u) {1966return FALSE;1967}1968if (!CopyFileData(hFile, m_nExtraOffset, m_nFileSize - m_nExtraOffset)) {1969return FALSE;1970}1971}197219731974//////////////////////////////////////////////////// Finalize Headers.1975//19761977if (SetFilePointer(hFile, m_nPeOffset, NULL, FILE_BEGIN) == ~0u) {1978return FALSE;1979}1980if (!WriteFile(hFile, &m_NtHeader, sizeof(m_NtHeader), &cbDone)) {1981return FALSE;1982}19831984if (SetFilePointer(hFile, m_nSectionsOffset, NULL, FILE_BEGIN) == ~0u) {1985return FALSE;1986}1987if (!WriteFile(hFile, &m_SectionHeaders,1988sizeof(m_SectionHeaders[0])1989* m_NtHeader.FileHeader.NumberOfSections,1990&cbDone)) {1991return FALSE;1992}19931994m_cbPostPE = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);1995if (m_cbPostPE == ~0u) {1996return FALSE;1997}1998m_cbPostPE = m_NtHeader.OptionalHeader.SizeOfHeaders - m_cbPostPE;19992000return TRUE;2001}20022003}; // namespace Detour200420052006//////////////////////////////////////////////////////////////////////////////2007//2008PDETOUR_BINARY WINAPI DetourBinaryOpen(HANDLE hFile)2009{2010Detour::CImage *pImage = new Detour::CImage;2011if (pImage == NULL) {2012SetLastError(ERROR_OUTOFMEMORY);2013return FALSE;2014}20152016if (!pImage->Read(hFile)) {2017delete pImage;2018return FALSE;2019}20202021return (PDETOUR_BINARY)pImage;2022}20232024BOOL WINAPI DetourBinaryWrite(PDETOUR_BINARY pdi, HANDLE hFile)2025{2026Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2027if (pImage == NULL) {2028return FALSE;2029}20302031return pImage->Write(hFile);2032}20332034PVOID WINAPI DetourBinaryEnumeratePayloads(PDETOUR_BINARY pdi,2035GUID *pGuid,2036DWORD *pcbData,2037DWORD *pnIterator)2038{2039Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2040if (pImage == NULL) {2041return FALSE;2042}20432044return pImage->DataEnum(pGuid, pcbData, pnIterator);2045}20462047PVOID WINAPI DetourBinaryFindPayload(PDETOUR_BINARY pdi,2048REFGUID rguid,2049DWORD *pcbData)2050{2051Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2052if (pImage == NULL) {2053return FALSE;2054}20552056return pImage->DataFind(rguid, pcbData);2057}20582059PVOID WINAPI DetourBinarySetPayload(PDETOUR_BINARY pdi,2060REFGUID rguid,2061PVOID pvData,2062DWORD cbData)2063{2064Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2065if (pImage == NULL) {2066return FALSE;2067}20682069return pImage->DataSet(rguid, (PBYTE)pvData, cbData);2070}20712072BOOL WINAPI DetourBinaryDeletePayload(PDETOUR_BINARY pdi,2073REFGUID rguid)2074{2075Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2076if (pImage == NULL) {2077return FALSE;2078}20792080return pImage->DataDelete(rguid);2081}20822083BOOL WINAPI DetourBinaryPurgePayloads(PDETOUR_BINARY pdi)2084{2085Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2086if (pImage == NULL) {2087return FALSE;2088}20892090return pImage->DataPurge();2091}20922093//////////////////////////////////////////////////////////////////////////////2094//2095static BOOL CALLBACK ResetBywayCallback(PVOID pContext,2096__in_z PCHAR pszFile,2097__deref PCHAR *ppszOutFile)2098{2099(void)pContext;2100(void)pszFile;21012102*ppszOutFile = NULL;2103return TRUE;2104}21052106static BOOL CALLBACK ResetFileCallback(PVOID pContext,2107__in_z PCHAR pszOrigFile,2108__in_z PCHAR pszFile,2109__deref PCHAR *ppszOutFile)2110{2111(void)pContext;2112(void)pszFile;21132114*ppszOutFile = pszOrigFile;2115return TRUE;2116}21172118static BOOL CALLBACK ResetSymbolCallback(PVOID pContext,2119ULONG nOrigOrdinal,2120ULONG nOrdinal,2121ULONG *pnOutOrdinal,2122__in_z PCHAR pszOrigSymbol,2123__in_z PCHAR pszSymbol,2124__deref PCHAR *ppszOutSymbol)2125{2126(void)pContext;2127(void)nOrdinal;2128(void)pszSymbol;21292130*pnOutOrdinal = nOrigOrdinal;2131*ppszOutSymbol = pszOrigSymbol;2132return TRUE;2133}21342135BOOL WINAPI DetourBinaryResetImports(PDETOUR_BINARY pdi)2136{2137Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2138if (pImage == NULL) {2139return FALSE;2140}21412142return pImage->EditImports(NULL,2143ResetBywayCallback,2144ResetFileCallback,2145ResetSymbolCallback,2146NULL);2147}21482149//////////////////////////////////////////////////////////////////////////////2150//2151BOOL WINAPI DetourBinaryEditImports(PDETOUR_BINARY pdi,2152PVOID pContext,2153PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,2154PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,2155PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,2156PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback)2157{2158Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2159if (pImage == NULL) {2160return FALSE;2161}21622163return pImage->EditImports(pContext,2164pfBywayCallback,2165pfFileCallback,2166pfSymbolCallback,2167pfCommitCallback);2168}21692170BOOL WINAPI DetourBinaryClose(PDETOUR_BINARY pdi)2171{2172Detour::CImage *pImage = Detour::CImage::IsValid(pdi);2173if (pImage == NULL) {2174return FALSE;2175}21762177BOOL bSuccess = pImage->Close();2178delete pImage;2179pImage = NULL;21802181return bSuccess;2182}21832184//2185///////////////////////////////////////////////////////////////// End of File.218621872188