论坛首页 密码学讨论区 阅读主题

ASProtect2.56脱壳分析及实例

430 浏览 1 回复
#1 楼主 2026-06-01 21:09:02
ASProtect 是远古四大猛壳之一。自 2010 年发布 ASProtect SKE 2.78 后便停止了更新。本文将分析其 2.56 版本。读者可以通过以下方式获取该软件:在看雪论坛的工具板块下载,也可以点击这里进行下载。Stolen code 和 IAT 加密是 ASProtect 壳的显著特点。接下来,让我们一起探讨和学习。  通过未加壳文件的 OEP 地址来定位加壳文件中的 OEP 位置,并在此处设置硬件执行断点。当程序停在原始 OEP 后,注意观察 esp-0x18 这个位置。   点击 0xC514F7 并按下 Enter 键进入汇编窗口(如下图)。其中 call 0xC5066C 是最终跳转到 OEP 的函数。因此,可以提取周围的特征码来定位到该位置。注: 0xC514F2地址位于VirtualAlloc第二次申请大小为0x60000的内存区域,其相对位置为:0x414f2。  当程序运行到壳的入口时,在代码区的起始地址设置硬件写入断点。解码完成后,在代码区再次设置内存访问断点。按 F9 运行,会断在如下位置:   接着进行回溯。在回溯过程中,程序可能会跑飞直接运行,记录下来哪个函数跑飞的,然后再次调试并进入该函数。通过这种反复的过程,无需回溯太远,最终停在地址 0xBF14F2(如下图)。注意观察 esp+0x14 这个位置,在0x3470000地址下硬件执行断点。注: 0xBF14F2地址位于VirtualAlloc第二次申请大小为0x60000的内存区域,其相对位置为:0x414f2。 按 F9 继续运行。当进入地址 0x3470000 后,经过一系列解码操作,最终获取到真实 OEP 的确切地址。下方箭头所指的 jmp eax 指令即为跳转到真实 OEP 的指令。  在使用 ASProtect 进行程序保护时,即使没有勾选任何保护选项,该壳仍会默认对 IAT 进行加密处理。本节将对 ASProtect 的 IAT 加密机制做一个简要的分析,并给出一个有效的 IAT 表修复方案。破坏原始IAT结构。ASProtect会抹去PE头中的Improtect Table目录项,以及导入表中DLL名称和函数名的字符串。动态加载API。通过LoadLibrary和GetProcAddress来动态获取API地址,关键API的调用会被替换为跳板代码地址,伪代码示例如下:    以上便是 IAT 加密的大致流程。此外,IAT 加密的另一种方式是动态解密 API 地址。即跳板地址并不直接跳转到 API 的地址,而是根据加密的 API 标识符跳转到壳的解析逻辑。解析逻辑获取真实的 API 地址后,将其存储在壳分配的堆内存地址中,然后将该地址回填到 ASProtect_Resolver。执行权随后返回到 call 指令处,像第一种方式一样调用 API。伪代码示例如下:  要修复 IAT 表,首先需要找到加密的位置。在获取 OEP 入口后,定位到一个需要填写跳板地址的 call 指令(见下图),并设置硬件写入断点(注意要四字节对齐,否则断点会设置失败),然后重新开始调试。    在断点触发的位置,向上追踪执行流程,即可定位IAT加密的实现代码。只要确定 IAT 表的三个关键要素(函数名称、函数地址以及回填地址),并在关键位置设置硬件执行断点,收集到与 IAT 表相关的必要信息后,便可完成对 IAT 表的修复。以下展示的是 IAT 表两种加密方式的关键位置代码。IAT加密的第一种方式:  IAT表加密的第二种方式:收集到的 IAT 表数据可以回填到原 IAT 表的空余位置,从而完成 IAT 表的修复。  如何确定原IAT表中的空余位置?  首先,需要获取程序初始化时的 IAT 表数据。当程序运行到 OEP 时,再次获取当前 IAT 表数据,并与初始化时的数据进行对比,就能识别出 IAT 表中的空余位置。  寻找初始化 IAT 表数据的具体方法:只需确定哪个 DLL 的导出表函数地址最先被填入 IAT 表中,然后在相应的 IAT 表地址处设置硬件写入断点。再次开始调试,当断点触发后,向上追踪执行流程,便可定位到初始化IAT表数据的实现代码(见下图)。  勾选此选项,加壳程序会加密资源节内容,但在执行流转移至原始入口点(OEP)前会自动解密。如遇脱壳后资源显示问题,新建节区转移资源即可解决。此选项作用似乎不大。此壳有三种方式检测程序是否被调试,分别如下:注:fs:[0x30] 指向线程环境块(TEB)的基址。在 TEB 中,偏移量 0x2(即 fs:[0x30] + 0x2)处的字节是一个标志,用于指示当前进程是否正在被调试。  校验保护主要包括内存校验和文件校验。内存校验会实时检测关键代码段是否被修改。对抗内存校验的最简单方法是尽量避免使用软件断点。文件校验则用于验证磁盘文件是否被篡改。以下对文件校验做一个简单的流程分析:  壳程序首先调用 CreateFile 函数打开文件,然后通过 CreateFileMapping 创建映射对象,最后使用MapViewOfFile 将其映射到内存中。映射文件的所有字节会被分成多段,并通过 MD5 算法进行处理。整个处理过程实际上是在解码跳转到 OEP 的那段代码数据(如上文中寻找 OEP 入口的以 0x3470000 地址开始的代码数据)。文件中的每个字节都相当于一个密钥,因此,只要磁盘文件被修改,最终解出的那段代码数据必定会出错。此选项勾选后没有效果,不知是否是破解版本的问题?模拟标准系统函数,不知是何意?分析勾选了此选项的被保护程序时,并未遇到显著的障碍。  高级输入表保护与 IAT 加密的第二种方式类似,唯一的区别在于解析出的 API 地址存储在壳分配的堆内存中,而不会回填到跳板代码处,每次解析后直接运行。此外,解析 IAT 表有两条路径(见下图),因此需要在这两条路径的相应位置设置硬件断点,用来收集导入表函数的地址。    勾选了此选项后,运行被保护程序时,会弹窗以下的输入窗口:    可以随意输入一些字符串,然后调试观察。要绕过此保护,只需在GetDlgItemTextA函数下断,然后返回用户地址。可以看到,正如下图所示,该保护有哈希比较的验证机制,如果哈希值相等,则不会跳转。    除此此外,还有另外两个位置需要改变跳转流程才能绕过此保护。可以通过单步调试来找到这两个关键位置。第一处,跳过:  第二处,不跳:    要使用此功能,请勾选“使用激活密钥”选项,然后在密钥栏中填写注册名,最后点击“创建”即可生成注册码。  注册码生成操作:    勾选了此选项并生成证书后,运行被保护程序时,会弹窗以下的输入窗口:    输入任意名称和注册码,如果输入有误,将会弹出一个错误窗口:    绕过这个注册窗口非常简单。只需在 MessageBoxA 函数处设置断点,然后回溯执行流程找到关键跳转并跳过它,即可成功绕过注册验证。  要启用激活密钥属性,必须选中“使用激活密钥”选项。此外,通过“帮助 -> 注册”可以获取密钥栏中的硬件ID。激活密钥属性是“使用激活密钥”保护策略的一部分,因此一旦绕过“使用激活密钥”选项,这个保护也将被绕过。  获取硬件 ID 的

...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-286248.htm
#2 2026-06-01 21:09:02
太牛了,如果能对细节更详细点就好了

请登录后参与讨论

立即登录 注册账号