pe.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. pe.c
  5. Abstract:
  6. This module implements functionality for manipulating Portable Executable
  7. (PE) binaries.
  8. Author:
  9. Evan Green 13-Oct-2012
  10. Environment:
  11. Any
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include "imp.h"
  17. #include "pe.h"
  18. //
  19. // ---------------------------------------------------------------- Definitions
  20. //
  21. //
  22. // ----------------------------------------------- Internal Function Prototypes
  23. //
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. //
  28. // -------------------------------------------------------------------- Globals
  29. //
  30. //
  31. // ------------------------------------------------------------------ Functions
  32. //
  33. BOOL
  34. ImpPeGetHeaders (
  35. PIMAGE_BUFFER Buffer,
  36. PIMAGE_NT_HEADERS *PeHeaders
  37. )
  38. /*++
  39. Routine Description:
  40. This routine returns a pointer to the PE image headers given a buffer
  41. containing the executable image mapped in memory.
  42. Arguments:
  43. Buffer - Supplies a pointer to the buffer to get the headers from.
  44. PeHeaders - Supplies a pointer where the location of the PE headers will
  45. be returned.
  46. Return Value:
  47. TRUE on success.
  48. FALSE otherwise.
  49. --*/
  50. {
  51. PIMAGE_DOS_HEADER DosHeader;
  52. //
  53. // Read the DOS header to find out where the PE headers are located.
  54. //
  55. DosHeader = ImpReadBuffer(NULL, Buffer, 0, sizeof(IMAGE_DOS_HEADER));
  56. if (DosHeader == NULL) {
  57. return FALSE;
  58. }
  59. if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  60. return FALSE;
  61. }
  62. *PeHeaders = ImpReadBuffer(NULL,
  63. Buffer,
  64. DosHeader->e_lfanew,
  65. sizeof(IMAGE_NT_HEADERS));
  66. if (*PeHeaders == NULL) {
  67. return FALSE;
  68. }
  69. //
  70. // Perform a few basic checks on the headers to make sure they're valid.
  71. //
  72. if (((*PeHeaders)->FileHeader.Characteristics &
  73. IMAGE_FILE_EXECUTABLE_IMAGE) == 0) {
  74. return FALSE;
  75. }
  76. if ((*PeHeaders)->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  77. return FALSE;
  78. }
  79. if ((*PeHeaders)->FileHeader.NumberOfSections == 0) {
  80. return FALSE;
  81. }
  82. return TRUE;
  83. }
  84. BOOL
  85. ImpPeGetSection (
  86. PIMAGE_BUFFER Buffer,
  87. PSTR SectionName,
  88. PVOID *Section,
  89. PULONGLONG VirtualAddress,
  90. PULONG SectionSizeInFile,
  91. PULONG SectionSizeInMemory
  92. )
  93. /*++
  94. Routine Description:
  95. This routine gets a pointer to the given section in a PE image given a
  96. memory mapped file.
  97. Arguments:
  98. Buffer - Supplies a pointer to the file buffer.
  99. SectionName - Supplies the name of the desired section.
  100. Section - Supplies a pointer where the pointer to the section will be
  101. returned.
  102. VirtualAddress - Supplies a pointer where the virtual address of the section
  103. will be returned, if applicable.
  104. SectionSizeInFile - Supplies a pointer where the size of the section as it
  105. appears in the file will be returned.
  106. SectionSizeInMemory - Supplies a pointer where the size of the section as it
  107. appears after being loaded in memory will be returned.
  108. Return Value:
  109. TRUE on success.
  110. FALSE otherwise.
  111. --*/
  112. {
  113. ULONG ItemsScanned;
  114. KSTATUS KStatus;
  115. BOOL Match;
  116. PSTR Name;
  117. ULONG Offset;
  118. PIMAGE_NT_HEADERS PeHeaders;
  119. BOOL Result;
  120. PVOID ReturnSection;
  121. ULONG ReturnSectionFileSize;
  122. ULONG ReturnSectionMemorySize;
  123. ULONG ReturnSectionVirtualAddress;
  124. PIMAGE_SECTION_HEADER SectionHeader;
  125. ULONG SectionIndex;
  126. PSTR StringTable;
  127. ULONG StringTableSize;
  128. PULONG StringTableSizePointer;
  129. ReturnSection = NULL;
  130. ReturnSectionFileSize = 0;
  131. ReturnSectionMemorySize = 0;
  132. ReturnSectionVirtualAddress = (UINTN)NULL;
  133. StringTable = NULL;
  134. StringTableSize = 0;
  135. if (SectionName == NULL) {
  136. Result = FALSE;
  137. goto GetSectionEnd;
  138. }
  139. Result = ImpPeGetHeaders(Buffer, &PeHeaders);
  140. if (Result == FALSE) {
  141. goto GetSectionEnd;
  142. }
  143. //
  144. // Read in the string table as well.
  145. //
  146. if (PeHeaders->FileHeader.PointerToSymbolTable != 0) {
  147. Offset = PeHeaders->FileHeader.PointerToSymbolTable +
  148. (PeHeaders->FileHeader.NumberOfSymbols * sizeof(COFF_SYMBOL));
  149. StringTableSizePointer = ImpReadBuffer(NULL, Buffer, Offset, 4);
  150. if (StringTableSizePointer == NULL) {
  151. Result = FALSE;
  152. goto GetSectionEnd;
  153. }
  154. StringTableSize = *StringTableSizePointer;
  155. StringTable = ImpReadBuffer(NULL, Buffer, Offset, StringTableSize);
  156. if (StringTable == NULL) {
  157. Result = FALSE;
  158. goto GetSectionEnd;
  159. }
  160. }
  161. //
  162. // Loop through all sections looking for the desired one.
  163. //
  164. SectionHeader = (PIMAGE_SECTION_HEADER)(PeHeaders + 1);
  165. for (SectionIndex = 0;
  166. SectionIndex < PeHeaders->FileHeader.NumberOfSections;
  167. SectionIndex += 1) {
  168. if (SectionHeader->Name[0] == '/') {
  169. if (StringTable == NULL) {
  170. Result = FALSE;
  171. goto GetSectionEnd;
  172. }
  173. KStatus = RtlStringScan((PSTR)(SectionHeader->Name + 1),
  174. IMAGE_SIZEOF_SHORT_NAME - 1,
  175. "%d",
  176. sizeof("%d"),
  177. CharacterEncodingAscii,
  178. &ItemsScanned,
  179. &Offset);
  180. if ((!KSUCCESS(KStatus)) || (ItemsScanned != 1)) {
  181. Result = FALSE;
  182. goto GetSectionEnd;
  183. }
  184. Name = StringTable + Offset;
  185. Match = RtlAreStringsEqual(Name,
  186. SectionName,
  187. StringTableSize - Offset);
  188. } else {
  189. Match = RtlAreStringsEqual((PSTR)SectionHeader->Name,
  190. SectionName,
  191. IMAGE_SIZEOF_SHORT_NAME);
  192. }
  193. //
  194. // If the name matches, return that section.
  195. //
  196. if (Match != FALSE) {
  197. ReturnSection = ImpReadBuffer(NULL,
  198. Buffer,
  199. SectionHeader->PointerToRawData,
  200. SectionHeader->SizeOfRawData);
  201. if (ReturnSection == NULL) {
  202. Result = FALSE;
  203. goto GetSectionEnd;
  204. }
  205. ReturnSectionFileSize = SectionHeader->SizeOfRawData;
  206. ReturnSectionMemorySize = SectionHeader->Misc.VirtualSize;
  207. //
  208. // The file size seems to always be rounded up to 0x200. Give the
  209. // more accurate number if possible.
  210. //
  211. if (ReturnSectionMemorySize < ReturnSectionFileSize) {
  212. ReturnSectionFileSize = ReturnSectionMemorySize;
  213. }
  214. ReturnSectionVirtualAddress = SectionHeader->VirtualAddress +
  215. PeHeaders->OptionalHeader.ImageBase;
  216. break;
  217. }
  218. SectionHeader += 1;
  219. }
  220. Result = TRUE;
  221. GetSectionEnd:
  222. if (Section != NULL) {
  223. *Section = ReturnSection;
  224. }
  225. if (VirtualAddress != NULL) {
  226. *VirtualAddress = ReturnSectionVirtualAddress;
  227. }
  228. if (SectionSizeInFile != NULL) {
  229. *SectionSizeInFile = ReturnSectionFileSize;
  230. }
  231. if (SectionSizeInMemory != NULL) {
  232. *SectionSizeInMemory = ReturnSectionMemorySize;
  233. }
  234. return Result;
  235. }
  236. //
  237. // --------------------------------------------------------- Internal Functions
  238. //