仿LordPE获取PE结构
乍一看LordPE一个小工具一般般,真的动手做起来才知道技术含量高的很。
当前只是获取到PE结构并打印,仅此而已。
PE.h
1 #pragma once 2 #include <stdio.h> 3 #include <stdarg.h> 4 5 #include <Windows.h> 6 #include <time.h> 7 8 9 HANDLE m_hFile = NULL; // 文件句柄 10 HANDLE m_hMap = NULL; // 文件映射句柄 11 LPVOID m_lpBase = NULL; // 映射基址 12 DWORD m_dwLen = 0; // 文件数据大小 13 IMAGE_DOS_HEADER *m_pDosHeader = NULL; // Dos头 14 IMAGE_NT_HEADERS *m_pNtHeaders = NULL; // NT头 15 IMAGE_SECTION_HEADER *m_pSecHeader = NULL; 16 17 /* 18 读取PE磁盘文件 19 fileUrl:文件路径 20 lpSaveData:保存数据的指针 21 成功返回数据大小,失败返回0. 22 */ 23 DWORD ReadPeFile(char *fileUrl, LPVOID lpSaveData); 24 25 VOID DestroryFunc(void);
PE.cpp
1 #include "PE.h" 2 3 DWORD ReadPeFile(char *fileUrl, LPVOID lpSaveData) 4 { 5 m_hFile = CreateFile(fileUrl, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 6 if (m_hFile == INVALID_HANDLE_VALUE) 7 { 8 printf("[ReadPeFile]:Can't open file!\n"); 9 return 0; 10 } 11 m_hMap = CreateFileMapping(m_hFile, NULL, PAGE_READWRITE | SEC_IMAGE, 0, 0, 0); 12 if (!m_hMap) 13 { 14 printf("[ReadPeFile]:Can't create filemap!\n"); 15 return 0; 16 } 17 m_lpBase = MapViewOfFile(m_hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); 18 if (!m_lpBase) 19 { 20 printf("[ReadPeFile]:MapViewOfFile bad!\n"); 21 return 0; 22 } 23 m_dwLen = GetFileSize(m_hFile, &m_dwLen); 24 m_pDosHeader = (PIMAGE_DOS_HEADER)m_lpBase; 25 if (m_pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) 26 { 27 printf("[ReadPeFile]:Not is pe file!\n"); 28 return 0; 29 } 30 m_pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)m_lpBase + m_pDosHeader->e_lfanew); 31 if (m_pNtHeaders->Signature != IMAGE_NT_SIGNATURE) 32 { 33 printf("[ReadPeFile]:Not is execut programmer!\n"); 34 return 0; 35 } 36 m_pSecHeader = (PIMAGE_SECTION_HEADER)((DWORD)&(m_pNtHeaders->OptionalHeader) + m_pNtHeaders->FileHeader.SizeOfOptionalHeader); 37 return m_dwLen; 38 } 39 40 VOID DestroryFunc(void) 41 { 42 CloseHandle(m_hMap); 43 CloseHandle(m_hFile); 44 UnmapViewOfFile(m_lpBase); 45 } 46 47 LPCSTR _getMachineName(WORD wMachine) 48 { 49 char *name = (char *)malloc(125); 50 51 switch (wMachine) 52 { 53 case 0: 54 lstrcpy(name, "Unknown"); 55 break; 56 case 0x14c: 57 lstrcpy(name, "Intel 386"); 58 break; 59 case 0x0162: 60 lstrcpy(name, "MIPS little-endian, 0x160 big-endian"); 61 break; 62 case 0x0166: 63 lstrcpy(name, "MIPS little-endian"); 64 break; 65 case 0x0168: 66 lstrcpy(name, "MIPS little-endian"); 67 break; 68 case 0x0169: 69 lstrcpy(name, "MIPS little-endian WCE v2"); 70 break; 71 case 0x0184: 72 lstrcpy(name, "Alpha_AXP"); 73 break; 74 case 0x01a2: 75 lstrcpy(name, "SH3 little-endian"); 76 break; 77 case 0x01a4: 78 lstrcpy(name, "SH3E little-endian"); 79 break; 80 case 0x01a6: 81 lstrcpy(name, "SH4 little-endian"); 82 break; 83 case 0x01a8: 84 lstrcpy(name, "SH5"); 85 break; 86 case 0x01c0: 87 lstrcpy(name, "ARM Little-Endian"); 88 break; 89 case 0x01c2: 90 lstrcpy(name, "ARM Thumb/Thumb-2 Little-Endian"); 91 break; 92 case 0x01c4: 93 lstrcpy(name, "ARM Thumb-2 Little-Endian"); 94 break; 95 case 0x01F0: 96 lstrcpy(name, "IBM PowerPC Little-Endian"); 97 break; 98 case 0x0200: 99 lstrcpy(name, "Intel 64"); 100 break; 101 case 0x0266: 102 lstrcpy(name, "MIPS"); 103 break; 104 case 0x0284: 105 lstrcpy(name, "ALPHA64"); 106 break; 107 case 0x0366: 108 lstrcpy(name, "MIPS"); 109 break; 110 case 0x0466: 111 lstrcpy(name, "MIPS"); 112 break; 113 case 0x0520: 114 lstrcpy(name, "Infineon"); 115 break; 116 case 0x0EBC: 117 lstrcpy(name, "EFI Byte Code"); 118 break; 119 case 0x8664: 120 lstrcpy(name, "AMD64 (K8)"); 121 break; 122 case 0x9041: 123 lstrcpy(name, "M32R little-endian"); 124 break; 125 default: 126 free(name); 127 return NULL; 128 break; 129 } 130 return name; 131 } 132 133 VOID _printFormat(char *dataName, WORD *dataAddr, int nSize) 134 { 135 printf("\t%s:", dataName); 136 for (int i = 0; i < (int)(13 - strlen(dataName)); i++) 137 { 138 printf(" "); 139 } 140 printf("0x"); 141 for (int i = 0; i < nSize; i++) 142 { 143 printf("%04X", dataAddr[i]); 144 } 145 printf("\n"); 146 } 147 148 VOID test_PrintPeInfo(void) 149 { 150 char infoTmp[50] = { 0 }; 151 152 printf("->DOS Header\n"); 153 _printFormat("e_magic", &m_pDosHeader->e_magic, 1); 154 _printFormat("e_cblp", &m_pDosHeader->e_cblp, 1); 155 _printFormat("e_cp", &m_pDosHeader->e_cp, 1); 156 _printFormat("e_crlc", &m_pDosHeader->e_crlc, 1); 157 _printFormat("e_cparhdr", &m_pDosHeader->e_cparhdr, 1); 158 _printFormat("e_minalloc", &m_pDosHeader->e_minalloc, 1); 159 _printFormat("e_maxalloc", &m_pDosHeader->e_maxalloc, 1); 160 _printFormat("e_ss", &m_pDosHeader->e_ss, 1); 161 _printFormat("e_sp", &m_pDosHeader->e_sp, 1); 162 _printFormat("e_csum", &m_pDosHeader->e_csum, 1); 163 _printFormat("e_ip", &m_pDosHeader->e_ip, 1); 164 _printFormat("e_cs", &m_pDosHeader->e_cs, 1); 165 _printFormat("e_lfarlc", &m_pDosHeader->e_lfarlc, 1); 166 _printFormat("e_ovno", &m_pDosHeader->e_ovno, 1); 167 _printFormat("e_res", m_pDosHeader->e_res, 4); 168 _printFormat("e_oeminfo", &m_pDosHeader->e_oemid, 1); 169 _printFormat("e_oeminfo", &m_pDosHeader->e_oeminfo, 1); 170 _printFormat("e_res2", m_pDosHeader->e_res2, 10); 171 printf("\te_lfanew: 0x%08X\n\n", m_pDosHeader->e_lfanew); 172 173 printf("->File Header\n"); 174 printf("\tMachine: 0x%04X (%s)\n", m_pNtHeaders->FileHeader.Machine,_getMachineName(m_pNtHeaders->FileHeader.Machine)); 175 printf("\tNumberOfSections: 0x%04X\n", m_pNtHeaders->FileHeader.NumberOfSections); 176 struct tm Tm = { 0 }; 177 gmtime_s(&Tm, (time_t *)&(m_pNtHeaders->FileHeader.TimeDateStamp)); 178 printf("\tTimeDateStamp: 0x%04X (%d/%d/%d %d:%d:%d)\n", m_pNtHeaders->FileHeader.TimeDateStamp, Tm.tm_year + 1900, Tm.tm_mon + 1, Tm.tm_mday, Tm.tm_hour, Tm.tm_min, Tm.tm_sec); 179 printf("\tPointerToSymbolTable: 0x%04X\n", m_pNtHeaders->FileHeader.PointerToSymbolTable); 180 printf("\tNumberOfSymbols: 0x%04X\n", m_pNtHeaders->FileHeader.NumberOfSymbols); 181 printf("\tSizeOfOptionalHeader: 0x%04X\n", m_pNtHeaders->FileHeader.SizeOfOptionalHeader); 182 printf("\tCharacteristics: 0x%04X\n\n", m_pNtHeaders->FileHeader.Characteristics); 183 184 printf("->Optional Header\n"); 185 printf("\tMagic: 0x%04X",m_pNtHeaders->OptionalHeader.Magic); 186 switch (m_pNtHeaders->OptionalHeader.Magic) 187 { 188 case IMAGE_NT_OPTIONAL_HDR32_MAGIC: 189 printf(" (HDR32_MAGIC)\n"); 190 break; 191 case IMAGE_NT_OPTIONAL_HDR64_MAGIC: 192 printf(" (HDR64_MAGIC)\n"); 193 break; 194 case IMAGE_ROM_OPTIONAL_HDR_MAGIC: 195 printf(" (ROM_MAGIC)\n"); 196 break; 197 default: 198 printf(" (Unknown)\n"); 199 break; 200 } 201 printf("\tMajorLinkerVersion: 0x%02X\n", m_pNtHeaders->OptionalHeader.MajorLinkerVersion); 202 printf("\tMinorLinkerVersion: 0x%02X -> %d.%02d\n", m_pNtHeaders->OptionalHeader.MinorLinkerVersion,m_pNtHeaders->OptionalHeader.MajorLinkerVersion,m_pNtHeaders->OptionalHeader.MinorLinkerVersion); 203 printf("\tSizeOfCode: 0x%08X\n", m_pNtHeaders->OptionalHeader.SizeOfCode); 204 printf("\tSizeOfInitializedData: 0x%08X\n", m_pNtHeaders->OptionalHeader.SizeOfInitializedData); 205 printf("\tSizeOfUninitializedData: 0x%08X\n", m_pNtHeaders->OptionalHeader.SizeOfUninitializedData); 206 printf("\tAddressOfEntryPoint: 0x%08X\n", m_pNtHeaders->OptionalHeader.AddressOfEntryPoint); 207 printf("\tBaseOfCode: 0x%08X\n", m_pNtHeaders->OptionalHeader.BaseOfCode); 208 printf("\tBaseOfData: 0x%08X\n", m_pNtHeaders->OptionalHeader.BaseOfData); 209 printf("\tImageBase: 0x%08X\n", m_pNtHeaders->OptionalHeader.ImageBase); 210 printf("\tSectionAlignment: 0x%08X\n", m_pNtHeaders->OptionalHeader.SectionAlignment); 211 printf("\tFileAlignment: 0x%08X\n", m_pNtHeaders->OptionalHeader.FileAlignment); 212 printf("\tMajorOperatingSystemVersion: 0x%08X\n", m_pNtHeaders->OptionalHeader.MajorOperatingSystemVersion); 213 printf("\tMinorOperatingSystemVersion: 0x%08X -> %d.%02d\n", m_pNtHeaders->OptionalHeader.MinorOperatingSystemVersion, m_pNtHeaders->OptionalHeader.MajorOperatingSystemVersion, m_pNtHeaders->OptionalHeader.MinorOperatingSystemVersion); 214 printf("\tMajorImageVersion: 0x%08X\n", m_pNtHeaders->OptionalHeader.MajorImageVersion); 215 printf("\tMinorImageVersion: 0x%08X -> %d.%02d\n", m_pNtHeaders->OptionalHeader.MinorImageVersion, m_pNtHeaders->OptionalHeader.MajorImageVersion, m_pNtHeaders->OptionalHeader.MinorImageVersion); 216 printf("\tMajorSubsystemVersion: 0x%08X\n", m_pNtHeaders->OptionalHeader.MajorSubsystemVersion); 217 printf("\tMinorSubsystemVersion: 0x%08X -> %d.%02d\n", m_pNtHeaders->OptionalHeader.MinorSubsystemVersion, m_pNtHeaders->OptionalHeader.MajorSubsystemVersion, m_pNtHeaders->OptionalHeader.MinorSubsystemVersion); 218 printf("\tWin32VersionValue: 0x%08X\n", m_pNtHeaders->OptionalHeader.Win32VersionValue); 219 printf("\tSizeOfImage: 0x%08X\n", m_pNtHeaders->OptionalHeader.SizeOfImage); 220 printf("\tSizeOfHeaders: 0x%08X\n", m_pNtHeaders->OptionalHeader.SizeOfHeaders); 221 printf("\tCheckSum: 0x%08X\n", m_pNtHeaders->OptionalHeader.CheckSum); 222 printf("\tSubsystem: 0x%04X", m_pNtHeaders->OptionalHeader.Subsystem); 223 switch (m_pNtHeaders->OptionalHeader.Subsystem) 224 { 225 case IMAGE_SUBSYSTEM_UNKNOWN: 226 printf(" (Unknown)\n"); 227 break; 228 case IMAGE_SUBSYSTEM_NATIVE: 229 printf(" (Driver And SysPro)\n"); 230 break; 231 case IMAGE_SUBSYSTEM_WINDOWS_GUI: 232 printf(" (Windows_GUI)\n"); 233 break; 234 case IMAGE_SUBSYSTEM_WINDOWS_CUI: 235 printf(" (Windows_CUI)\n"); 236 break; 237 case IMAGE_SUBSYSTEM_OS2_CUI: 238 printf(" (OS/2_CUI)\n"); 239 break; 240 case IMAGE_SUBSYSTEM_POSIX_CUI: 241 printf(" (POSIX_CUI)\n"); 242 break; 243 case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: 244 printf(" (WinCE_GUI)\n"); 245 break; 246 case IMAGE_SUBSYSTEM_EFI_APPLICATION: 247 printf(" (EFI)\n"); 248 break; 249 case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: 250 printf(" (EFI_Driver)\n"); 251 break; 252 case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: 253 printf(" (EFI_Dirver Run-Time)\n"); 254 break; 255 case IMAGE_SUBSYSTEM_EFI_ROM: 256 printf(" (EFI_ROM)\n"); 257 break; 258 case IMAGE_SUBSYSTEM_XBOX: 259 printf(" (XBox)\n"); 260 break; 261 case IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION: 262 printf(" (Boot Application)\n"); 263 break; 264 default: 265 printf(" (Unknown!)"); 266 break; 267 } 268 printf("\tDllCharacteristics: 0x%04X\n", m_pNtHeaders->OptionalHeader.DllCharacteristics); 269 printf("\tSizeOfStackReserve: 0x%08X\n", m_pNtHeaders->OptionalHeader.SizeOfStackReserve); 270 printf("\tSizeOfStackCommit: 0x%08X\n", m_pNtHeaders->OptionalHeader.SizeOfStackCommit); 271 printf("\tSizeOfHeapReserve: 0x%08X\n", m_pNtHeaders->OptionalHeader.SizeOfHeapReserve); 272 printf("\tLoaderFlags: 0x%08X\n", m_pNtHeaders->OptionalHeader.LoaderFlags); 273 printf("\tNumberOfRvaAndSizes: 0x%08X\n\n", m_pNtHeaders->OptionalHeader.NumberOfRvaAndSizes); 274 275 printf("\tDataDirectory(16) RVA Size\n"); 276 printf("\t----------------- ---------- ----------\n"); 277 for (DWORD dwI = 0; dwI < m_pNtHeaders->OptionalHeader.NumberOfRvaAndSizes; dwI++) 278 { 279 switch (dwI) 280 { 281 case 0: 282 printf("\t%-29s", "ExportTable"); 283 break; 284 case 1: 285 printf("\t%-29s", "ImportTable"); 286 break; 287 case 2: 288 printf("\t%-29s", "Resource"); 289 break; 290 case 3: 291 printf("\t%-29s", "Exception"); 292 break; 293 case 4: 294 printf("\t%-29s", "Security"); 295 break; 296 case 5: 297 printf("\t%-29s", "Relocation"); 298 break; 299 case 6: 300 printf("\t%-29s", "Debug"); 301 break; 302 case 7: 303 printf("\t%-29s", "Copyright"); 304 break; 305 case 8: 306 printf("\t%-29s", "GlobalPtr"); 307 break; 308 case 9: 309 printf("\t%-29s", "TLSTable"); 310 break; 311 case 10: 312 printf("\t%-29s", "LoadConfig"); 313 break; 314 case 11: 315 printf("\t%-29s", "BoundImport"); 316 break; 317 case 12: 318 printf("\t%-29s", "IAT"); 319 break; 320 case 13: 321 printf("\t%-29s", "DelayImport"); 322 break; 323 case 14: 324 printf("\t%-29s", "COM"); 325 break; 326 case 15: 327 printf("\t%-29s", "Reserved"); 328 break; 329 default: 330 printf("\t%-29s", "Unknown"); 331 break; 332 } 333 printf("0x%08X 0x%08X", m_pNtHeaders->OptionalHeader.DataDirectory[dwI].VirtualAddress, m_pNtHeaders->OptionalHeader.DataDirectory[dwI].Size); 334 for (WORD wI = 0; wI < m_pNtHeaders->FileHeader.NumberOfSections; wI++) 335 { 336 // 如果该数据目录的起始地址>某节起始地址 && 该数据目录的结束地址<某节结束地址,那么就说明该数据目录存在此节中. 337 if ((m_pSecHeader[wI].VirtualAddress <= m_pNtHeaders->OptionalHeader.DataDirectory[dwI].VirtualAddress) && ((m_pSecHeader[wI].VirtualAddress + m_pSecHeader[wI].Misc.VirtualSize) >= (m_pNtHeaders->OptionalHeader.DataDirectory[dwI].VirtualAddress + m_pNtHeaders->OptionalHeader.DataDirectory[dwI].Size))) 338 { 339 printf(" (\"%s\")", m_pSecHeader[wI].Name); 340 break; 341 } 342 } 343 printf("\n"); 344 } 345 return; 346 } 347 348 int main(void) 349 { 350 351 LPVOID lpData = NULL; 352 printf("Hello Pe!\n"); 353 ReadPeFile("C:\\Users\\Hades\\Desktop\\测试程序.exe", lpData); 354 test_PrintPeInfo(); 355 DestroryFunc(); 356 system("pause"); 357 return 0; 358 }
效果图:
以后有机会我要一步步的仿造出LordPE的所有功能。