代码保护和混淆
抵御静态分析
对于二进制程序分析,工具都要先进行反汇编,所以要进行抵御,可以对汇编进行特殊处理来干扰工具的分析
花指令
函数头处增加pushfd,popfd和nop指令
1 | ;常规的函数头 |
插入脏字节并设置跳转
1 | push ebp |
条件跳转来干扰递归下降反汇编器
递归下降反汇编器虽然部分模拟了程序执行的控制流过程,但是并不是真正的运行,不能获取所有的信息,
利用这点插入条件跳转来让其反汇编所有的分支,这样就会导致0xe8被解析为指令,导致错误
1 | push ebp |
例题见逆向做题总结
同时将代码打乱顺序
1 | push ebp |
指令替换
将一些指令替换为另一组相同或相似效果的指令来混淆,虽然程序效果没有变化,但是特殊的指令会让反汇编器出现错误
例如call,ret指令会让反汇编器解析出的函数地址范围和调用关系出现错误
1 | ;call指令 |
代码自修改(SMC)
SMC技术会对程序特定部分在运行时进行特定的处理,并被使用函数指针来作为代码直接调用,属于动态代码加密技术.
常见于壳类程序中,静态分析时IDA等工具会将处理前的部分解析为数据,导致错误.
SMC中会对.text中某块内存的属性进行修改,然后进行解密等操作,让该部分转换为实际可执行的指令.
修改属性常使用VirtualProtect()函数(windows中)和mprotect()函数(Linux中):
VirtualProtect()
1 |
|
lpAddress
:要改变属性的内存起始地址dwSize
:要改变属性的内存区域大小flAllocationType
:内存新的属性类型lpflOldProtect
:内存原始属性类型保存地址
常见的属性类型如下(SMC常用0x40):
mprotect()
1 |
|
- 该系统调用修改起始位置为
addr
,长度为length
字节的虚拟内存区域中分页上的保护 addr
地址必须为分页大小的整数倍,length
会被向上舍入到系统分页大小的下一个整数倍prot
参数是一个位掩码,常见值如下(值分别为1,2,7)
分析方法
动调
下断点调试后,待SMC解密过程结束后,选中包括加密区域的整个函数代码,进行强制分析,然后F5就能得到正确的代码.(例题:[羊城杯 2021]BabySmc)
加密
加密壳程序分为数据加密,代码加密,算法加密
数据加密一般是在合适的时机对程序中已有的数据进行即时的解密
代码加密同理,例如SMC技术
算法加密偏重算法的混淆,模糊与隐藏,例如VM虚拟机保护
反调试
x64dbg和OD使用SharpOD
反反调试插件来绕过反调试.
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 WAHAHA's blog!
评论