Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

648 lines
17 KiB

  1. #include "pefile.h"
  2. // #include <stdio.h>
  3. HANDLE hDll;
  4. /*
  5. BOOL WINAPI DLLEntry (
  6. HANDLE hModule,
  7. DWORD dwFunction,
  8. LPVOID lpNot)
  9. {
  10. hDll = hModule;
  11. return TRUE;
  12. }
  13. */
  14. /* copy dos header information to structure */
  15. BOOL WINAPI GetDosHeader (
  16. LPVOID lpFile,
  17. PIMAGE_DOS_HEADER pHeader)
  18. {
  19. /* dos header rpresents first structure of bytes in file */
  20. if (*(USHORT *)lpFile == IMAGE_DOS_SIGNATURE)
  21. CopyMemory ((LPVOID)pHeader, lpFile, sizeof (IMAGE_DOS_HEADER));
  22. else
  23. return FALSE;
  24. return TRUE;
  25. }
  26. /* return file signature */
  27. DWORD WINAPI ImageFileType (
  28. LPVOID lpFile)
  29. {
  30. /* dos file signature comes first */
  31. if (*(USHORT *)lpFile == IMAGE_DOS_SIGNATURE)
  32. {
  33. /* determine location of PE File header from dos header */
  34. if (LOWORD (*(DWORD *)NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE ||
  35. LOWORD (*(DWORD *)NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE_LE)
  36. return (DWORD)LOWORD(*(DWORD *)NTSIGNATURE (lpFile));
  37. else if (*(DWORD *)NTSIGNATURE (lpFile) == IMAGE_NT_SIGNATURE)
  38. return IMAGE_NT_SIGNATURE;
  39. else
  40. return IMAGE_DOS_SIGNATURE;
  41. }
  42. else
  43. /* unknown file type */
  44. return 0;
  45. }
  46. /* copy file header information to structure */
  47. BOOL WINAPI GetPEFileHeader (
  48. LPVOID lpFile,
  49. PIMAGE_FILE_HEADER pHeader)
  50. {
  51. /* file header follows dos header */
  52. if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE)
  53. CopyMemory ((LPVOID)pHeader, PEFHDROFFSET (lpFile), sizeof (IMAGE_FILE_HEADER));
  54. else
  55. return FALSE;
  56. return TRUE;
  57. }
  58. /* copy optional header info to structure */
  59. BOOL WINAPI GetPEOptionalHeader (
  60. LPVOID lpFile,
  61. PIMAGE_OPTIONAL_HEADER pHeader)
  62. {
  63. /* optional header follows file header and dos header */
  64. if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE)
  65. CopyMemory ((LPVOID)pHeader, OPTHDROFFSET (lpFile), sizeof (IMAGE_OPTIONAL_HEADER));
  66. else
  67. return FALSE;
  68. return TRUE;
  69. }
  70. /* function returns the entry point for an exe module lpFile must
  71. be a memory mapped file pointer to the beginning of the image file */
  72. LONG_PTR WINAPI GetModuleEntryPoint (
  73. LPVOID lpFile)
  74. {
  75. PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  76. if (poh != NULL)
  77. return (LONG_PTR)(poh->AddressOfEntryPoint);
  78. else
  79. return 0L;
  80. }
  81. /* return the total number of sections in the module */
  82. int WINAPI NumOfSections (
  83. LPVOID lpFile)
  84. {
  85. /* number os sections is indicated in file header */
  86. return ((int)((PIMAGE_FILE_HEADER)PEFHDROFFSET (lpFile))->NumberOfSections);
  87. }
  88. /* retrieve entry point */
  89. LPVOID WINAPI GetImageBase (
  90. LPVOID lpFile)
  91. {
  92. PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  93. if (poh != NULL)
  94. return (LPVOID)(poh->ImageBase);
  95. else
  96. return NULL;
  97. }
  98. /* return offset to specified IMAGE_DIRECTORY entry */
  99. LPVOID WINAPI ImageDirectoryOffset (
  100. LPVOID lpFile,
  101. DWORD dwIMAGE_DIRECTORY)
  102. {
  103. PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  104. PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile);
  105. int nSections = NumOfSections (lpFile);
  106. int i = 0;
  107. LONG_PTR VAImageDir;
  108. /* must be 0 thru (NumberOfRvaAndSizes-1) */
  109. if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes)
  110. return NULL;
  111. /* locate specific image directory's relative virtual address */
  112. VAImageDir = (LONG_PTR)poh->DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;
  113. /* locate section containing image directory */
  114. while (i++<nSections)
  115. {
  116. if (psh->VirtualAddress <= (DWORD)VAImageDir &&
  117. psh->VirtualAddress + psh->SizeOfRawData > (DWORD)VAImageDir)
  118. break;
  119. psh++;
  120. }
  121. if (i > nSections)
  122. return NULL;
  123. /* return image import directory offset */
  124. return (LPVOID)(((LONG_PTR)lpFile + (LONG_PTR)VAImageDir - psh->VirtualAddress) +
  125. (LONG_PTR)psh->PointerToRawData);
  126. }
  127. /* function retrieve names of all the sections in the file */
  128. int WINAPI GetSectionNames (
  129. LPVOID lpFile,
  130. HANDLE hHeap,
  131. char **pszSections)
  132. {
  133. int nSections = NumOfSections (lpFile);
  134. int i, nCnt = 0;
  135. PIMAGE_SECTION_HEADER psh;
  136. char *ps;
  137. if (ImageFileType (lpFile) != IMAGE_NT_SIGNATURE ||
  138. (psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) == NULL)
  139. return 0;
  140. /* count the number of chars used in the section names */
  141. for (i=0; i<nSections; i++)
  142. nCnt += strlen (psh[i].Name) + 1;
  143. /* allocate space for all section names from heap */
  144. ps = *pszSections = (char *)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt);
  145. for (i=0; i<nSections; i++)
  146. {
  147. strcpy (ps, psh[i].Name);
  148. ps += strlen (psh[i].Name) + 1;
  149. }
  150. return nCnt;
  151. }
  152. /* function gets the function header for a section identified by name */
  153. BOOL WINAPI GetSectionHdrByName (
  154. LPVOID lpFile,
  155. IMAGE_SECTION_HEADER *sh,
  156. char *szSection)
  157. {
  158. PIMAGE_SECTION_HEADER psh;
  159. int nSections = NumOfSections (lpFile);
  160. int i;
  161. if ((psh = (PIMAGE_SECTION_HEADER)SECHDROFFSET (lpFile)) != NULL)
  162. {
  163. /* find the section by name */
  164. for (i=0; i<nSections; i++)
  165. {
  166. if (!strcmp (psh->Name, szSection))
  167. {
  168. /* copy data to header */
  169. CopyMemory ((LPVOID)sh, (LPVOID)psh, sizeof (IMAGE_SECTION_HEADER));
  170. return TRUE;
  171. }
  172. else
  173. psh++;
  174. }
  175. }
  176. return FALSE;
  177. }
  178. /* get import modules names separated by null terminators, return module count */
  179. int WINAPI GetImportModuleNames (
  180. LPVOID lpFile,
  181. // HANDLE hHeap,
  182. char* SectionName,
  183. char **pszModules)
  184. {
  185. PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)
  186. ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
  187. IMAGE_SECTION_HEADER idsh;
  188. BYTE *pData = (BYTE *)pid;
  189. int nCnt = 0, nSize = 0, i;
  190. char *pModule[1024]; /* hardcoded maximum number of modules?? */
  191. char *psz;
  192. /* locate section header for ".idata" section */
  193. if (!GetSectionHdrByName (lpFile, &idsh, SectionName /*".idata" "INIT"*/))
  194. return 0;
  195. /* extract all import modules */
  196. while (pid->dwRVAModuleName)
  197. {
  198. /* allocate temporary buffer for absolute string offsets */
  199. pModule[nCnt] = (char *)(pData + (pid->dwRVAModuleName-idsh.VirtualAddress));
  200. nSize += strlen (pModule[nCnt]) + 1;
  201. /* increment to the next import directory entry */
  202. pid++;
  203. nCnt++;
  204. }
  205. /* copy all strings to one chunk of heap memory */
  206. *pszModules = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
  207. psz = *pszModules;
  208. for (i=0; i<nCnt; i++)
  209. {
  210. strcpy (psz, pModule[i]);
  211. psz += strlen (psz) + 1;
  212. }
  213. return nCnt;
  214. }
  215. /* get import module function names separated by null terminators, return function count */
  216. int WINAPI GetImportFunctionNamesByModule (
  217. LPVOID lpFile,
  218. // HANDLE hHeap,
  219. char* SectionName,
  220. char *pszModule,
  221. char **pszFunctions)
  222. {
  223. PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)
  224. ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
  225. IMAGE_SECTION_HEADER idsh;
  226. LONG_PTR dwBase;
  227. int nCnt = 0, nSize = 0;
  228. DWORD dwFunction;
  229. char *psz;
  230. /* locate section header for ".idata" section */
  231. if (!GetSectionHdrByName (lpFile, &idsh, SectionName/*".idata" "INIT"*/))
  232. return 0;
  233. dwBase = ((LONG_PTR)pid - idsh.VirtualAddress);
  234. /* find module's pid */
  235. while (pid->dwRVAModuleName &&
  236. strcmp (pszModule, (char *)(pid->dwRVAModuleName+dwBase)))
  237. pid++;
  238. /* exit if the module is not found */
  239. if (!pid->dwRVAModuleName)
  240. return 0;
  241. /* count number of function names and length of strings */
  242. dwFunction = pid->dwRVAFunctionNameList;
  243. while (dwFunction &&
  244. *(DWORD *)(dwFunction + dwBase) &&
  245. (!IsBadReadPtr ( (char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2), 1 ) ) &&
  246. *(char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2))
  247. /*
  248. while (dwFunction &&
  249. *(DWORD *)(dwFunction + dwBase) &&
  250. *(char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2))
  251. */
  252. {
  253. nSize += strlen ((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)) + 1;
  254. dwFunction += 4;
  255. nCnt++;
  256. }
  257. /* allocate memory off heap for function names */
  258. *pszFunctions = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
  259. psz = *pszFunctions;
  260. /* copy function names to mempry pointer */
  261. dwFunction = pid->dwRVAFunctionNameList;
  262. while (dwFunction &&
  263. *(DWORD *)(dwFunction + dwBase) &&
  264. (!IsBadReadPtr ( (char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2), 1 ) ) &&
  265. *(char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2))
  266. /*
  267. while (dwFunction &&
  268. *(DWORD *)(dwFunction + dwBase) &&
  269. *((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)))
  270. */
  271. {
  272. strcpy (psz, (char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2));
  273. psz += strlen ((char *)((*(DWORD *)(dwFunction + dwBase)) + dwBase+2)) + 1;
  274. dwFunction += 4;
  275. }
  276. // fprintf (stderr, "nCnt = %d\n", nCnt);
  277. return nCnt;
  278. }
  279. /* get exported function names separated by null terminators, return count of functions */
  280. int WINAPI GetExportFunctionNames (
  281. LPVOID lpFile,
  282. HANDLE hHeap,
  283. char **pszFunctions)
  284. {
  285. IMAGE_SECTION_HEADER sh;
  286. PIMAGE_EXPORT_DIRECTORY ped;
  287. char *pNames, *pCnt;
  288. int i, nCnt;
  289. /* get section header and pointer to data directory for .edata section */
  290. if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
  291. (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL)
  292. return 0;
  293. GetSectionHdrByName (lpFile, &sh, ".edata");
  294. /* determine the offset of the export function names */
  295. pNames = (char *)(*(int *)((int)ped->AddressOfNames -
  296. (int)sh.VirtualAddress +
  297. (int)sh.PointerToRawData +
  298. (LONG_PTR)lpFile) -
  299. (int)sh.VirtualAddress +
  300. (int)sh.PointerToRawData +
  301. (LONG_PTR)lpFile);
  302. /* figure out how much memory to allocate for all strings */
  303. pCnt = pNames;
  304. for (i=0; i<(int)ped->NumberOfNames; i++)
  305. while (*pCnt++);
  306. nCnt = (int)(pCnt - pNames);
  307. /* allocate memory off heap for function names */
  308. *pszFunctions = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt);
  309. /* copy all string to buffer */
  310. CopyMemory ((LPVOID)*pszFunctions, (LPVOID)pNames, nCnt);
  311. return nCnt;
  312. }
  313. /* return the number of exported functions in the module */
  314. int WINAPI GetNumberOfExportedFunctions (
  315. LPVOID lpFile)
  316. {
  317. PIMAGE_EXPORT_DIRECTORY ped;
  318. /* get section header and pointer to data directory for .edata section */
  319. if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
  320. (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL)
  321. return 0;
  322. else
  323. return (int)ped->NumberOfNames;
  324. }
  325. /* return a pointer to the list of function entry points */
  326. LPVOID WINAPI GetExportFunctionEntryPoints (
  327. LPVOID lpFile)
  328. {
  329. IMAGE_SECTION_HEADER sh;
  330. PIMAGE_EXPORT_DIRECTORY ped;
  331. /* get section header and pointer to data directory for .edata section */
  332. if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
  333. (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL)
  334. return NULL;
  335. GetSectionHdrByName (lpFile, &sh, ".edata");
  336. /* determine the offset of the export function entry points */
  337. return (LPVOID) ((int)ped->AddressOfFunctions -
  338. (int)sh.VirtualAddress +
  339. (int)sh.PointerToRawData +
  340. (LONG_PTR)lpFile);
  341. }
  342. /* return a pointer to the list of function ordinals */
  343. LPVOID WINAPI GetExportFunctionOrdinals (
  344. LPVOID lpFile)
  345. {
  346. IMAGE_SECTION_HEADER sh;
  347. PIMAGE_EXPORT_DIRECTORY ped;
  348. /* get section header and pointer to data directory for .edata section */
  349. if ((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
  350. (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL)
  351. return NULL;
  352. GetSectionHdrByName (lpFile, &sh, ".edata");
  353. /* determine the offset of the export function entry points */
  354. return (LPVOID) ((int)ped->AddressOfNameOrdinals -
  355. (int)sh.VirtualAddress +
  356. (int)sh.PointerToRawData +
  357. (LONG_PTR)lpFile);
  358. }
  359. /* determine the total number of resources in the section */
  360. int WINAPI GetNumberOfResources (
  361. LPVOID lpFile)
  362. {
  363. PIMAGE_RESOURCE_DIRECTORY prdRoot, prdType;
  364. PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
  365. int nCnt=0, i;
  366. /* get root directory of resource tree */
  367. if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY)ImageDirectoryOffset
  368. (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
  369. return 0;
  370. /* set pointer to first resource type entry */
  371. prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LONG_PTR)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
  372. /* loop through all resource directory entry types */
  373. for (i=0; i<prdRoot->NumberOfIdEntries; i++)
  374. {
  375. /* locate directory or each resource type */
  376. prdType = (PIMAGE_RESOURCE_DIRECTORY)((LONG_PTR)prdRoot + (LONG_PTR)prde->OffsetToData);
  377. /* mask off most significant bit of the data offset */
  378. prdType = (PIMAGE_RESOURCE_DIRECTORY)((LONG_PTR)prdType ^ 0x80000000);
  379. /* increment count of name'd and ID'd resources in directory */
  380. nCnt += prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries;
  381. /* increment to next entry */
  382. prde++;
  383. }
  384. return nCnt;
  385. }
  386. /* name each type of resource in the section */
  387. int WINAPI GetListOfResourceTypes (
  388. LPVOID lpFile,
  389. HANDLE hHeap,
  390. char **pszResTypes)
  391. {
  392. PIMAGE_RESOURCE_DIRECTORY prdRoot;
  393. PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
  394. char *pMem;
  395. int nCnt, i;
  396. /* get root directory of resource tree */
  397. if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY)ImageDirectoryOffset
  398. (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
  399. return 0;
  400. /* allocate enuff space from heap to cover all types */
  401. nCnt = prdRoot->NumberOfIdEntries * (MAXRESOURCENAME + 1);
  402. *pszResTypes = (char *)HeapAlloc (hHeap,
  403. HEAP_ZERO_MEMORY,
  404. nCnt);
  405. if ((pMem = *pszResTypes) == NULL)
  406. return 0;
  407. /* set pointer to first resource type entry */
  408. prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LONG_PTR)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
  409. /* loop through all resource directory entry types */
  410. for (i=0; i<prdRoot->NumberOfIdEntries; i++)
  411. {
  412. if (LoadString (hDll, prde->Name, pMem, MAXRESOURCENAME))
  413. pMem += strlen (pMem) + 1;
  414. prde++;
  415. }
  416. return nCnt;
  417. }
  418. /* function indicates whether debug info has been stripped from file */
  419. BOOL WINAPI IsDebugInfoStripped (
  420. LPVOID lpFile)
  421. {
  422. PIMAGE_FILE_HEADER pfh;
  423. pfh = (PIMAGE_FILE_HEADER)PEFHDROFFSET (lpFile);
  424. return (pfh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
  425. }
  426. /* retrieve the module name from the debug misc. structure */
  427. int WINAPI RetrieveModuleName (
  428. LPVOID lpFile,
  429. HANDLE hHeap,
  430. char **pszModule)
  431. {
  432. PIMAGE_DEBUG_DIRECTORY pdd;
  433. PIMAGE_DEBUG_MISC pdm = NULL;
  434. int nCnt;
  435. if (!(pdd = (PIMAGE_DEBUG_DIRECTORY)ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_DEBUG)))
  436. return 0;
  437. while (pdd->SizeOfData)
  438. {
  439. if (pdd->Type == IMAGE_DEBUG_TYPE_MISC)
  440. {
  441. pdm = (PIMAGE_DEBUG_MISC)((DWORD)pdd->PointerToRawData + (LONG_PTR)lpFile);
  442. *pszModule = (char *)HeapAlloc (hHeap,
  443. HEAP_ZERO_MEMORY,
  444. (nCnt = (lstrlen (pdm->Data)*(pdm->Unicode?2:1)))+1);
  445. CopyMemory (*pszModule, pdm->Data, nCnt);
  446. break;
  447. }
  448. pdd ++;
  449. }
  450. if (pdm != NULL)
  451. return nCnt;
  452. else
  453. return 0;
  454. }
  455. /* determine if this is a valid debug file */
  456. BOOL WINAPI IsDebugFile (
  457. LPVOID lpFile)
  458. {
  459. PIMAGE_SEPARATE_DEBUG_HEADER psdh;
  460. psdh = (PIMAGE_SEPARATE_DEBUG_HEADER)lpFile;
  461. return (psdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE);
  462. }
  463. /* copy separate debug header structure from debug file */
  464. BOOL WINAPI GetSeparateDebugHeader (
  465. LPVOID lpFile,
  466. PIMAGE_SEPARATE_DEBUG_HEADER psdh)
  467. {
  468. PIMAGE_SEPARATE_DEBUG_HEADER pdh;
  469. pdh = (PIMAGE_SEPARATE_DEBUG_HEADER)lpFile;
  470. if (pdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE)
  471. {
  472. CopyMemory ((LPVOID)psdh, (LPVOID)pdh, sizeof (IMAGE_SEPARATE_DEBUG_HEADER));
  473. return TRUE;
  474. }
  475. return FALSE;
  476. }