前言
修改PE文件一般有两种思路。
- 第一种是通过编程语言来修改,这种方式的Visual Studio的
Windows.h
头文件里面有完全的PE相关管理结构的完整定义,通过编程来修改比较烦,但是优点是可以自动化进行,并且不需要去找相关的工具; - 第二种方法是通过一些二进制工具来进行修改,这种方式是交互式的,能够直观的感受到整个过程,缺点是需要熟悉相关工具的UI使用方式,而且修改大量方式的时候市面上的这些工具一般都不提供编程接口;
因为本次实验仅仅是一个探索,所以就采用第二种方式。
需要的工具
本次实验用到的工具如下:
- CFF Explorer:用于结构化查看PE管理结构,同时也提供方便的PE文件修改(之前不知道的时候一直是用Winhex直接修改的);
- Winhex:用于在二进制层面修改PE文件,在本次实验中主要用于在新添加的节里面添加自己的代码;
- Ollydbg:用于调试自己的ShellCode;
- 相关能够生成本地字节码的编译环境:用于生成和观察相关汇编指令的字节码
实验前需要注意的事项
由于PE文件中的很多字段是相互关联的,这里需要先列一下要修改/注意的事项,等到修改的时候对照清单一步一步的看:
- FileAlignment:文件中的节对齐大小,等下设置新的节的时候节大小必须对齐;
- SectionAlignment:内存中的节大小,设置节内存起始偏移的时候必须对齐;
- SizeofImage:内存中的PE镜像对齐后的总大小
- SizeofHeader:这个值是按照FileAlignment的值对齐的,也就是说大部分情况下Header的地址范围内是有空洞的,可以利用,如果没有空洞的话这个值需要修改,并需要依次后移PE文件的数据;
- AddressOfEntryPoint:入口点
- NumberOFSections:节表长度
整个的修改流程应该是:
- 计算新增加的节的内存布局范围
- 修改NumberOFSections
- 使用Winhex扩展新节
- 在新节里面填入汇编代码
任意选择一个PE文件,我这里选择的是DbgView,一款用于查看OutputDebugString
函数输出字符串的软件。
新增一个节
计算PE新增加的节的内存布局
首先需要先观察一下原PE文件的内存布局:
我们选择在最后一个节后面插入自己的节,这里列一下计算过程:
- Name:随便取
- Virtual Size:都可,这里为了方便起见就去0x1000吧
- Virtual Address:这里是RVA,之前的的节的地址范围为
[0x55000,0x55000+0x31FBB+(0x1000-0x31fbb%0x1000)-1]
,所以实际的范围应该是[0x55000,0x86fff]
,那么新的节的起始地址应该是0x87000
- Raw Size: 这里取最小的粒度0x200
- Raw Address:
0X3D000+0x32000=0x6F000
- Reloc Address、Linenumbers…:PE文件中不是很重要的东西;
- Characteristics:属性,这里取和.text段属性一样的值,顺便提一嘴这个位图实际上包括了两种类型的标记,一种是内存管理的属性&#