前言
在上一节中我们分析了栈指针平衡和花指令,它们往往会在中等难度的二进制题目中出现。接下来分析一下另外的两种常用反静态分析的方法,还是和往常一样,我们会用真实的CTF赛题来剖析其原理,希望大家可以真真实实地自己动手操作起来。
第三节 SMC自解码
什么是SMC?
SMC(Self-Modifying Code)(自解码),可以在一段代码执行前对它进行修改。常常利用这个特性,把代码以加密的形式保存在可自行文件中,然后在程序执行的时候进行动态解析。这样我们在采用静态分析时,看到的都是加密的内容,从而阻断了静态调试的可能性。
SMC的执行流程如下:
对SMC有个大致的理解,为了更好的理解这种反静态调试手段,我们用CTF赛题来感受一下,并在实战中找到解决这种反调试的方法。
SMC题目实战
(1)静态分析
我们分析的题目为“北邮杯”的一个宁夏是哪个题目,在附件中我会上传该题目
首先我们还是用IDA分析一下,看看有没有有用的信息可以给我们利用。
我们很轻松的反汇编出伪代码,看看逻辑,并不是很难。从中我们获取到三个信息点
(1)、输入的长度为28(不过这和我们理解SMC没有关系)
(2)、图中有一个异或处理,然而处理的不是输入的内容,而是一个数组
(3)、在最后竟然对这个看着像数组的东西进行传参并对输入的内容进行处理。能够传参的肯定是函数,按照惯例我们会分析这个函数。
当我们跟进这个函数的时候,我们发现这个函数是这样的:
一大串的数据,根本就不是函数,我们也就无法分析这个函数,进而我们不知道对我们的输入做了怎样的处理。
这就是典型的对某段代码进行了加密处理,上面的异或操作既是加密操作也是也解密操作,这样我们静态分析就进行不下去了。这样的情况就是SMC自解码问题。
PS:运用SMC躲过杀毒软件的查杀或者迷惑反病毒工作者对代码进行分析,同时也是一种保护代码的方式。SMC学得好,可以自己写怎样加密我们的代码,(后面我会单独开文章来讲《怎样写自己的SMC》)。
在CTF比赛中,遇到这样的典型问题,我们就只能放弃静态分析,采用动态分析,因此接下来,我们就来动态分析看看,到底和静态分析有什么不同。
(2)动态分析
我们直接用ollyDbg,找到主函数。就开始单步执行,看看都做了什么
大部分的逻辑就是下面注释的地方,我们需要关注的重点在于找到处理输入函数的地方,看看在解密后的那个函数是怎样对输入内容进行比较或者变幻的。
当运行到这个地步的时候,我们就发现函数快运行到结束了
我们发现,有一个地方很可疑,在函数结束之前,调用了EAX,其实就是解密后的函数。这个地方就是我们静态分析想要分析的地方。因此,在这里我们就可以跟进去。因为现在那个数组经过解密后已经是一个函数了。
进入之后我们就发现了比较的指令。看看比较的内容,翻译一下就是BUPT{,这就是输入比较的前五个。但是我们发现这个函数又快要结束了,但是这个场景有点熟悉,这个地方又是SMC的运用。然后呢,我们要分析出这个题目,就需要跟进去。这就是应对SMC自解码处理的程序分析步骤。
至于这题的详细题解,可以自行百度。我会将题目上传在附件中。
小结一下:
SMC自解码,可以针对部分代码进行加密,在运行到这段代码时,就对该段代码解密。 当我们遇到这样的题目就可以采取静态分析与动态分析结合的方式。在后面的文章中我会单独写一篇如何编写SMC。
第四节 MOV混淆
MOV这种混淆是怎样产生的呢?剑桥大学的Stephen Dolan证明了x86的mov指令可以完成几乎所有功能了(可能还需要jmp),其他指令都是“多余的”。受此启发,有个大牛做了一个虚拟机加密编译器。它是一个修改版的LCC编译器,输入是C语言代码,输出的obj里面直接包含了虚拟机加密后的代码。如它的名字,函数的所有代码只有mov指令,没有其他任何指令。这个加密编译器在网上是开源的项目。
这里是这个编译器开源项目的地址,有兴趣的小伙伴可以配置来玩玩。
https://github.com/xoreaxeaxeax/movfuscator
我们今天的主题是分析CTF中的movfuscator混淆的处理方法?
这种题目的特征就是:汇编代码的汇编指令几乎全部就是MOV
其编译的效果就像下面这样:
这样的题目,我们几乎无法直接阅读汇编代码,因此,我们只能另辟蹊径
下面我们分析一道CTF题目:
AlexCTF 2017的re
具体的详解请自行百度。今天我们讨论的仅仅是MOV混淆。
脱完壳反汇编后,我们发现如下场景:
除了MOV指令就只有call,这样我们是无法阅读这样的汇编代码
我们直接查看一下字符串
看到这个我们就分析,字符串的提示,我们就看看错误提示
查看一下有什么地方调用了这个错误提示的这个函数:
这么多都调用了这个打印错误信息的函数,因此我们就想,这里的每一条错误提示中肯定会是一个输入的比较。经过mov混淆后,比较语句就被拆分成为多个,一一比较,然后比较到什么地方,不对就会立即报错。
我们就从最后的报错信息分析走,看看有没有标志性
从这里一一往上找,按照CTF的题目输入要求,最后一定是“}”。我们往上寻找。
果然发现了这样的符号。继续往上找。
每一段比较,我们都可以找到这样的语句。因此我们大胆的猜测,R2后的操作数就是我们想要的结果。
于是我们就全局搜索一下R2,我们就可以得到我们想要的
但是,我们发现,做这样的题目感觉完全是凭借眼睛来看,没有什么技巧可言。在此,我先总结一下:
1、 字符串的搜索是给我们最好的提示。
2、 MOV混淆是不会混淆函数的逻辑的。因此函数的逻辑还是不变的。
3、 大多数汇编代码的意思是可以猜测的。可以大概推测出具体操作了什么。
在这里我提供一个开源的工具,是针对这的MOV混淆的工具
地址:https://github.com/kirschju/demovfuscator
这个工具可以很好的帮助我们分析MOV混淆。
小结一下
第三节讲的是SMC自解码问题,自解码问题在CTF比赛中还是比较常见的,主要意图是在考察动态分析能力。但是SMC自解码问题还有一种解法就是待全部SMC解码后,dump出来进行静态分析。而第四节讲的是MOV混淆,这种混淆显然不会是人工汇编出来的,是直接采用工具混淆。这样的弊端在于,不会有变化。但是同样也是有很好的利用效果。这样混淆的方式在面对复杂的结构是就很有效果。在实际的软件逆向中,可以几种反静态分析方法一起用,相互辅助。
在下一节中我们会讲OLLVM混淆,还有涉及一些其他的反静态分析的技巧。