论坛首页 安全编程开发区 阅读主题

[原创]归纳PE结构基础知识,顺便手撕个PE

231 浏览 18 回复
#1 楼主 2026-06-01 21:08:58
PE是由微软设计的一种程序文件规范格式,微软设计PE文件格式的目的主要有二:a.为了兼容16位DOS系统;b.为了兼容其它操作系统。且不论初心是否达成,只是如此的雄心壮志,就注定导致PE的学习是需要掉他个大把头发的,因为当中设计了诸多与DOS和其它操作系统相关的内容,一眼望去茫茫一片着实让人心慌。尤其在学习PE之初,面对PE内容体系繁杂的结构和内容,难免心生忐忑(比如楼主,至今看到PE这两个字依然打哆嗦),不过我可可爱爱的王老师说了:用不到的,不用管它!对此楼主表示深以为然。
在正式开始手撕PE之前,还是要先捋捋相关的理论概念。可执行文件就是无需借助其它应用程序,由操作系统直接负责加载运行的文件,如.exe后缀文件。反之需要借助其它软件才能被加载使用的诸如.txt等后缀文件,即为非可执行文件。此处的后缀名说明仅作为辅助理解,实际上,在操作系统中,判断可执行文件的主要依据并非文件名后缀标识,而是文件结构格式。本文将以Windows平台的"PE文件格式"作为研究对象,相关资料来源于科锐学习笔记,如有错漏不妥之处,还望各位大佬多多指教。图3-1    PE结构详图图3-2    IMAGE_DOS_HEADER成员图析MAGE_FILE_HEADER:描述磁盘上PE文件的相关信息。*定位文件头地址:DOS头中的e_lfanew+4图3-3    IMAGE_FILE_HEADER成员图析IMAGE_FILE_HEADER::以供操作系统加载PE文件使用,必选。*定位选项头地址:DOS头中的e_lfanew+4+0x14(文件头大小)。图3-4    IMAGE_OPTIONAL_HEADER成员图析节表:描述PE文件与内存之间的映射关系,由一系列的IMAGE_SECTION_HEADER结构排列而成,每个结构用来描述一个节(每个节占用0x28B),说明PE文件的指定内容拷贝至内存的哪个位置、拷贝大小及内存属性的设置。结构的排列顺序和它们描述的节在文件中的排列顺序是一致的。全部有效结构的最后以一个空的IMAGE_SECTION_HEADER结构作为结束,所以节表中总的IMAGE_SECTION_HEADER结构数量等于节的数量加一。节表总是被存放在紧接在PE文件头的地方。节表大小 = FileHeader.NumberOfSections(节数量)* IMAGE_SECTION_HEADER 结构体。图3-5    节属性常用位含义节表置于选项头之后,节表首地址 计算方法:(1)选项头的地址 + 选项头的大小;(2) e_lfanew+4+0x14(文件头大小)+0xE0(32位选项头大小)。图3-6   节表定位图析数据目录用来描述PE中各个表的位置及大小信息,重点表:导出表、导入表、重定位表、资源表。在这个数据目录结构体中只有两个成员 VirtualAddress 和 Size :参数1VirtualAddress指定了数据块的相对虚拟地址(RVA),因为当exe在处理导入表的时候,已经映射进进程内存了,取值RVA更方便。Size则指定了该数据块的大小,有时并不是该类型数据的总大小,可能只是该类型数据一个数据项的大小。这两个成员(主要是VirtualAddress)成为了定位各种表的关键,所以一定要知道每个数组元素所指向的数据块类型,以下表格就是它的对应关系:图3-7    IMAGE_DATA_DIRECTORY数组元素项图析定位数据目录的技巧:数据目录向上找10h,+4即为DataDirectory的地址,编译器生成的一般都是10h。图3-8    数据目录定位图析IMP(导入表):导入表用来描述模块调用的API列表,位于PE数据目录中的第二项即DataDirectory[1],其中记录了导入表的地址和大小,VirtualAddress指向IMAGE_IMPORT_DESCRIPTOR 结构体数组,这个结构体数组中的每个元素对应着一个dll文件,以全0作为最后一个元素结尾。程序产生调用会生成CALL指令,两大问题及解决思路如下:1.地址存放问题:出于运行环境等因素考虑,导入函数的地址不能为固定地址。所以在exe中保存导入函数的相关信息,系统和链接器对其进行约定:链接器在生成exe的时候,为所有调用API的地方填写一个间接地址,当程序运行起来后,相应地址则会被写入真正API的地址,此区域即为IAT表(导入地址表);2.exe如何存储导入dll及其函数信息:dll与函数是一对多的关系,原则上应该设计为多方填写1方信息的数据关系,但考虑到数据较多的情况,遍历不便。反过来设计为1方存储多方信息的数据结构,虽然会造成插入删除的不方便,但是考虑到exe加载dll的实际场景,无插入删除需求,所以应该设计为后者结构更贴合遍历查询需求。IAT(导入地址表):IMP中的FirstThunk指向IAT表。INT(导入名称表):IMP中的OriginalFirstThunk指向INT表,也是DataDirectory[12]项。PE加载后,IAT有变:加载后的IAT每一项存储的是所对应的导入函数地址。图3-9    PE加载前后IMP、IAT、INT之间的关系节数据:即是由不同属性数据组成的不同节。实现目标:手写实现196 Byte大小的PE文件(又名:畸形PE/变形PE),要求MessageBox弹框显示"hello world"。实现要点:充分利用空间,在保证遵循PE结构的基础上对数据结构进行重构存放。运行环境--XP系统:XP对于畸形PE的兼容性更高。编辑器--winhex:用于编写PE文件。使用winhex工具,新建196字节大小的PE文件并将数据初始化为全CC,以便分辨空闲区。图4-1    myWinPE.exe文件创建流程文件偏移+0x00(注1),WORD e_magic→'MZ'文件头标识:0x5A4D(注2)文件偏移+0x3C,LONG e_lfanew→指向NT头'PE'标识的地址:0x00000004此处设置NT头地址为0x4偏移的原因:1.充分利用每字节可用空间,DOS除首尾两字段外都非必要字段,可用;2.当NT头置于0x4处,0x3C的功能不仅是指向NT头标识,还将成为选项头的成员SectionAlignment(文件对齐值),在XP中,此项最小值为4。综上两点,此处写入0x4最为合适。图4-2    DOS_HEADER部分内容文件偏移+0x04,DWORD Signature→'PE00'NT头标识:0x00004550图4-3    NT头的Signature部分内容文件偏移+0x08,WORD Machine→指定程序的运行平台:0x104C(运行于Intel 386)文件偏移+0x0A,WORD NumberOfSections→PE中的节数量:0x0001(最小限值)图4-4    NT头的FILE_HEADER部分内容文件偏移+0x1C,WORD Magic→PE标志字即程序位数:0x010B(32位系统)文件偏移+0x2C,DWORD AddressOfEntryPoint→程序执行入口RVA:0x00000000图4-5    NT头的OPTIONAL_HEADER

