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.

233 lines
9.9 KiB

  1. /*
  2. PEWhack - Corrupts a PE binary to be non-executable but still useful when
  3. debugging memory dumps.
  4. */
  5. #include <windows.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <dbghelp.h>
  9. #include <strsafe.h>
  10. #include <PEWhack.h>
  11. BOOL CorruptDataDirectories(PIMAGE_DOS_HEADER pDosHdr, ULONG DirCount);
  12. BOOL CorruptSections(PIMAGE_SECTION_HEADER pSection, ULONG ulSections, PIMAGE_DOS_HEADER ImageBase);
  13. BOOL CorruptSections(PIMAGE_SECTION_HEADER pSection, ULONG ulSections, PIMAGE_DOS_HEADER ImageBase) {
  14. BOOL ReturnValue = FALSE;
  15. ULONG i;
  16. for ( i=0; i < ulSections; i++ ) {
  17. // .data sections can be killed
  18. if ( strncmp(".data", (CHAR*)(pSection[i].Name), 5) == 0 ) {
  19. // writeable sections can go away...
  20. if ( (pSection[i].Characteristics & IMAGE_SCN_MEM_WRITE) ) {
  21. if ( pSection[i].PointerToRawData != 0 ) {
  22. ZeroMemory( (VOID*)( (pSection+i)->PointerToRawData + (ULONG_PTR)ImageBase), pSection[i].SizeOfRawData);
  23. }
  24. pSection[i].PointerToRawData= 0;
  25. pSection[i].SizeOfRawData = 0;
  26. pSection[i].Characteristics = 0;
  27. ReturnValue = TRUE;
  28. }
  29. }
  30. }
  31. return(ReturnValue);
  32. }
  33. //
  34. // Verifies an image is a PE binary and, if so, corrupts it to be
  35. // non-executable but still useful for debugging memory dumps.
  36. //
  37. DWORD CorruptFile(LPCTSTR Filename) {
  38. DWORD Return = PEWHACK_SUCCESS;
  39. HANDLE hFile;
  40. HANDLE hFileMap;
  41. PIMAGE_DOS_HEADER pDosHeader = NULL;
  42. PIMAGE_NT_HEADERS32 pPe32Header = NULL;
  43. PIMAGE_SECTION_HEADER pSectionHeader = NULL;
  44. IMAGE_DEBUG_DIRECTORY UNALIGNED *pDebugDir = NULL;
  45. ULONG DebugSize;
  46. ULONG SectionIndex;
  47. hFile = CreateFile( (LPCTSTR)Filename,
  48. GENERIC_WRITE|GENERIC_READ,
  49. 0,
  50. NULL,
  51. OPEN_EXISTING,
  52. FILE_ATTRIBUTE_NORMAL,
  53. NULL);
  54. if (hFile != INVALID_HANDLE_VALUE) {
  55. hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
  56. if (hFileMap != NULL) {
  57. pDosHeader = (PIMAGE_DOS_HEADER)MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
  58. if (pDosHeader != NULL) {
  59. // Verify this is an PE image
  60. if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
  61. //
  62. // Start by assuming a 32bit binary until we check the machine type
  63. //
  64. pPe32Header = (PIMAGE_NT_HEADERS32)( (PCHAR)(pDosHeader) + (ULONG)(pDosHeader)->e_lfanew);
  65. if (pPe32Header->Signature == IMAGE_NT_SIGNATURE) {
  66. //
  67. // 32bit header
  68. //
  69. if (pPe32Header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  70. // Mark the image as non-executable
  71. pPe32Header->FileHeader.Characteristics &= ~IMAGE_FILE_EXECUTABLE_IMAGE;
  72. // Whack some optional header info
  73. pPe32Header->OptionalHeader.SizeOfInitializedData = 0;
  74. pPe32Header->OptionalHeader.SizeOfUninitializedData = 0;
  75. pPe32Header->OptionalHeader.MajorOperatingSystemVersion = 0xFFFF; // absurdly high
  76. pPe32Header->OptionalHeader.MinorOperatingSystemVersion = 0xFFFF; // absurdly high
  77. pPe32Header->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_UNKNOWN;
  78. // Corrupt the section data
  79. pSectionHeader = IMAGE_FIRST_SECTION(pPe32Header);
  80. CorruptSections(pSectionHeader, pPe32Header->FileHeader.NumberOfSections, pDosHeader);
  81. // Corrupt data directories
  82. CorruptDataDirectories(pDosHeader, pPe32Header->OptionalHeader.NumberOfRvaAndSizes);
  83. pPe32Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = 0;
  84. pPe32Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = 0;
  85. pPe32Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
  86. pPe32Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
  87. //
  88. // 64bit header
  89. //
  90. } else if (pPe32Header->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  91. PIMAGE_NT_HEADERS64 pPe64Header = (PIMAGE_NT_HEADERS64)pPe32Header;
  92. // Mark the image as non-executable
  93. pPe64Header->FileHeader.Characteristics &= ~IMAGE_FILE_EXECUTABLE_IMAGE;
  94. // Whack some optional header info
  95. pPe64Header->OptionalHeader.SizeOfInitializedData = 0;
  96. pPe64Header->OptionalHeader.SizeOfUninitializedData = 0;
  97. pPe64Header->OptionalHeader.MajorOperatingSystemVersion = 0xFFFF; // absurdly high
  98. pPe64Header->OptionalHeader.MinorOperatingSystemVersion = 0xFFFF; // absurdly high
  99. pPe64Header->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_UNKNOWN;
  100. // Corrupt the section data
  101. pSectionHeader = IMAGE_FIRST_SECTION(pPe64Header);
  102. CorruptSections( pSectionHeader, pPe64Header->FileHeader.NumberOfSections, pDosHeader);
  103. // Corrupt data directories
  104. CorruptDataDirectories(pDosHeader, pPe64Header->OptionalHeader.NumberOfRvaAndSizes);
  105. pPe64Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = 0;
  106. pPe64Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = 0;
  107. pPe64Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
  108. pPe64Header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
  109. } else {
  110. Return = PEWHACK_BAD_ARCHITECTURE;
  111. }
  112. } else {
  113. Return = PEWHACK_BAD_PE_SIG;
  114. }
  115. } else {
  116. Return = PEWHACK_BAD_DOS_SIG;
  117. }
  118. FlushViewOfFile(pDosHeader, 0);
  119. UnmapViewOfFile(pDosHeader);
  120. } else {
  121. Return = PEWHACK_MAPVIEW_FAILED;
  122. }
  123. CloseHandle(hFileMap);
  124. } else {
  125. Return = PEWHACK_CREATEMAP_FAILED;
  126. }
  127. CloseHandle(hFile);
  128. } else {
  129. Return = PEWHACK_CREATEFILE_FAILED;
  130. }
  131. return(Return);
  132. }
  133. //
  134. // Corrupts the data directories of a binary. Machine independent.
  135. //
  136. BOOL CorruptDataDirectories(PIMAGE_DOS_HEADER pDosHdr, ULONG DirCount) {
  137. PIMAGE_SECTION_HEADER pImageSectionHeader = NULL;
  138. ULONG Loop;
  139. BOOL RetVal = FALSE;
  140. for (Loop=0;Loop<DirCount;Loop++) {
  141. PCHAR pData;
  142. ULONG Size;
  143. pData = (PCHAR)ImageDirectoryEntryToDataEx(pDosHdr, FALSE, (USHORT)Loop, &Size, &pImageSectionHeader);
  144. if (pData) {
  145. switch (Loop) {
  146. //
  147. // Sections to corrupt wholesale
  148. //
  149. case IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
  150. case IMAGE_DIRECTORY_ENTRY_BASERELOC:
  151. ZeroMemory(pData, Size);
  152. pImageSectionHeader->Misc.PhysicalAddress = 0;
  153. pImageSectionHeader->VirtualAddress = 0;
  154. pImageSectionHeader->SizeOfRawData = 0;
  155. pImageSectionHeader->Characteristics = 0;
  156. pImageSectionHeader->PointerToRawData = 0;
  157. RetVal = TRUE;
  158. break;
  159. //
  160. // Wholesale corruption of these sections make it impossible
  161. // to use the binary with the debugger. It may be worthwhile
  162. // to look into limited corruption of each section.
  163. //
  164. case IMAGE_DIRECTORY_ENTRY_IMPORT:
  165. case IMAGE_DIRECTORY_ENTRY_EXPORT:
  166. case IMAGE_DIRECTORY_ENTRY_DEBUG:
  167. case IMAGE_DIRECTORY_ENTRY_IAT:
  168. case IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
  169. case IMAGE_DIRECTORY_ENTRY_RESOURCE:
  170. break;
  171. //
  172. // The binaries I've checked so far lack these sections, so I'm
  173. // not sure if they're corruptable or not.
  174. //
  175. case IMAGE_DIRECTORY_ENTRY_EXCEPTION:
  176. case IMAGE_DIRECTORY_ENTRY_SECURITY:
  177. case IMAGE_DIRECTORY_ENTRY_ARCHITECTURE:
  178. case IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
  179. case IMAGE_DIRECTORY_ENTRY_TLS:
  180. case IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
  181. case IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
  182. default:
  183. break;
  184. }
  185. }
  186. }
  187. return(RetVal);
  188. }