从0开始写ShellCode加载器0x5-代码混淆
这是从0开始写ShellCode加载器的第5篇文章,文章列表,样本demo已上传到GitHub
尝试了几种公开的源码混淆,软件壳方案,效果并不理想。代码混淆这个点暂时搁置。
免杀技术日新月异,然而除非有巧妙的思路出现,多数情况下只是和杀软标记的特征在做对抗。这个过程有点像绕WAF规则。我们先是将shellcode分离加载,又将导入表中敏感函数自定义,又将url地址采用命令行参数的方式传参给程序。上述这些行为的目的都是规避杀软的特征检测。
代码混淆
然而一般情况下,C/C++程序中的字符串常量会被硬编码到程序中(.data段,也就是数据段),尤其是全局变量最容易被定位到。使用strings命令查看
程序中的函数名,字符串常量一览无遗。尽管我们隐藏了导入地址表,VirtualAlloc等字符串还是在里面的。那么对此有什么解决办法吗?在倾旋的文章中,将”VirtualAlloc”字符串base64编码后传入,调用时再将base64的密文隐式解密。这样程序中只有”VmlydHVhbEFsbG9j”之类的字符串,没有敏感函数名了。
这是一个十分巧妙的方法,但不足之处是要在编写代码时考虑好加密解密的问题,如果能有自动化的工具帮助来完成这一过程就再好不过了。
代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。 代码混淆可以用于程序源代码,也可以用于程序编译而成的中间代码。 执行代码混淆的程序被称作代码混淆器。 已经存在许多种功能各异的代码混淆器。
我想要一个在源码级的代码混淆工具,尝试了很多工具后没有找到满意的。代码混淆只是在静态上加强逆向的难度,对于程序的函数调用,行为等并没有混淆作用。这一块先暂时搁置,未来看一些OLLVM相关的知识。
shellcode混淆
使用msf生成的shellcode也是具有特征的,对shellcode进行处理可以消除特征。最基本的处理方式是异或加密,实现代码很简单。但经过查询资料,我发现异或操作本身也很敏感。于是我想到了自己写一个加密方式。
首先我们来写对shellcode进行加密的程序。在分离免杀中,我已经将shellcode转换成了字符型数组。继续这个思路对数组进行加密。
1 | int main() { |
1 | ------加密前---------- |
把加密后的数组拿出来,再写一个解密加载程序
1 | int main() { |
测试一下效果,轻松过360,被defender乱杀
软件加壳
除了源码级的混淆之外,还有另一种减少特征的方法。杀软检测的编译好的exe文件,一般情况下是不会对照源码进行特征标记的,mimikatz那种著名程序除外。exe中的字符主要是存储在.data段中,如果我们先将.data段中的数据加密,运行时再解密,那么杀软静态面对的是加密后的数据,无法检测特征。
这个过程其实就是软件加壳的过程,市面有很多加壳工具,比如著名的UPXshell。
重新检测加壳后的程序,函数名和字符串都没有了,我们自定义的函数没有了,而且文件体积减小了。并且能正常运行。效果可以说非常好。
然而,UPXshell特征也被杀软标记了,原本杀软不报毒的程序,加壳后反而报毒。同样的还有VMP壳,也被杀软标记,敢加就敢杀。
软件加壳算是复杂技术,免费可用很少,github上直接可以拿来用的也大多数被杀毒软件标记了。
https://github.com/czs108/PE-Packer,这个项目加壳效果不错,只可惜也被杀软标记了。软件加壳比起源码混淆,可以说是一劳永逸。但要熟练掌握PE结构和汇编才能完成。