...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-270210.htm
#2 2026-06-01 21:08:58
原来是shanshan sister,认出来了,刚好可以复习一下
#3 2026-06-01 21:08:58
波波_509343

运行不了。那里出错了。。。
八成是在xp虚拟机里跑,不同操作系统解析的方式有差异
#4 2026-06-01 21:08:58
运行不了。那里出错了。。。
#5 2026-06-01 21:08:58
妹妹太强了,我要拜你为师
#6 2026-06-01 21:08:58
看雪里面光大佬啊,我刚学PE不管咋样我都要先手撕一下PE先充实一下自己
#7 2026-06-01 21:08:58
受教
#8 2026-06-01 21:08:58
学习
#9 2026-06-01 21:08:58
文件偏移+0x08,WORD Machine→指定程序的运行平台:0x104C(运行于Intel 386)
这里应该是014c
这篇文章应该设置为精华,对PE,特别是输入表的理解应该是相当透彻了
感谢MM
#10 2026-06-01 21:08:58
什么学校
#11 2026-06-01 21:08:58
shanjie YYDS
#12 2026-06-01 21:08:58
大魔法狮子


手撸shellcode +手撸pe=最小最精简可执行文件--》变种=自己组织可执行带重定位和导入导出结构的类pe文件

今天刚接触到shellcode,等琢磨明白了就跟着大佬的思路来一个,谢谢指点
#13 2026-06-01 21:08:58
手撸shellcode +手撸pe=最小最精简可执行文件--》变种=自己组织可执行带重定位和导入导出结构的类pe文件
#14 2026-06-01 21:08:58
0xC5


很不错,我猜你可能是我的学弟学妹[em_48]

40期学妹表示久闻学长大名,感谢肯定,会继续加油哒
#15 2026-06-01 21:08:58
瑞皇


写的挺好的,刨析了较小PE的结构,加油!!!
#16 2026-06-01 21:08:58
wx_〒_〒


shanjie YYDS

夸夸师强哥持续在线
‹ 上一页 1 2 下一页 ›

请登录后参与讨论

立即登录 注册账号