二进制混淆对抗技术研究
一、前言 在软件安全领域,二进制混淆与逆向工程始终处于动态对抗的两端。恶意软件利用混淆技术逃避检测,而安全研究人员则必须突破这些屏障,分析恶意行为或验证程序安全性。本文将从实战角度简述主流混淆技术的实现并给出可能的对抗方案。 二、对抗可执行文件变异 静态分析软件 IDA pro/Ghidra 等,直接以可执行文件 (PE, ELF, …) 作为输入。软件开发者为阻止逆向分析工程师使用相关软件进行分析,可以对编译生成的可执行文件进行变异以干扰静态分析软件加载目标程序, 常见的编译方式有: 加壳 压缩/加密原始可执行文件,并在运行时解压/解密 导入表隐藏 如 PE 的 IAT 表用户导入程序需要使用的外部函数,逆向工程师常常借助外部函数符号推断程序功能 头文件修改 修改如 PE 文件头等加载时必要的数据结构,以阻止静态分析工具加载程序内存DUMP 典型的加壳软件有 UPX,此类软件一般会设法将原始程序A 保存在新构造的程序 B 中,随后 B 在运行时会解压并释放执行原始程序 A,由于原始程序被压缩,静态分析软件无法直接从 B 中开始分析。 对抗此类加壳保护时, 我们有所谓的 “ESP 定律脱壳”: 其假设大部分此类壳采用栈的方式保存程序入口点时的CPU上下文,如 x86 下使用 pushad 之类的指令 在加壳后的程序完成解压或者解密动作后,其可能会为了模拟原始程序刚进入口点时的上下文效果从栈中恢复先前保存的上下文 逆向工程师可以利用硬件访问断点,在开始保存有上下文的栈中地址处设置硬件读断点,如果按预想触发,随后不久就可能看到代码跳转至原始程序的入口点处执行 脱壳的方式主要还是取决于加壳器的做法,有些壳可能只会加密部分代码段,此时他可能利用一些系统API提供的函数来提前在用户代码被执行前完成解密,比如 Windows 下的 TLSCallback,或 C Runtime 提供的init数组等。 二进制加壳使用的主要技术实际上源于静态二进制修改,一般来说你很难对代码段进行修补,会出现很多指令大小,占用空间的问题,所以一般的做法很多都是拷贝代码到另外一处,修补相关偏移等,所以他仍然需要在原始代码区域布置 jmp 等跳转,另外有些加密壳任然会保留原始代码的内存区域,只是将数据加密,所以可以简单通过布置执行断点完成脱壳。 总结来说逆向此类目标应该是利用各种方式接近代码解密完成后,真实程序刚好开始执行的位置,但实际上也不一定需要这么严谨,从分析的角度来看,如果不是需要成功脱壳并将其转化成无壳并可以执行的状态,则无需刻意分析其 OEP 等位置,只要将内存镜像 DUMP 下来后修正其 Header,保证 IDA 能加载分析即可。 DUMP 镜像的修复主要需要考虑的是 Header 的映射字段部分,需要将其Raw Addr调整至符合内存镜像的 Virtual Addr 处。...