////////////////////////////////////////////////////////////////////////////// // // Module: detours.lib // File: detours.cpp // Author: Galen Hunt // // Detours for binary functions. Version 1.2. (Build 35) // // Copyright 1995-1999, Microsoft Corporation // // http://research.microsoft.com/sn/detours // //#include #include "stdafx.h" #include ////////////////////////////////////////////////////////////////////////////// // enum { OP_JMP_DS = 0x25, OP_JA = 0x77, OP_NOP = 0x90, OP_CALL = 0xe8, OP_JMP = 0xe9, OP_PREFIX = 0xff, OP_MOV_EAX = 0xa1, OP_SET_EAX = 0xb8, OP_JMP_EAX = 0xe0, OP_RET_POP = 0xc2, OP_RET = 0xc3, OP_BRK = 0xcc, SIZE_OF_JMP = 5, SIZE_OF_NOP = 1, SIZE_OF_BRK = 1, SIZE_OF_TRP_OPS = SIZE_OF_JMP /* + SIZE_OF_BRK */, }; class CEnableWriteOnCodePage { public: CEnableWriteOnCodePage(PBYTE pbCode, LONG cbCode = DETOUR_TRAMPOLINE_SIZE) { m_pbCode = pbCode; m_cbCode = cbCode; m_dwOldPerm = 0; m_hProcess = GetCurrentProcess(); if (m_pbCode && m_cbCode) { if (!FlushInstructionCache(m_hProcess, pbCode, cbCode)) { return; } if (!VirtualProtect(pbCode, cbCode, PAGE_EXECUTE_READWRITE, &m_dwOldPerm)) { return; } } } ~CEnableWriteOnCodePage() { if (m_dwOldPerm && m_pbCode && m_cbCode) { DWORD dwTemp = 0; if (!FlushInstructionCache(m_hProcess, m_pbCode, m_cbCode)) { return; } if (!VirtualProtect(m_pbCode, m_cbCode, m_dwOldPerm, &dwTemp)) { return; } } } BOOL SetPermission(DWORD dwPerms) { if (m_dwOldPerm && m_pbCode && m_cbCode) { m_dwOldPerm = dwPerms; return TRUE; } return FALSE; } BOOL IsValid(VOID) { return m_pbCode && m_cbCode && m_dwOldPerm; } private: HANDLE m_hProcess; PBYTE m_pbCode; LONG m_cbCode; DWORD m_dwOldPerm; }; ////////////////////////////////////////////////////////////////////////////// // static BOOL detour_insert_jump(PBYTE pbCode, PBYTE pbDest, LONG cbCode) { if (cbCode < SIZE_OF_JMP) return FALSE; *pbCode++ = OP_JMP; LONG offset = (LONG)pbDest - (LONG)(pbCode + 4); *((PDWORD&)pbCode)++ = offset; for (cbCode -= SIZE_OF_JMP; cbCode > 0; cbCode--) *pbCode++ = OP_BRK; return TRUE; } static BOOL detour_insert_detour(PBYTE pbTarget, PBYTE pbTrampoline, PBYTE pbDetour) { if (pbTarget[0] == OP_NOP) return FALSE; if (pbTarget[0] == OP_JMP) // Already has a detour. return FALSE; PBYTE pbCont = pbTarget; for (LONG cbTarget = 0; cbTarget < SIZE_OF_TRP_OPS;) { BYTE bOp = *pbCont; pbCont = DetourCopyInstruction(NULL, pbCont, NULL); cbTarget = pbCont - pbTarget; if (bOp == OP_JMP || bOp == OP_JMP_DS || bOp == OP_JMP_EAX || bOp == OP_RET_POP || bOp == OP_RET) { break; } } if (cbTarget < SIZE_OF_TRP_OPS) { // Too few instructions. return FALSE; } if (cbTarget > (DETOUR_TRAMPOLINE_SIZE - SIZE_OF_JMP - SIZE_OF_NOP - 1)) { // Too many instructions. return FALSE; } //////////////////////////////////////////////////////// Finalize Reroute. // CEnableWriteOnCodePage ewTrampoline(pbTrampoline, DETOUR_TRAMPOLINE_SIZE); CEnableWriteOnCodePage ewTarget(pbTarget, cbTarget); if (!ewTrampoline.SetPermission(PAGE_EXECUTE_READWRITE)) return FALSE; if (!ewTarget.IsValid()) return FALSE; pbTrampoline[0] = OP_NOP; PBYTE pbSrc = pbTarget; PBYTE pbDst = pbTrampoline + SIZE_OF_NOP; for (LONG cbCopy = 0; cbCopy < cbTarget;) { pbSrc = DetourCopyInstruction(pbDst, pbSrc, NULL); cbCopy = pbSrc - pbTarget; pbDst = pbTrampoline + SIZE_OF_NOP + cbCopy; } if (cbCopy != cbTarget) // Count came out different! return FALSE; pbCont = pbTarget + cbTarget; if (!detour_insert_jump(pbTrampoline + 1 + cbTarget, pbCont, SIZE_OF_JMP)) return FALSE; pbTrampoline[DETOUR_TRAMPOLINE_SIZE-1] = (BYTE)cbTarget; if (!detour_insert_jump(pbTarget, pbDetour, cbTarget)) return FALSE; return TRUE; } ////////////////////////////////////////////////////////////////////////////// // BOOL WINAPI DetourRemoveWithTrampoline(PBYTE pbTrampoline, PBYTE pbDetour) { pbTrampoline = DetourFindFinalCode(pbTrampoline); pbDetour = DetourFindFinalCode(pbDetour); ////////////////////////////////////// Verify that Trampoline is in place. // if (pbTrampoline[0] != OP_NOP) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } LONG cbTarget = pbTrampoline[DETOUR_TRAMPOLINE_SIZE-1]; if (cbTarget == 0 || cbTarget >= DETOUR_TRAMPOLINE_SIZE - 1) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (pbTrampoline[cbTarget + SIZE_OF_NOP] != OP_JMP) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } LONG offset = *((PDWORD)&pbTrampoline[cbTarget + SIZE_OF_NOP + 1]); PBYTE pbTarget = pbTrampoline + SIZE_OF_NOP + cbTarget + SIZE_OF_JMP + offset - cbTarget; if (pbTarget[0] != OP_JMP) { // Missing detour. SetLastError(ERROR_INVALID_BLOCK); return FALSE; } offset = *((PDWORD)&pbTarget[1]); PBYTE pbTargetDetour = pbTarget + SIZE_OF_JMP + offset; if (pbTargetDetour != pbDetour) { SetLastError(ERROR_INVALID_ACCESS); return FALSE; } /////////////////////////////////////////////////////// Remove the Detour. CEnableWriteOnCodePage ewTarget(pbTarget, cbTarget); PBYTE pbSrc = pbTrampoline + SIZE_OF_NOP; PBYTE pbDst = pbTarget; for (LONG cbCopy = 0; cbCopy < cbTarget; pbDst = pbTarget + cbCopy) { pbSrc = DetourCopyInstruction(pbDst, pbSrc, NULL); cbCopy = pbSrc - (pbTrampoline + SIZE_OF_NOP); } if (cbCopy != cbTarget) { // Count came out different! SetLastError(ERROR_INVALID_DATA); return FALSE; } return TRUE; } PBYTE WINAPI DetourFunction(PBYTE pbTarget, PBYTE pbDetour) { PBYTE pbTrampoline = new BYTE [DETOUR_TRAMPOLINE_SIZE]; if (pbTrampoline == NULL) return NULL; pbTarget = DetourFindFinalCode(pbTarget); pbDetour = DetourFindFinalCode(pbDetour); if (detour_insert_detour(pbTarget, pbTrampoline, pbDetour)) return pbTrampoline; delete[] pbTrampoline; return NULL; } BOOL WINAPI DetourFunctionWithEmptyTrampoline(PBYTE pbTrampoline, PBYTE pbTarget, PBYTE pbDetour) { return DetourFunctionWithEmptyTrampolineEx(pbTrampoline, pbTarget, pbDetour, NULL, NULL, NULL); } BOOL WINAPI DetourFunctionWithEmptyTrampolineEx(PBYTE pbTrampoline, PBYTE pbTarget, PBYTE pbDetour, PBYTE *ppbRealTrampoline, PBYTE *ppbRealTarget, PBYTE *ppbRealDetour) { pbTrampoline = DetourFindFinalCode(pbTrampoline); pbTarget = DetourFindFinalCode(pbTarget); pbDetour = DetourFindFinalCode(pbDetour); if (ppbRealTrampoline) *ppbRealTrampoline = pbTrampoline; if (ppbRealTarget) *ppbRealTarget = pbTarget; if (ppbRealDetour) *ppbRealDetour = pbDetour; if (pbTrampoline == NULL || pbDetour == NULL || pbTarget == NULL) return FALSE; if (pbTrampoline[0] == OP_NOP && pbTrampoline[1] != OP_NOP) { // Already Patched. return 2; } if (pbTrampoline[0] != OP_NOP || pbTrampoline[1] != OP_NOP) { return FALSE; } return detour_insert_detour(pbTarget, pbTrampoline, pbDetour); } BOOL WINAPI DetourFunctionWithTrampoline(PBYTE pbTrampoline, PBYTE pbDetour) { return DetourFunctionWithTrampolineEx(pbTrampoline, pbDetour, NULL, NULL); } BOOL WINAPI DetourFunctionWithTrampolineEx(PBYTE pbTrampoline, PBYTE pbDetour, PBYTE *ppbRealTrampoline, PBYTE *ppbRealTarget) { PBYTE pbTarget = NULL; pbTrampoline = DetourFindFinalCode(pbTrampoline); pbDetour = DetourFindFinalCode(pbDetour); if (ppbRealTrampoline) *ppbRealTrampoline = pbTrampoline; if (ppbRealTarget) *ppbRealTarget = NULL; if (pbTrampoline == NULL || pbDetour == NULL) return FALSE; if (pbTrampoline[0] == OP_NOP && pbTrampoline[1] != OP_NOP) { // Already Patched. return 2; } if (pbTrampoline[0] != OP_NOP || pbTrampoline[1] != OP_NOP || pbTrampoline[2] != OP_CALL || pbTrampoline[7] != OP_PREFIX || pbTrampoline[8] != OP_JMP_EAX) { return FALSE; } PVOID (__fastcall * pfAddr)(VOID); pfAddr = (PVOID (__fastcall *)(VOID))(pbTrampoline + SIZE_OF_NOP + SIZE_OF_NOP + SIZE_OF_JMP + *(LONG *)&pbTrampoline[3]); pbTarget = DetourFindFinalCode((PBYTE)(*pfAddr)()); if (ppbRealTarget) *ppbRealTarget = pbTarget; return detour_insert_detour(pbTarget, pbTrampoline, pbDetour); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////// // typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion); typedef BOOL (NTAPI *PF_SymInitialize)(IN HANDLE hProcess, IN LPSTR UserSearchPath, IN BOOL fInvadeProcess); typedef DWORD (NTAPI *PF_SymSetOptions)(IN DWORD SymOptions); typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); typedef BOOL (NTAPI *PF_SymLoadModule)(IN HANDLE hProcess, IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, IN DWORD BaseOfDll, IN DWORD SizeOfDll); typedef BOOL (NTAPI *PF_SymGetModuleInfo)(IN HANDLE hProcess, IN DWORD dwAddr, OUT PIMAGEHLP_MODULE ModuleInfo); typedef BOOL (NTAPI *PF_SymGetSymFromName)(IN HANDLE hProcess, IN LPSTR Name, OUT PIMAGEHLP_SYMBOL Symbol); typedef BOOL (NTAPI *PF_BindImage)(IN LPSTR pszImageName, IN LPSTR pszDllPath, IN LPSTR pszSymbolPath); static HANDLE s_hProcess = NULL; static HINSTANCE s_hImageHlp = NULL; static PF_ImagehlpApiVersionEx s_pfImagehlpApiVersionEx = NULL; static PF_SymInitialize s_pfSymInitialize = NULL; static PF_SymSetOptions s_pfSymSetOptions = NULL; static PF_SymGetOptions s_pfSymGetOptions = NULL; static PF_SymLoadModule s_pfSymLoadModule = NULL; static PF_SymGetModuleInfo s_pfSymGetModuleInfo = NULL; static PF_SymGetSymFromName s_pfSymGetSymFromName = NULL; static PF_BindImage s_pfBindImage = NULL; static BOOL LoadImageHlp(VOID) { if (s_hImageHlp) return TRUE; if (s_hProcess == NULL) { s_hProcess = GetCurrentProcess(); s_hImageHlp = LoadLibraryA("imagehlp.dll"); if (s_hImageHlp == NULL) return FALSE; s_pfImagehlpApiVersionEx = (PF_ImagehlpApiVersionEx)GetProcAddress(s_hImageHlp, "ImagehlpApiVersionEx"); s_pfSymInitialize = (PF_SymInitialize)GetProcAddress(s_hImageHlp, "SymInitialize"); s_pfSymSetOptions = (PF_SymSetOptions)GetProcAddress(s_hImageHlp, "SymSetOptions"); s_pfSymGetOptions = (PF_SymGetOptions)GetProcAddress(s_hImageHlp, "SymGetOptions"); s_pfSymLoadModule = (PF_SymLoadModule)GetProcAddress(s_hImageHlp, "SymLoadModule"); s_pfSymGetModuleInfo = (PF_SymGetModuleInfo)GetProcAddress(s_hImageHlp, "SymGetModuleInfo"); s_pfSymGetSymFromName = (PF_SymGetSymFromName)GetProcAddress(s_hImageHlp, "SymGetSymFromName"); s_pfBindImage = (PF_BindImage)GetProcAddress(s_hImageHlp, "BindImage"); API_VERSION av; ZeroMemory(&av, sizeof(av)); av.MajorVersion = API_VERSION_NUMBER; if (s_pfImagehlpApiVersionEx) { (*s_pfImagehlpApiVersionEx)(&av); } if (s_pfImagehlpApiVersionEx == NULL || av.MajorVersion < API_VERSION_NUMBER) { FreeLibrary(s_hImageHlp); s_hImageHlp = NULL; return FALSE; } if (s_pfSymInitialize) { (*s_pfSymInitialize)(s_hProcess, NULL, FALSE); } if (s_pfSymGetOptions && s_pfSymSetOptions) { DWORD dw = (*s_pfSymGetOptions)(); dw &= (SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); (*s_pfSymSetOptions)(dw); } return TRUE; } return FALSE; } ////////////////////////////////////////////////////////////////////////////// // PBYTE WINAPI DetourFindFinalCode(PBYTE pbCode) { if (pbCode == NULL) return NULL; //BUGBUG PBYTE pbTemp = pbCode; if (pbCode[0] == OP_JMP) { // Reference passed. pbCode = pbCode + SIZE_OF_JMP + *(LONG *)&pbCode[1]; } else if (pbCode[0] == OP_PREFIX && pbCode[1] == OP_JMP_DS) { pbCode = *(PBYTE *)&pbCode[2]; pbCode = *(PBYTE *)pbCode; } return pbCode; } PBYTE WINAPI DetourFindFunction(PCHAR pszModule, PCHAR pszFunction) { /////////////////////////////////////////////// First, Try GetProcAddress. // HINSTANCE hInst = LoadLibraryA(pszModule); if (hInst == NULL) { return NULL; } PBYTE pbCode = (PBYTE)GetProcAddress(hInst, pszFunction); if (pbCode) { return pbCode; } ////////////////////////////////////////////////////// Then Try ImageHelp. // if (!LoadImageHlp() || s_pfSymLoadModule == NULL || s_pfSymGetModuleInfo == NULL || s_pfSymGetSymFromName == NULL) { return NULL; } (*s_pfSymLoadModule)(s_hProcess, NULL, pszModule, NULL, (DWORD)hInst, 0); IMAGEHLP_MODULE modinfo; ZeroMemory(&modinfo, sizeof(modinfo)); if (!(*s_pfSymGetModuleInfo)(s_hProcess, (DWORD)hInst, &modinfo)) { return NULL; } CHAR szFullName[512]; strcpy(szFullName, modinfo.ModuleName); strcat(szFullName, "!"); strcat(szFullName, pszFunction); //BUGBUG DWORD nDisplacement = 0; struct CFullSymbol : IMAGEHLP_SYMBOL { CHAR szRestOfName[512]; } symbol; ZeroMemory(&symbol, sizeof(symbol)); symbol.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); symbol.MaxNameLength = sizeof(symbol.szRestOfName)/sizeof(0); if (!(*s_pfSymGetSymFromName)(s_hProcess, szFullName, &symbol)) { return NULL; } return (PBYTE)symbol.Address; } //////////////////////////////////////////////////// Instance Image Functions. // HINSTANCE WINAPI DetourEnumerateInstances(HINSTANCE hinstLast) { PBYTE pbLast; if (hinstLast == NULL) { pbLast = (PBYTE)0x10000; } else { pbLast = (PBYTE)hinstLast + 0x10000; } MEMORY_BASIC_INFORMATION mbi; ZeroMemory(&mbi, sizeof(mbi)); for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) { if (VirtualQuery((PVOID)pbLast, &mbi, sizeof(mbi)) <= 0) { return NULL; } if (mbi.State != MEM_COMMIT) continue; __try { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbLast; if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { continue; } PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + pDosHeader->e_lfanew); if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { continue; } return (HINSTANCE)pDosHeader; } __except(EXCEPTION_EXECUTE_HANDLER) { /* nothing. */ } } return NULL; } PBYTE WINAPI DetourFindEntryPointForInstance(HINSTANCE hInst) { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hInst; if (hInst == NULL) { pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL); } __try { if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + pDosHeader->e_lfanew); if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { SetLastError(ERROR_INVALID_EXE_SIGNATURE); return NULL; } if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { SetLastError(ERROR_EXE_MARKED_INVALID); return NULL; } return (PBYTE)pNtHeader->OptionalHeader.AddressOfEntryPoint + pNtHeader->OptionalHeader.ImageBase; } __except(EXCEPTION_EXECUTE_HANDLER) { } SetLastError(ERROR_EXE_MARKED_INVALID); return NULL; } static inline PBYTE RvaAdjust(HINSTANCE hInst, DWORD raddr) { if (raddr != NULL) { return (PBYTE)hInst + raddr; } return NULL; } BOOL WINAPI DetourEnumerateExportsForInstance(HINSTANCE hInst, PVOID pContext, PF_DETOUR_BINARY_EXPORT_CALLBACK pfExport) { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hInst; if (hInst == NULL) { pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL); } __try { if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + pDosHeader->e_lfanew); if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { SetLastError(ERROR_INVALID_EXE_SIGNATURE); return FALSE; } if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { SetLastError(ERROR_EXE_MARKED_INVALID); return FALSE; } PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY) RvaAdjust(hInst, pNtHeader->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); //BUGBUG ULONG cbExportDir = pNtHeader->OptionalHeader //BUGBUG .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if (pExportDir == NULL) { SetLastError(ERROR_EXE_MARKED_INVALID); return FALSE; } //BUGBUG PCHAR pszName = (PCHAR)RvaAdjust(hInst, pExportDir->Name); PDWORD pdwFunctions = (PDWORD)RvaAdjust(hInst, pExportDir->AddressOfFunctions); PDWORD pdwNames = (PDWORD)RvaAdjust(hInst, pExportDir->AddressOfNames); PWORD pwOrdinals = (PWORD)RvaAdjust(hInst, pExportDir->AddressOfNameOrdinals); for (DWORD nFunc = 0; nFunc < pExportDir->NumberOfFunctions; nFunc++) { PBYTE pbCode = (PBYTE)RvaAdjust(hInst, pdwFunctions[nFunc]); PCHAR pszName = (nFunc < pExportDir->NumberOfNames) ? (PCHAR)RvaAdjust(hInst, pdwNames[nFunc]) : NULL; ULONG nOrdinal = pExportDir->Base + pwOrdinals[nFunc]; if (!(*pfExport)(pContext, nOrdinal, pszName, pbCode)) { break; } } SetLastError(NO_ERROR); return TRUE; } __except(EXCEPTION_EXECUTE_HANDLER) { } SetLastError(ERROR_EXE_MARKED_INVALID); return FALSE; } PDETOUR_LOADED_BINARY WINAPI DetourBinaryFromInstance(HINSTANCE hInst) { PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hInst; if (hInst == NULL) { pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL); } __try { if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + pDosHeader->e_lfanew); if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { SetLastError(ERROR_INVALID_EXE_SIGNATURE); return NULL; } if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { SetLastError(ERROR_EXE_MARKED_INVALID); return NULL; } PIMAGE_SECTION_HEADER pSectionHeaders = (PIMAGE_SECTION_HEADER)((PBYTE)pNtHeader + sizeof(pNtHeader->Signature) + sizeof(pNtHeader->FileHeader) + pNtHeader->FileHeader.SizeOfOptionalHeader); for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; n++) { if (strcmp((PCHAR)pSectionHeaders[n].Name, ".detour") == 0) { if (pSectionHeaders[n].VirtualAddress == 0 || pSectionHeaders[n].SizeOfRawData == 0) { break; } PBYTE pbData = (PBYTE)pDosHeader + pSectionHeaders[n].VirtualAddress; DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pbData; if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) || pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) { break; } if (pHeader->nDataOffset == 0) { pHeader->nDataOffset = pHeader->cbHeaderSize; } return (PBYTE)pHeader; } } } __except(EXCEPTION_EXECUTE_HANDLER) { } SetLastError(ERROR_EXE_MARKED_INVALID); return NULL; } DWORD WINAPI DetourGetSizeOfBinary(PDETOUR_LOADED_BINARY pBinary) { __try { DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary; if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) || pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) { SetLastError(ERROR_INVALID_HANDLE); return 0; } return pHeader->cbDataSize; } __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError(ERROR_INVALID_HANDLE); return 0; } SetLastError(ERROR_INVALID_HANDLE); return 0; } PBYTE WINAPI DetourFindPayloadInBinary(PDETOUR_LOADED_BINARY pBinary, REFGUID rguid, DWORD * pcbData) { PBYTE pbData = NULL; //BUGBUG DWORD cbData = 0; if (pcbData) { *pcbData = 0; } if (pBinary == NULL) { pBinary = DetourBinaryFromInstance(NULL); } __try { DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary; if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) || pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) { SetLastError(ERROR_INVALID_EXE_SIGNATURE); return NULL; } PBYTE pbBeg = ((PBYTE)pHeader) + pHeader->nDataOffset; PBYTE pbEnd = ((PBYTE)pHeader) + pHeader->cbDataSize; for (pbData = pbBeg; pbData < pbEnd;) { DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData; if (pSection->guid == rguid) { if (pcbData) { *pcbData = pSection->cbBytes - sizeof(*pSection); return (PBYTE)(pSection + 1); } } pbData = (PBYTE)pSection + pSection->cbBytes; } } __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError(ERROR_INVALID_HANDLE); return NULL; } SetLastError(ERROR_INVALID_HANDLE); return NULL; } ////////////////////////////////////////////////////////////////////////////// // BOOL WINAPI DetourBinaryBindA(PCHAR pszFile, PCHAR pszDll, PCHAR pszPath) { if (!LoadImageHlp()) { SetLastError(ERROR_MOD_NOT_FOUND); return FALSE; } if (s_pfBindImage) { return (*s_pfBindImage)(pszFile, pszDll ? pszDll : ".", pszPath ? pszPath : "."); } SetLastError(ERROR_INVALID_FUNCTION); return FALSE; } static void UnicodeToOem(PWCHAR pwzIn, PCHAR pszOut, INT cbOut) { cbOut = WideCharToMultiByte(CP_OEMCP, 0, pwzIn, lstrlenW(pwzIn), pszOut, cbOut-1, NULL, NULL); pszOut[cbOut] = '\0'; } BOOL WINAPI DetourBinaryBindW(PWCHAR pwzFile, PWCHAR pwzDll, PWCHAR pwzPath) { if (!LoadImageHlp()) { SetLastError(ERROR_MOD_NOT_FOUND); return FALSE; } CHAR szFile[MAX_PATH]; CHAR szDll[MAX_PATH]; CHAR szPath[MAX_PATH]; UnicodeToOem(pwzFile, szFile, sizeof(szFile)); UnicodeToOem(pwzDll, szDll, sizeof(szDll)); UnicodeToOem(pwzPath, szPath, sizeof(szPath)); if (s_pfBindImage) { return (s_pfBindImage)(szFile, szDll, szPath); } SetLastError(ERROR_INVALID_FUNCTION); return FALSE; } // End of File