pe首先分为三大块:dos 头,pe头,区块/节点。
分析工具:PETool 和010Editor。
一、dos头
dos头为一个64个字节的结构体(大小固定的),需要记住它的开头是e_magic ,结尾是e_lfanew。
DOS Header (MS-DOS Header)
winHex打开后前四行为dos头,一般开头是e_magic为4D5A,显示数据为“MZ”,此处不能修改,否则可能执行不成功,用od打开会失败。
第四行的结尾假设是0000 00F8 代表的是偏移。就是pe头和dos头的距离,但是在内存中dos头不是从0000 0000开始的。 所以,用内存中的开始地址+结尾的e_lfanew得出pe头的位置。
二、pe头
NT头/pe头=dos头+偏移。那么对于不加壳的软件,在dos尾和pe头之间的部分为垃圾区,加壳软件则可能会在这个区域之间做一些文章。
pe头分为pe文件标志(4个字节),文件头(大小固定,里面有存放可选PE头的大小),可选PE头(大小可变)。
2. File Header (PE Header)
3. Optional Header 可选pe头
SizeOfHeaders怎么算的?
计算公式:64+4 + 20+ SizeOfOptionalHeader (需知道是224还是240 )+
NumberOfSections(区块或者节点数量)* 40 = SizeOfHeaders
EntryPoint 偏移地址(OEP)+ImageBase = 程序的入口点。
此时若od反编译后,程序入口点不是该地址。说明程序编译链接时,选择了随机基址。
怎么改成固定地址,分为自己写的程序和修改他人程序2种情况:
1.如果是自己vs写的程序,打开项目属性,链接器,高级,随机基址选否,固定基址选是,关闭运行后验证。
2.如果是别人写的程序改成固定基址,注意可选pe头中的DllCharacteristics这个属性,用010Editor点进去后,进入这个结构体,找到DYNAMIC_BASE ,把值改成0,然后保存。
只适用于exe文件,dll文件最好不要改成固定基址。因为一个exe可能加载多个dll,如果都放在固定位置可能会造成冲突。
其他思路:EntryPoint 偏移地址(OEP)+getMoudleHandle 获取基址 = 程序入口
代码示范:
int main()
{
HANDLE hfile = CreateFileA("内联汇编.exe",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if (hfile == INVALID_HANDLE_VALUE) {
GetLastError();
}
DWORD fileSize=GetFileSize(hfile,NULL);
char* fileBuff = new char[fileSize]; // 基址
DWORD reallyRead = 0;
BOOL bsucess = FALSE;
// pe头
PIMAGE_NT_HEADERS pNtHeaders = 0;
// 文件头
PIMAGE_FILE_HEADER pFileHeader = 0;
// 可选pe头
PIMAGE_OPTIONAL_HEADER pOptionHeaders = 0;
bsucess=ReadFile(hfile, fileBuff,fileSize,&reallyRead,NULL);
if (bsucess) {
PIMAGE_DOS_HEADER pDosHeaders = (PIMAGE_DOS_HEADER)fileBuff;
if (pDosHeaders->e_magic!=0x5A4D) {
printf("该文件不是有效的pe文件 ");
return 0;
}
cout << "pe头的偏移地址e_lfanew= " << pDosHeaders->e_lfanew << endl;
pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD) pDosHeaders->e_lfanew + (DWORD)fileBuff);
DWORD pe=pNtHeaders->Signature;
if (0x4550 != pe) {
printf("该文件不是有效的pe文件 ");
delete[] fileBuff;
}
pFileHeader = &(pNtHeaders->FileHeader);
// cpu类型
cout << "pFileHeader->Machine:"<<::hex << pFileHeader->Machine << endl;
cout << "pFileHeader->Characteristics" << ::hex << pFileHeader->Characteristics << endl;
cout << "pFileHeader->NumberOfSections"<< pFileHeader->NumberOfSections << endl;
// 可选pe头的大小
cout << "pFileHeader->SizeOfOptionalHeader" << pFileHeader->SizeOfOptionalHeader << endl;
// 基于pe头得到可选pe头
pOptionHeaders =&pNtHeaders->OptionalHeader;
}
delete[] fileBuff;
CloseHandle(hfile);
return 0;
}
作业: 自己写去定位可选pe头
到此这篇pe文件是什么意思(电脑pe文件是什么)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/78843.html