modules.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Module Enumeration Functions (modules.cpp of detours.lib)
  4. //
  5. // Microsoft Research Detours Package, Version 2.1.
  6. //
  7. // Copyright (c) Microsoft Corporation. All rights reserved.
  8. //
  9. // Module enumeration functions.
  10. //
  11. #include <windows.h>
  12. #if (_MSC_VER < 1310)
  13. #else
  14. #include <strsafe.h>
  15. #endif
  16. //#define DETOUR_DEBUG 1
  17. #define DETOURS_INTERNAL
  18. #include "detours.h"
  19. //////////////////////////////////////////////////////////////////////////////
  20. //
  21. #ifndef _STRSAFE_H_INCLUDED_
  22. static inline HRESULT StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch)
  23. {
  24. HRESULT hr = S_OK;
  25. size_t cchMaxPrev = cchMax;
  26. if (cchMax > 2147483647)
  27. {
  28. return ERROR_INVALID_PARAMETER;
  29. }
  30. while (cchMax && (*psz != '\0'))
  31. {
  32. psz++;
  33. cchMax--;
  34. }
  35. if (cchMax == 0)
  36. {
  37. // the string is longer than cchMax
  38. hr = ERROR_INVALID_PARAMETER;
  39. }
  40. if (SUCCEEDED(hr) && pcch)
  41. {
  42. *pcch = cchMaxPrev - cchMax;
  43. }
  44. return hr;
  45. }
  46. static inline HRESULT StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc)
  47. {
  48. HRESULT hr = S_OK;
  49. if (cchDest == 0)
  50. {
  51. // can not null terminate a zero-byte dest buffer
  52. hr = ERROR_INVALID_PARAMETER;
  53. }
  54. else
  55. {
  56. while (cchDest && (*pszSrc != '\0'))
  57. {
  58. *pszDest++ = *pszSrc++;
  59. cchDest--;
  60. }
  61. if (cchDest == 0)
  62. {
  63. // we are going to truncate pszDest
  64. pszDest--;
  65. hr = ERROR_INVALID_PARAMETER;
  66. }
  67. *pszDest= '\0';
  68. }
  69. return hr;
  70. }
  71. static inline HRESULT StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc)
  72. {
  73. HRESULT hr;
  74. size_t cchDestCurrent;
  75. if (cchDest > 2147483647)
  76. {
  77. return ERROR_INVALID_PARAMETER;
  78. }
  79. hr = StringCchLengthA(pszDest, cchDest, &cchDestCurrent);
  80. if (SUCCEEDED(hr))
  81. {
  82. hr = StringCchCopyA(pszDest + cchDestCurrent,
  83. cchDest - cchDestCurrent,
  84. pszSrc);
  85. }
  86. return hr;
  87. }
  88. #endif
  89. //////////////////////////////////////////////////////////////////////////////
  90. //
  91. const GUID DETOUR_EXE_RESTORE_GUID = {
  92. 0x2ed7a3ff, 0x3339, 0x4a8d,
  93. { 0x80, 0x5c, 0xd4, 0x98, 0x15, 0x3f, 0xc2, 0x8f }};
  94. //////////////////////////////////////////////////////////////////////////////
  95. //
  96. PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
  97. {
  98. static DETOUR_SYM_INFO symInfo;
  99. static PDETOUR_SYM_INFO pSymInfo = NULL;
  100. static BOOL failed = false;
  101. if (failed) {
  102. return NULL;
  103. }
  104. if (pSymInfo != NULL) {
  105. return pSymInfo;
  106. }
  107. ZeroMemory(&symInfo, sizeof(symInfo));
  108. // Create a real handle to the process.
  109. #if 0
  110. DuplicateHandle(GetCurrentProcess(),
  111. GetCurrentProcess(),
  112. GetCurrentProcess(),
  113. &symInfo.hProcess,
  114. 0,
  115. FALSE,
  116. DUPLICATE_SAME_ACCESS);
  117. #else
  118. symInfo.hProcess = GetCurrentProcess();
  119. #endif
  120. symInfo.hDbgHelp = LoadLibraryA("dbghelp.dll");
  121. if (symInfo.hDbgHelp == NULL) {
  122. abort:
  123. failed = true;
  124. if (symInfo.hDbgHelp != NULL) {
  125. FreeLibrary(symInfo.hDbgHelp);
  126. }
  127. symInfo.pfImagehlpApiVersionEx = NULL;
  128. symInfo.pfSymInitialize = NULL;
  129. symInfo.pfSymSetOptions = NULL;
  130. symInfo.pfSymGetOptions = NULL;
  131. symInfo.pfSymLoadModule64 = NULL;
  132. symInfo.pfSymGetModuleInfo64 = NULL;
  133. symInfo.pfSymFromName = NULL;
  134. return NULL;
  135. }
  136. symInfo.pfImagehlpApiVersionEx
  137. = (PF_ImagehlpApiVersionEx)GetProcAddress(symInfo.hDbgHelp,
  138. "ImagehlpApiVersionEx");
  139. symInfo.pfSymInitialize
  140. = (PF_SymInitialize)GetProcAddress(symInfo.hDbgHelp, "SymInitialize");
  141. symInfo.pfSymSetOptions
  142. = (PF_SymSetOptions)GetProcAddress(symInfo.hDbgHelp, "SymSetOptions");
  143. symInfo.pfSymGetOptions
  144. = (PF_SymGetOptions)GetProcAddress(symInfo.hDbgHelp, "SymGetOptions");
  145. symInfo.pfSymLoadModule64
  146. = (PF_SymLoadModule64)GetProcAddress(symInfo.hDbgHelp, "SymLoadModule64");
  147. symInfo.pfSymGetModuleInfo64
  148. = (PF_SymGetModuleInfo64)GetProcAddress(symInfo.hDbgHelp, "SymGetModuleInfo64");
  149. symInfo.pfSymFromName
  150. = (PF_SymFromName)GetProcAddress(symInfo.hDbgHelp, "SymFromName");
  151. API_VERSION av;
  152. ZeroMemory(&av, sizeof(av));
  153. av.MajorVersion = API_VERSION_NUMBER;
  154. if (symInfo.pfImagehlpApiVersionEx == NULL ||
  155. symInfo.pfSymInitialize == NULL ||
  156. symInfo.pfSymLoadModule64 == NULL ||
  157. symInfo.pfSymGetModuleInfo64 == NULL ||
  158. symInfo.pfSymFromName == NULL) {
  159. goto abort;
  160. }
  161. symInfo.pfImagehlpApiVersionEx(&av);
  162. if (av.MajorVersion < API_VERSION_NUMBER) {
  163. goto abort;
  164. }
  165. if (!symInfo.pfSymInitialize(symInfo.hProcess, NULL, FALSE)) {
  166. // We won't retry the initialize if it fails.
  167. goto abort;
  168. }
  169. if (symInfo.pfSymGetOptions != NULL && symInfo.pfSymSetOptions != NULL) {
  170. DWORD dw = symInfo.pfSymGetOptions();
  171. dw &= ~(SYMOPT_CASE_INSENSITIVE |
  172. SYMOPT_UNDNAME |
  173. SYMOPT_DEFERRED_LOADS |
  174. 0);
  175. dw |= (
  176. #if defined(SYMOPT_EXACT_SYMBOLS)
  177. SYMOPT_EXACT_SYMBOLS |
  178. #endif
  179. #if defined(SYMOPT_NO_UNQUALIFIED_LOADS)
  180. SYMOPT_NO_UNQUALIFIED_LOADS |
  181. #endif
  182. SYMOPT_DEFERRED_LOADS |
  183. #if defined(SYMOPT_FAIL_CRITICAL_ERRORS)
  184. SYMOPT_FAIL_CRITICAL_ERRORS |
  185. #endif
  186. #if defined(SYMOPT_INCLUDE_32BIT_MODULES)
  187. SYMOPT_INCLUDE_32BIT_MODULES |
  188. #endif
  189. 0);
  190. symInfo.pfSymSetOptions(dw);
  191. }
  192. pSymInfo = &symInfo;
  193. return pSymInfo;
  194. }
  195. PVOID WINAPI DetourFindFunction(PCSTR pszModule, PCSTR pszFunction)
  196. {
  197. /////////////////////////////////////////////// First, try GetProcAddress.
  198. //
  199. HMODULE hModule = LoadLibraryA(pszModule);
  200. if (hModule == NULL) {
  201. return NULL;
  202. }
  203. PBYTE pbCode = (PBYTE)GetProcAddress(hModule, pszFunction);
  204. if (pbCode) {
  205. return pbCode;
  206. }
  207. ////////////////////////////////////////////////////// Then try ImageHelp.
  208. //
  209. DETOUR_TRACE(("DetourFindFunction(%s, %s)\n", pszModule, pszFunction));
  210. PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
  211. if (pSymInfo == NULL) {
  212. DETOUR_TRACE(("DetourLoadImageHlp failed: %d\n",
  213. GetLastError()));
  214. return NULL;
  215. }
  216. if (pSymInfo->pfSymLoadModule64(pSymInfo->hProcess, NULL,
  217. (PCHAR)pszModule, NULL,
  218. (DWORD64)hModule, 0) == 0) {
  219. DETOUR_TRACE(("SymLoadModule64(%p) failed: %d\n",
  220. pSymInfo->hProcess, GetLastError()));
  221. // We don't stop because some version of dbghelp fail secondary calls.
  222. //return NULL;
  223. }
  224. HRESULT hrRet;
  225. CHAR szFullName[512];
  226. IMAGEHLP_MODULE64 modinfo;
  227. ZeroMemory(&modinfo, sizeof(modinfo));
  228. modinfo.SizeOfStruct = sizeof(modinfo);
  229. if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) {
  230. DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %d\n",
  231. pSymInfo->hProcess, hModule, GetLastError()));
  232. return NULL;
  233. }
  234. hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
  235. if (FAILED(hrRet)) {
  236. DETOUR_TRACE(("StringCchCopyA failed: %08x\n", hrRet));
  237. return NULL;
  238. }
  239. hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
  240. if (FAILED(hrRet)) {
  241. DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
  242. return NULL;
  243. }
  244. hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
  245. if (FAILED(hrRet)) {
  246. DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
  247. return NULL;
  248. }
  249. struct CFullSymbol : SYMBOL_INFO {
  250. CHAR szRestOfName[512];
  251. } symbol;
  252. ZeroMemory(&symbol, sizeof(symbol));
  253. //symbol.ModBase = (ULONG64)hModule;
  254. symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
  255. #ifdef DBHLPAPI
  256. symbol.MaxNameLen = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
  257. #else
  258. symbol.MaxNameLength = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
  259. #endif
  260. if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
  261. DETOUR_TRACE(("SymFromName(%s) failed: %d\n", szFullName, GetLastError()));
  262. return NULL;
  263. }
  264. #ifdef DETOURS_IA64
  265. // On the IA64, we get a raw code pointer from the symbol engine
  266. // and have to convert it to a wrapped [code pointer, global pointer].
  267. //
  268. PPLABEL_DESCRIPTOR pldEntry = (PPLABEL_DESCRIPTOR)DetourGetEntryPoint(hModule);
  269. PPLABEL_DESCRIPTOR pldSymbol = new PLABEL_DESCRIPTOR;
  270. pldSymbol->EntryPoint = symbol.Address;
  271. pldSymbol->GlobalPointer = pldEntry->GlobalPointer;
  272. return (PBYTE)pldSymbol;
  273. #else
  274. return (PBYTE)symbol.Address;
  275. #endif
  276. }
  277. //////////////////////////////////////////////////// Module Image Functions.
  278. //
  279. HMODULE WINAPI DetourEnumerateModules(HMODULE hModuleLast)
  280. {
  281. PBYTE pbLast;
  282. if (hModuleLast == NULL) {
  283. pbLast = (PBYTE)0x10000;
  284. }
  285. else {
  286. pbLast = (PBYTE)hModuleLast + 0x10000;
  287. }
  288. MEMORY_BASIC_INFORMATION mbi;
  289. ZeroMemory(&mbi, sizeof(mbi));
  290. // Find the next memory region that contains a mapped PE image.
  291. //
  292. for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
  293. if (VirtualQuery((PVOID)pbLast, &mbi, sizeof(mbi)) <= 0) {
  294. break;
  295. }
  296. // Skip uncommitted regions and guard pages.
  297. //
  298. if ((mbi.State != MEM_COMMIT) || (mbi.Protect & PAGE_GUARD)) {
  299. continue;
  300. }
  301. __try {
  302. PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbLast;
  303. if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  304. continue;
  305. }
  306. PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
  307. pDosHeader->e_lfanew);
  308. if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
  309. continue;
  310. }
  311. return (HMODULE)pDosHeader;
  312. }
  313. __except(EXCEPTION_EXECUTE_HANDLER) {
  314. return NULL;
  315. }
  316. }
  317. return NULL;
  318. }
  319. PVOID WINAPI DetourGetEntryPoint(HMODULE hModule)
  320. {
  321. PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
  322. if (hModule == NULL) {
  323. pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
  324. }
  325. __try {
  326. if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  327. SetLastError(ERROR_BAD_EXE_FORMAT);
  328. return NULL;
  329. }
  330. PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
  331. pDosHeader->e_lfanew);
  332. if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
  333. SetLastError(ERROR_INVALID_EXE_SIGNATURE);
  334. return NULL;
  335. }
  336. if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
  337. SetLastError(ERROR_EXE_MARKED_INVALID);
  338. return NULL;
  339. }
  340. SetLastError(NO_ERROR);
  341. return ((PBYTE)pDosHeader) +
  342. pNtHeader->OptionalHeader.AddressOfEntryPoint;
  343. }
  344. __except(EXCEPTION_EXECUTE_HANDLER) {
  345. SetLastError(ERROR_EXE_MARKED_INVALID);
  346. return NULL;
  347. }
  348. }
  349. ULONG WINAPI DetourGetModuleSize(HMODULE hModule)
  350. {
  351. PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
  352. if (hModule == NULL) {
  353. pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
  354. }
  355. __try {
  356. if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  357. SetLastError(ERROR_BAD_EXE_FORMAT);
  358. return NULL;
  359. }
  360. PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
  361. pDosHeader->e_lfanew);
  362. if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
  363. SetLastError(ERROR_INVALID_EXE_SIGNATURE);
  364. return NULL;
  365. }
  366. if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
  367. SetLastError(ERROR_EXE_MARKED_INVALID);
  368. return NULL;
  369. }
  370. SetLastError(NO_ERROR);
  371. return (pNtHeader->OptionalHeader.SizeOfImage);
  372. }
  373. __except(EXCEPTION_EXECUTE_HANDLER) {
  374. SetLastError(ERROR_EXE_MARKED_INVALID);
  375. return NULL;
  376. }
  377. }
  378. static inline PBYTE RvaAdjust(PIMAGE_DOS_HEADER pDosHeader, DWORD raddr)
  379. {
  380. if (raddr != NULL) {
  381. return ((PBYTE)pDosHeader) + raddr;
  382. }
  383. return NULL;
  384. }
  385. BOOL WINAPI DetourEnumerateExports(HMODULE hModule,
  386. PVOID pContext,
  387. PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
  388. {
  389. PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
  390. if (hModule == NULL) {
  391. pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
  392. }
  393. __try {
  394. if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  395. SetLastError(ERROR_BAD_EXE_FORMAT);
  396. return NULL;
  397. }
  398. PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
  399. pDosHeader->e_lfanew);
  400. if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
  401. SetLastError(ERROR_INVALID_EXE_SIGNATURE);
  402. return FALSE;
  403. }
  404. if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
  405. SetLastError(ERROR_EXE_MARKED_INVALID);
  406. return FALSE;
  407. }
  408. PIMAGE_EXPORT_DIRECTORY pExportDir
  409. = (PIMAGE_EXPORT_DIRECTORY)
  410. RvaAdjust(pDosHeader,
  411. pNtHeader->OptionalHeader
  412. .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  413. if (pExportDir == NULL) {
  414. SetLastError(ERROR_EXE_MARKED_INVALID);
  415. return FALSE;
  416. }
  417. PDWORD pdwFunctions = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfFunctions);
  418. PDWORD pdwNames = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNames);
  419. PWORD pwOrdinals = (PWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNameOrdinals);
  420. for (DWORD nFunc = 0; nFunc < pExportDir->NumberOfFunctions; nFunc++) {
  421. PBYTE pbCode = (pdwFunctions != NULL)
  422. ? (PBYTE)RvaAdjust(pDosHeader, pdwFunctions[nFunc]) : NULL;
  423. PCHAR pszName = NULL;
  424. for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) {
  425. if (pwOrdinals[n] == nFunc) {
  426. pszName = (pdwNames != NULL)
  427. ? (PCHAR)RvaAdjust(pDosHeader, pdwNames[n]) : NULL;
  428. break;
  429. }
  430. }
  431. ULONG nOrdinal = pExportDir->Base + nFunc;
  432. if (!pfExport(pContext, nOrdinal, pszName, pbCode)) {
  433. break;
  434. }
  435. }
  436. SetLastError(NO_ERROR);
  437. return TRUE;
  438. }
  439. __except(EXCEPTION_EXECUTE_HANDLER) {
  440. SetLastError(ERROR_EXE_MARKED_INVALID);
  441. return NULL;
  442. }
  443. }
  444. static PDETOUR_LOADED_BINARY WINAPI GetPayloadSectionFromModule(HMODULE hModule)
  445. {
  446. PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
  447. if (hModule == NULL) {
  448. pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
  449. }
  450. __try {
  451. if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  452. SetLastError(ERROR_BAD_EXE_FORMAT);
  453. return NULL;
  454. }
  455. PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
  456. pDosHeader->e_lfanew);
  457. if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
  458. SetLastError(ERROR_INVALID_EXE_SIGNATURE);
  459. return NULL;
  460. }
  461. if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
  462. SetLastError(ERROR_EXE_MARKED_INVALID);
  463. return NULL;
  464. }
  465. PIMAGE_SECTION_HEADER pSectionHeaders
  466. = (PIMAGE_SECTION_HEADER)((PBYTE)pNtHeader
  467. + sizeof(pNtHeader->Signature)
  468. + sizeof(pNtHeader->FileHeader)
  469. + pNtHeader->FileHeader.SizeOfOptionalHeader);
  470. for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; n++) {
  471. if (strcmp((PCHAR)pSectionHeaders[n].Name, ".detour") == 0) {
  472. if (pSectionHeaders[n].VirtualAddress == 0 ||
  473. pSectionHeaders[n].SizeOfRawData == 0) {
  474. break;
  475. }
  476. PBYTE pbData = (PBYTE)pDosHeader + pSectionHeaders[n].VirtualAddress;
  477. DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pbData;
  478. if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
  479. pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
  480. break;
  481. }
  482. if (pHeader->nDataOffset == 0) {
  483. pHeader->nDataOffset = pHeader->cbHeaderSize;
  484. }
  485. SetLastError(NO_ERROR);
  486. return (PBYTE)pHeader;
  487. }
  488. }
  489. SetLastError(ERROR_EXE_MARKED_INVALID);
  490. return NULL;
  491. }
  492. __except(EXCEPTION_EXECUTE_HANDLER) {
  493. SetLastError(ERROR_EXE_MARKED_INVALID);
  494. return NULL;
  495. }
  496. }
  497. DWORD WINAPI DetourGetSizeOfPayloads(HMODULE hModule)
  498. {
  499. PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
  500. if (pBinary == NULL) {
  501. // Error set by GetPayloadSectonFromModule.
  502. return 0;
  503. }
  504. __try {
  505. DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
  506. if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
  507. pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
  508. SetLastError(ERROR_INVALID_HANDLE);
  509. return 0;
  510. }
  511. SetLastError(NO_ERROR);
  512. return pHeader->cbDataSize;
  513. }
  514. __except(EXCEPTION_EXECUTE_HANDLER) {
  515. SetLastError(ERROR_INVALID_HANDLE);
  516. return 0;
  517. }
  518. }
  519. PVOID WINAPI DetourFindPayload(HMODULE hModule, REFGUID rguid, DWORD * pcbData)
  520. {
  521. PBYTE pbData = NULL;
  522. if (pcbData) {
  523. *pcbData = 0;
  524. }
  525. PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
  526. if (pBinary == NULL) {
  527. // Error set by GetPayloadSectonFromModule.
  528. return NULL;
  529. }
  530. __try {
  531. DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
  532. if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
  533. pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
  534. SetLastError(ERROR_INVALID_EXE_SIGNATURE);
  535. return NULL;
  536. }
  537. PBYTE pbBeg = ((PBYTE)pHeader) + pHeader->nDataOffset;
  538. PBYTE pbEnd = ((PBYTE)pHeader) + pHeader->cbDataSize;
  539. for (pbData = pbBeg; pbData < pbEnd;) {
  540. DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
  541. if (pSection->guid.Data1 == rguid.Data1 &&
  542. pSection->guid.Data2 == rguid.Data2 &&
  543. pSection->guid.Data3 == rguid.Data3 &&
  544. pSection->guid.Data4[0] == rguid.Data4[0] &&
  545. pSection->guid.Data4[1] == rguid.Data4[1] &&
  546. pSection->guid.Data4[2] == rguid.Data4[2] &&
  547. pSection->guid.Data4[3] == rguid.Data4[3] &&
  548. pSection->guid.Data4[4] == rguid.Data4[4] &&
  549. pSection->guid.Data4[5] == rguid.Data4[5] &&
  550. pSection->guid.Data4[6] == rguid.Data4[6] &&
  551. pSection->guid.Data4[7] == rguid.Data4[7]) {
  552. if (pcbData) {
  553. *pcbData = pSection->cbBytes - sizeof(*pSection);
  554. SetLastError(NO_ERROR);
  555. return (PBYTE)(pSection + 1);
  556. }
  557. }
  558. pbData = (PBYTE)pSection + pSection->cbBytes;
  559. }
  560. SetLastError(ERROR_INVALID_HANDLE);
  561. return NULL;
  562. }
  563. __except(EXCEPTION_EXECUTE_HANDLER) {
  564. SetLastError(ERROR_INVALID_HANDLE);
  565. return NULL;
  566. }
  567. }
  568. BOOL WINAPI DetourRestoreAfterWithEx(PVOID pvData, DWORD cbData)
  569. {
  570. PDETOUR_EXE_RESTORE pder = (PDETOUR_EXE_RESTORE)pvData;
  571. if (pder->cb != sizeof(*pder) || pder->cb > cbData) {
  572. SetLastError(ERROR_BAD_EXE_FORMAT);
  573. return FALSE;
  574. }
  575. DWORD dwPermIdh;
  576. DWORD dwPermInh;
  577. DWORD dwPermClr;
  578. DWORD dwOld;
  579. BOOL fSucceeded = FALSE;
  580. if (!VirtualProtect(pder->pidh, sizeof(pder->idh),
  581. PAGE_EXECUTE_READWRITE, &dwPermIdh)) {
  582. goto end0;
  583. }
  584. if (!VirtualProtect(pder->pinh, sizeof(pder->inh),
  585. PAGE_EXECUTE_READWRITE, &dwPermInh)) {
  586. goto end1;
  587. }
  588. if (pder->pclrFlags != NULL) {
  589. if (!VirtualProtect(pder->pclrFlags, sizeof(pder->clrFlags),
  590. PAGE_EXECUTE_READWRITE, &dwPermClr)) {
  591. goto end2;
  592. }
  593. }
  594. CopyMemory(pder->pidh, &pder->idh, sizeof(pder->idh));
  595. CopyMemory(pder->pinh, &pder->inh, sizeof(pder->inh));
  596. if (pder->pclrFlags != NULL) {
  597. CopyMemory(pder->pclrFlags, &pder->clrFlags, sizeof(pder->clrFlags));
  598. }
  599. fSucceeded = TRUE;
  600. if (pder->pclrFlags != NULL) {
  601. VirtualProtect(pder->pclrFlags, sizeof(pder->clrFlags), dwPermIdh, &dwOld);
  602. }
  603. end2:
  604. VirtualProtect(pder->pinh, sizeof(pder->inh), dwPermInh, &dwOld);
  605. end1:
  606. VirtualProtect(pder->pidh, sizeof(pder->idh), dwPermIdh, &dwOld);
  607. end0:
  608. return fSucceeded;
  609. }
  610. BOOL WINAPI DetourRestoreAfterWith()
  611. {
  612. for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
  613. PVOID pvData;
  614. DWORD cbData;
  615. pvData = DetourFindPayload(hMod, DETOUR_EXE_RESTORE_GUID, &cbData);
  616. if (pvData == NULL || cbData == 0) {
  617. continue;
  618. }
  619. return DetourRestoreAfterWithEx(pvData, cbData);
  620. }
  621. SetLastError(ERROR_MOD_NOT_FOUND);
  622. return FALSE;
  623. }
  624. // End of File