背景
最近用到一个PE的知识,然后看几篇文章,决定自己二进制编辑器构建一个简单windows exe执行程序,目前这篇文章知识构建一个能够运行,但什么都不会发生程序,因为执行代码只是0xcc 对应汇编只是int 3一个调试中断而已,但已经能够说明一个pe的执行,后续系列会增加全局变量和导入函数等等,慢慢构建能用,同时可能会增加更多好玩地方。
准备工作
- imhex(开源二进制编辑工具)
- PE-bear(pe格式工具)
- CFF Explore(pe格式工具)
这里用到2个PE工具,因为可以结合起来用,非常方便,CFE 修改 PE文件更加方便,PE-bear看一些PE字段更加清晰。
过程
- 分配0x600 大小 文件对齐0x200 2个基本满足了(一个头,一个节点)
- 调到0x0设置MZ,直接点击右边数据...设置MZ(0x4d4a)
- 跳转到0x3c,这个是dos head 最后一个元素,这个长度是0x4,dos head 大小是0x40。
- dos sub 是0x39 ,一般这么大,后面我可以去掉这个dos sub对我们没有用。
- 那么pe下面0x40+0x39 下一个0x80,这样子设置PE,这样子可以对比其他的exe直接操作
- 调到0x3c设置0x110 (1001),主要方便自己的,这里包含rich head,我也不知道是什么,这样子方便进行(coffHeaderPointer 对应pe结构元素 e_lfanew)
- 跳到 0x110 进入option header 设置 signature ,PE
- 跳到0x114 ArchitectureType 设置0x4c01 小端值:0x14c 代表i8386
- 跳到0x116 numberOfSections 节的个数,我们这里是0x0100 小端0x1 2个字节
- 跳到0x124 sizeOfOptionalHeader 0xe000 2个字节设置可选头大小,一般就是这个值,所以可选头大小可以扩充的,因为目录的可以增加或者减少(后面我们减少看看)
- 跳到0x126 Characteristics 设置 0x0201 小端0x102 代表小程序和32位
- 0x128 进入了option 设置magic PE 4个字节
- 0x12c sizeOfCode 0x0002 小端0x200 我们后面大小单独文件对齐的一个
- 0x138 入口点这里是虚拟地址(加载内存地址,这里对齐4k),0x00100000 小端0x1000(真正最开始的入口,我们设置自己函数,) (这里有点意思)
- 0x13c baseOfCode 代码的 0x1000 (代码开始的地方)0x00100000 这里基本就是0x1000 因为代码.txt第一个节就是我们代码块。
- 0x148 内存对齐0x00100000(0x1000)(这个非常重要)
- 0x14c 0x00020000(0x200) 文件对齐(这个非常重要)
- 0x150 majorOperatingSystemVersion 0x0600系统主版本(6)(2个字节)win7
- 0x158 6
- 0x160 sizeOfImage 内存大小0x0020(0x2000) (一个头,一个节点
- 0x164 sizeOfHeaders 头大小(文件的大小,不是内存的大小)0x0004(0x400)
- 0x16c subsystem 0x0100 设置控台(2个字节)
- 0x16E 0x4081(0x8140) 这个有用字段,我们可以去掉dll can move 这个模块基地址就不会变动。
- 0x184 numberOfRVAsAndSizes 0x10000000(0x10) 16个
- 调到0x1000 设置0xcc 设置int 3 代表中断触发调试,这个代码最简单的逻辑,这个地方我们扩展可以导入shell code,直接编辑,这样子不用考虑导入表。我们可以从网上找一段
补充说明
上面开始一个个设置记录,但不一定全对,因为我后面用PE工具修改数字,因为自己写的时候小端二进制写反了,然后我用PE工具直接修改了(当几个PE字段填写后,PE工具就能识别,这个时候修改更加方便)
重要的几个字段
os (marjor) 和 Subystem(major) 不能填0,否则系统认为不兼容,会弹出对话框然后你程序无法执行。
im hex 使用
一、创建新的空的文件
二、分配大小0x600
三、编辑十六进制
双击你要地方就可以输入数字进行修改,你修改ascll的话,你点击右边即可。
错误处理方法
如果运行不了,你可以用PE工具打开,PE工具一般会提示错误,你一个一个对比看,基本就能排查错误,这个版本什么都看不了,不过你可以用反编译工具进行调试,这样子有感觉一点,你同时可以修改汇编代码,比喻进行加法运算,后续就要增加其他逻辑,比喻重定位表操作等等,慢慢增加一个能用的程序。
目的
更加直接了解程序运行,而不用看复杂书籍。
pe结构
https://learn.microsoft.com/zh-cn/windows/win32/debug/pe-format
微软的文档介绍
本质就是二进制描述一个文件,不管是exe还是其他的格式都是类似,这个格式与mp4,mp3,只是exe是被windows 解析加载然后运行而已,具体格式可以自己查资料找到。
难理解点
文件对齐与内存对齐
刚开始很难理解理解这是什么意思,这里网上的资料因为内存0x1000 4k对齐,文件是存储是0x200 512对齐,所以为了性能PE加载内存4k中对齐,然后没有加载内存前是0x200对齐,PE文件(没有加载内存前),里面有填写内存地址(虚拟地址),大部分是文件地址,所以我们填写字段就要计算内存对齐和文件对齐,这样子,但计算位置对于新手搞不明白,所以又会遇到不懂的地方。
这里隐藏知识点:
1.PE头文件对齐
2.节对齐
只有2个地方对齐,我开始因为option 对齐一下,NT对齐,所以就混乱,虽然书上图花很清楚,但没有明确写清楚。
文件地址和内存地址怎么转换
因为一个按照内存对齐,一个按照文件对齐,所以地址不是一样,但是相对地址偏移是固定。
比喻说
[xxxxxxxxxxxxxA]
假设这个A在某个位置内容,假设不够内存0x1000,需要对齐那么内存会变成
[xxxxxxxxxxxxxAxxxxxxxxxxxxx]
对比上面2个就看出来了,所以节起始地址+偏移地址。
头文件偏移和内存偏移一样,因为起始点一样,就算后面补齐长度不一样,因为不影响偏移,但节不一样,节在补齐头后面。
导入表理解
导入表结构看起来很简单,但后面手动构建导入表时候就发现一些问题,下篇文章再补充
总结
这篇文章只是想写了,很多细节没有写,只是想给自己开始,不然又不知道何年去写了