image.cpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Image manipulation functions (image.cpp of detours.lib)
  4. //
  5. // Microsoft Research Detours Package, Version 2.1.
  6. //
  7. // Copyright (c) Microsoft Corporation. All rights reserved.
  8. //
  9. // Used for for payloads, byways, and imports.
  10. //
  11. #include <windows.h>
  12. #if (_MSC_VER < 1310)
  13. #else
  14. #include <strsafe.h>
  15. #endif
  16. #if (_MSC_VER < 1299)
  17. #pragma warning(disable: 4710)
  18. #else
  19. #endif
  20. //#define DETOUR_DEBUG 1
  21. #define DETOURS_INTERNAL
  22. #include "detours.h"
  23. namespace Detour
  24. {
  25. //////////////////////////////////////////////////////////////////////////////
  26. //
  27. #ifndef _STRSAFE_H_INCLUDED_
  28. static inline HRESULT StringCchLengthA( const char * psz , size_t cchMax , size_t * pcch )
  29. {
  30. HRESULT hr = S_OK;
  31. size_t cchMaxPrev = cchMax;
  32. if ( cchMax > 2147483647 )
  33. {
  34. return ERROR_INVALID_PARAMETER;
  35. }
  36. while ( cchMax && ( *psz != '\0' ) )
  37. {
  38. psz++;
  39. cchMax--;
  40. }
  41. if ( cchMax == 0 )
  42. {
  43. // the string is longer than cchMax
  44. hr = ERROR_INVALID_PARAMETER;
  45. }
  46. if ( SUCCEEDED( hr ) && pcch )
  47. {
  48. *pcch = cchMaxPrev - cchMax;
  49. }
  50. return hr;
  51. }
  52. static inline HRESULT StringCchCopyA( char * pszDest , size_t cchDest , const char * pszSrc )
  53. {
  54. HRESULT hr = S_OK;
  55. if ( cchDest == 0 )
  56. {
  57. // can not null terminate a zero-byte dest buffer
  58. hr = ERROR_INVALID_PARAMETER;
  59. }
  60. else
  61. {
  62. while ( cchDest && ( *pszSrc != '\0' ) )
  63. {
  64. *pszDest++ = *pszSrc++;
  65. cchDest--;
  66. }
  67. if ( cchDest == 0 )
  68. {
  69. // we are going to truncate pszDest
  70. pszDest--;
  71. hr = ERROR_INVALID_PARAMETER;
  72. }
  73. *pszDest = '\0';
  74. }
  75. return hr;
  76. }
  77. static inline HRESULT StringCchCatA( char * pszDest , size_t cchDest , const char * pszSrc )
  78. {
  79. HRESULT hr;
  80. size_t cchDestCurrent;
  81. if ( cchDest > 2147483647 )
  82. {
  83. return ERROR_INVALID_PARAMETER;
  84. }
  85. hr = StringCchLengthA( pszDest,cchDest,&cchDestCurrent );
  86. if ( SUCCEEDED( hr ) )
  87. {
  88. hr = StringCchCopyA( pszDest + cchDestCurrent,cchDest - cchDestCurrent,pszSrc );
  89. }
  90. return hr;
  91. }
  92. #endif
  93. ///////////////////////////////////////////////////////////////////////////////
  94. //
  95. class CImageData
  96. {
  97. friend class CImage;
  98. public:
  99. CImageData( PBYTE pbData , DWORD cbData );
  100. ~CImageData();
  101. PBYTE Enumerate( GUID * pGuid , DWORD * pcbData , DWORD * pnIterator );
  102. PBYTE Find( REFGUID rguid , DWORD * pcbData );
  103. PBYTE Set( REFGUID rguid , PBYTE pbData , DWORD cbData );
  104. BOOL Delete( REFGUID rguid );
  105. BOOL Purge();
  106. BOOL IsEmpty()
  107. {
  108. return m_cbData == 0;
  109. }
  110. BOOL IsValid();
  111. protected:
  112. BOOL SizeTo( DWORD cbData );
  113. protected:
  114. PBYTE m_pbData;
  115. DWORD m_cbData;
  116. DWORD m_cbAlloc;
  117. };
  118. class CImageImportFile
  119. {
  120. friend class CImage;
  121. friend class CImageImportName;
  122. public:
  123. CImageImportFile();
  124. ~CImageImportFile();
  125. public:
  126. CImageImportFile * m_pNextFile;
  127. BOOL m_fByway;
  128. CImageImportName * m_pImportNames;
  129. DWORD m_nImportNames;
  130. DWORD m_rvaOriginalFirstThunk;
  131. DWORD m_rvaFirstThunk;
  132. DWORD m_nForwarderChain;
  133. PCHAR m_pszOrig;
  134. PCHAR m_pszName;
  135. };
  136. class CImageImportName
  137. {
  138. friend class CImage;
  139. friend class CImageImportFile;
  140. public:
  141. CImageImportName();
  142. ~CImageImportName();
  143. public:
  144. WORD m_nHint;
  145. ULONG m_nOrig;
  146. ULONG m_nOrdinal;
  147. PCHAR m_pszOrig;
  148. PCHAR m_pszName;
  149. };
  150. class CImage
  151. {
  152. friend class CImageThunks;
  153. friend class CImageChars;
  154. friend class CImageImportFile;
  155. friend class CImageImportName;
  156. public:
  157. CImage();
  158. ~CImage();
  159. static CImage * IsValid( PDETOUR_BINARY pBinary );
  160. public: // File Functions
  161. BOOL Read( HANDLE hFile );
  162. BOOL Write( HANDLE hFile );
  163. BOOL Close();
  164. public: // Manipulation Functions
  165. PBYTE DataEnum( GUID * pGuid , DWORD * pcbData , DWORD * pnIterator );
  166. PBYTE DataFind( REFGUID rguid , DWORD * pcbData );
  167. PBYTE DataSet( REFGUID rguid , PBYTE pbData , DWORD cbData );
  168. BOOL DataDelete( REFGUID rguid );
  169. BOOL DataPurge();
  170. BOOL EditImports( PVOID pContext , PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback , PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback , PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback , PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback );
  171. protected:
  172. BOOL WriteFile( HANDLE hFile , LPCVOID lpBuffer , DWORD nNumberOfBytesToWrite , LPDWORD lpNumberOfBytesWritten );
  173. BOOL CopyFileData( HANDLE hFile , DWORD nOldPos , DWORD cbData );
  174. BOOL ZeroFileData( HANDLE hFile , DWORD cbData );
  175. BOOL AlignFileData( HANDLE hFile );
  176. BOOL SizeOutputBuffer( DWORD cbData );
  177. PBYTE AllocateOutput( DWORD cbData , DWORD * pnVirtAddr );
  178. PVOID RvaToVa( ULONG_PTR nRva );
  179. DWORD RvaToFileOffset( DWORD nRva );
  180. DWORD FileAlign( DWORD nAddr );
  181. DWORD SectionAlign( DWORD nAddr );
  182. BOOL CheckImportsNeeded( DWORD * pnTables , DWORD * pnThunks , DWORD * pnChars );
  183. CImageImportFile * NewByway( __in_z PCHAR pszName );
  184. private:
  185. DWORD m_dwValidSignature;
  186. CImageData * m_pImageData; // Read & Write
  187. HANDLE m_hMap; // Read & Write
  188. PBYTE m_pMap; // Read & Write
  189. DWORD m_nNextFileAddr; // Write
  190. DWORD m_nNextVirtAddr; // Write
  191. IMAGE_DOS_HEADER m_DosHeader; // Read & Write
  192. IMAGE_NT_HEADERS m_NtHeader; // Read & Write
  193. IMAGE_SECTION_HEADER m_SectionHeaders[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
  194. DWORD m_nPrePE;
  195. DWORD m_cbPrePE;
  196. DWORD m_cbPostPE;
  197. DWORD m_nPeOffset;
  198. DWORD m_nSectionsOffset;
  199. DWORD m_nExtraOffset;
  200. DWORD m_nFileSize;
  201. DWORD m_nOutputVirtAddr;
  202. DWORD m_nOutputVirtSize;
  203. DWORD m_nOutputFileAddr;
  204. PBYTE m_pbOutputBuffer;
  205. DWORD m_cbOutputBuffer;
  206. CImageImportFile * m_pImportFiles;
  207. DWORD m_nImportFiles;
  208. BOOL m_fHadDetourSection;
  209. private:
  210. enum
  211. {
  212. DETOUR_IMAGE_VALID_SIGNATURE = 0xfedcba01 , // "Dtr\0"
  213. };
  214. };
  215. //////////////////////////////////////////////////////////////////////////////
  216. //
  217. static BYTE s_rbDosCode[0x10] ={0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, '*', '*'};
  218. static inline DWORD Max( DWORD a , DWORD b )
  219. {
  220. return a > b ? a : b;
  221. }
  222. static inline DWORD Align( DWORD a , DWORD size )
  223. {
  224. size--;
  225. return ( a + size ) & ~size;
  226. }
  227. static inline DWORD QuadAlign( DWORD a )
  228. {
  229. return Align( a,8 );
  230. }
  231. static PCHAR DuplicateString( __in_z PCHAR pszIn )
  232. {
  233. if ( pszIn )
  234. {
  235. UINT nIn = ( UINT ) strlen( pszIn );
  236. PCHAR pszOut = new CHAR[nIn + 1];
  237. if ( pszOut == NULL )
  238. {
  239. SetLastError( ERROR_OUTOFMEMORY );
  240. }
  241. else
  242. {
  243. CopyMemory( pszOut,pszIn,nIn + 1 );
  244. }
  245. return pszOut;
  246. }
  247. return NULL;
  248. }
  249. static PCHAR ReplaceString( __deref_out PCHAR * ppsz , __in_z PCHAR pszIn )
  250. {
  251. if ( ppsz == NULL )
  252. {
  253. return NULL;
  254. }
  255. UINT nIn;
  256. if ( *ppsz != NULL )
  257. {
  258. if ( strcmp( *ppsz,pszIn ) == 0 )
  259. {
  260. return *ppsz;
  261. }
  262. nIn = ( UINT ) strlen( pszIn );
  263. if ( strlen( *ppsz ) == nIn )
  264. {
  265. CopyMemory( *ppsz,pszIn,nIn + 1 );
  266. return *ppsz;
  267. }
  268. else
  269. {
  270. delete[] * ppsz;
  271. *ppsz = NULL;
  272. }
  273. }
  274. else
  275. {
  276. nIn = ( UINT ) strlen( pszIn );
  277. }
  278. *ppsz = new CHAR[nIn + 1];
  279. if ( *ppsz == NULL )
  280. {
  281. SetLastError( ERROR_OUTOFMEMORY );
  282. }
  283. else
  284. {
  285. CopyMemory( *ppsz,pszIn,nIn + 1 );
  286. }
  287. return *ppsz;
  288. }
  289. //////////////////////////////////////////////////////////////////////////////
  290. //
  291. CImageImportFile::CImageImportFile()
  292. {
  293. m_pNextFile = NULL;
  294. m_fByway = FALSE;
  295. m_pImportNames = NULL;
  296. m_nImportNames = 0;
  297. m_rvaOriginalFirstThunk = 0;
  298. m_rvaFirstThunk = 0;
  299. m_nForwarderChain = ( UINT ) 0;
  300. m_pszName = NULL;
  301. m_pszOrig = NULL;
  302. }
  303. CImageImportFile::~CImageImportFile()
  304. {
  305. if ( m_pNextFile )
  306. {
  307. delete m_pNextFile;
  308. m_pNextFile = NULL;
  309. }
  310. if ( m_pImportNames )
  311. {
  312. delete[] m_pImportNames;
  313. m_pImportNames = NULL;
  314. m_nImportNames = 0;
  315. }
  316. if ( m_pszName )
  317. {
  318. delete[] m_pszName;
  319. m_pszName = NULL;
  320. }
  321. if ( m_pszOrig )
  322. {
  323. delete[] m_pszOrig;
  324. m_pszOrig = NULL;
  325. }
  326. }
  327. CImageImportName::CImageImportName()
  328. {
  329. m_nOrig = 0;
  330. m_nOrdinal = 0;
  331. m_nHint = 0;
  332. m_pszName = NULL;
  333. m_pszOrig = NULL;
  334. }
  335. CImageImportName::~CImageImportName()
  336. {
  337. if ( m_pszName )
  338. {
  339. delete[] m_pszName;
  340. m_pszName = NULL;
  341. }
  342. if ( m_pszOrig )
  343. {
  344. delete[] m_pszOrig;
  345. m_pszOrig = NULL;
  346. }
  347. }
  348. //////////////////////////////////////////////////////////////////////////////
  349. //
  350. CImageData::CImageData( PBYTE pbData , DWORD cbData )
  351. {
  352. m_pbData = pbData;
  353. m_cbData = cbData;
  354. m_cbAlloc = 0;
  355. }
  356. CImageData::~CImageData()
  357. {
  358. IsValid();
  359. if ( m_cbAlloc == 0 )
  360. {
  361. m_pbData = NULL;
  362. }
  363. if ( m_pbData )
  364. {
  365. delete[] m_pbData;
  366. m_pbData = NULL;
  367. }
  368. m_cbData = 0;
  369. m_cbAlloc = 0;
  370. }
  371. BOOL CImageData::SizeTo( DWORD cbData )
  372. {
  373. IsValid();
  374. if ( cbData <= m_cbAlloc )
  375. {
  376. return TRUE;
  377. }
  378. PBYTE pbNew = new BYTE[cbData];
  379. if ( pbNew == NULL )
  380. {
  381. SetLastError( ERROR_OUTOFMEMORY );
  382. return FALSE;
  383. }
  384. if ( m_pbData )
  385. {
  386. CopyMemory( pbNew,m_pbData,m_cbData );
  387. if ( m_cbAlloc > 0 )
  388. {
  389. delete[] m_pbData;
  390. }
  391. m_pbData = NULL;
  392. }
  393. m_pbData = pbNew;
  394. m_cbAlloc = cbData;
  395. IsValid();
  396. return TRUE;
  397. }
  398. BOOL CImageData::Purge()
  399. {
  400. m_cbData = 0;
  401. IsValid();
  402. return TRUE;
  403. }
  404. BOOL CImageData::IsValid()
  405. {
  406. if ( m_pbData == NULL )
  407. {
  408. return TRUE;
  409. }
  410. PBYTE pbBeg = m_pbData;
  411. PBYTE pbEnd = m_pbData + m_cbData;
  412. for ( PBYTE pbIter = pbBeg; pbIter < pbEnd; )
  413. {
  414. PDETOUR_SECTION_RECORD pRecord = ( PDETOUR_SECTION_RECORD ) pbIter;
  415. if ( pRecord->cbBytes < sizeof( DETOUR_SECTION_RECORD ) )
  416. {
  417. return FALSE;
  418. }
  419. if ( pRecord->nReserved != 0 )
  420. {
  421. return FALSE;
  422. }
  423. pbIter += pRecord->cbBytes;
  424. }
  425. return TRUE;
  426. }
  427. PBYTE CImageData::Enumerate( GUID * pGuid , DWORD * pcbData , DWORD * pnIterator )
  428. {
  429. IsValid();
  430. if ( pnIterator == NULL || m_cbData < *pnIterator + sizeof( DETOUR_SECTION_RECORD ) )
  431. {
  432. if ( pcbData )
  433. {
  434. *pcbData = 0;
  435. }
  436. if ( pGuid )
  437. {
  438. ZeroMemory( pGuid,sizeof( *pGuid ) );
  439. }
  440. return NULL;
  441. }
  442. PDETOUR_SECTION_RECORD pRecord = ( PDETOUR_SECTION_RECORD ) ( m_pbData + *pnIterator );
  443. if ( pGuid )
  444. {
  445. *pGuid = pRecord->guid;
  446. }
  447. if ( pcbData )
  448. {
  449. *pcbData = pRecord->cbBytes - sizeof( DETOUR_SECTION_RECORD );
  450. }
  451. *pnIterator = ( LONG ) ( ( ( PBYTE ) pRecord - m_pbData ) + pRecord->cbBytes );
  452. return ( PBYTE ) ( pRecord + 1 );
  453. }
  454. PBYTE CImageData::Find( REFGUID rguid , DWORD * pcbData )
  455. {
  456. IsValid();
  457. DWORD cbBytes = sizeof( DETOUR_SECTION_RECORD );
  458. for ( DWORD nOffset = 0; nOffset < m_cbData; nOffset += cbBytes )
  459. {
  460. PDETOUR_SECTION_RECORD pRecord = ( PDETOUR_SECTION_RECORD ) ( m_pbData + nOffset );
  461. cbBytes = pRecord->cbBytes;
  462. if ( cbBytes > m_cbData )
  463. {
  464. break;
  465. }
  466. if ( cbBytes < sizeof( DETOUR_SECTION_RECORD ) )
  467. {
  468. continue;
  469. }
  470. if ( pRecord->guid.Data1 == rguid.Data1 && pRecord->guid.Data2 == rguid.Data2 && pRecord->guid.Data3 == rguid.Data3 && pRecord->guid.Data4[0] == rguid.Data4[0] && pRecord->guid.Data4[1] == rguid.Data4[1] && pRecord->guid.Data4[2] == rguid.Data4[2] && pRecord->guid.Data4[3] == rguid.Data4[3] && pRecord->guid.Data4[4] == rguid.Data4[4] && pRecord->guid.Data4[5] == rguid.Data4[5] && pRecord->guid.Data4[6] == rguid.Data4[6] && pRecord->guid.Data4[7] == rguid.Data4[7] )
  471. {
  472. *pcbData = cbBytes - sizeof( DETOUR_SECTION_RECORD );
  473. return ( PBYTE ) ( pRecord + 1 );
  474. }
  475. }
  476. if ( pcbData )
  477. {
  478. *pcbData = 0;
  479. }
  480. return NULL;
  481. }
  482. BOOL CImageData::Delete( REFGUID rguid )
  483. {
  484. IsValid();
  485. PBYTE pbFound = NULL;
  486. DWORD cbFound = 0;
  487. pbFound = Find( rguid,&cbFound );
  488. if ( pbFound == NULL )
  489. {
  490. SetLastError( ERROR_MOD_NOT_FOUND );
  491. return FALSE;
  492. }
  493. pbFound -= sizeof( DETOUR_SECTION_RECORD );
  494. cbFound += sizeof( DETOUR_SECTION_RECORD );
  495. PBYTE pbRestData = pbFound + cbFound;
  496. DWORD cbRestData = m_cbData - ( LONG ) ( pbRestData - m_pbData );
  497. if ( cbRestData )
  498. {
  499. MoveMemory( pbFound,pbRestData,cbRestData );
  500. }
  501. m_cbData -= cbFound;
  502. IsValid();
  503. return TRUE;
  504. }
  505. PBYTE CImageData::Set( REFGUID rguid , PBYTE pbData , DWORD cbData )
  506. {
  507. IsValid();
  508. Delete( rguid );
  509. DWORD cbAlloc = QuadAlign( cbData );
  510. if ( !SizeTo( m_cbData + cbAlloc + sizeof( DETOUR_SECTION_RECORD ) ) )
  511. {
  512. return NULL;
  513. }
  514. PDETOUR_SECTION_RECORD pRecord = ( PDETOUR_SECTION_RECORD ) ( m_pbData + m_cbData );
  515. pRecord->cbBytes = cbAlloc + sizeof( DETOUR_SECTION_RECORD );
  516. pRecord->nReserved = 0;
  517. pRecord->guid = rguid;
  518. PBYTE pbDest = ( PBYTE ) ( pRecord + 1 );
  519. if ( pbData )
  520. {
  521. CopyMemory( pbDest,pbData,cbData );
  522. if ( cbData < cbAlloc )
  523. {
  524. ZeroMemory( pbDest + cbData,cbAlloc - cbData );
  525. }
  526. }
  527. else
  528. {
  529. if ( cbAlloc > 0 )
  530. {
  531. ZeroMemory( pbDest,cbAlloc );
  532. }
  533. }
  534. m_cbData += cbAlloc + sizeof( DETOUR_SECTION_RECORD );
  535. IsValid();
  536. return pbDest;
  537. }
  538. //////////////////////////////////////////////////////////////////////////////
  539. //
  540. class CImageThunks
  541. {
  542. private:
  543. CImage * m_pImage;
  544. PIMAGE_THUNK_DATA m_pThunks;
  545. DWORD m_nThunks;
  546. DWORD m_nThunksMax;
  547. DWORD m_nThunkVirtAddr;
  548. public:
  549. CImageThunks( CImage * pImage , DWORD nThunksMax , DWORD * pnAddr )
  550. {
  551. m_pImage = pImage;
  552. m_nThunks = 0;
  553. m_nThunksMax = nThunksMax;
  554. m_pThunks = ( PIMAGE_THUNK_DATA ) m_pImage->AllocateOutput( sizeof( IMAGE_THUNK_DATA ) * nThunksMax,&m_nThunkVirtAddr );
  555. *pnAddr = m_nThunkVirtAddr;
  556. }
  557. PIMAGE_THUNK_DATA Current( DWORD * pnVirtAddr )
  558. {
  559. if ( m_nThunksMax > 1 )
  560. {
  561. *pnVirtAddr = m_nThunkVirtAddr;
  562. return m_pThunks;
  563. }
  564. *pnVirtAddr = 0;
  565. return NULL;
  566. }
  567. PIMAGE_THUNK_DATA Allocate( ULONG_PTR nData , DWORD * pnVirtAddr )
  568. {
  569. if ( m_nThunks < m_nThunksMax )
  570. {
  571. *pnVirtAddr = m_nThunkVirtAddr;
  572. m_nThunks++;
  573. m_nThunkVirtAddr += sizeof( IMAGE_THUNK_DATA );
  574. m_pThunks->u1.Ordinal = nData;
  575. return m_pThunks++;
  576. }
  577. *pnVirtAddr = 0;
  578. return NULL;
  579. }
  580. DWORD Size()
  581. {
  582. return m_nThunksMax * sizeof( IMAGE_THUNK_DATA );
  583. }
  584. };
  585. //////////////////////////////////////////////////////////////////////////////
  586. //
  587. class CImageChars
  588. {
  589. private:
  590. CImage * m_pImage;
  591. PCHAR m_pChars;
  592. DWORD m_nChars;
  593. DWORD m_nCharsMax;
  594. DWORD m_nCharVirtAddr;
  595. public:
  596. CImageChars( CImage * pImage , DWORD nCharsMax , DWORD * pnAddr )
  597. {
  598. m_pImage = pImage;
  599. m_nChars = 0;
  600. m_nCharsMax = nCharsMax;
  601. m_pChars = ( PCHAR ) m_pImage->AllocateOutput( nCharsMax,&m_nCharVirtAddr );
  602. *pnAddr = m_nCharVirtAddr;
  603. }
  604. PCHAR Allocate( __in_z PCHAR pszString , DWORD * pnVirtAddr )
  605. {
  606. DWORD nLen = ( DWORD ) strlen( pszString ) + 1;
  607. nLen += ( nLen & 1 );
  608. if ( m_nChars + nLen > m_nCharsMax )
  609. {
  610. *pnVirtAddr = 0;
  611. return NULL;
  612. }
  613. *pnVirtAddr = m_nCharVirtAddr;
  614. HRESULT hrRet = StringCchCopyA( m_pChars,m_nCharsMax,pszString );
  615. if ( FAILED( hrRet ) )
  616. {
  617. return NULL;
  618. }
  619. pszString = m_pChars;
  620. m_pChars += nLen;
  621. m_nChars += nLen;
  622. m_nCharVirtAddr += nLen;
  623. return pszString;
  624. }
  625. PCHAR Allocate( PCHAR pszString , DWORD nHint , DWORD * pnVirtAddr )
  626. {
  627. DWORD nLen = ( DWORD ) strlen( pszString ) + 1 + sizeof( USHORT );
  628. nLen += ( nLen & 1 );
  629. if ( m_nChars + nLen > m_nCharsMax )
  630. {
  631. *pnVirtAddr = 0;
  632. return NULL;
  633. }
  634. *pnVirtAddr = m_nCharVirtAddr;
  635. *( USHORT * ) m_pChars = ( USHORT ) nHint;
  636. HRESULT hrRet = StringCchCopyA( m_pChars + sizeof( USHORT ),m_nCharsMax,pszString );
  637. if ( FAILED( hrRet ) )
  638. {
  639. return NULL;
  640. }
  641. pszString = m_pChars + sizeof( USHORT );
  642. m_pChars += nLen;
  643. m_nChars += nLen;
  644. m_nCharVirtAddr += nLen;
  645. return pszString;
  646. }
  647. DWORD Size()
  648. {
  649. return m_nChars;
  650. }
  651. };
  652. //////////////////////////////////////////////////////////////////////////////
  653. //
  654. CImage * CImage::IsValid( PDETOUR_BINARY pBinary )
  655. {
  656. if ( pBinary )
  657. {
  658. CImage * pImage = ( CImage * ) pBinary;
  659. if ( pImage->m_dwValidSignature == DETOUR_IMAGE_VALID_SIGNATURE )
  660. {
  661. return pImage;
  662. }
  663. }
  664. SetLastError( ERROR_INVALID_HANDLE );
  665. return NULL;
  666. }
  667. CImage::CImage()
  668. {
  669. m_dwValidSignature = ( DWORD ) DETOUR_IMAGE_VALID_SIGNATURE;
  670. m_hMap = NULL;
  671. m_pMap = NULL;
  672. m_nPeOffset = 0;
  673. m_nSectionsOffset = 0;
  674. m_pbOutputBuffer = NULL;
  675. m_cbOutputBuffer = 0;
  676. m_pImageData = NULL;
  677. m_pImportFiles = NULL;
  678. m_nImportFiles = 0;
  679. m_fHadDetourSection = FALSE;
  680. }
  681. CImage::~CImage()
  682. {
  683. Close();
  684. m_dwValidSignature = 0;
  685. }
  686. BOOL CImage::Close()
  687. {
  688. if ( m_pImportFiles )
  689. {
  690. delete m_pImportFiles;
  691. m_pImportFiles = NULL;
  692. m_nImportFiles = 0;
  693. }
  694. if ( m_pImageData )
  695. {
  696. delete m_pImageData;
  697. m_pImageData = NULL;
  698. }
  699. if ( m_pMap != NULL )
  700. {
  701. UnmapViewOfFile( m_pMap );
  702. m_pMap = NULL;
  703. }
  704. if ( m_hMap )
  705. {
  706. CloseHandle( m_hMap );
  707. m_hMap = NULL;
  708. }
  709. if ( m_pbOutputBuffer )
  710. {
  711. delete[] m_pbOutputBuffer;
  712. m_pbOutputBuffer = NULL;
  713. m_cbOutputBuffer = 0;
  714. }
  715. return TRUE;
  716. }
  717. //////////////////////////////////////////////////////////////////////////////
  718. //
  719. PBYTE CImage::DataEnum( GUID * pGuid , DWORD * pcbData , DWORD * pnIterator )
  720. {
  721. if ( m_pImageData == NULL )
  722. {
  723. return NULL;
  724. }
  725. return m_pImageData->Enumerate( pGuid,pcbData,pnIterator );
  726. }
  727. PBYTE CImage::DataFind( REFGUID rguid , DWORD * pcbData )
  728. {
  729. if ( m_pImageData == NULL )
  730. {
  731. return NULL;
  732. }
  733. return m_pImageData->Find( rguid,pcbData );
  734. }
  735. PBYTE CImage::DataSet( REFGUID rguid , PBYTE pbData , DWORD cbData )
  736. {
  737. if ( m_pImageData == NULL )
  738. {
  739. return NULL;
  740. }
  741. return m_pImageData->Set( rguid,pbData,cbData );
  742. }
  743. BOOL CImage::DataDelete( REFGUID rguid )
  744. {
  745. if ( m_pImageData == NULL )
  746. {
  747. return FALSE;
  748. }
  749. return m_pImageData->Delete( rguid );
  750. }
  751. BOOL CImage::DataPurge()
  752. {
  753. if ( m_pImageData == NULL )
  754. {
  755. return TRUE;
  756. }
  757. return m_pImageData->Purge();
  758. }
  759. //////////////////////////////////////////////////////////////////////////////
  760. //
  761. BOOL CImage::SizeOutputBuffer( DWORD cbData )
  762. {
  763. if ( m_cbOutputBuffer < cbData )
  764. {
  765. if ( cbData < 1024 )
  766. {
  767. //65536
  768. cbData = 1024;
  769. }
  770. cbData = FileAlign( cbData );
  771. PBYTE pOutput = new BYTE[cbData];
  772. if ( pOutput == NULL )
  773. {
  774. SetLastError( ERROR_OUTOFMEMORY );
  775. return FALSE;
  776. }
  777. if ( m_pbOutputBuffer )
  778. {
  779. CopyMemory( pOutput,m_pbOutputBuffer,m_cbOutputBuffer );
  780. delete[] m_pbOutputBuffer;
  781. m_pbOutputBuffer = NULL;
  782. }
  783. ZeroMemory( pOutput + m_cbOutputBuffer,cbData - m_cbOutputBuffer ),
  784. m_pbOutputBuffer = pOutput;
  785. m_cbOutputBuffer = cbData;
  786. }
  787. return TRUE;
  788. }
  789. PBYTE CImage::AllocateOutput( DWORD cbData , DWORD * pnVirtAddr )
  790. {
  791. cbData = QuadAlign( cbData );
  792. PBYTE pbData = m_pbOutputBuffer + m_nOutputVirtSize;
  793. *pnVirtAddr = m_nOutputVirtAddr + m_nOutputVirtSize;
  794. m_nOutputVirtSize += cbData;
  795. if ( m_nOutputVirtSize > m_cbOutputBuffer )
  796. {
  797. SetLastError( ERROR_OUTOFMEMORY );
  798. return NULL;
  799. }
  800. ZeroMemory( pbData,cbData );
  801. return pbData;
  802. }
  803. //////////////////////////////////////////////////////////////////////////////
  804. //
  805. DWORD CImage::FileAlign( DWORD nAddr )
  806. {
  807. return Align( nAddr,m_NtHeader.OptionalHeader.FileAlignment );
  808. }
  809. DWORD CImage::SectionAlign( DWORD nAddr )
  810. {
  811. return Align( nAddr,m_NtHeader.OptionalHeader.SectionAlignment );
  812. }
  813. //////////////////////////////////////////////////////////////////////////////
  814. //
  815. PVOID CImage::RvaToVa( ULONG_PTR nRva )
  816. {
  817. if ( nRva == 0 )
  818. {
  819. return NULL;
  820. }
  821. for ( DWORD n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++ )
  822. {
  823. DWORD vaStart = m_SectionHeaders[n].VirtualAddress;
  824. DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;
  825. if ( nRva >= vaStart && nRva < vaEnd )
  826. {
  827. return ( PBYTE ) m_pMap + m_SectionHeaders[n].PointerToRawData + nRva - m_SectionHeaders[n].VirtualAddress;
  828. }
  829. }
  830. return NULL;
  831. }
  832. DWORD CImage::RvaToFileOffset( DWORD nRva )
  833. {
  834. DWORD n;
  835. for ( n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++ )
  836. {
  837. DWORD vaStart = m_SectionHeaders[n].VirtualAddress;
  838. DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;
  839. if ( nRva >= vaStart && nRva < vaEnd )
  840. {
  841. return m_SectionHeaders[n].PointerToRawData + nRva - m_SectionHeaders[n].VirtualAddress;
  842. }
  843. }
  844. return 0;
  845. }
  846. //////////////////////////////////////////////////////////////////////////////
  847. //
  848. BOOL CImage::WriteFile( HANDLE hFile , LPCVOID lpBuffer , DWORD nNumberOfBytesToWrite , LPDWORD lpNumberOfBytesWritten )
  849. {
  850. return ::WriteFile( hFile,lpBuffer,nNumberOfBytesToWrite,lpNumberOfBytesWritten,NULL );
  851. }
  852. BOOL CImage::CopyFileData( HANDLE hFile , DWORD nOldPos , DWORD cbData )
  853. {
  854. DWORD cbDone = 0;
  855. return WriteFile( hFile,m_pMap + nOldPos,cbData,&cbDone );
  856. }
  857. BOOL CImage::ZeroFileData( HANDLE hFile , DWORD cbData )
  858. {
  859. if ( !SizeOutputBuffer( 4096 ) )
  860. {
  861. return FALSE;
  862. }
  863. ZeroMemory( m_pbOutputBuffer,4096 );
  864. for ( DWORD cbLeft = cbData; cbLeft > 0; )
  865. {
  866. DWORD cbStep = cbLeft > sizeof( m_pbOutputBuffer ) ? sizeof( m_pbOutputBuffer ) : cbLeft;
  867. DWORD cbDone = 0;
  868. if ( !WriteFile( hFile,m_pbOutputBuffer,cbStep,&cbDone ) )
  869. {
  870. return FALSE;
  871. }
  872. if ( cbDone == 0 )
  873. {
  874. break;
  875. }
  876. cbLeft -= cbDone;
  877. }
  878. return TRUE;
  879. }
  880. BOOL CImage::AlignFileData( HANDLE hFile )
  881. {
  882. DWORD nLastFileAddr = m_nNextFileAddr;
  883. m_nNextFileAddr = FileAlign( m_nNextFileAddr );
  884. m_nNextVirtAddr = SectionAlign( m_nNextVirtAddr );
  885. if ( hFile != INVALID_HANDLE_VALUE )
  886. {
  887. if ( m_nNextFileAddr > nLastFileAddr )
  888. {
  889. if ( SetFilePointer( hFile,nLastFileAddr,NULL,FILE_BEGIN ) == ~0u )
  890. {
  891. return FALSE;
  892. }
  893. return ZeroFileData( hFile,m_nNextFileAddr - nLastFileAddr );
  894. }
  895. }
  896. return TRUE;
  897. }
  898. BOOL CImage::Read( HANDLE hFile )
  899. {
  900. DWORD n;
  901. PBYTE pbData = NULL;
  902. DWORD cbData = 0;
  903. if ( hFile == INVALID_HANDLE_VALUE )
  904. {
  905. SetLastError( ERROR_INVALID_HANDLE );
  906. return FALSE;
  907. }
  908. ///////////////////////////////////////////////////////// Create mapping.
  909. //
  910. m_nFileSize = GetFileSize( hFile,NULL );
  911. if ( m_nFileSize == ( DWORD ) - 1 )
  912. {
  913. return FALSE;
  914. }
  915. m_hMap = CreateFileMapping( hFile,NULL,PAGE_READONLY,0,0,NULL );
  916. if ( m_hMap == NULL )
  917. {
  918. return FALSE;
  919. }
  920. m_pMap = ( PBYTE ) MapViewOfFile( m_hMap,FILE_MAP_READ,0,0,0 );
  921. if ( m_pMap == NULL )
  922. {
  923. return FALSE;
  924. }
  925. ////////////////////////////////////////////////////// Process DOS Header.
  926. //
  927. PIMAGE_DOS_HEADER pDosHeader = ( PIMAGE_DOS_HEADER ) m_pMap;
  928. if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
  929. {
  930. SetLastError( ERROR_BAD_EXE_FORMAT );
  931. return FALSE;
  932. }
  933. m_nPeOffset = pDosHeader->e_lfanew;
  934. m_nPrePE = 0;
  935. m_cbPrePE = QuadAlign( pDosHeader->e_lfanew );
  936. CopyMemory( &m_DosHeader,m_pMap + m_nPrePE,sizeof( m_DosHeader ) );
  937. /////////////////////////////////////////////////////// Process PE Header.
  938. //
  939. CopyMemory( &m_NtHeader,m_pMap + m_nPeOffset,sizeof( m_NtHeader ) );
  940. if ( m_NtHeader.Signature != IMAGE_NT_SIGNATURE )
  941. {
  942. SetLastError( ERROR_INVALID_EXE_SIGNATURE );
  943. return FALSE;
  944. }
  945. if ( m_NtHeader.FileHeader.SizeOfOptionalHeader == 0 )
  946. {
  947. SetLastError( ERROR_EXE_MARKED_INVALID );
  948. return FALSE;
  949. }
  950. m_nSectionsOffset = m_nPeOffset + sizeof( m_NtHeader.Signature ) + sizeof( m_NtHeader.FileHeader ) + m_NtHeader.FileHeader.SizeOfOptionalHeader;
  951. ///////////////////////////////////////////////// Process Section Headers.
  952. //
  953. if ( m_NtHeader.FileHeader.NumberOfSections > ( sizeof( m_SectionHeaders ) / sizeof( m_SectionHeaders[0] ) ) )
  954. {
  955. SetLastError( ERROR_EXE_MARKED_INVALID );
  956. return FALSE;
  957. }
  958. CopyMemory( &m_SectionHeaders,m_pMap + m_nSectionsOffset,sizeof( m_SectionHeaders[0] ) * m_NtHeader.FileHeader.NumberOfSections );
  959. /////////////////////////////////////////////////// Parse .detour Section.
  960. //
  961. DWORD rvaOriginalImageDirectory = 0;
  962. DWORD rvaDetourBeg = 0;
  963. DWORD rvaDetourEnd = 0;
  964. for ( n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++ )
  965. {
  966. if ( strcmp( ( PCHAR ) m_SectionHeaders[n].Name,".detour" ) == 0 )
  967. {
  968. DETOUR_SECTION_HEADER dh;
  969. CopyMemory( &dh,m_pMap + m_SectionHeaders[n].PointerToRawData,sizeof( dh ) );
  970. rvaOriginalImageDirectory = dh.nOriginalImportVirtualAddress;
  971. if ( dh.cbPrePE != 0 )
  972. {
  973. m_nPrePE = m_SectionHeaders[n].PointerToRawData + sizeof( dh );
  974. m_cbPrePE = dh.cbPrePE;
  975. }
  976. rvaDetourBeg = m_SectionHeaders[n].VirtualAddress;
  977. rvaDetourEnd = rvaDetourBeg + m_SectionHeaders[n].SizeOfRawData;
  978. }
  979. }
  980. //////////////////////////////////////////////////////// Get Import Table.
  981. //
  982. DWORD rvaImageDirectory = m_NtHeader.OptionalHeader
  983. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  984. PIMAGE_IMPORT_DESCRIPTOR iidp = ( PIMAGE_IMPORT_DESCRIPTOR ) RvaToVa( rvaImageDirectory );
  985. PIMAGE_IMPORT_DESCRIPTOR oidp = ( PIMAGE_IMPORT_DESCRIPTOR ) RvaToVa( rvaOriginalImageDirectory );
  986. if ( oidp == NULL )
  987. {
  988. oidp = iidp;
  989. }
  990. if ( iidp == NULL || oidp == NULL )
  991. {
  992. SetLastError( ERROR_EXE_MARKED_INVALID );
  993. return FALSE;
  994. }
  995. DWORD nFiles = 0;
  996. for ( ; iidp[nFiles].OriginalFirstThunk != 0; nFiles++ )
  997. {
  998. }
  999. CImageImportFile ** ppLastFile = &m_pImportFiles;
  1000. m_pImportFiles = NULL;
  1001. for ( n = 0; n < nFiles; n++, iidp++ )
  1002. {
  1003. ULONG_PTR rvaName = iidp->Name;
  1004. PCHAR pszName = ( PCHAR ) RvaToVa( rvaName );
  1005. if ( pszName == NULL )
  1006. {
  1007. SetLastError( ERROR_EXE_MARKED_INVALID );
  1008. goto fail;
  1009. }
  1010. CImageImportFile * pImportFile = new CImageImportFile;
  1011. if ( pImportFile == NULL )
  1012. {
  1013. SetLastError( ERROR_OUTOFMEMORY );
  1014. goto fail;
  1015. }
  1016. *ppLastFile = pImportFile;
  1017. ppLastFile = &pImportFile->m_pNextFile;
  1018. m_nImportFiles++;
  1019. pImportFile->m_pszName = DuplicateString( pszName );
  1020. if ( pImportFile->m_pszName == NULL )
  1021. {
  1022. goto fail;
  1023. }
  1024. pImportFile->m_rvaOriginalFirstThunk = iidp->OriginalFirstThunk;
  1025. pImportFile->m_rvaFirstThunk = iidp->FirstThunk;
  1026. pImportFile->m_nForwarderChain = iidp->ForwarderChain;
  1027. pImportFile->m_pImportNames = NULL;
  1028. pImportFile->m_nImportNames = 0;
  1029. pImportFile->m_fByway = FALSE;
  1030. if ( ( ULONG ) iidp->FirstThunk >= rvaDetourBeg && ( ULONG ) iidp->FirstThunk < rvaDetourEnd )
  1031. {
  1032. pImportFile->m_pszOrig = NULL;
  1033. pImportFile->m_fByway = TRUE;
  1034. continue;
  1035. }
  1036. rvaName = oidp->Name;
  1037. pszName = ( PCHAR ) RvaToVa( rvaName );
  1038. if ( pszName == NULL )
  1039. {
  1040. SetLastError( ERROR_EXE_MARKED_INVALID );
  1041. goto fail;
  1042. }
  1043. pImportFile->m_pszOrig = DuplicateString( pszName );
  1044. if ( pImportFile->m_pszOrig == NULL )
  1045. {
  1046. goto fail;
  1047. }
  1048. DWORD rvaThunk = iidp->OriginalFirstThunk;
  1049. PIMAGE_THUNK_DATA pAddrThunk = ( PIMAGE_THUNK_DATA ) RvaToVa( rvaThunk );
  1050. rvaThunk = oidp->OriginalFirstThunk;
  1051. PIMAGE_THUNK_DATA pLookThunk = ( PIMAGE_THUNK_DATA ) RvaToVa( rvaThunk );
  1052. DWORD nNames = 0;
  1053. if ( pAddrThunk )
  1054. {
  1055. for ( ; pAddrThunk[nNames].u1.Ordinal; nNames++ )
  1056. {
  1057. }
  1058. }
  1059. if ( pAddrThunk && nNames )
  1060. {
  1061. pImportFile->m_nImportNames = nNames;
  1062. pImportFile->m_pImportNames = new CImageImportName[nNames];
  1063. if ( pImportFile->m_pImportNames == NULL )
  1064. {
  1065. SetLastError( ERROR_OUTOFMEMORY );
  1066. goto fail;
  1067. }
  1068. CImageImportName * pImportName = &pImportFile->m_pImportNames[0];
  1069. for ( DWORD f = 0; f < nNames; f++, pImportName++ )
  1070. {
  1071. pImportName->m_nOrig = 0;
  1072. pImportName->m_nOrdinal = 0;
  1073. pImportName->m_nHint = 0;
  1074. pImportName->m_pszName = NULL;
  1075. pImportName->m_pszOrig = NULL;
  1076. rvaName = pAddrThunk[f].u1.Ordinal;
  1077. if ( rvaName & IMAGE_ORDINAL_FLAG )
  1078. {
  1079. pImportName->m_nOrig = ( ULONG ) IMAGE_ORDINAL( rvaName );
  1080. pImportName->m_nOrdinal = pImportName->m_nOrig;
  1081. }
  1082. else
  1083. {
  1084. PIMAGE_IMPORT_BY_NAME pName = ( PIMAGE_IMPORT_BY_NAME ) RvaToVa( rvaName );
  1085. if ( pName )
  1086. {
  1087. pImportName->m_nHint = pName->Hint;
  1088. pImportName->m_pszName = DuplicateString( ( PCHAR ) pName->Name );
  1089. if ( pImportName->m_pszName == NULL )
  1090. {
  1091. goto fail;
  1092. }
  1093. }
  1094. rvaName = pLookThunk[f].u1.Ordinal;
  1095. if ( rvaName & IMAGE_ORDINAL_FLAG )
  1096. {
  1097. pImportName->m_nOrig = ( ULONG ) IMAGE_ORDINAL( rvaName );
  1098. pImportName->m_nOrdinal = ( ULONG ) IMAGE_ORDINAL( rvaName );
  1099. }
  1100. else
  1101. {
  1102. pName = ( PIMAGE_IMPORT_BY_NAME ) RvaToVa( rvaName );
  1103. if ( pName )
  1104. {
  1105. pImportName->m_pszOrig = DuplicateString( ( PCHAR ) pName->Name );
  1106. if ( pImportName->m_pszOrig == NULL )
  1107. {
  1108. goto fail;
  1109. }
  1110. }
  1111. }
  1112. }
  1113. }
  1114. }
  1115. oidp++;
  1116. }
  1117. ////////////////////////////////////////////////////////// Parse Sections.
  1118. //
  1119. m_nExtraOffset = 0;
  1120. for ( n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++ )
  1121. {
  1122. m_nExtraOffset = Max( m_SectionHeaders[n].PointerToRawData + m_SectionHeaders[n].SizeOfRawData,m_nExtraOffset );
  1123. if ( strcmp( ( PCHAR ) m_SectionHeaders[n].Name,".detour" ) == 0 )
  1124. {
  1125. DETOUR_SECTION_HEADER dh;
  1126. CopyMemory( &dh,m_pMap + m_SectionHeaders[n].PointerToRawData,sizeof( dh ) );
  1127. if ( dh.nDataOffset == 0 )
  1128. {
  1129. dh.nDataOffset = dh.cbHeaderSize;
  1130. }
  1131. cbData = dh.cbDataSize - dh.nDataOffset;
  1132. pbData = ( m_pMap + m_SectionHeaders[n].PointerToRawData + dh.nDataOffset );
  1133. m_nExtraOffset = Max( m_SectionHeaders[n].PointerToRawData + m_SectionHeaders[n].SizeOfRawData,m_nExtraOffset );
  1134. m_NtHeader.FileHeader.NumberOfSections--;
  1135. m_NtHeader.OptionalHeader
  1136. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = dh.nOriginalImportVirtualAddress;
  1137. m_NtHeader.OptionalHeader
  1138. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = dh.nOriginalImportSize;
  1139. m_NtHeader.OptionalHeader
  1140. .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = dh.nOriginalBoundImportVirtualAddress;
  1141. m_NtHeader.OptionalHeader
  1142. .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = dh.nOriginalBoundImportSize;
  1143. m_NtHeader.OptionalHeader
  1144. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dh.nOriginalIatVirtualAddress;
  1145. m_NtHeader.OptionalHeader
  1146. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = dh.nOriginalIatSize;
  1147. m_NtHeader.OptionalHeader.CheckSum = 0;
  1148. m_NtHeader.OptionalHeader.SizeOfImage = dh.nOriginalSizeOfImage;
  1149. m_fHadDetourSection = TRUE;
  1150. }
  1151. }
  1152. m_pImageData = new CImageData( pbData,cbData );
  1153. if ( m_pImageData == NULL )
  1154. {
  1155. SetLastError( ERROR_OUTOFMEMORY );
  1156. }
  1157. return TRUE;
  1158. fail:
  1159. return FALSE;
  1160. }
  1161. static inline BOOL strneq( __in_z PCHAR pszOne , __in_z PCHAR pszTwo )
  1162. {
  1163. if ( pszOne == pszTwo )
  1164. {
  1165. return FALSE;
  1166. }
  1167. if ( !pszOne || !pszTwo )
  1168. {
  1169. return TRUE;
  1170. }
  1171. return ( strcmp( pszOne,pszTwo ) != 0 );
  1172. }
  1173. BOOL CImage::CheckImportsNeeded( DWORD * pnTables , DWORD * pnThunks , DWORD * pnChars )
  1174. {
  1175. DWORD nTables = 0;
  1176. DWORD nThunks = 0;
  1177. DWORD nChars = 0;
  1178. BOOL fNeedDetourSection = FALSE;
  1179. for ( CImageImportFile *pImportFile = m_pImportFiles; pImportFile != NULL; pImportFile = pImportFile->m_pNextFile )
  1180. {
  1181. nChars += ( int ) strlen( pImportFile->m_pszName ) + 1;
  1182. nChars += nChars & 1;
  1183. if ( pImportFile->m_fByway )
  1184. {
  1185. fNeedDetourSection = TRUE;
  1186. nThunks++;
  1187. }
  1188. else
  1189. {
  1190. if ( !fNeedDetourSection && strneq( pImportFile->m_pszName,pImportFile->m_pszOrig ) )
  1191. {
  1192. fNeedDetourSection = TRUE;
  1193. }
  1194. for ( DWORD n = 0; n < pImportFile->m_nImportNames; n++ )
  1195. {
  1196. CImageImportName * pImportName = &pImportFile->m_pImportNames[n];
  1197. if ( !fNeedDetourSection && strneq( pImportName->m_pszName,pImportName->m_pszOrig ) )
  1198. {
  1199. fNeedDetourSection = TRUE;
  1200. }
  1201. if ( pImportName->m_pszName )
  1202. {
  1203. nChars += sizeof( WORD ); // Hint
  1204. nChars += ( int ) strlen( pImportName->m_pszName ) + 1;
  1205. nChars += nChars & 1;
  1206. }
  1207. nThunks++;
  1208. }
  1209. }
  1210. nThunks++;
  1211. nTables++;
  1212. }
  1213. nTables++;
  1214. *pnTables = nTables;
  1215. *pnThunks = nThunks;
  1216. *pnChars = nChars;
  1217. return fNeedDetourSection;
  1218. }
  1219. //////////////////////////////////////////////////////////////////////////////
  1220. //
  1221. CImageImportFile * CImage::NewByway( __in_z PCHAR pszName )
  1222. {
  1223. CImageImportFile * pImportFile = new CImageImportFile;
  1224. if ( pImportFile == NULL )
  1225. {
  1226. SetLastError( ERROR_OUTOFMEMORY );
  1227. goto fail;
  1228. }
  1229. pImportFile->m_pNextFile = NULL;
  1230. pImportFile->m_fByway = TRUE;
  1231. pImportFile->m_pszName = DuplicateString( pszName );
  1232. if ( pImportFile->m_pszName == NULL )
  1233. {
  1234. goto fail;
  1235. }
  1236. pImportFile->m_rvaOriginalFirstThunk = 0;
  1237. pImportFile->m_rvaFirstThunk = 0;
  1238. pImportFile->m_nForwarderChain = ( UINT ) 0;
  1239. pImportFile->m_pImportNames = NULL;
  1240. pImportFile->m_nImportNames = 0;
  1241. m_nImportFiles++;
  1242. return pImportFile;
  1243. fail:
  1244. if ( pImportFile )
  1245. {
  1246. delete pImportFile;
  1247. pImportFile = NULL;
  1248. }
  1249. return NULL;
  1250. }
  1251. BOOL CImage::EditImports( PVOID pContext , PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback , PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback , PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback , PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback )
  1252. {
  1253. CImageImportFile * pImportFile = NULL;
  1254. CImageImportFile ** ppLastFile = &m_pImportFiles;
  1255. SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
  1256. while ( ( pImportFile = *ppLastFile ) != NULL )
  1257. {
  1258. if ( pfBywayCallback )
  1259. {
  1260. PCHAR pszFile = NULL;
  1261. if ( !( *pfBywayCallback ) ( pContext,pszFile,& pszFile ) )
  1262. {
  1263. goto fail;
  1264. }
  1265. if ( pszFile )
  1266. {
  1267. // Insert a new Byway.
  1268. CImageImportFile * pByway = NewByway( pszFile );
  1269. if ( pByway == NULL )
  1270. {
  1271. return FALSE;
  1272. }
  1273. pByway->m_pNextFile = pImportFile;
  1274. *ppLastFile = pByway;
  1275. ppLastFile = &pByway->m_pNextFile;
  1276. continue; // Retry after Byway.
  1277. }
  1278. }
  1279. if ( pImportFile->m_fByway )
  1280. {
  1281. if ( pfBywayCallback )
  1282. {
  1283. PCHAR pszFile = pImportFile->m_pszName;
  1284. if ( !( *pfBywayCallback ) ( pContext,pszFile,& pszFile ) )
  1285. {
  1286. goto fail;
  1287. }
  1288. if ( pszFile )
  1289. {
  1290. // Replace? Byway
  1291. if ( ReplaceString( &pImportFile->m_pszName,pszFile ) == NULL )
  1292. {
  1293. goto fail;
  1294. }
  1295. }
  1296. else
  1297. {
  1298. // Delete Byway
  1299. *ppLastFile = pImportFile->m_pNextFile;
  1300. pImportFile->m_pNextFile = NULL;
  1301. delete pImportFile;
  1302. pImportFile = *ppLastFile;
  1303. m_nImportFiles--;
  1304. continue; // Retry after delete.
  1305. }
  1306. }
  1307. }
  1308. else
  1309. {
  1310. if ( pfFileCallback )
  1311. {
  1312. PCHAR pszFile = pImportFile->m_pszName;
  1313. if ( !( *pfFileCallback ) ( pContext,pImportFile->m_pszOrig,pszFile,& pszFile ) )
  1314. {
  1315. goto fail;
  1316. }
  1317. if ( pszFile != NULL )
  1318. {
  1319. if ( ReplaceString( &pImportFile->m_pszName,pszFile ) == NULL )
  1320. {
  1321. goto fail;
  1322. }
  1323. }
  1324. }
  1325. if ( pfSymbolCallback )
  1326. {
  1327. for ( DWORD n = 0; n < pImportFile->m_nImportNames; n++ )
  1328. {
  1329. CImageImportName * pImportName = &pImportFile->m_pImportNames[n];
  1330. PCHAR pszName = pImportName->m_pszName;
  1331. ULONG nOrdinal = pImportName->m_nOrdinal;
  1332. if ( !( *pfSymbolCallback ) ( pContext,pImportName->m_nOrig,nOrdinal,& nOrdinal,pImportName->m_pszOrig,pszName,& pszName ) )
  1333. {
  1334. goto fail;
  1335. }
  1336. if ( pszName != NULL )
  1337. {
  1338. pImportName->m_nOrdinal = 0;
  1339. if ( ReplaceString( &pImportName->m_pszName,pszName ) == NULL )
  1340. {
  1341. goto fail;
  1342. }
  1343. }
  1344. else if ( nOrdinal != 0 )
  1345. {
  1346. pImportName->m_nOrdinal = nOrdinal;
  1347. if ( pImportName->m_pszName != NULL )
  1348. {
  1349. delete[] pImportName->m_pszName;
  1350. pImportName->m_pszName = NULL;
  1351. }
  1352. }
  1353. }
  1354. }
  1355. }
  1356. ppLastFile = &pImportFile->m_pNextFile;
  1357. pImportFile = pImportFile->m_pNextFile;
  1358. }
  1359. for ( ; ; )
  1360. {
  1361. if ( pfBywayCallback )
  1362. {
  1363. PCHAR pszFile = NULL;
  1364. if ( !( *pfBywayCallback ) ( pContext,NULL,& pszFile ) )
  1365. {
  1366. goto fail;
  1367. }
  1368. if ( pszFile )
  1369. {
  1370. // Insert a new Byway.
  1371. CImageImportFile * pByway = NewByway( pszFile );
  1372. if ( pByway == NULL )
  1373. {
  1374. return FALSE;
  1375. }
  1376. pByway->m_pNextFile = pImportFile;
  1377. *ppLastFile = pByway;
  1378. ppLastFile = &pByway->m_pNextFile;
  1379. continue; // Retry after Byway.
  1380. }
  1381. }
  1382. break;
  1383. }
  1384. if ( pfCommitCallback )
  1385. {
  1386. if ( !( *pfCommitCallback ) ( pContext ) )
  1387. {
  1388. goto fail;
  1389. }
  1390. }
  1391. SetLastError( NO_ERROR );
  1392. return TRUE;
  1393. fail:
  1394. return FALSE;
  1395. }
  1396. BOOL CImage::Write( HANDLE hFile )
  1397. {
  1398. DWORD cbDone;
  1399. if ( hFile == INVALID_HANDLE_VALUE )
  1400. {
  1401. SetLastError( ERROR_INVALID_HANDLE );
  1402. return FALSE;
  1403. }
  1404. m_nNextFileAddr = 0;
  1405. m_nNextVirtAddr = 0;
  1406. DWORD nTables = 0;
  1407. DWORD nThunks = 0;
  1408. DWORD nChars = 0;
  1409. BOOL fNeedDetourSection = CheckImportsNeeded( &nTables,&nThunks,&nChars );
  1410. //////////////////////////////////////////////////////////// Copy Headers.
  1411. //
  1412. if ( SetFilePointer( hFile,0,NULL,FILE_BEGIN ) == ~0u )
  1413. {
  1414. return FALSE;
  1415. }
  1416. if ( !CopyFileData( hFile,0,m_NtHeader.OptionalHeader.SizeOfHeaders ) )
  1417. {
  1418. return FALSE;
  1419. }
  1420. if ( fNeedDetourSection || !m_pImageData->IsEmpty() )
  1421. {
  1422. // Replace the file's DOS header with our own.
  1423. m_nPeOffset = sizeof( m_DosHeader ) + sizeof( s_rbDosCode );
  1424. m_nSectionsOffset = m_nPeOffset + sizeof( m_NtHeader.Signature ) + sizeof( m_NtHeader.FileHeader ) + m_NtHeader.FileHeader.SizeOfOptionalHeader;
  1425. m_DosHeader.e_lfanew = m_nPeOffset;
  1426. if ( SetFilePointer( hFile,0,NULL,FILE_BEGIN ) == ~0u )
  1427. {
  1428. return FALSE;
  1429. }
  1430. if ( !WriteFile( hFile,&m_DosHeader,sizeof( m_DosHeader ),&cbDone ) )
  1431. {
  1432. return FALSE;
  1433. }
  1434. if ( !WriteFile( hFile,&s_rbDosCode,sizeof( s_rbDosCode ),&cbDone ) )
  1435. {
  1436. return FALSE;
  1437. }
  1438. }
  1439. else
  1440. {
  1441. // Restore the file's original DOS header.
  1442. if ( m_nPrePE != 0 )
  1443. {
  1444. m_nPeOffset = m_cbPrePE;
  1445. m_nSectionsOffset = m_nPeOffset + sizeof( m_NtHeader.Signature ) + sizeof( m_NtHeader.FileHeader ) + m_NtHeader.FileHeader.SizeOfOptionalHeader;
  1446. m_DosHeader.e_lfanew = m_nPeOffset;
  1447. if ( SetFilePointer( hFile,0,NULL,FILE_BEGIN ) == ~0u )
  1448. {
  1449. return FALSE;
  1450. }
  1451. if ( !CopyFileData( hFile,m_nPrePE,m_cbPrePE ) )
  1452. {
  1453. return FALSE;
  1454. }
  1455. }
  1456. }
  1457. m_nNextFileAddr = m_NtHeader.OptionalHeader.SizeOfHeaders;
  1458. m_nNextVirtAddr = 0;
  1459. if ( !AlignFileData( hFile ) )
  1460. {
  1461. return FALSE;
  1462. }
  1463. /////////////////////////////////////////////////////////// Copy Sections.
  1464. //
  1465. DWORD n = 0;
  1466. for ( ; n < m_NtHeader.FileHeader.NumberOfSections; n++ )
  1467. {
  1468. if ( m_SectionHeaders[n].SizeOfRawData )
  1469. {
  1470. if ( SetFilePointer( hFile,m_SectionHeaders[n].PointerToRawData,NULL,FILE_BEGIN ) == ~0u )
  1471. {
  1472. return FALSE;
  1473. }
  1474. if ( !CopyFileData( hFile,m_SectionHeaders[n].PointerToRawData,m_SectionHeaders[n].SizeOfRawData ) )
  1475. {
  1476. return FALSE;
  1477. }
  1478. }
  1479. m_nNextFileAddr = Max( m_SectionHeaders[n].PointerToRawData + m_SectionHeaders[n].SizeOfRawData,m_nNextFileAddr );
  1480. m_nNextVirtAddr = Max( m_SectionHeaders[n].VirtualAddress + m_SectionHeaders[n].Misc.VirtualSize,m_nNextVirtAddr );
  1481. m_nExtraOffset = Max( m_nNextFileAddr,m_nExtraOffset );
  1482. if ( !AlignFileData( hFile ) )
  1483. {
  1484. return FALSE;
  1485. }
  1486. }
  1487. if ( fNeedDetourSection || !m_pImageData->IsEmpty() )
  1488. {
  1489. ////////////////////////////////////////////// Insert .detour Section.
  1490. //
  1491. DWORD nSection = m_NtHeader.FileHeader.NumberOfSections++;
  1492. DETOUR_SECTION_HEADER dh;
  1493. ZeroMemory( &dh,sizeof( dh ) );
  1494. ZeroMemory( &m_SectionHeaders[nSection],sizeof( m_SectionHeaders[nSection] ) );
  1495. dh.cbHeaderSize = sizeof( DETOUR_SECTION_HEADER );
  1496. dh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE;
  1497. dh.nOriginalImportVirtualAddress = m_NtHeader.OptionalHeader
  1498. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  1499. dh.nOriginalImportSize = m_NtHeader.OptionalHeader
  1500. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
  1501. dh.nOriginalBoundImportVirtualAddress = m_NtHeader.OptionalHeader
  1502. .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;
  1503. dh.nOriginalBoundImportSize = m_NtHeader.OptionalHeader
  1504. .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size;
  1505. dh.nOriginalIatVirtualAddress = m_NtHeader.OptionalHeader
  1506. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
  1507. dh.nOriginalIatSize = m_NtHeader.OptionalHeader
  1508. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
  1509. dh.nOriginalSizeOfImage = m_NtHeader.OptionalHeader.SizeOfImage;
  1510. DWORD clrAddr = m_NtHeader.OptionalHeader
  1511. .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
  1512. DWORD clrSize = m_NtHeader.OptionalHeader
  1513. .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
  1514. if ( clrAddr && clrSize )
  1515. {
  1516. PDETOUR_CLR_HEADER pHdr = ( PDETOUR_CLR_HEADER ) RvaToVa( clrAddr );
  1517. if ( pHdr != NULL )
  1518. {
  1519. DETOUR_CLR_HEADER hdr;
  1520. hdr = *pHdr;
  1521. dh.nOriginalClrFlags = hdr.Flags;
  1522. }
  1523. }
  1524. HRESULT hrRet = StringCchCopyA( ( PCHAR ) m_SectionHeaders[nSection].Name,IMAGE_SIZEOF_SHORT_NAME,".detour" );
  1525. if ( FAILED( hrRet ) )
  1526. return FALSE;
  1527. m_SectionHeaders[nSection].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
  1528. m_nOutputVirtAddr = m_nNextVirtAddr;
  1529. m_nOutputVirtSize = 0;
  1530. m_nOutputFileAddr = m_nNextFileAddr;
  1531. dh.nDataOffset = 0; // pbData
  1532. dh.cbDataSize = m_pImageData->m_cbData;
  1533. dh.cbPrePE = m_cbPrePE;
  1534. //////////////////////////////////////////////////////////////////////////
  1535. //
  1536. DWORD rvaImportTable = 0;
  1537. DWORD rvaLookupTable = 0;
  1538. DWORD rvaBoundTable = 0;
  1539. DWORD rvaNameTable = 0;
  1540. DWORD nImportTableSize = nTables * sizeof( IMAGE_IMPORT_DESCRIPTOR );
  1541. if ( !SizeOutputBuffer( QuadAlign( sizeof( dh ) ) + m_cbPrePE + QuadAlign( m_pImageData->m_cbData ) + QuadAlign( sizeof( IMAGE_THUNK_DATA ) * nThunks ) + QuadAlign( sizeof( IMAGE_THUNK_DATA ) * nThunks ) + QuadAlign( nChars ) + QuadAlign( nImportTableSize ) ) )
  1542. {
  1543. return FALSE;
  1544. }
  1545. DWORD vaHead = 0;
  1546. PBYTE pbHead = NULL;
  1547. DWORD vaPrePE = 0;
  1548. PBYTE pbPrePE = NULL;
  1549. DWORD vaData = 0;
  1550. PBYTE pbData = NULL;
  1551. if ( ( pbHead = AllocateOutput( sizeof( dh ),&vaHead ) ) == NULL )
  1552. {
  1553. return FALSE;
  1554. }
  1555. if ( ( pbPrePE = AllocateOutput( m_cbPrePE,&vaPrePE ) ) == NULL )
  1556. {
  1557. return FALSE;
  1558. }
  1559. CImageThunks lookupTable ( this,nThunks,&rvaLookupTable );
  1560. CImageThunks boundTable ( this,nThunks,&rvaBoundTable );
  1561. CImageChars nameTable ( this,nChars,&rvaNameTable );
  1562. if ( ( pbData = AllocateOutput( m_pImageData->m_cbData,&vaData ) ) == NULL )
  1563. {
  1564. return FALSE;
  1565. }
  1566. dh.nDataOffset = vaData - vaHead;
  1567. dh.cbDataSize = dh.nDataOffset + m_pImageData->m_cbData;
  1568. CopyMemory( pbHead,&dh,sizeof( dh ) );
  1569. CopyMemory( pbPrePE,m_pMap + m_nPrePE,m_cbPrePE );
  1570. CopyMemory( pbData,m_pImageData->m_pbData,m_pImageData->m_cbData );
  1571. PIMAGE_IMPORT_DESCRIPTOR piidDst = ( PIMAGE_IMPORT_DESCRIPTOR ) AllocateOutput( nImportTableSize,&rvaImportTable );
  1572. if ( piidDst == NULL )
  1573. {
  1574. return FALSE;
  1575. }
  1576. //////////////////////////////////////////////// Step Through Imports.
  1577. //
  1578. for ( CImageImportFile *pImportFile = m_pImportFiles; pImportFile != NULL; pImportFile = pImportFile->m_pNextFile )
  1579. {
  1580. ZeroMemory( piidDst,sizeof( piidDst ) );
  1581. nameTable.Allocate( pImportFile->m_pszName,( DWORD * ) &piidDst->Name );
  1582. piidDst->TimeDateStamp = 0;
  1583. piidDst->ForwarderChain = pImportFile->m_nForwarderChain;
  1584. if ( pImportFile->m_fByway )
  1585. {
  1586. ULONG rvaIgnored;
  1587. lookupTable.Allocate( IMAGE_ORDINAL_FLAG + 1,( DWORD * ) &piidDst->OriginalFirstThunk );
  1588. boundTable.Allocate( IMAGE_ORDINAL_FLAG + 1,( DWORD * ) &piidDst->FirstThunk );
  1589. lookupTable.Allocate( 0,&rvaIgnored );
  1590. boundTable.Allocate( 0,&rvaIgnored );
  1591. }
  1592. else
  1593. {
  1594. ULONG rvaIgnored;
  1595. piidDst->FirstThunk = ( ULONG ) pImportFile->m_rvaFirstThunk;
  1596. lookupTable.Current( ( DWORD * ) &piidDst->OriginalFirstThunk );
  1597. for ( n = 0; n < pImportFile->m_nImportNames; n++ )
  1598. {
  1599. CImageImportName * pImportName = &pImportFile->m_pImportNames[n];
  1600. if ( pImportName->m_pszName )
  1601. {
  1602. ULONG nDstName = 0;
  1603. nameTable.Allocate( pImportName->m_pszName,pImportName->m_nHint,&nDstName );
  1604. lookupTable.Allocate( nDstName,&rvaIgnored );
  1605. }
  1606. else
  1607. {
  1608. lookupTable.Allocate( IMAGE_ORDINAL_FLAG + pImportName->m_nOrdinal,&rvaIgnored );
  1609. }
  1610. }
  1611. lookupTable.Allocate( 0,&rvaIgnored );
  1612. }
  1613. piidDst++;
  1614. }
  1615. ZeroMemory( piidDst,sizeof( piidDst ) );
  1616. //////////////////////////////////////////////////////////////////////////
  1617. //
  1618. m_nNextVirtAddr += m_nOutputVirtSize;
  1619. m_nNextFileAddr += FileAlign( m_nOutputVirtSize );
  1620. if ( !AlignFileData( hFile ) )
  1621. {
  1622. return FALSE;
  1623. }
  1624. //////////////////////////////////////////////////////////////////////////
  1625. //
  1626. m_SectionHeaders[nSection].VirtualAddress = m_nOutputVirtAddr;
  1627. m_SectionHeaders[nSection].Misc.VirtualSize = m_nOutputVirtSize;
  1628. m_SectionHeaders[nSection].PointerToRawData = m_nOutputFileAddr;
  1629. m_SectionHeaders[nSection].SizeOfRawData = FileAlign( m_nOutputVirtSize );
  1630. m_NtHeader.OptionalHeader
  1631. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = rvaImportTable;
  1632. m_NtHeader.OptionalHeader
  1633. .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = nImportTableSize;
  1634. m_NtHeader.OptionalHeader
  1635. .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
  1636. m_NtHeader.OptionalHeader
  1637. .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
  1638. //////////////////////////////////////////////////////////////////////////
  1639. //
  1640. if ( SetFilePointer( hFile,m_SectionHeaders[nSection].PointerToRawData,NULL,FILE_BEGIN ) == ~0u )
  1641. {
  1642. return FALSE;
  1643. }
  1644. if ( !WriteFile( hFile,m_pbOutputBuffer,m_SectionHeaders[nSection].SizeOfRawData,&cbDone ) )
  1645. {
  1646. return FALSE;
  1647. }
  1648. }
  1649. ///////////////////////////////////////////////////// Adjust Extra Data.
  1650. //
  1651. LONG nExtraAdjust = m_nNextFileAddr - m_nExtraOffset;
  1652. for ( n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++ )
  1653. {
  1654. if ( m_SectionHeaders[n].PointerToRawData > m_nExtraOffset )
  1655. {
  1656. m_SectionHeaders[n].PointerToRawData += nExtraAdjust;
  1657. }
  1658. if ( m_SectionHeaders[n].PointerToRelocations > m_nExtraOffset )
  1659. {
  1660. m_SectionHeaders[n].PointerToRelocations += nExtraAdjust;
  1661. }
  1662. if ( m_SectionHeaders[n].PointerToLinenumbers > m_nExtraOffset )
  1663. {
  1664. m_SectionHeaders[n].PointerToLinenumbers += nExtraAdjust;
  1665. }
  1666. }
  1667. if ( m_NtHeader.FileHeader.PointerToSymbolTable > m_nExtraOffset )
  1668. {
  1669. m_NtHeader.FileHeader.PointerToSymbolTable += nExtraAdjust;
  1670. }
  1671. m_NtHeader.OptionalHeader.CheckSum = 0;
  1672. m_NtHeader.OptionalHeader.SizeOfImage = m_nNextVirtAddr;
  1673. ////////////////////////////////////////////////// Adjust Debug Directory.
  1674. //
  1675. DWORD debugAddr = m_NtHeader.OptionalHeader
  1676. .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  1677. DWORD debugSize = m_NtHeader.OptionalHeader
  1678. .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
  1679. if ( debugAddr && debugSize )
  1680. {
  1681. DWORD nFileOffset = RvaToFileOffset( debugAddr );
  1682. if ( SetFilePointer( hFile,nFileOffset,NULL,FILE_BEGIN ) == ~0u )
  1683. {
  1684. return FALSE;
  1685. }
  1686. PIMAGE_DEBUG_DIRECTORY pDir = ( PIMAGE_DEBUG_DIRECTORY ) RvaToVa( debugAddr );
  1687. if ( pDir == NULL )
  1688. {
  1689. return FALSE;
  1690. }
  1691. DWORD nEntries = debugSize / sizeof( *pDir );
  1692. for ( n = 0; n < nEntries; n++ )
  1693. {
  1694. IMAGE_DEBUG_DIRECTORY dir = pDir[n];
  1695. if ( dir.PointerToRawData > m_nExtraOffset )
  1696. {
  1697. dir.PointerToRawData += nExtraAdjust;
  1698. }
  1699. if ( !WriteFile( hFile,&dir,sizeof( dir ),&cbDone ) )
  1700. {
  1701. return FALSE;
  1702. }
  1703. }
  1704. }
  1705. /////////////////////////////////////////////////////// Adjust CLR Header.
  1706. //
  1707. DWORD clrAddr = m_NtHeader.OptionalHeader
  1708. .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
  1709. DWORD clrSize = m_NtHeader.OptionalHeader
  1710. .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
  1711. if ( clrAddr && clrSize && fNeedDetourSection )
  1712. {
  1713. DWORD nFileOffset = RvaToFileOffset( clrAddr );
  1714. if ( SetFilePointer( hFile,nFileOffset,NULL,FILE_BEGIN ) == ~0u )
  1715. {
  1716. return FALSE;
  1717. }
  1718. PDETOUR_CLR_HEADER pHdr = ( PDETOUR_CLR_HEADER ) RvaToVa( clrAddr );
  1719. if ( pHdr == NULL )
  1720. {
  1721. return FALSE;
  1722. }
  1723. DETOUR_CLR_HEADER hdr;
  1724. hdr = *pHdr;
  1725. hdr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag.
  1726. if ( !WriteFile( hFile,&hdr,sizeof( hdr ),&cbDone ) )
  1727. {
  1728. return FALSE;
  1729. }
  1730. }
  1731. ///////////////////////////////////////////////// Copy Left-over Data.
  1732. //
  1733. if ( m_nFileSize > m_nExtraOffset )
  1734. {
  1735. if ( SetFilePointer( hFile,m_nNextFileAddr,NULL,FILE_BEGIN ) == ~0u )
  1736. {
  1737. return FALSE;
  1738. }
  1739. if ( !CopyFileData( hFile,m_nExtraOffset,m_nFileSize - m_nExtraOffset ) )
  1740. {
  1741. return FALSE;
  1742. }
  1743. }
  1744. //////////////////////////////////////////////////// Finalize Headers.
  1745. //
  1746. if ( SetFilePointer( hFile,m_nPeOffset,NULL,FILE_BEGIN ) == ~0u )
  1747. {
  1748. return FALSE;
  1749. }
  1750. if ( !WriteFile( hFile,&m_NtHeader,sizeof( m_NtHeader ),&cbDone ) )
  1751. {
  1752. return FALSE;
  1753. }
  1754. if ( SetFilePointer( hFile,m_nSectionsOffset,NULL,FILE_BEGIN ) == ~0u )
  1755. {
  1756. return FALSE;
  1757. }
  1758. if ( !WriteFile( hFile,&m_SectionHeaders,sizeof( m_SectionHeaders[0] ) * m_NtHeader.FileHeader.NumberOfSections,&cbDone ) )
  1759. {
  1760. return FALSE;
  1761. }
  1762. m_cbPostPE = SetFilePointer( hFile,0,NULL,FILE_CURRENT );
  1763. if ( m_cbPostPE == ~0u )
  1764. {
  1765. return FALSE;
  1766. }
  1767. m_cbPostPE = m_NtHeader.OptionalHeader.SizeOfHeaders - m_cbPostPE;
  1768. return TRUE;
  1769. }
  1770. }; // namespace Detour
  1771. PDETOUR_BINARY WINAPI DetourBinaryOpen( HANDLE hFile )
  1772. {
  1773. Detour::CImage * pImage = new Detour::CImage;
  1774. if ( pImage == NULL )
  1775. {
  1776. SetLastError( ERROR_OUTOFMEMORY );
  1777. return FALSE;
  1778. }
  1779. if ( !pImage->Read( hFile ) )
  1780. {
  1781. delete pImage;
  1782. return FALSE;
  1783. }
  1784. return ( PDETOUR_BINARY ) pImage;
  1785. }
  1786. BOOL WINAPI DetourBinaryWrite( PDETOUR_BINARY pdi , HANDLE hFile )
  1787. {
  1788. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1789. if ( pImage == NULL )
  1790. {
  1791. return FALSE;
  1792. }
  1793. return pImage->Write( hFile );
  1794. }
  1795. PVOID WINAPI DetourBinaryEnumeratePayloads( PDETOUR_BINARY pdi , GUID * pGuid , DWORD * pcbData , DWORD * pnIterator )
  1796. {
  1797. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1798. if ( pImage == NULL )
  1799. {
  1800. return FALSE;
  1801. }
  1802. return pImage->DataEnum( pGuid,pcbData,pnIterator );
  1803. }
  1804. PVOID WINAPI DetourBinaryFindPayload( PDETOUR_BINARY pdi , REFGUID rguid , DWORD * pcbData )
  1805. {
  1806. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1807. if ( pImage == NULL )
  1808. {
  1809. return FALSE;
  1810. }
  1811. return pImage->DataFind( rguid,pcbData );
  1812. }
  1813. PVOID WINAPI DetourBinarySetPayload( PDETOUR_BINARY pdi , REFGUID rguid , PVOID pvData , DWORD cbData )
  1814. {
  1815. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1816. if ( pImage == NULL )
  1817. {
  1818. return FALSE;
  1819. }
  1820. return pImage->DataSet( rguid,( PBYTE ) pvData,cbData );
  1821. }
  1822. BOOL WINAPI DetourBinaryDeletePayload( PDETOUR_BINARY pdi , REFGUID rguid )
  1823. {
  1824. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1825. if ( pImage == NULL )
  1826. {
  1827. return FALSE;
  1828. }
  1829. return pImage->DataDelete( rguid );
  1830. }
  1831. BOOL WINAPI DetourBinaryPurgePayloads( PDETOUR_BINARY pdi )
  1832. {
  1833. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1834. if ( pImage == NULL )
  1835. {
  1836. return FALSE;
  1837. }
  1838. return pImage->DataPurge();
  1839. }
  1840. //////////////////////////////////////////////////////////////////////////////
  1841. //
  1842. static BOOL CALLBACK ResetBywayCallback( PVOID pContext , __in_z PCHAR pszFile , __deref PCHAR * ppszOutFile )
  1843. {
  1844. ( void ) pContext;
  1845. ( void ) pszFile;
  1846. *ppszOutFile = NULL;
  1847. return TRUE;
  1848. }
  1849. static BOOL CALLBACK ResetFileCallback( PVOID pContext , __in_z PCHAR pszOrigFile , __in_z PCHAR pszFile , __deref PCHAR * ppszOutFile )
  1850. {
  1851. ( void ) pContext;
  1852. ( void ) pszFile;
  1853. *ppszOutFile = pszOrigFile;
  1854. return TRUE;
  1855. }
  1856. static BOOL CALLBACK ResetSymbolCallback( PVOID pContext , ULONG nOrigOrdinal , ULONG nOrdinal , ULONG * pnOutOrdinal , __in_z PCHAR pszOrigSymbol , __in_z PCHAR pszSymbol , __deref PCHAR * ppszOutSymbol )
  1857. {
  1858. ( void ) pContext;
  1859. ( void ) nOrdinal;
  1860. ( void ) pszSymbol;
  1861. *pnOutOrdinal = nOrigOrdinal;
  1862. *ppszOutSymbol = pszOrigSymbol;
  1863. return TRUE;
  1864. }
  1865. BOOL WINAPI DetourBinaryResetImports( PDETOUR_BINARY pdi )
  1866. {
  1867. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1868. if ( pImage == NULL )
  1869. {
  1870. return FALSE;
  1871. }
  1872. return pImage->EditImports( NULL,ResetBywayCallback,ResetFileCallback,ResetSymbolCallback,NULL );
  1873. }
  1874. //////////////////////////////////////////////////////////////////////////////
  1875. //
  1876. BOOL WINAPI DetourBinaryEditImports( PDETOUR_BINARY pdi , PVOID pContext , PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback , PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback , PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback , PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback )
  1877. {
  1878. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1879. if ( pImage == NULL )
  1880. {
  1881. return FALSE;
  1882. }
  1883. return pImage->EditImports( pContext,pfBywayCallback,pfFileCallback,pfSymbolCallback,pfCommitCallback );
  1884. }
  1885. BOOL WINAPI DetourBinaryClose( PDETOUR_BINARY pdi )
  1886. {
  1887. Detour::CImage * pImage = Detour::CImage::IsValid( pdi );
  1888. if ( pImage == NULL )
  1889. {
  1890. return FALSE;
  1891. }
  1892. BOOL bSuccess = pImage->Close();
  1893. delete pImage;
  1894. pImage = NULL;
  1895. return bSuccess;
  1896. }
  1897. //
  1898. ///////////////////////////////////////////////////////////////// End of File.