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
WindowsPE权威指南 第二章 小工具 PEInfo代码的C语言实现的更多相关文章
- WindowsPE权威指南 第二章 小工具 PEComp代码的C语言实现
主程序代码 PEComp.c #include <windows.h> #include <Richedit.h> #include <Commctrl.h> #i ...
- WindowsPE权威指南 第二章 小工具 pedump代码的C语言实现
2016-11-16 16:29:07 主程序代码 pedump.c #include <windows.h> #include <Richedit.h> #include & ...
- Javascript权威指南——第二章词法结构,第三章类型、值和变量,第四章表达式和运算符,第五章语句
第二章 词法结构 一.HTML并不区分大小写(尽管XHTML区分大小写),而javascript区分大小写:在HTML中,这些标签和属性名可以使用大写也可以使用小写,而在javascript中必须小写 ...
- 【笔记】javascript权威指南-第二章-词法结构
词法结构 //本书是指:javascript权威指南 //以下内容摘记时间为:2013.7.28 字符集 UTF-8和UTF-16的区别?Unicode和UTF是什么关系?Unicode转义 ...
- JavaScript权威指南 第二章 词法结构
这章主要把保留字说一下 JavaScript 把一些标识符拿出来用做自己的关键字.因此,就不能再在程序中把这些关键字用做标识符了: break delete function return typeo ...
- HTTP 权威指南 第二章 URL 与资源
前言 这一章节讲述了关于 URL 的相关知识,主要包括下面的内容: URL 语法 URL 快捷方式 URL 编码与字符规则 常见的 URL 方案 URL 的未来——URN URL 语法 一般格式(九个 ...
- PADSPCB权威指南-第一章 PADS软件系统(部分)(原创)
PADSPCB权威指南-第一章(部分)豆丁地址:http://www.docin.com/p-707128286.html
- 《Mysql 公司职员学习篇》 第二章 小A的惊喜
第二章 小A的惊喜 ---- 认识数据库 吃完饭后,小Y和小A回到了家里,并打开电脑开始学习Mysql. 小Y:"小A,你平时的Excell文件很多的情况下,怎么样存放Exce ...
- Knockout应用开发指南 第二章:监控属性(Observables)
原文:Knockout应用开发指南 第二章:监控属性(Observables) 关于Knockout的3个重要概念(Observables,DependentObservables,Observabl ...
随机推荐
- Vue相关文章
1.新手向:Vue 2.0 的建议学习顺序 2.用webstorm搭建vue项目 3.vue-cli3.0项目结构
- SQL Server死锁诊断--同一行数据在不同索引操作下引起的死锁
死锁概述 对于数据库中出现的死锁,通俗地解释就是:不同Session(会话)持有一部分资源,并且同时相互排他性地申请对方持有的资源,然后双方都得不到自己想要的资源,从而造成的一种僵持的现象.当然,在任 ...
- Centos6.3下搭建apache+https服务
1. 安装插件 yum install mod_ssl openssl openssl-devel --downloadonly --downloaddir=/home/https 2.生成私钥 op ...
- mybatis sql in not in的使用
xml配置 <select id="SelectAllByNotsampleNo" resultMap="BaseResultMap" parameter ...
- svn仓库迁移
注意事项 1.仅迁移代码.日志.版本信息,(用户.权限.配置即conf目录需要手动移动或重新配置) 2.新仓库需无代码,即新建仓库后不要进行上传操作,否则迁移可能造成冲突,导致迁移失败 操作步骤 1. ...
- Linux-04
文件处理命令 文件处理命令:rmdir 命令名称:rmdir 命令英文原意:remove empty directories 命令所在路径:/bin/rmdir 执行权限:所有用户 语法:rmdir ...
- delete 和 delete [] 的真正区别
c++中对new申请的内存的释放方式有delete和delete[两种方式,到底这两者有什么区别呢? 1.我们通常从教科书上看到这样的说明: delete 释放new分配的单个对象指针指向的内存 de ...
- js计算日期相减天数
代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head ...
- 48-设置tomcat虚拟路径的两种方法(Eclipse、tomcat、IDEA)
设置tomcat虚拟路径的两种方法(Eclipse.tomcat.IDEA) 三种方式设置虚拟服务器路径如果我们要实现一个上传文件的功能,但是又想要上传的文件不会随着自己web服务器的重启而不能访问了 ...
- css去掉滚动条
.main-layout-side::-webkit-scrollbar { display: none; } 主要代码: ::-webkit-scrollbar {display: none;}