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

时间:2023-03-08 15:19:35
WindowsPE权威指南 第二章 小工具 PEInfo代码的C语言实现

主程序代码 PEInfo.c

 #include <Windows.h>
#include<Richedit.h>
#include "resource.h" HINSTANCE hInstance;
HWND hWinEdit; /*
初始化窗口程序
*/
void _Init(HWND hWinMain)
{ HICON hIcon;
CHARFORMAT stCf;
TCHAR szFont[] = TEXT("宋体"); hWinEdit = GetDlgItem(hWinMain, IDC_INFO);
hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ICO_MAIN));
SendMessage(hWinMain, WM_SETICON, ICON_BIG, (LPARAM)hIcon); //为窗口设置图标
SendMessage(hWinEdit, EM_SETTEXTMODE, TM_PLAINTEXT, ); //设置编辑控件 RtlZeroMemory(&stCf, sizeof(stCf));
stCf.cbSize = sizeof(stCf);
stCf.yHeight = * ;
stCf.dwMask = CFM_FACE | CFM_SIZE | CFM_BOLD;
lstrcpy(stCf.szFaceName, szFont);
SendMessage(hWinEdit, EM_SETCHARFORMAT, , (LPARAM)&stCf); SendMessage(hWinEdit, EM_EXLIMITTEXT, , -);
} /*
往文本框中追加文本
*/
void _appendInfo(PTCHAR _lpsz)
{
CHARRANGE stCR;
int iTextLength; iTextLength = GetWindowTextLength(hWinEdit);
stCR.cpMin = iTextLength;
stCR.cpMax = iTextLength; SendMessage(hWinEdit, EM_EXSETSEL, , (LPARAM)&stCR);
SendMessage(hWinEdit, EM_REPLACESEL, FALSE, (LPARAM)_lpsz); } /*
从内存中获取PE文件的主要信息
*/
void _getMainInfo(PTCHAR _lpPeHead, PTCHAR szFileName)
{
PIMAGE_NT_HEADERS pImageNtHeaders;
PIMAGE_SECTION_HEADER pImageSectionHeader;
TCHAR szBuffer[];
TCHAR szSecName[];
WORD dNumberOfSections;
TCHAR szMsg[] = TEXT("文件名:%s\n"
"-----------------------------------------\n\n\n"
"运行平台: 0x%04x (014c:Intel 386 014dh:Intel 486 014eh:Intel 586)\n"
"节的数量: %d\n"
"文件属性: 0x%04x (大尾-禁止多处理器-DLL-系统文件-禁止网络运行-禁止优盘运行-无调试-32位-小尾-X-X-X-无符号-无行-可执行-无重定位)\n"
"建议装入基地址: 0x%08x\n"
"文件执行入口(RVA地址): 0x%04x\n\n"); TCHAR szMsgSec[] = TEXT("---------------------------------------------------------------------------------\n"
"节的属性参考:\n"
" 00000020h 包含代码\n"
" 00000040h 包含已经初始化的数据,如.const\n"
" 00000080h 包含未初始化数据,如 .data?\n"
" 02000000h 数据在进程开始以后被丢弃,如.reloc\n"
" 04000000h 节中数据不经过缓存\n"
" 08000000h 节中数据不会被交换到磁盘\n"
" 10000000h 数据将被不同进程共享\n"
" 20000000h 可执行\n"
" 40000000h 可读\n"
" 80000000h 可写\n"
"常见的代码节一般为:60000020h,数据节一般为:c0000040h,常量节一般为:40000040h\n"
"---------------------------------------------------------------------------------\n\n\n"
"节的名称 未对齐前真实长度 内存中的偏移(对齐后的) 文件中对齐后的长度 文件中的偏移 节的属性\n"
"---------------------------------------------------------------------------------------------\n"); TCHAR szFmtSec[] = TEXT("%s %08x %08x %08x %08x %08x\n\n\n"); pImageNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead;
//文件名,运行平台,节的数量,文件的属性,建议装入的地址,入口点
wsprintf(szBuffer, szMsg, szFileName, pImageNtHeaders->FileHeader.Machine,
pImageNtHeaders->FileHeader.NumberOfSections, pImageNtHeaders->FileHeader.Characteristics,
pImageNtHeaders->OptionalHeader.ImageBase, pImageNtHeaders->OptionalHeader.AddressOfEntryPoint); SetWindowText(hWinEdit, szBuffer);//添加到编辑框中 //显示每个节的主要信息
_appendInfo(szMsgSec); dNumberOfSections =pImageNtHeaders->FileHeader.NumberOfSections;
pImageSectionHeader = (PIMAGE_SECTION_HEADER)(pImageNtHeaders + ); while (dNumberOfSections--)
{
//获取节的名称,注意长度为8的名称并不以0结尾
RtlZeroMemory(szSecName, sizeof(szSecName));
for (int i = ; i < ; ++i)
{
if (pImageSectionHeader->Name[i])
{
szSecName[i] = pImageSectionHeader->Name[i];
}
else
{
szSecName[i] = ' ';//如果名称为0,则显示为空格
}
} //获取节的主要信息
wsprintf(szBuffer, szFmtSec, szSecName, pImageSectionHeader->Misc.VirtualSize,
pImageSectionHeader->VirtualAddress, pImageSectionHeader->SizeOfRawData,
pImageSectionHeader->PointerToRawData, pImageSectionHeader->Characteristics);
_appendInfo(szBuffer); ++pImageSectionHeader;//指向下一个节表项
}
} /*
将内存偏移量RVA转换为文件偏移
lp_FileHead为文件头的起始地址
_dwRVA为给定的RVA地址
*/
DWORD _RVAToOffset(PTCHAR _lpFileHead, DWORD _dwRVA)
{
PIMAGE_NT_HEADERS pImageNtHeaders;
PIMAGE_SECTION_HEADER pImageSectionHeader;
WORD dNumberOfSections; pImageNtHeaders = (PIMAGE_NT_HEADERS)(_lpFileHead + ((PIMAGE_DOS_HEADER)_lpFileHead)->e_lfanew);
pImageSectionHeader = (PIMAGE_SECTION_HEADER)(pImageNtHeaders + );
dNumberOfSections = pImageNtHeaders->FileHeader.NumberOfSections; //遍历节表
while (dNumberOfSections--)
{
if (_dwRVA >= pImageSectionHeader->VirtualAddress &&
_dwRVA < pImageSectionHeader->VirtualAddress + pImageSectionHeader->SizeOfRawData)//计算该节结束RVA,不用Misc的主要原因是有些段的Misc值是错误的!
{
return _dwRVA - pImageSectionHeader->VirtualAddress + pImageSectionHeader->PointerToRawData;
}
++pImageSectionHeader;
}
return -;
} /*
获取RVA所在节的名称
*/
PTCHAR _getRVASectionName(PTCHAR _lpFileHead, DWORD _dwRVA)
{
PIMAGE_NT_HEADERS pImageNtHeaders;
PIMAGE_SECTION_HEADER pImageSectionHeader;
WORD dNumberOfSections; pImageNtHeaders = (PIMAGE_NT_HEADERS)(_lpFileHead + ((PIMAGE_DOS_HEADER)_lpFileHead)->e_lfanew);
pImageSectionHeader = (PIMAGE_SECTION_HEADER)(pImageNtHeaders + );
dNumberOfSections = pImageNtHeaders->FileHeader.NumberOfSections; while (dNumberOfSections--)
{
if (_dwRVA >= pImageSectionHeader->VirtualAddress &&
_dwRVA < pImageSectionHeader->VirtualAddress + pImageSectionHeader->SizeOfRawData)//计算该节结束RVA,不用Misc的主要原因是有些段的Misc值是错误的!
{
return pImageSectionHeader->Name;
}
++pImageSectionHeader;
}
return TEXT("无法查找");
} void _getImportInfo(PTCHAR _lpFile, PTCHAR _lpPeHead)
{
PIMAGE_NT_HEADERS pImagenNtHeaders;
DWORD dwVirtualAddress;
PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor;
TCHAR szBuffer[];
PIMAGE_THUNK_DATA pImageThunkData;
PIMAGE_IMPORT_BY_NAME pImageImportByName; TCHAR szMsg1[] = TEXT("\n\n\n---------------------------------------------------------------------------------------------\n"
"导入表所处的节:%s\n"
"---------------------------------------------------------------------------------------------\n"); TCHAR szMsgImport[] = TEXT("\n\n导入库:%s\n"
"-----------------------------\n\n"
"OriginalFirstThunk %08x\n"
"TimeDateStamp %08x\n"
"ForwarderChain %08x\n"
"FirstThunk %08x\n"
"-----------------------------\n\n"); pImagenNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead; dwVirtualAddress = pImagenNtHeaders->OptionalHeader.DataDirectory[].VirtualAddress;
if (dwVirtualAddress)
{
pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(_lpFile +
_RVAToOffset(_lpFile, dwVirtualAddress));//计算引入表所在文件偏移位置 wsprintf(szBuffer, szMsg1, _getRVASectionName(_lpFile,
pImageImportDescriptor->OriginalFirstThunk)); //显示节名
_appendInfo(szBuffer); while (pImageImportDescriptor->OriginalFirstThunk || pImageImportDescriptor->TimeDateStamp ||
pImageImportDescriptor->ForwarderChain || pImageImportDescriptor->Name ||
pImageImportDescriptor->FirstThunk)
{
wsprintf(szBuffer, szMsgImport, _lpFile + _RVAToOffset(_lpFile,pImageImportDescriptor->Name),
pImageImportDescriptor->OriginalFirstThunk, pImageImportDescriptor->TimeDateStamp,
pImageImportDescriptor->ForwarderChain, pImageImportDescriptor->FirstThunk);
_appendInfo(szBuffer); //获取IMAGE_THUNK_DATA列表
if (pImageImportDescriptor->OriginalFirstThunk)
{
pImageThunkData = (PIMAGE_THUNK_DATA)(_lpFile +
_RVAToOffset(_lpFile, pImageImportDescriptor->OriginalFirstThunk));
}
else
{
pImageThunkData = (PIMAGE_THUNK_DATA)(_lpFile +
_RVAToOffset(_lpFile, pImageImportDescriptor->FirstThunk));
} while (*(PDWORD)pImageThunkData)
{
if (*(PDWORD)pImageThunkData & IMAGE_ORDINAL_FLAG32)//按序号导入
{
wsprintf(szBuffer, TEXT("%08u(无函数名,按序号导入)\n"),
*(PDWORD)pImageThunkData & 0xffff);
}
else//按名称导入
{
pImageImportByName = (PIMAGE_IMPORT_BY_NAME)(_lpFile +
_RVAToOffset(_lpFile, *(PDWORD)pImageThunkData));
wsprintf(szBuffer, TEXT("%08u %s\n"), pImageImportByName->Hint,
pImageImportByName->Name);
}
_appendInfo(szBuffer);
++pImageThunkData;
}
++pImageImportDescriptor;
}
}
else
{
_appendInfo(TEXT("\n\n未发现该文件有导入函数\n\n"));
}
} /*
获取PE文件的导出表
*/
void _getExportInfo(PTCHAR _lpFile, PTCHAR _lpPeHead)
{
PIMAGE_NT_HEADERS pImageNtHeaders;
DWORD dwVirtualAddress;
PIMAGE_EXPORT_DIRECTORY pImageExportDirectory;
TCHAR szBuffer[];
TCHAR ** lpAddressOfNames;
PWORD lpAddressOfNameOrdinals;
PDWORD lpAddressOfFunctions;
WORD wIndex;
DWORD dwNumberOfFunctions, dwNumberOfNames;
PTCHAR dwFunRaw; TCHAR szMsgExport[] = TEXT("\n\n\n---------------------------------------------------------------------------------------------\n"
"导出表所处的节:%s\n"
"---------------------------------------------------------------------------------------------\n"
"原始文件名:%s\n"
"nBase %08x\n"
"NumberOfFunctions %08x\n"
"NuberOfNames %08x\n"
"AddressOfFunctions %08x\n"
"AddressOfNames %08x\n"
"AddressOfNameOrd %08x\n"
"-------------------------------------\n\n"
"导出序号 虚拟地址 导出函数名称\n"
"-------------------------------------\n"); pImageNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead; dwVirtualAddress = pImageNtHeaders->OptionalHeader.DataDirectory[].VirtualAddress;
if (dwVirtualAddress)
{
pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(_lpFile +
_RVAToOffset(_lpFile, dwVirtualAddress));//计算导出表所在文件偏移位置 wsprintf(szBuffer, szMsgExport, _getRVASectionName(_lpFile, pImageExportDirectory->Name),
_lpFile + _RVAToOffset(_lpFile, pImageExportDirectory->Name),
pImageExportDirectory->Base, pImageExportDirectory->NumberOfFunctions,
pImageExportDirectory->NumberOfNames, pImageExportDirectory->AddressOfFunctions,
pImageExportDirectory->AddressOfNames, pImageExportDirectory->AddressOfNameOrdinals);
_appendInfo(szBuffer); lpAddressOfNames = (TCHAR **)(_lpFile + _RVAToOffset(_lpFile,
pImageExportDirectory->AddressOfNames));//函数名字的地址表 lpAddressOfNameOrdinals = (PWORD)(_lpFile + _RVAToOffset(_lpFile,
pImageExportDirectory->AddressOfNameOrdinals));//函数编号的地址表 lpAddressOfFunctions = (PDWORD)(_lpFile + _RVAToOffset(_lpFile,
pImageExportDirectory->AddressOfFunctions));//函数的地址表 dwNumberOfFunctions = pImageExportDirectory->NumberOfFunctions;
wIndex = ;
while (dwNumberOfFunctions--)
{
dwNumberOfNames = pImageExportDirectory->NumberOfNames;
DWORD i;
for (i = ; i < dwNumberOfNames; ++i)
{
if (lpAddressOfNameOrdinals[i] == wIndex)//找编号
{
break;
}
}
//找到函数名称
if (i < dwNumberOfNames)
{
dwFunRaw = _lpFile + _RVAToOffset(_lpFile, (DWORD)lpAddressOfNames[i]);
}
else
{
dwFunRaw = TEXT("(按照序号导出)");
} wsprintf(szBuffer, TEXT("%08x %08x %s\n"), pImageExportDirectory->Base+wIndex++,
*lpAddressOfFunctions++, dwFunRaw); _appendInfo(szBuffer);
}
}
else
{
_appendInfo(TEXT("\n\n未发现该文件有导出函数\n\n"));
}
} /*
获取PE文件的重定位信息
*/
void _getRelocInfo(PTCHAR _lpFile, PTCHAR _lpPeHead)
{
PIMAGE_NT_HEADERS pImageNtHeaders;
DWORD dwVirtualAddress;
PIMAGE_BASE_RELOCATION pImageBaseRelocation;
int dwRelNum;
PWORD lpRelAdd;
DWORD dwRelAdd;
TCHAR szBuffer[]; TCHAR szMsgReloc2[] = TEXT("\n--------------------------------------------------------------------------------------------\n"
"重定位基地址: %08x\n"
"重定位项数量: %d\n"
"--------------------------------------------------------------------------------------------\n"
"需要重定位的地址列表(ffffffff表示对齐用,不需要重定位)\n"
"--------------------------------------------------------------------------------------------\n"); pImageNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead; dwVirtualAddress = pImageNtHeaders->OptionalHeader.DataDirectory[].VirtualAddress;
if (dwVirtualAddress)
{ wsprintf(szBuffer, TEXT("\n重定位表所处的节:%s\n"),
_getRVASectionName(_lpFile, dwVirtualAddress));
_appendInfo(szBuffer); pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)(_lpFile +
_RVAToOffset(_lpFile, dwVirtualAddress)); //循环处理每个重定位块
while (pImageBaseRelocation->VirtualAddress)
{
dwRelNum = (pImageBaseRelocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / ;//项数
wsprintf(szBuffer, szMsgReloc2, pImageBaseRelocation->VirtualAddress, dwRelNum);
_appendInfo(szBuffer); lpRelAdd = (PWORD)(pImageBaseRelocation + );//指向第一个重定位项
for (int i = ; i < dwRelNum; ++i)
{
if ((*lpRelAdd & 0xf000) == 0x3000)//重定位地址指向的双字的32位都需要休正
{
dwRelAdd = (*lpRelAdd & 0x0fff) + pImageBaseRelocation->VirtualAddress;
}
else
{
dwRelAdd = -;
}
wsprintf(szBuffer, TEXT("%08x "), dwRelAdd);
if ((i + ) % == )
{
lstrcat(szBuffer, TEXT("\n"));
}
_appendInfo(szBuffer); ++lpRelAdd;//指向下一个重定位项 } if (dwRelNum % )//每显示8个项目换行
{
_appendInfo(TEXT("\n"));
} pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)lpRelAdd;//指向下一个重定位块 } }
else
{
_appendInfo(TEXT("\n\n未发现该文件有重定位信息.\n\n"));
}
} /*
递归函数,遍历资源表项
_lpFile:文件地址
_lpRes:资源表地址
_lpResDir:目录地址
_dwLevel:目录级别
*/
void _processRes(PTCHAR _lpFile, PTCHAR _lpRes, PTCHAR _lpResDir, DWORD _dwLevel)
{
PIMAGE_RESOURCE_DIRECTORY pResourceDirectory;
DWORD dwNumber;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResourceDirectoryEntry;
DWORD OffsetToData;
DWORD dwName;
TCHAR szResName[];
PTCHAR lpResName;
TCHAR szBuffer[]; TCHAR szType[][] = {TEXT("1-光标 "),
TEXT("2-位图 "),
TEXT("3-图标 "),
TEXT("4-菜单 "),
TEXT("5-对话框 "),
TEXT("6-字符串 "),
TEXT("7-字体目录 "),
TEXT("8-字体 "),
TEXT("9-加速键 "),
TEXT("10-未格式化资源"),
TEXT("11-消息表 "),
TEXT("12-光标组 "),
TEXT("13-未知类型 "),
TEXT("14-图标组 "),
TEXT("15-未知类型 "),
TEXT("16-版本信息 ") }; TCHAR szOut5[] = TEXT("%d(自定义编号)");
TCHAR szLevel1[] = TEXT("|-- %s\n"
"| |\n");
TCHAR szLevel2[] = TEXT("| |-- %s\n"
"| | |\n");
TCHAR szOut6[] = TEXT("| |-- ID %d\n"
"| | |\n");
TCHAR szLevel3[] = TEXT("| | |-- 代码页:%d 资源所在文件位置:0x%08x 资源长度:%d\n"); pResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)_lpResDir;//指向目录表
dwNumber = pResourceDirectory->NumberOfIdEntries + pResourceDirectory->NumberOfNamedEntries;//计算目录项的个数
pResourceDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceDirectory + );//跳过目录头定位到目录项 while (dwNumber > )
{
OffsetToData = pResourceDirectoryEntry->OffsetToData;//查看IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData
if (OffsetToData & 0x80000000)//如果最高位为1
{
OffsetToData = (OffsetToData & 0x7fffffff) + (DWORD)_lpRes;//为下一次递归准备第三个参数,偏移是基于资源表起始地址的
if (_dwLevel == )//如果是第一级资源类别
{
dwName = pResourceDirectoryEntry->Name;
if (dwName & 0x80000000)//如果是按名称定义的资源类型
{
dwName = (dwName & 0x7fffffff) + (DWORD)_lpRes;//指向了名称字符串结构IMAGE_RESOURCE_DIR_STRING_U
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,//将UNICODE字符转换为多字节字符
((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->NameString,//名字地址
((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->Length, //名字长度
szResName, sizeof szResName, NULL, NULL);
szResName[((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->Length] = ;//结束符
lpResName = szResName;//指向了名称字符串
}
else//如果是按编号定义的资源类型
{
if (dwName <= 0x10)//系统内定的资源编号
{
lpResName = szType[dwName - ];//定位编号所在字符串
}
else//自定义资源类型
{
wsprintf(szResName, szOut5, dwName);
lpResName = szResName;
}
}
wsprintf(szBuffer, szLevel1, lpResName);
}
else if (_dwLevel == )//如果是第二级资源ID
{
dwName = pResourceDirectoryEntry->Name;
if (dwName & 0x80000000) //如果是按字符串定义的资源ID
{
dwName = (dwName & 0x7fffffff) + (DWORD)_lpRes;
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,//将UNICODE字符转换为多字节字符
((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->NameString,
((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->Length,
szResName, sizeof szResName, NULL, NULL);
szResName[((PIMAGE_RESOURCE_DIR_STRING_U)dwName)->Length] = ;//结束符
wsprintf(szBuffer, szLevel2, szResName);
}
else//如果是按编号定义的资源类型
{
wsprintf(szBuffer, szOut6, dwName);
}
}
else
{//跳出递归
break;
} _appendInfo(szBuffer);
_processRes(_lpFile, _lpRes, (PTCHAR)OffsetToData, _dwLevel + );
}
//如果IMAGE_RESOURCE_DIRECTORY_ENTRY.OffsetToData最高位为0
else//第三级目录
{
OffsetToData += (DWORD)_lpRes; wsprintf(szBuffer, szLevel3,pResourceDirectoryEntry->Name,//代码页
_RVAToOffset(_lpFile, ((PIMAGE_RESOURCE_DATA_ENTRY)OffsetToData)->OffsetToData),
((PIMAGE_RESOURCE_DATA_ENTRY)OffsetToData)->Size); _appendInfo(szBuffer);
} ++pResourceDirectoryEntry;
--dwNumber;
}
} /*
获取PE文件的资源信息
*/
void _getResource(PTCHAR _lpFile, PTCHAR _lpPeHead)
{
PIMAGE_NT_HEADERS pNtHeaders;
DWORD dwVirtualAddress;
TCHAR szBuffer[];
PTCHAR lpRes; TCHAR szOut4[] = TEXT("\n\n\n"
"---------------------------------------------------------------------------------------------\n"
"资源表所处的节:%s\n"
"---------------------------------------------------------------------------------------------\n"
"\n\n"
"根目录\n"
"|\n"); pNtHeaders = (PIMAGE_NT_HEADERS)_lpPeHead;
if (dwVirtualAddress = (pNtHeaders->OptionalHeader.DataDirectory)[].VirtualAddress)
{
wsprintf(szBuffer, szOut4, _getRVASectionName(_lpFile, dwVirtualAddress));
_appendInfo(szBuffer); //求资源表在文件的偏移
lpRes = _lpFile + _RVAToOffset(_lpFile, dwVirtualAddress); //传入的四个参数分别表示
//1、文件头位置
//2、资源表位置
//3、目录位置
//4、目录级别
_processRes(_lpFile, lpRes, lpRes, );
}
else
{
_appendInfo(TEXT("\n未发现该文件有资源表\n"));
return;
} } /*
打开PE文件并处理
*/
void _openFile(HWND hWinMain)
{
OPENFILENAME stOF;
HANDLE hFile, hMapFile;
DWORD dwFileSize; //文件大小
PTCHAR lpMemory; //内存映像文件在内存的起始位置
PTCHAR lpMem; TCHAR szFileName[MAX_PATH] = { }; //要打开的文件路径及名称名
TCHAR szExtPe[] = TEXT("PE Files\0*.exe;*.dll;*.scr;*.fon;*.drv\0All Files(*.*)\0*.*\0\0"); RtlZeroMemory(&stOF, sizeof(stOF));
stOF.lStructSize = sizeof(stOF);
stOF.hwndOwner = hWinMain;
stOF.lpstrFilter = szExtPe;
stOF.lpstrFile = szFileName;
stOF.nMaxFile = MAX_PATH;
stOF.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; if (GetOpenFileName(&stOF)) //让用户选择打开的文件
{
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
dwFileSize = GetFileSize(hFile, NULL);//获取文件大小
if (dwFileSize)
{
hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, , , NULL);//内存映射文件
if (hMapFile)
{
lpMemory = (PTCHAR)MapViewOfFile(hMapFile, FILE_MAP_READ, , , );//获得文件在内存的映象起始位置
if (lpMemory)
{
if (((PIMAGE_DOS_HEADER)lpMemory)->e_magic == IMAGE_DOS_SIGNATURE)//判断是否有MZ字样
{
lpMem = lpMemory + ((PIMAGE_DOS_HEADER)lpMemory)->e_lfanew;
if (((PIMAGE_NT_HEADERS)lpMem)->Signature == IMAGE_NT_SIGNATURE)//判断是否有PE字样
{
//到此为止,该文件的验证已经完成。为PE结构文件
//接下来分析分件映射到内存中的数据,并显示主要参数
_getMainInfo(lpMem, szFileName); //显示导入表
_getImportInfo(lpMemory, lpMem); //显示导出表
_getExportInfo(lpMemory, lpMem); //显示重定位信息
_getRelocInfo(lpMemory, lpMem); //显示资源表信息
_getResource(lpMemory, lpMem); }
else
{
MessageBox(hWinMain, TEXT("这个文件不是PE格式的文件!"), NULL, MB_OK);
}
}
else
{
MessageBox(hWinMain, TEXT("这个文件不是PE格式的文件!"), NULL, MB_OK);
}
UnmapViewOfFile(lpMemory);
}
CloseHandle(hMapFile);
}
}
CloseHandle(hFile);
}
}
} /*
窗口程序
*/
INT_PTR CALLBACK _ProcDlgMain(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
switch (wMsg)
{
case WM_CLOSE:
EndDialog(hWnd, );
break; case WM_INITDIALOG: //初始化
_Init(hWnd);
break; case WM_COMMAND: //菜单
switch (LOWORD(wParam))
{
case IDM_EXIT: //退出
EndDialog(hWnd, );
break; case IDM_OPEN: //打开文件
_openFile(hWnd);
break; case IDM_1:
case IDM_2:
case IDM_3:
default:
break;
}
break; default:
return FALSE;
} return TRUE;
} int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HMODULE hRichEdit; hInstance = hInst;
hRichEdit = LoadLibrary(TEXT("RichEd20.dll"));
DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, _ProcDlgMain, (LPARAM)NULL);
FreeLibrary(hRichEdit);
return ;
}

头文件 resource.h

 //{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Resource.rc 使用
//
#define ICO_MAIN 101
#define IDR_MENU1 102
#define IDM_MAIN 102
#define DLG_MAIN 103
#define IDC_INFO 1001
#define IDM_OPEN 40001
#define IDM_EXIT 40002
#define ID_40003 40003
#define ID_40004 40004
#define ID_40005 40005
#define ID_40006 40006
#define IDM_1 40007
#define IDM_2 40008
#define IDM_3 40009
#define IDM_4 40010 // Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40011
#define _APS_NEXT_CONTROL_VALUE 1002
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

资源文件 resource.rc

 // Microsoft Visual C++ generated resource script.
//
#include "resource.h" #define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h" /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS /////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
// TEXTINCLUDE
BEGIN
"resource.h\0"
END TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END #endif // APSTUDIO_INVOKED /////////////////////////////////////////////////////////////////////////////
//
// Icon
// // Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
ICO_MAIN ICON "main.ico" /////////////////////////////////////////////////////////////////////////////
//
// Menu
// IDM_MAIN MENU
BEGIN
POPUP "文件(&F)"
BEGIN
MENUITEM "打开文件(&O)...", IDM_OPEN
MENUITEM SEPARATOR
MENUITEM "退出(&x)", IDM_EXIT
END
POPUP "编辑(&E)"
BEGIN
MENUITEM SEPARATOR
END
POPUP "格式(&O)"
BEGIN
MENUITEM SEPARATOR
END
POPUP "查看(&V)"
BEGIN
MENUITEM "源文件", IDM_1
MENUITEM "窗口透明度", IDM_2
MENUITEM SEPARATOR
MENUITEM "大小", IDM_3
MENUITEM "宽度", IDM_4
END
POPUP "帮助(&H)"
BEGIN
MENUITEM SEPARATOR
END
END /////////////////////////////////////////////////////////////////////////////
//
// Dialog
// DLG_MAIN DIALOG , , ,
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "PEInfo"
MENU IDM_MAIN
FONT , "宋体"
BEGIN
CONTROL "",IDC_INFO,"RichEdit20A",ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | ES_WANTRETURN | WS_BORDER | WS_VSCROLL | WS_TABSTOP,,,,
END /////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
// #ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
DLG_MAIN, DIALOG
BEGIN
LEFTMARGIN,
RIGHTMARGIN,
TOPMARGIN,
BOTTOMMARGIN,
HORZGUIDE,
END
END
#endif // APSTUDIO_INVOKED #endif // 中文(简体,中国) resources
///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED