主程序代码 PEInfo.c
1 #include <Windows.h> 2 #include<Richedit.h> 3 #include "resource.h" 4 5 6 HINSTANCE hInstance; 7 HWND hWinEdit; 8 9 10 11 12 /* 13 初始化窗口程序 14 */ 15 void _Init(HWND hWinMain) 16 { 17 18 HICON hIcon; 19 CHARFORMAT stCf; 20 TCHAR szFont[] = TEXT("宋体"); 21 22 23 hWinEdit = GetDlgItem(hWinMain, IDC_INFO); 24 hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ICO_MAIN)); 25 SendMessage(hWinMain, WM_SETICON, ICON_BIG, (LPARAM)hIcon); //为窗口设置图标 26 SendMessage(hWinEdit, EM_SETTEXTMODE, TM_PLAINTEXT, 0); //设置编辑控件 27 28 RtlZeroMemory(&stCf, sizeof(stCf)); 29 stCf.cbSize = sizeof(stCf); 30 stCf.yHeight = 9 * 20; 31 stCf.dwMask = CFM_FACE | CFM_SIZE | CFM_BOLD; 32 lstrcpy(stCf.szFaceName, szFont); 33 SendMessage(hWinEdit, EM_SETCHARFORMAT, 0, (LPARAM)&stCf); 34 35 SendMessage(hWinEdit, EM_EXLIMITTEXT, 0, -1); 36 } 37 38 39 /* 40 往文本框中追加文本 41 */ 42 void _appendInfo(PTCHAR _lpsz) 43 { 44 CHARRANGE stCR; 45 int iTextLength; 46 47 iTextLength = GetWindowTextLength(hWinEdit); 48 stCR.cpMin = iTextLength; 49 stCR.cpMax = iTextLength; 50 51 SendMessage(hWinEdit, EM_EXSETSEL, 0, (LPARAM)&stCR); 52 SendMessage(hWinEdit, EM_REPLACESEL, FALSE, (LPARAM)_lpsz); 53 54 } 55 56 57 58 /* 59 从内存中获取PE文件的主要信息 60 */ 61 void _getMainInfo(PTCHAR _lpPeHead, PTCHAR szFileName) 62 { 63 PIMAGE_NT_HEADERS pImageNtHeaders; 64 PIMAGE_SECTION_HEADER pImageSectionHeader; 65 TCHAR szBuffer[1024]; 66 TCHAR szSecName[16]; 67 WORD dNumberOfSections; 68 TCHAR szMsg[] = TEXT("文件名:%s\n" 69 "-----------------------------------------\n\n\n" 70 "运行平台: 0x%04x (014c:Intel 386 014dh:Intel 486 014eh:Intel 586)\n" 71 "节的数量: %d\n" 72 "文件属性: 0x%04x (大尾-禁止多处理器-DLL-系统文件-禁止网络运行-禁止优盘运行-无调试-32位-小尾-X-X-X-无符号-无行-可执行-无重定位)\n" 73 "建议装入基地址: 0x%08x\n" 74 "文件执行入口(RVA地址): 0x%04x\n\n"); 75 76 TCHAR szMsgSec[] = TEXT("---------------------------------------------------------------------------------\n" 77 "节的属性参考:\n" 78 " 00000020h 包含代码\n" 79 " 00000040h 包含已经初始化的数据,如.const\n" 80 " 00000080h 包含未初始化数据,如 .data?\n" 81 " 02000000h 数据在进程开始以后被丢弃,如.reloc\n" 82 " 04000000h 节中数据不经过缓存\n" 83 " 08000000h 节中数据不会被交换到磁盘\n" 84 " 10000000h 数据将被不同进程共享\n" 85 " 20000000h 可执行\n" 86 " 40000000h 可读\n" 87 " 80000000h 可写\n" 88 "常见的代码节一般为:60000020h,数据节一般为:c0000040h,常量节一般为:40000040h\n" 89 "---------------------------------------------------------------------------------\n\n\n" 90 "节的名称 未对齐前真实长度 内存中的偏移(对齐后的) 文件中对齐后的长度 文件中的偏移 节的属性\n" 91 "---------------------------------------------------------------------------------------------\n"); 92 93 TCHAR szFmtSec[] = TEXT("%s %08x %08x %08x %08x %08x\n\n\n"); 94 95 pImageNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead; 96 //文件名,运行平台,节的数量,文件的属性,建议装入的地址,入口点 97 wsprintf(szBuffer, szMsg, szFileName, pImageNtHeaders->FileHeader.Machine, 98 pImageNtHeaders->FileHeader.NumberOfSections, pImageNtHeaders->FileHeader.Characteristics, 99 pImageNtHeaders->OptionalHeader.ImageBase, pImageNtHeaders->OptionalHeader.AddressOfEntryPoint); 100 101 SetWindowText(hWinEdit, szBuffer);//添加到编辑框中 102 103 //显示每个节的主要信息 104 _appendInfo(szMsgSec); 105 106 dNumberOfSections =pImageNtHeaders->FileHeader.NumberOfSections; 107 pImageSectionHeader = (PIMAGE_SECTION_HEADER)(pImageNtHeaders + 1); 108 109 while (dNumberOfSections--) 110 { 111 //获取节的名称,注意长度为8的名称并不以0结尾 112 RtlZeroMemory(szSecName, sizeof(szSecName)); 113 for (int i = 0; i < 8; ++i) 114 { 115 if (pImageSectionHeader->Name[i]) 116 { 117 szSecName[i] = pImageSectionHeader->Name[i]; 118 } 119 else 120 { 121 szSecName[i] = ' ';//如果名称为0,则显示为空格 122 } 123 } 124 125 //获取节的主要信息 126 wsprintf(szBuffer, szFmtSec, szSecName, pImageSectionHeader->Misc.VirtualSize, 127 pImageSectionHeader->VirtualAddress, pImageSectionHeader->SizeOfRawData, 128 pImageSectionHeader->PointerToRawData, pImageSectionHeader->Characteristics); 129 _appendInfo(szBuffer); 130 131 ++pImageSectionHeader;//指向下一个节表项 132 } 133 } 134 135 136 137 /* 138 将内存偏移量RVA转换为文件偏移 139 lp_FileHead为文件头的起始地址 140 _dwRVA为给定的RVA地址 141 */ 142 DWORD _RVAToOffset(PTCHAR _lpFileHead, DWORD _dwRVA) 143 { 144 PIMAGE_NT_HEADERS pImageNtHeaders; 145 PIMAGE_SECTION_HEADER pImageSectionHeader; 146 WORD dNumberOfSections; 147 148 149 pImageNtHeaders = (PIMAGE_NT_HEADERS)(_lpFileHead + ((PIMAGE_DOS_HEADER)_lpFileHead)->e_lfanew); 150 pImageSectionHeader = (PIMAGE_SECTION_HEADER)(pImageNtHeaders + 1); 151 dNumberOfSections = pImageNtHeaders->FileHeader.NumberOfSections; 152 153 //遍历节表 154 while (dNumberOfSections--) 155 { 156 if (_dwRVA >= pImageSectionHeader->VirtualAddress && 157 _dwRVA < pImageSectionHeader->VirtualAddress + pImageSectionHeader->SizeOfRawData)//计算该节结束RVA,不用Misc的主要原因是有些段的Misc值是错误的! 158 { 159 return _dwRVA - pImageSectionHeader->VirtualAddress + pImageSectionHeader->PointerToRawData; 160 } 161 ++pImageSectionHeader; 162 } 163 return -1; 164 } 165 166 167 /* 168 获取RVA所在节的名称 169 */ 170 PTCHAR _getRVASectionName(PTCHAR _lpFileHead, DWORD _dwRVA) 171 { 172 PIMAGE_NT_HEADERS pImageNtHeaders; 173 PIMAGE_SECTION_HEADER pImageSectionHeader; 174 WORD dNumberOfSections; 175 176 pImageNtHeaders = (PIMAGE_NT_HEADERS)(_lpFileHead + ((PIMAGE_DOS_HEADER)_lpFileHead)->e_lfanew); 177 pImageSectionHeader = (PIMAGE_SECTION_HEADER)(pImageNtHeaders + 1); 178 dNumberOfSections = pImageNtHeaders->FileHeader.NumberOfSections; 179 180 while (dNumberOfSections--) 181 { 182 if (_dwRVA >= pImageSectionHeader->VirtualAddress && 183 _dwRVA < pImageSectionHeader->VirtualAddress + pImageSectionHeader->SizeOfRawData)//计算该节结束RVA,不用Misc的主要原因是有些段的Misc值是错误的! 184 { 185 return pImageSectionHeader->Name; 186 } 187 ++pImageSectionHeader; 188 } 189 return TEXT("无法查找"); 190 } 191 192 193 194 void _getImportInfo(PTCHAR _lpFile, PTCHAR _lpPeHead) 195 { 196 PIMAGE_NT_HEADERS pImagenNtHeaders; 197 DWORD dwVirtualAddress; 198 PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor; 199 TCHAR szBuffer[1024]; 200 PIMAGE_THUNK_DATA pImageThunkData; 201 PIMAGE_IMPORT_BY_NAME pImageImportByName; 202 203 204 TCHAR szMsg1[] = TEXT("\n\n\n---------------------------------------------------------------------------------------------\n" 205 "导入表所处的节:%s\n" 206 "---------------------------------------------------------------------------------------------\n"); 207 208 TCHAR szMsgImport[] = TEXT("\n\n导入库:%s\n" 209 "-----------------------------\n\n" 210 "OriginalFirstThunk %08x\n" 211 "TimeDateStamp %08x\n" 212 "ForwarderChain %08x\n" 213 "FirstThunk %08x\n" 214 "-----------------------------\n\n"); 215 216 217 pImagenNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead; 218 219 dwVirtualAddress = pImagenNtHeaders->OptionalHeader.DataDirectory[1].VirtualAddress; 220 if (dwVirtualAddress) 221 { 222 pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(_lpFile + 223 _RVAToOffset(_lpFile, dwVirtualAddress));//计算引入表所在文件偏移位置 224 225 wsprintf(szBuffer, szMsg1, _getRVASectionName(_lpFile, 226 pImageImportDescriptor->OriginalFirstThunk)); //显示节名 227 _appendInfo(szBuffer); 228 229 while (pImageImportDescriptor->OriginalFirstThunk || pImageImportDescriptor->TimeDateStamp || 230 pImageImportDescriptor->ForwarderChain || pImageImportDescriptor->Name || 231 pImageImportDescriptor->FirstThunk) 232 { 233 wsprintf(szBuffer, szMsgImport, _lpFile + _RVAToOffset(_lpFile,pImageImportDescriptor->Name), 234 pImageImportDescriptor->OriginalFirstThunk, pImageImportDescriptor->TimeDateStamp, 235 pImageImportDescriptor->ForwarderChain, pImageImportDescriptor->FirstThunk); 236 _appendInfo(szBuffer); 237 238 //获取IMAGE_THUNK_DATA列表 239 if (pImageImportDescriptor->OriginalFirstThunk) 240 { 241 pImageThunkData = (PIMAGE_THUNK_DATA)(_lpFile + 242 _RVAToOffset(_lpFile, pImageImportDescriptor->OriginalFirstThunk)); 243 } 244 else 245 { 246 pImageThunkData = (PIMAGE_THUNK_DATA)(_lpFile + 247 _RVAToOffset(_lpFile, pImageImportDescriptor->FirstThunk)); 248 } 249 250 while (*(PDWORD)pImageThunkData) 251 { 252 if (*(PDWORD)pImageThunkData & IMAGE_ORDINAL_FLAG32)//按序号导入 253 { 254 wsprintf(szBuffer, TEXT("%08u(无函数名,按序号导入)\n"), 255 *(PDWORD)pImageThunkData & 0xffff); 256 } 257 else//按名称导入 258 { 259 pImageImportByName = (PIMAGE_IMPORT_BY_NAME)(_lpFile + 260 _RVAToOffset(_lpFile, *(PDWORD)pImageThunkData)); 261 wsprintf(szBuffer, TEXT("%08u %s\n"), pImageImportByName->Hint, 262 pImageImportByName->Name); 263 } 264 _appendInfo(szBuffer); 265 ++pImageThunkData; 266 } 267 ++pImageImportDescriptor; 268 } 269 } 270 else 271 { 272 _appendInfo(TEXT("\n\n未发现该文件有导入函数\n\n")); 273 } 274 } 275 276 277 278 /* 279 获取PE文件的导出表 280 */ 281 void _getExportInfo(PTCHAR _lpFile, PTCHAR _lpPeHead) 282 { 283 PIMAGE_NT_HEADERS pImageNtHeaders; 284 DWORD dwVirtualAddress; 285 PIMAGE_EXPORT_DIRECTORY pImageExportDirectory; 286 TCHAR szBuffer[1024]; 287 TCHAR ** lpAddressOfNames; 288 PWORD lpAddressOfNameOrdinals; 289 PDWORD lpAddressOfFunctions; 290 WORD wIndex; 291 DWORD dwNumberOfFunctions, dwNumberOfNames; 292 PTCHAR dwFunRaw; 293 294 TCHAR szMsgExport[] = TEXT("\n\n\n---------------------------------------------------------------------------------------------\n" 295 "导出表所处的节:%s\n" 296 "---------------------------------------------------------------------------------------------\n" 297 "原始文件名:%s\n" 298 "nBase %08x\n" 299 "NumberOfFunctions %08x\n" 300 "NuberOfNames %08x\n" 301 "AddressOfFunctions %08x\n" 302 "AddressOfNames %08x\n" 303 "AddressOfNameOrd %08x\n" 304 "-------------------------------------\n\n" 305 "导出序号 虚拟地址 导出函数名称\n" 306 "-------------------------------------\n"); 307 308 309 pImageNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead; 310 311 dwVirtualAddress = pImageNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress; 312 if (dwVirtualAddress) 313 { 314 pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(_lpFile + 315 _RVAToOffset(_lpFile, dwVirtualAddress));//计算导出表所在文件偏移位置 316 317 wsprintf(szBuffer, szMsgExport, _getRVASectionName(_lpFile, pImageExportDirectory->Name), 318 _lpFile + _RVAToOffset(_lpFile, pImageExportDirectory->Name), 319 pImageExportDirectory->Base, pImageExportDirectory->NumberOfFunctions, 320 pImageExportDirectory->NumberOfNames, pImageExportDirectory->AddressOfFunctions, 321 pImageExportDirectory->AddressOfNames, pImageExportDirectory->AddressOfNameOrdinals); 322 _appendInfo(szBuffer); 323 324 325 lpAddressOfNames = (TCHAR **)(_lpFile + _RVAToOffset(_lpFile, 326 pImageExportDirectory->AddressOfNames));//函数名字的地址表 327 328 lpAddressOfNameOrdinals = (PWORD)(_lpFile + _RVAToOffset(_lpFile, 329 pImageExportDirectory->AddressOfNameOrdinals));//函数编号的地址表 330 331 lpAddressOfFunctions = (PDWORD)(_lpFile + _RVAToOffset(_lpFile, 332 pImageExportDirectory->AddressOfFunctions));//函数的地址表 333 334 dwNumberOfFunctions = pImageExportDirectory->NumberOfFunctions; 335 wIndex = 0; 336 while (dwNumberOfFunctions--) 337 { 338 dwNumberOfNames = pImageExportDirectory->NumberOfNames; 339 DWORD i; 340 for (i = 0; i < dwNumberOfNames; ++i) 341 { 342 if (lpAddressOfNameOrdinals[i] == wIndex)//找编号 343 { 344 break; 345 } 346 } 347 //找到函数名称 348 if (i < dwNumberOfNames) 349 { 350 dwFunRaw = _lpFile + _RVAToOffset(_lpFile, (DWORD)lpAddressOfNames[i]); 351 } 352 else 353 { 354 dwFunRaw = TEXT("(按照序号导出)"); 355 } 356 357 wsprintf(szBuffer, TEXT("%08x %08x %s\n"), pImageExportDirectory->Base+wIndex++, 358 *lpAddressOfFunctions++, dwFunRaw); 359 360 _appendInfo(szBuffer); 361 } 362 } 363 else 364 { 365 _appendInfo(TEXT("\n\n未发现该文件有导出函数\n\n")); 366 } 367 } 368 369 370 371 /* 372 获取PE文件的重定位信息 373 */ 374 void _getRelocInfo(PTCHAR _lpFile, PTCHAR _lpPeHead) 375 { 376 PIMAGE_NT_HEADERS pImageNtHeaders; 377 DWORD dwVirtualAddress; 378 PIMAGE_BASE_RELOCATION pImageBaseRelocation; 379 int dwRelNum; 380 PWORD lpRelAdd; 381 DWORD dwRelAdd; 382 TCHAR szBuffer[1024]; 383 384 TCHAR szMsgReloc2[] = TEXT("\n--------------------------------------------------------------------------------------------\n" 385 "重定位基地址: %08x\n" 386 "重定位项数量: %d\n" 387 "--------------------------------------------------------------------------------------------\n" 388 "需要重定位的地址列表(ffffffff表示对齐用,不需要重定位)\n" 389 "--------------------------------------------------------------------------------------------\n"); 390 391 392 393 394 395 396 pImageNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead; 397 398 dwVirtualAddress = pImageNtHeaders->OptionalHeader.DataDirectory[5].VirtualAddress; 399 if (dwVirtualAddress) 400 { 401 402 wsprintf(szBuffer, TEXT("\n重定位表所处的节:%s\n"), 403 _getRVASectionName(_lpFile, dwVirtualAddress)); 404 _appendInfo(szBuffer); 405 406 pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)(_lpFile + 407 _RVAToOffset(_lpFile, dwVirtualAddress)); 408 409 //循环处理每个重定位块 410 while (pImageBaseRelocation->VirtualAddress) 411 { 412 dwRelNum = (pImageBaseRelocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 2;//项数 413 wsprintf(szBuffer, szMsgReloc2, pImageBaseRelocation->VirtualAddress, dwRelNum); 414 _appendInfo(szBuffer); 415 416 lpRelAdd = (PWORD)(pImageBaseRelocation + 1);//指向第一个重定位项 417 for (int i = 0; i < dwRelNum; ++i) 418 { 419 if ((*lpRelAdd & 0xf000) == 0x3000)//重定位地址指向的双字的32位都需要休正 420 { 421 dwRelAdd = (*lpRelAdd & 0x0fff) + pImageBaseRelocation->VirtualAddress; 422 } 423 else 424 { 425 dwRelAdd = -1; 426 } 427 wsprintf(szBuffer, TEXT("%08x "), dwRelAdd); 428 if ((i + 1) % 8 == 0) 429 { 430 lstrcat(szBuffer, TEXT("\n")); 431 } 432 _appendInfo(szBuffer); 433 434 ++lpRelAdd;//指向下一个重定位项 435 436 } 437 438 if (dwRelNum % 8)//每显示8个项目换行 439 { 440 _appendInfo(TEXT("\n")); 441 } 442 443 pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)lpRelAdd;//指向下一个重定位块 444 445 } 446 447 } 448 else 449 { 450 _appendInfo(TEXT("\n\n未发现该文件有重定位信息.\n\n")); 451 } 452 } 453 454 455 456 457 /* 458 递归函数,遍历资源表项 459 _lpFile:文件地址 460 _lpRes:资源表地址 461 _lpResDir:目录地址 462 _dwLevel:目录级别 463 */ 464 void _processRes(PTCHAR _lpFile, PTCHAR _lpRes, PTCHAR _lpResDir, DWORD _dwLevel) 465 { 466 PIMAGE_RESOURCE_DIRECTORY pResourceDirectory; 467 DWORD dwNumber; 468 PIMAGE_RESOURCE_DIRECTORY_ENTRY pResourceDirectoryEntry; 469 DWORD OffsetToData; 470 DWORD dwName; 471 TCHAR szResName[256]; 472 PTCHAR lpResName; 473 TCHAR szBuffer[1024]; 474 475 476 477 TCHAR szType[][16] = {TEXT("1-光标 "), 478 TEXT("2-位图 "), 479 TEXT("3-图标 "), 480 TEXT("4-菜单 "), 481 TEXT("5-对话框 "), 482 TEXT("6-字符串 "), 483 TEXT("7-字体目录 "), 484 TEXT("8-字体 "), 485 TEXT("9-加速键 "), 486 TEXT("10-未格式化资源"), 487 TEXT("11-消息表 "), 488 TEXT("12-光标组 "), 489 TEXT("13-未知类型 "), 490 TEXT("14-图标组 "), 491 TEXT("15-未知类型 "), 492 TEXT("16-版本信息 ") }; 493 494 TCHAR szOut5[] = TEXT("%d(自定义编号)"); 495 TCHAR szLevel1[] = TEXT("|-- %s\n" 496 "| |\n"); 497 TCHAR szLevel2[] = TEXT("| |-- %s\n" 498 "| | |\n"); 499 TCHAR szOut6[] = TEXT("| |-- ID %d\n" 500 "| | |\n"); 501 TCHAR szLevel3[] = TEXT("| | |-- 代码页:%d 资源所在文件位置:0x%08x 资源长度:%d\n"); 502 503 504 pResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)_lpResDir;//指向目录表 505 dwNumber = pResourceDirectory->NumberOfIdEntries + pResourceDirectory->NumberOfNamedEntries;//计算目录项的个数 506 pResourceDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceDirectory + 1);//跳过目录头定位到目录项 507 508 509 510 while (dwNumber > 0) 511 { 512 OffsetToData = pResourceDirectoryEntry->OffsetToData;//查看IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData 513 if (OffsetToData & 0x80000000)//如果最高位为1 514 { 515 OffsetToData = (OffsetToData & 0x7fffffff) + (DWORD)_lpRes;//为下一次递归准备第三个参数,偏移是基于资源表起始地址的 516 if (_dwLevel == 1)//如果是第一级资源类别 517 { 518 dwName = pResourceDirectoryEntry->Name; 519 if (dwName & 0x80000000)//如果是按名称定义的资源类型 520 { 521 dwName = (dwName & 0x7fffffff) + (DWORD)_lpRes;//指向了名称字符串结构IMAGE_RESOURCE_DIR_STRING_U 522 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,//将UNICODE字符转换为多字节字符 523 ((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->NameString,//名字地址 524 ((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->Length, //名字长度 525 szResName, sizeof szResName, NULL, NULL); 526 szResName[((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->Length] = 0;//结束符 527 lpResName = szResName;//指向了名称字符串 528 } 529 else//如果是按编号定义的资源类型 530 { 531 if (dwName <= 0x10)//系统内定的资源编号 532 { 533 lpResName = szType[dwName - 1];//定位编号所在字符串 534 } 535 else//自定义资源类型 536 { 537 wsprintf(szResName, szOut5, dwName); 538 lpResName = szResName; 539 } 540 } 541 wsprintf(szBuffer, szLevel1, lpResName); 542 } 543 else if (_dwLevel == 2)//如果是第二级资源ID 544 { 545 dwName = pResourceDirectoryEntry->Name; 546 if (dwName & 0x80000000) //如果是按字符串定义的资源ID 547 { 548 dwName = (dwName & 0x7fffffff) + (DWORD)_lpRes; 549 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,//将UNICODE字符转换为多字节字符 550 ((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->NameString, 551 ((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->Length, 552 szResName, sizeof szResName, NULL, NULL); 553 szResName[((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->Length] = 0;//结束符 554 wsprintf(szBuffer, szLevel2, szResName); 555 } 556 else//如果是按编号定义的资源类型 557 { 558 wsprintf(szBuffer, szOut6, dwName); 559 } 560 } 561 else 562 {//跳出递归 563 break; 564 } 565 566 _appendInfo(szBuffer); 567 _processRes(_lpFile, _lpRes, (PTCHAR)OffsetToData, _dwLevel + 1); 568 } 569 //如果IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData最高位为0 570 else//第三级目录 571 { 572 OffsetToData += (DWORD)_lpRes; 573 574 wsprintf(szBuffer, szLevel3,pResourceDirectoryEntry->Name,//代码页 575 _RVAToOffset(_lpFile, ((PIMAGE_RESOURCE_DATA_ENTRY)OffsetToData)->OffsetToData), 576 ((PIMAGE_RESOURCE_DATA_ENTRY)OffsetToData)->Size); 577 578 _appendInfo(szBuffer); 579 } 580 581 ++pResourceDirectoryEntry; 582 --dwNumber; 583 } 584 } 585 586 587 588 /* 589 获取PE文件的资源信息 590 */ 591 void _getResource(PTCHAR _lpFile, PTCHAR _lpPeHead) 592 { 593 PIMAGE_NT_HEADERS pNtHeaders; 594 DWORD dwVirtualAddress; 595 TCHAR szBuffer[1024]; 596 PTCHAR lpRes; 597 598 599 TCHAR szOut4[] = TEXT("\n\n\n" 600 "---------------------------------------------------------------------------------------------\n" 601 "资源表所处的节:%s\n" 602 "---------------------------------------------------------------------------------------------\n" 603 "\n\n" 604 "根目录\n" 605 "|\n"); 606 607 608 pNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead; 609 if (dwVirtualAddress = (pNtHeaders->OptionalHeader.DataDirectory)[2].VirtualAddress) 610 { 611 wsprintf(szBuffer, szOut4, _getRVASectionName(_lpFile, dwVirtualAddress)); 612 _appendInfo(szBuffer); 613 614 //求资源表在文件的偏移 615 lpRes = _lpFile + _RVAToOffset(_lpFile, dwVirtualAddress); 616 617 //传入的四个参数分别表示 618 //1、文件头位置 619 //2、资源表位置 620 //3、目录位置 621 //4、目录级别 622 _processRes(_lpFile, lpRes, lpRes, 1); 623 } 624 else 625 { 626 _appendInfo(TEXT("\n未发现该文件有资源表\n")); 627 return; 628 } 629 630 631 } 632 633 634 635 636 637 /* 638 打开PE文件并处理 639 */ 640 void _openFile(HWND hWinMain) 641 { 642 OPENFILENAME stOF; 643 HANDLE hFile, hMapFile; 644 DWORD dwFileSize; //文件大小 645 PTCHAR lpMemory; //内存映像文件在内存的起始位置 646 PTCHAR lpMem; 647 648 649 TCHAR szFileName[MAX_PATH] = { 0 }; //要打开的文件路径及名称名 650 TCHAR szExtPe[] = TEXT("PE Files\0*.exe;*.dll;*.scr;*.fon;*.drv\0All Files(*.*)\0*.*\0\0"); 651 652 653 654 RtlZeroMemory(&stOF, sizeof(stOF)); 655 stOF.lStructSize = sizeof(stOF); 656 stOF.hwndOwner = hWinMain; 657 stOF.lpstrFilter = szExtPe; 658 stOF.lpstrFile = szFileName; 659 stOF.nMaxFile = MAX_PATH; 660 stOF.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 661 662 if (GetOpenFileName(&stOF)) //让用户选择打开的文件 663 { 664 hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 665 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL); 666 if (hFile != INVALID_HANDLE_VALUE) 667 { 668 dwFileSize = GetFileSize(hFile, NULL);//获取文件大小 669 if (dwFileSize) 670 { 671 hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);//内存映射文件 672 if (hMapFile) 673 { 674 lpMemory = (PTCHAR)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);//获得文件在内存的映象起始位置 675 if (lpMemory) 676 { 677 if (((PIMAGE_DOS_HEADER)lpMemory)->e_magic == IMAGE_DOS_SIGNATURE)//判断是否有MZ字样 678 { 679 lpMem = lpMemory + ((PIMAGE_DOS_HEADER)lpMemory)->e_lfanew; 680 if (((PIMAGE_NT_HEADERS)lpMem)->Signature == IMAGE_NT_SIGNATURE)//判断是否有PE字样 681 { 682 //到此为止,该文件的验证已经完成。为PE结构文件 683 //接下来分析分件映射到内存中的数据,并显示主要参数 684 _getMainInfo(lpMem, szFileName); 685 686 //显示导入表 687 _getImportInfo(lpMemory, lpMem); 688 689 //显示导出表 690 _getExportInfo(lpMemory, lpMem); 691 692 //显示重定位信息 693 _getRelocInfo(lpMemory, lpMem); 694 695 //显示资源表信息 696 _getResource(lpMemory, lpMem); 697 698 } 699 else 700 { 701 MessageBox(hWinMain, TEXT("这个文件不是PE格式的文件!"), NULL, MB_OK); 702 } 703 } 704 else 705 { 706 MessageBox(hWinMain, TEXT("这个文件不是PE格式的文件!"), NULL, MB_OK); 707 } 708 UnmapViewOfFile(lpMemory); 709 } 710 CloseHandle(hMapFile); 711 } 712 } 713 CloseHandle(hFile); 714 } 715 } 716 } 717 718 719 720 721 722 /* 723 窗口程序 724 */ 725 INT_PTR CALLBACK _ProcDlgMain(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) 726 { 727 switch (wMsg) 728 { 729 case WM_CLOSE: 730 EndDialog(hWnd, 0); 731 break; 732 733 case WM_INITDIALOG: //初始化 734 _Init(hWnd); 735 break; 736 737 case WM_COMMAND: //菜单 738 switch (LOWORD(wParam)) 739 { 740 case IDM_EXIT: //退出 741 EndDialog(hWnd, 0); 742 break; 743 744 case IDM_OPEN: //打开文件 745 _openFile(hWnd); 746 break; 747 748 case IDM_1: 749 case IDM_2: 750 case IDM_3: 751 default: 752 break; 753 } 754 break; 755 756 default: 757 return FALSE; 758 } 759 760 return TRUE; 761 } 762 763 764 765 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 766 { 767 HMODULE hRichEdit; 768 769 hInstance = hInst; 770 hRichEdit = LoadLibrary(TEXT("RichEd20.dll")); 771 DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, _ProcDlgMain, (LPARAM)NULL); 772 FreeLibrary(hRichEdit); 773 return 0; 774 }
头文件 resource.h
1 //{{NO_DEPENDENCIES}} 2 // Microsoft Visual C++ 生成的包含文件。 3 // 供 Resource.rc 使用 4 // 5 #define ICO_MAIN 101 6 #define IDR_MENU1 102 7 #define IDM_MAIN 102 8 #define DLG_MAIN 103 9 #define IDC_INFO 1001 10 #define IDM_OPEN 40001 11 #define IDM_EXIT 40002 12 #define ID_40003 40003 13 #define ID_40004 40004 14 #define ID_40005 40005 15 #define ID_40006 40006 16 #define IDM_1 40007 17 #define IDM_2 40008 18 #define IDM_3 40009 19 #define IDM_4 40010 20 21 // Next default values for new objects 22 // 23 #ifdef APSTUDIO_INVOKED 24 #ifndef APSTUDIO_READONLY_SYMBOLS 25 #define _APS_NEXT_RESOURCE_VALUE 104 26 #define _APS_NEXT_COMMAND_VALUE 40011 27 #define _APS_NEXT_CONTROL_VALUE 1002 28 #define _APS_NEXT_SYMED_VALUE 101 29 #endif 30 #endif
资源文件 resource.rc
1 // Microsoft Visual C++ generated resource script. 2 // 3 #include "resource.h" 4 5 #define APSTUDIO_READONLY_SYMBOLS 6 ///////////////////////////////////////////////////////////////////////////// 7 // 8 // Generated from the TEXTINCLUDE 2 resource. 9 // 10 #include "winres.h" 11 12 ///////////////////////////////////////////////////////////////////////////// 13 #undef APSTUDIO_READONLY_SYMBOLS 14 15 ///////////////////////////////////////////////////////////////////////////// 16 // 中文(简体,中国) resources 17 18 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) 19 LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED 20 21 #ifdef APSTUDIO_INVOKED 22 ///////////////////////////////////////////////////////////////////////////// 23 // 24 // TEXTINCLUDE 25 // 26 27 1 TEXTINCLUDE 28 BEGIN 29 "resource.h\0" 30 END 31 32 2 TEXTINCLUDE 33 BEGIN 34 "#include ""winres.h""\r\n" 35 "\0" 36 END 37 38 3 TEXTINCLUDE 39 BEGIN 40 "\r\n" 41 "\0" 42 END 43 44 #endif // APSTUDIO_INVOKED 45 46 47 ///////////////////////////////////////////////////////////////////////////// 48 // 49 // Icon 50 // 51 52 // Icon with lowest ID value placed first to ensure application icon 53 // remains consistent on all systems. 54 ICO_MAIN ICON "main.ico" 55 56 ///////////////////////////////////////////////////////////////////////////// 57 // 58 // Menu 59 // 60 61 IDM_MAIN MENU 62 BEGIN 63 POPUP "文件(&F)" 64 BEGIN 65 MENUITEM "打开文件(&O)...", IDM_OPEN 66 MENUITEM SEPARATOR 67 MENUITEM "退出(&x)", IDM_EXIT 68 END 69 POPUP "编辑(&E)" 70 BEGIN 71 MENUITEM SEPARATOR 72 END 73 POPUP "格式(&O)" 74 BEGIN 75 MENUITEM SEPARATOR 76 END 77 POPUP "查看(&V)" 78 BEGIN 79 MENUITEM "源文件", IDM_1 80 MENUITEM "窗口透明度", IDM_2 81 MENUITEM SEPARATOR 82 MENUITEM "大小", IDM_3 83 MENUITEM "宽度", IDM_4 84 END 85 POPUP "帮助(&H)" 86 BEGIN 87 MENUITEM SEPARATOR 88 END 89 END 90 91 92 ///////////////////////////////////////////////////////////////////////////// 93 // 94 // Dialog 95 // 96 97 DLG_MAIN DIALOG 50, 50, 544, 399 98 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU 99 CAPTION "PEInfo" 100 MENU IDM_MAIN 101 FONT 9, "宋体" 102 BEGIN 103 CONTROL "",IDC_INFO,"RichEdit20A",ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | ES_WANTRETURN | WS_BORDER | WS_VSCROLL | WS_TABSTOP,0,0,540,396 104 END 105 106 107 ///////////////////////////////////////////////////////////////////////////// 108 // 109 // DESIGNINFO 110 // 111 112 #ifdef APSTUDIO_INVOKED 113 GUIDELINES DESIGNINFO 114 BEGIN 115 DLG_MAIN, DIALOG 116 BEGIN 117 LEFTMARGIN, 7 118 RIGHTMARGIN, 540 119 TOPMARGIN, 7 120 BOTTOMMARGIN, 396 121 HORZGUIDE, 391 122 END 123 END 124 #endif // APSTUDIO_INVOKED 125 126 #endif // 中文(简体,中国) resources 127 ///////////////////////////////////////////////////////////////////////////// 128 129 130 131 #ifndef APSTUDIO_INVOKED 132 ///////////////////////////////////////////////////////////////////////////// 133 // 134 // Generated from the TEXTINCLUDE 3 resource. 135 // 136 137 138 ///////////////////////////////////////////////////////////////////////////// 139 #endif // not APSTUDIO_INVOKED