modules.cpp 19 KB

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