SMC混淆
SMC混淆
这几天的Hgame和n1CTF都碰到了这个东西,所以专门来学一下。
SMC概念
SMC(Self Modifying Code),自修改代码,一种动态代码加密技术,或者局部加密技术,指通过修改代码或数据,阻止别人直接静态分析,然后在动态运行程序的时候对代码进行解密,达到程序能正常运行的结果。
具体的原理是将需要加密的代码区段单独编译成一个section(段),并将其标记为可读、可写、不可执行,然后通过某种方式在程序运行的时候将这个section解密为可执行的代码,并标记为可读、可执行、不可写。这样,攻击者就无法在内存中找到加密的代码,从而无法直接执行或修改加密的代码。
大概的实现的代码如下:
1 | proc main: |
代码段一般默认权限是不可写的(一般会开DEP保护),所以一般要实现SMC,就会涉及到改权限的操作,那么就会涉及到调用系统API(一般是VirtualProtect)临时赋予内存可写+可执行的权限
所以一般smc的特征就是如下先异或的操作然后进行一个类似函数调用的操作,但因为smc的缘故静态分析的过程函数全部变成了数据的形式:
还有种特征就是系统API的调用(如virtualprotect,linux下为mprotect)来修改内存
总之经过smc混淆后,关键代码部分无法静态分析,只能看到一堆数据
破解方法
第一种方法,既然他对函数代码进行了加密,并且在程序运行的时候会在函数调用之前解密,那么就直接通过动态调试到解密结束的地方dump
第二种方法,就是利用idc脚本将加密的函数直接解密
下面用一道非常经典的smc的例题来练练手,并且用两种不同的方法
网鼎杯2020青龙组jocker
32位无壳,打开之后发现main函数的栈指针不平衡(虽然能反编译,可能是ida版本的问题,但还是先把他的栈指针给修改一下)
如上有两处地方,call调用函数的时候调用前后应保证sp指针的偏移量是相同的,这样才能保证堆栈的平衡,因此快捷键Alt+k将栈指针更改之后就能正常反编译
进入到主函数,首先看到virtualprotect在修改内存,大概率是smc,然后看到wrong函数和omg函数下面有对encrypt函数内存区域那块进行异或操作,基本上可以实锤这是smc
当我们试图进入到encrypt函数的时候发现了报错,然后点击ok进去之后发现这个完全不是函数的样子,下面也是一堆数据,说明这里的smc混淆了我们静态分析encrypt这个函数
破解这个smc的第一种方法,就是写idc/idapython脚本来还原encrypt这个函数,脚本如下
1 | #include <idc.idc> |
运行完脚本之后,要先将整个函数u一下,然后c,然后再p,之后encrypt函数就可以正常反编译了
再将finally函数给转换成代码就可以了然后就可以正常解了
第二种方法就是动调,在调用encrypt的函数的地方下一个断点,因为这里程序运行起来的时候,在函数调用前一定会对这个函数解密,所以我们就在这个时候将对应的内存空间的数据u再c再p,就可以正常地反编译该函数
然后就可以得到相同的效果。
这题其他解密的部分就是简单的异或,以及flag的最后五位需要一点脑洞来异或解密,就不过多的阐述了
总结一下,smc就是自修改代码的技术,一般是通过修改访问内存的权限来对代码段的函数进行异或加密,当然,他会在程序运行的时候进行解密,因此只会影响我们对函数的静态分析。所以破解方法就是动调和写idc脚本两种。