首页
社区
课程
招聘
[原创]Armadillo(补充)及实例
发表于: 2025-2-11 22:11 1567

[原创]Armadillo(补充)及实例

2025-2-11 22:11
1567

  这篇文章作为上一篇的补充,并提供一个实例。如果觉得实例中有突兀奇怪的地方,可以参考上篇文章。


高级保护(补充)

① Enable Nanomites Processing(cc保护)

  此壳被称为强壳,其关键在于CC保护。Armadillo 会抽取被保护程序中的一些 JCC 指令,并将判断逻辑移至主程序中。实现方式是将每个JCC指令的第一个字节替换为INT 3 指令。当子程序执行到INT 3 时,会触发断点异常(0x80000003)。主程序在接收到该异常后,会利用 GetThreadContext 函数获取标志寄存器的值,以判断是否进行跳转。最后,再通过SetThreadContext函数设置指令指针(EIP),以控制子程序的执行流。要过掉此保护,难点在于需要花费大量时间解析JCC指令与约定数字之间的映射关系,以及跳转地址的信息。有关详细的过程,可以参考这篇文章:ARMADILLO和NANOMITES


② Enable Import Table Elimination(输入表乱序)


③ Enable Strategic Code Splicing(代码乱序拼接)

  代码乱序拼接是通过提取程序中的某些代码片段,并对其进行混淆处理。当程序执行到被提取的代码部分时,会跳转到指定地址,执行完成后再返回继续执行。这样做的目的是为了防止程序被 dump(内存转储),从而增强保护机制。

在上图中可以迅速识别出,只有两条指令是有效的,分别是"mov ebx ,A"和"push esp"。

以下总结此壳指令混淆的一些特征:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// =========== 特征1========== //
not reg1
...
...
...
not reg1
 
 
// =========== 特征2========== //
xchg reg1,reg2
...
...
...
xchg reg1,reg2
 
 
// =========== 特征3========== //
push reg1
...
...
...
pop reg1
 
 
// =========== 特征4========== //
bswap reg1
...
...
...
bswap reg1
 
 
// ========== 特征5========== //
地址1:    jcc/jmp 地址2
地址2
 
 
// ========== 特征6========== //
地址1:    jcc 地址3
地址2
地址3:
 
 
// ===== 特征7(冗余指令):===== //
xchg/mov reg1,reg1

特征1示例,如下图:

  这些指令的混淆相对简单,因此还原起来也比较容易。如果想要增强混淆效果,可以先对整个函数进行静态分析,提取相应的指令,然后再进行混淆处理。假如处理得当,几乎可以达到无法还原的效果。即使程序被内存转储(dump),分析人员也只能通过补区段的方式进行处理,这将给他们带来极大的困扰。


④ Enable Memory-Patching Protections(防止内存补丁保护)

该保护有以下几项保护功能。

1. 内存完整性检查

  该保护机制会定期检查程序的内存区域,以确保其未被篡改。通过计算和验证内存区域的校验和或哈希值,来检测是否有未经授权的修改。

2. 反调试技术

  保护机制可能会使用反调试技术来检测和阻止调试器的附加。这可以防止攻击者在调试器中修改程序的内存。

3. 代码混淆和加密

  通过混淆和加密关键代码段,使得即使攻击者能够访问内存,也难以理解和修改程序的逻辑。

4. 动态代码生成

  在运行时动态生成和执行代码,以防止静态分析和内存补丁。动态生成的代码通常会在执行后立即被清除,以减少被捕获的风险。

5. 自我修复机制

  如果检测到内存被篡改,程序可能会触发自我修复机制,恢复被修改的内存区域,或者直接终止程序运行。

6. 内存陷阱

  在内存中设置陷阱或诱饵区域,诱导攻击者进行修改。一旦这些区域被修改,程序会立即检测到并采取相应措施。


Ball5(实例)

Ball5来自黑鹰 VIP 破解提高班第 46 课提供的资料。

简介

Ball5是一款桌面台球的作弊软件,有试用次数,主界面如下:

脱壳分析

 经过Detect It Easy查看,是Armadillo壳。

 再用Armadillo find protected工具查看,可以看到,开启了双进程保护。

  因此,可以在WaitForDebugEvent设置断点,触发断点后,取消该断点。接着在WriteProcessMemory处设置断点,以收集回填到子进程代码区的数据。请注意,同一个区域的数据可能会被填写多次,只收集第一次的数据,其余都要忽略掉。这个其实就是绕过高级保护中Enable Memory-Patching Protections(防止内存补丁保护)的动态代码生成功能。在程序运行时,尽量点击所有按钮,以确保相关的代码区能够被解码并收集到。

  对于OEP,当第一次接收到异常调试事件,且异常码为0x80000001时,产生异常的地址就是该程序的OEP地址,参考下图:

  接下来,寻找IAT加密的部分。当收集到相关信息后,重新开始调试。这次,当第一次接收到异常码 0xC0000005 时,可以挂起子进程的所有线程,接着调用 DebugActiveProcessStop 函数以脱离子进程。然后附加子进程,并在 GetModuleHandleA 处设置硬件断点。恢复主线程后,按 Shift + F9 三次,观察堆栈变化(下图所示)。取消断点后,返回用户代码区。

  在相隔不远位置,就能找到关键指令je 1FA612F,把此条指令改为jmp 1FA612F,就可以跳过IAT加密了。

  注意,在执行上面操作时,再往下拉不是很远。在 jmp 246149 处设置软件断点后,再按 F9 运行。当断点触发后,取消该断点,然后将之前的 jmp 1FA612F 改回 je 1FA612F。这个其实就是绕过高级保护中Enable Memory-Patching Protections(防止内存补丁保护)的内存完整性检查功能。

  最后,在 OEP 处设置硬件执行断点。当程序运行到 OEP 后,将收集到的代码区数据复制到相关区域,就可以使用 Scylla 工具进行脱壳了。需要注意的是,Scylla 有时无法准确识别 IAT 表数据的大小,此时需要手动填写IAT表的大小。对于无效的IAT地址,直接剪掉即可。

去框分析

  运行Ball5时,弹出如下窗口,点击 "开始使用" 时,才会弹出主界面。现在需要去掉此窗口,以便在点击程序后直接就能进入主界面。

  启动并调试Ball5,当程序运行弹出上述窗口时,在 DestroyWindow 处设置断点。点击“开始使用”后,该断点会被触发,然后返回到用户空间,回溯即可找到关键位置 0x45EDC5。将je指令修改为 jmp,即可去掉启动窗口。


附件

附件上传的是Ball5程序的安装压缩包。


[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

最后于 2025-2-11 23:24 被舒默哦编辑 ,原因: 更正
上传的附件:
收藏
免费
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册