1、课程目标
- 回顾整个逆向分析章节的核心知识
- 通过综合实战巩固学习内容
- 掌握完整的逆向分析流程
- 为后续安全研究打下基础
2、知识回顾
| 课时 |
核心内容 |
| 课时01 |
定位目标功能、断点技术、字符串搜索 |
| 课时02 |
调用约定(cdecl/stdcall/fastcall/thiscall) |
| 课时03 |
if-else识别、条件跳转、短路求值 |
| 课时04 |
switch识别、跳转表分析 |
| 课时05 |
循环结构识别(for/while/do-while) |
| 课时06 |
数组与指针识别、内存寻址模式 |
| 课时07 |
类与对象识别、vtable分析 |
| 课时08 |
构造/析构函数识别 |
3、综合实战项目
3.1、项目1:密码验证程序分析
// 目标程序 - 分析并绕过密码验证
#include <stdio.h>
#include <string.h>
int CheckLicense(const char* serial) {
// 算法: 第1位 + 第3位 = 第5位
// 且长度为10
if (strlen(serial) != 10) return 0;
if ((serial[0] + serial[2]) % 10 != (serial[4] - '0'))
return 0;
return 1;
}
int main() {
char serial[64];
printf("Enter serial: ");
scanf("%63s", serial);
if (CheckLicense(serial)) {
printf("Valid license!\n");
} else {
printf("Invalid license!\n");
}
return 0;
}
/*
分析步骤:
1. 搜索字符串 "Valid" 定位成功分支
2. 向上找到比较/跳转逻辑
3. 分析CheckLicense函数
4. 理解序列号算法
5. 生成有效序列号或Patch程序
*/
3.2、项目2:类结构还原
// 根据以下反汇编还原类结构
/*
sub_401000: ; 构造函数
mov eax, ecx
mov dword ptr [eax], offset vtable_401200
mov dword ptr [eax+4], 0
mov dword ptr [eax+8], 0
mov dword ptr [eax+0Ch], 0
ret
sub_401020: ; 成员函数
mov eax, [ecx+4]
add eax, [ecx+8]
mov [ecx+0Ch], eax
ret
vtable_401200:
dd offset sub_401040
dd offset sub_401060
*/
// 还原结果:
class Unknown {
private:
int field1; // +0x04
int field2; // +0x08
int field3; // +0x0C
public:
Unknown() : field1(0), field2(0), field3(0) {}
void Calculate() {
field3 = field1 + field2;
}
virtual void VFunc1();
virtual void VFunc2();
};
3.3、项目3:循环算法还原
// 从反汇编还原算法
/*
sub_401000:
push ebp
mov ebp, esp
mov esi, [ebp+8] ; arr
mov ecx, [ebp+0Ch] ; count
xor eax, eax ; result = 0
test ecx, ecx
jle done
loop_start:
mov edx, [esi]
cmp edx, eax
jle skip
mov eax, edx
skip:
add esi, 4
dec ecx
jnz loop_start
done:
pop ebp
ret
*/
// 还原结果:
int FindMax(int* arr, int count) {
int result = 0;
if (count <= 0) return result;
for (int i = 0; i < count; i++) {
if (arr[i] > result) {
result = arr[i];
}
}
return result;
}
3.4、项目4:完整程序分析
// 综合分析流程
/*
1. 初步分析:
- 查看PE信息(导入表、导出表)
- 确定程序类型(GUI/Console)
- 查看字符串表
2. 定位关键代码:
- 通过字符串搜索
- 通过API断点
- 通过交叉引用
3. 分析函数:
- 识别调用约定
- 识别控制结构
- 识别数据结构
4. 还原算法:
- 理解数据流
- 还原逻辑关系
- 编写等价代码
5. 验证结果:
- 动态调试确认
- 对比行为是否一致
*/
3.5、项目5:Patch技术
// 常见的Patch方法
/*
1. 跳转改NOP:
原: jnz fail_label
改: nop nop (90 90)
2. 跳转条件反转:
原: jz success (74 xx)
改: jnz success (75 xx)
3. 改返回值:
原: xor eax, eax (33 C0)
改: mov eax, 1; ret (B8 01 00 00 00)
4. 改比较值:
原: cmp eax, 1234
改: cmp eax, eax (39 C0, 永远相等)
5. 直接跳过:
jmp over_check (EB xx)
*/
// x64dbg中的Patch操作:
// 1. 在目标位置按空格键
// 2. 输入新的指令
// 3. File -> Patch file -> 保存
4、逆向分析速查表
4.1、常见代码模式
| 模式 |
含义 |
| xor eax, eax |
eax = 0 |
| test eax, eax |
检查eax是否为0 |
| cmp eax, ebx; jz |
if (eax == ebx) |
| lea eax, [ebx+ecx*4] |
数组寻址 |
| mov ecx, obj; call |
thiscall调用 |
| mov eax, [ecx]; call [eax] |
虚函数调用 |
| add esp, N |
cdecl清栈 |
| ret N |
stdcall清栈 |
4.2、IDA快捷键
| 快捷键 |
功能 |
| G |
跳转到地址 |
| X |
查看交叉引用 |
| N |
重命名 |
| Y |
修改类型 |
| H |
十六进制/十进制切换 |
| Space |
图形/文本视图切换 |
| F5 |
反编译(Hex-Rays) |
4.3、调试技巧
| 技巧 |
用途 |
| 硬件断点 |
跟踪内存访问 |
| 条件断点 |
特定条件触发 |
| 日志断点 |
记录但不暂停 |
| 跟踪执行 |
观察执行流程 |
5、课后作业
- CrackMe练习:找一个简单的CrackMe程序进行分析
- 类还原:从真实程序中还原一个类结构
- 算法分析:分析并还原一个加密算法
- 完整分析:对一个小程序进行完整的逆向分析