回顾

  1. PE文件的Magic code(魔数、幻数)是什么?
    MZ头、PE头
    2. PE文件中文件头的信息有哪些?
    运行平台、时间戳、PE文件属性、区段数量、扩展头的大小
    3. PE文件中扩展头的信息有哪些?
    EP的RVA、ImageBase(400000)、代码段起始地址、数据段起始地址
    数据目录表、数据目录表项数量、文件对齐、内存对齐、映像总大小
    4. PE文件中区段信息有哪些?
    区段名称、虚拟地址、虚拟大小、文件偏移、文件大小、区段属
    性(C0000020、60000020)
    5. PE文件中数据目录表有哪些表?
    导出表、导入表、异常表、tls表、资源表、IAT、重定位表
    6. 一个进程,三环下有哪些数据结构?
    进程环境块(PEB)、线程环境块(TEB)、tls结构
    7. 导入表结构体字段有几个,分别是什么?
    5个字段,第一个是OrginalFirstThunk,里面是rva,指向的INT,第二个是时间戳,第三个是转
    发机制用到的ForWarderChain,第四个是name,rva,dll名称字符串,第五个是FirstThunk,指
    向的是IAT。
    INT或IAT在文件中存的是一样的,存的是指向名称字符串的rva或者一个序号

    手工加壳

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

    步骤:
    1. 添加一个区段(文件大小、区段数量)
    2. 将原OEP修改为新区段中的地址
    3. 将代码段异或加密
    4. 在新区段新OEP处,添加异或解密代码

    注意:

    ① 代码段默认没有可写属性,需要修改。
    ② 有随机基址属性的程序会重定位代码,一般我们会去掉这个属性
    如果没有去掉,就需要在壳代码中进行重定位

    具体:

    我们先用没有加壳的demo.exe进行测试
    源代码:
  1. #include <stdio.h>
  2. #include <windows.h>
  3. int a = 100;
  4. void fun(int* num)
  5. {
  6. *num += 20;
  7. }
  8. int main()
  9. {
  10. fun(&a);
  11. printf("hello world\n");
  12. printf("%d\n",a);
  13. //system("pause");
  14. return 0;
  15. }

编译而成的exe是:demo.zip、demo.exe为9kb(release版本)

1. 添加区段

image.png
只使用LordPE,添加完区段,程序是无法运行的,因为虚拟大小、文件大小都是空的
image.png
使用LordPE编辑区段信息
image.png
再使用010Editor添加文件数据
image.png
demo_添加区段.zip、demo.exe为9.5kb,是可以正常运行的

2. 修改OEP,增加OEP代码

原OEP:000011D2
新OEP:17000
修改OEP
image.png

添加代码

image.png
demo添加区段加壳_1.zip
image.png

通过技巧获取基地址再跳转

image.png
demo添加区段加壳_2.zip
image.png

另一种改法

image.png

demo添加区段加壳_3.zip
image.png

关于代码的演化

① 如果直接去掉随机基址,我们可以在新OEP处,直接写代码跳转到原始OEP
image.png
② 我们可以在新OEP处定义出模块基地址,然后再加上原始OEP RVA
image.png
③ 可以在新OEP处通过call pop 组合获取当前指令地址,再减去偏移,计算出模块基址
image.png
以上代码的机器码复制到有随机基址的同一程序同一位置中,同样也是可以正常运行的
image.png

3. 加密代码段

代码段信息
image.png
在010Editor中操作代码段
③ 选中代码段
image.png
④ 异或代码段
image.png
image.png
demo添加区段加密.zip这时候是不能正常运行的
image.png

4. 增加解密代码

由于代码段本身有重定位信息,那么如果加密之后,重定位会出现问题,所以应该去掉随机
基址
40 81 ­> 00 81
image.png

  1. PUSHAD
  2. MOV EBX,0x401000
  3. MOV ECX,0xE00
  4. DEC ECX
  5. XOR BYTE PTR DS:[ECX+EBX],0x15
  6. CMP ECX,0x0
  7. JNZ 0040600B //根据实际的地址改变,跳到dec ecx那条语句的地址
  8. POPAD
  9. MOV EAX,0x12CA
  10. ADD EAX,0x400000
  11. JMP EAX

image.png
image.png

image.png
demo_解密2.zip成功运行
image.png

脱壳

脱壳的目的:

  1. Cracker(破解者) 脱壳、解密、破解
    2. 杀毒引擎(脱壳引擎、反病毒虚拟机) 解密、查杀病毒、扫描特征
    脱壳的步骤:
    1. 找到原始OEP
    一般来说,找到原始OEP或者我们跟踪到原始OEP时,程序都会完成解密操作
    2. Dump内存到文件
    当可执行文件在内存已经完成解密之后,我们将内存中代码数据转储(dump)到文件,就
    可以进行进一步分析。
    3. 修复文件(常见于修复IAT,重建导入表)
    从内存中转储的内存数据代码有一些与原本文件中的内容是不一致的。比如说IAT表,内
    存中IAT表会被初始为函数地址表,而文件中IAT表与INT表内容一致。所以要想让程序
    正常运行,一般都需要修复IAT,因为加壳之后程序一般都会自己去处理导入表、IAT以
    及重定位等。
    image.png
    IAT表在文件中保存的是一个RVA数组,每一项指向指向了函数字符串结构
    image.png
    在内存中,这个RVA数组,被修改为函数地址,每一个函数地址就是之前对应的函数字符串
    的函数
    image.png
    所以从内存中dump出的文件,必须进行IAT修复或者修复导入表。

    脱自己加的壳

    1. 找到原始OEP

    单步跟踪,很容易找到原始OEP

    2. Dump内存到文件

    在原始OEP处进行DUMP内存,原因就是这个时候内存没有做太多的初始化
    image.png
    image.png

3. 修复IAT或者修复导入表

使用ImportREC修复。
image.png