WindowsPE权威指南 第二章 小工具 PEInfo代码的C语言实现

主程序代码 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

 

转载于:https://www.cnblogs.com/JOUO4/p/6103491.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值