一. 回顾

  1. PE 文件的 Magic code(魔数、幻数)是 MZ 头、PE 头

  2. PE 文件中头文件的信息有运行平台、时间戳、PE 文件属性、区段数量、扩展头大小

  3. PE 文件中的扩展头信息有 OEP 的 RVA、ImageBase(0x400000)、代码段、数据段起始地址、数据目录表、数据目录表项数、文件对齐粒度、内存对齐粒度、映像总大小

  4. PE 文件区段信息有区段名、虚拟地址、虚拟大小、文件偏移、文件大小、区段属性(C0000020, 60000020等)

  5. PE 文件中数据目录表有导入导出表、异常表、tls表、资源表、IAT、重定位表

  6. 一个进程三环下的数据结构有进程环境块(PEB)、线程环境块(TEB)、tls 结构

  7. 导入表结构体有5个字段,第一个 OriginalFirstThunk,指向 INT,第二个是时间戳,第三个是转发机制用到的 ForWarderChain,第四个是 Name,dll 名称字符,第五个是 FirstThunk,指向的是 IAT

    INT 和 IAT 在文件中存在是一样的,都指向名称字符串的 RVA 或一个序号

二. 手工加壳

目标:将代码段加密,防止 IDA 等静态工具分析

步骤:

  1. 添加一个区段(文件大小、区段数量)

    用 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

    image-20200113215632886

    然后使用 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 个字节,保存后再次打开程序,发现能够运行

  1. 修改 OEP,增加 OEP 代码

    将程序的入口点改为新添加区段的 RVA,原区段入口点为 0x11343

    ![2020.1.13-7](D:\git png\2020.1.13-7.png)

使用 OD 打开程序

  1. 直接跳转到原来的 OEP 可以成功,因为 jmp 指令后面是相对偏移

    ![2020.1.13-8](D:\git png\2020.1.13-8.png)

  2. 第二种方法,使用技巧获取基地址再跳转,call 指令后,将 0x100005 入栈,pop eaxeax = 0x100005,然后减去 0x20005 得到模块基址,基址加上原 OEP 即为原 OEP 的入口地址

    ![2020.1.13-9](D:\git png\2020.1.13-9.png)

  3. 第三种方法,将上面的 sub add 合并计算出偏移,入口点地址+5-(入口点地址-新OEP+原OEP)

    ![2020.1.13-10](D:\git png\2020.1.13-10.png)

代码演化,去掉随机基址

  1. 在新的 OEP 处直接跳转到原来的 OEP

    ![2020.1.14-1](D:\git png\2020.1.14-1.png)

  2. 在新的 OEP 处定义出模块基址,然后加上原始 OEP,RVA

    ![2020.1.14-2](D:\git png\2020.1.14-2.png)

  3. 在新的 OEP 处通过 call pop 组合获取当前指令地址,再减去偏移,计算出模块基地址

    ![2020.1.14-3](D:\git png\2020.1.14-3.png)

  1. 加密代码段

    代码段信息

    ![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)

  1. 增加解密代码

    由于代码本身有重定位信息,加密之后重定位会出现问题,故应去掉随机基址

    在 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)

脱壳

脱壳目的:

  1. Cracker 脱壳、解密、破解
  2. 杀毒引擎解密、查杀病毒、扫描特征

脱壳步骤:

  1. 找到原始 OEP

    一般来说,找到原始 OEP 或跟踪到原始 OEP 时,程序都会完成解密操作

  2. dump 内存到文件

    当可执行文件在内存中完成解密后,将内存中代码数据转储(dump)到文件,就可以进一步分析

  3. 修复文件(常见于修复 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)

脱自己的壳

  1. 找到原始 OEP

    单步跟踪,在 POPAD 附近寻找

  2. dump 内存到文件

    在原始 OEP 处进行 dump 内存,因为这时内存未做太多的初始化,右击,选择 用OllyDump脱壳调试进程

    ![2020.1.14-13](D:\git png\2020.1.14-13.png)

    填入当前模块的起始地址和原来的 OEP,取消选择 重建输入表,脱壳

  3. 修复 IAT 或修复导入表

    使用 ImportREC 15pb专用版

    ![2020.1.14-14](D:\git png\2020.1.14-14.png)

打开该工具,选择脱壳进程,设置 OEP,方便查找 IAT,点击 自动查找IAT,获取 IAT 信息,点击 获取输入表,获取输入表信息,若输入表函数有无效的,就需要修复,最后将输入表信息转储到文件,完成修复