一. 回顾
PE 文件的 Magic code(魔数、幻数)是 MZ 头、PE 头
PE 文件中头文件的信息有运行平台、时间戳、PE 文件属性、区段数量、扩展头大小
PE 文件中的扩展头信息有 OEP 的 RVA、ImageBase(0x400000)、代码段、数据段起始地址、数据目录表、数据目录表项数、文件对齐粒度、内存对齐粒度、映像总大小
PE 文件区段信息有区段名、虚拟地址、虚拟大小、文件偏移、文件大小、区段属性(C0000020, 60000020等)
PE 文件中数据目录表有导入导出表、异常表、tls表、资源表、IAT、重定位表
一个进程三环下的数据结构有进程环境块(PEB)、线程环境块(TEB)、tls 结构
导入表结构体有5个字段,第一个
OriginalFirstThunk
,指向 INT,第二个是时间戳,第三个是转发机制用到的ForWarderChain
,第四个是Name
,dll 名称字符,第五个是FirstThunk
,指向的是 IATINT 和 IAT 在文件中存在是一样的,都指向名称字符串的 RVA 或一个序号
二. 手工加壳
目标:将代码段加密,防止 IDA 等静态工具分析
步骤:
添加一个区段(文件大小、区段数量)
用 LoadPE 打开一个自己用 VS2017 编写的简单程序,添加区段,默认名为 NewSec
![2020.1.13-1](D:\git png\2020.1.13-1.png)
![2020.1.13-2](D:\git png\2020.1.13-2.png)
添加完成后发现无法打开程序,因为添加的虚拟大小、文件大小都是空的
![2020.1.13-3](D:\git png\2020.1.13-3.png)
使用 LoadPE 编辑区段信息,添加虚拟大小和文件大小都是 0x200
然后使用 010Editor 添加文件数据
![2020.1.13-5](D:\git png\2020.1.13-5.png)
![2020.1.13-6](D:\git png\2020.1.13-6.png)
在文件末尾添加 200H 个字节,保存后再次打开程序,发现能够运行
修改 OEP,增加 OEP 代码
将程序的入口点改为新添加区段的 RVA,原区段入口点为 0x11343
![2020.1.13-7](D:\git png\2020.1.13-7.png)
使用 OD 打开程序
直接跳转到原来的 OEP 可以成功,因为 jmp 指令后面是相对偏移
![2020.1.13-8](D:\git png\2020.1.13-8.png)
第二种方法,使用技巧获取基地址再跳转,
call
指令后,将 0x100005 入栈,pop eax
即eax = 0x100005
,然后减去 0x20005 得到模块基址,基址加上原 OEP 即为原 OEP 的入口地址![2020.1.13-9](D:\git png\2020.1.13-9.png)
第三种方法,将上面的
sub add
合并计算出偏移,入口点地址+5-(入口点地址-新OEP+原OEP)
![2020.1.13-10](D:\git png\2020.1.13-10.png)
代码演化,去掉随机基址
在新的 OEP 处直接跳转到原来的 OEP
![2020.1.14-1](D:\git png\2020.1.14-1.png)
在新的 OEP 处定义出模块基址,然后加上原始 OEP,RVA
![2020.1.14-2](D:\git png\2020.1.14-2.png)
在新的 OEP 处通过
call pop
组合获取当前指令地址,再减去偏移,计算出模块基地址![2020.1.14-3](D:\git png\2020.1.14-3.png)
加密代码段
代码段信息
![2020.1.14-4](D:\git png\2020.1.14-4.png)
在 010Editor 中操作代码段
选中代码段
![2020.1.14-8](D:\git png\2020.1.14-8.png)
异或加密代码段
![2020.1.14-6](D:\git png\2020.1.14-6.png)
![2020.1.14-7](D:\git png\2020.1.14-7.png)
增加解密代码
由于代码本身有重定位信息,加密之后重定位会出现问题,故应去掉随机基址
在 010Editor 中将 40 81 改为 00 81
将 .text 段的标志设为可写入
![2020.1.14-10](D:\git png\2020.1.14-10.png)
在程序入口点编辑代码进行解密
![2020.1.14-11](D:\git png\2020.1.14-11.png)
脱壳
脱壳目的:
- Cracker 脱壳、解密、破解
- 杀毒引擎解密、查杀病毒、扫描特征
脱壳步骤:
找到原始 OEP
一般来说,找到原始 OEP 或跟踪到原始 OEP 时,程序都会完成解密操作
dump 内存到文件
当可执行文件在内存中完成解密后,将内存中代码数据转储(dump)到文件,就可以进一步分析
修复文件(常见于修复 IAT,重建导入表)
从内存中转储的内存数据代码有一些与原文件中的内容不一致,比如 IAT 表,内存中 IAT 表会被初始化为函数地址表,而文件中 IAT 表与 INT 表内容一致,所以想要程序正常运行,一般都要修复 IAT,加壳后程序一般会自己处理导入表、IAT 及重定位等
导入表和 IAT、INT
![2020.1.14-9](D:\git png\2020.1.14-9.png)
IAT 在文件中保存的是一个 RVA 数组,每一项指向函数字符串结构,在内存中这个 RVA 数组被修改为函数地址,每个函数地址就是之前对应的函数字符串的函数,所以从内存中 dump 出的文件必须进行 IAT 修复或导入表修复
![2020.1.14-12](D:\git png\2020.1.14-12.png)
脱自己的壳
找到原始 OEP
单步跟踪,在
POPAD
附近寻找dump 内存到文件
在原始 OEP 处进行 dump 内存,因为这时内存未做太多的初始化,右击,选择
用OllyDump脱壳调试进程
![2020.1.14-13](D:\git png\2020.1.14-13.png)
填入当前模块的起始地址和原来的 OEP,取消选择
重建输入表
,脱壳修复 IAT 或修复导入表
使用 ImportREC 15pb专用版
![2020.1.14-14](D:\git png\2020.1.14-14.png)
打开该工具,选择脱壳进程,设置 OEP,方便查找 IAT,点击 自动查找IAT
,获取 IAT 信息,点击 获取输入表
,获取输入表信息,若输入表函数有无效的,就需要修复,最后将输入表信息转储到文件,完成修复