SMC代码自修改
SMC
代码自修改,简而言之,就是程序中的部分代码在运行之前被加密成一段数据,不可反编译,通过程序运行后执行相关的解码功能,对加密的代码数据进行解密,让其恢复正常功能
原理
通过 SMC 代码自修改技术可以实现程序的保护,同时也可以将一些特征代码变形隐藏
- 代码在二进制文件中就是字节码,本身也就是一段二进制数据
- 提前将一部分代码通过某些方式替换为加密数据
- 程序在被反编译的时候,核心代码就是一串数据,无法反编译,而程序在运行的时候又能成功将这段核心代码复原
SMC 示例
以本站的《【攻防世界】BABYRE》这道题为例
- 可以看到程序一开始就使用了一个 182 次的 for 循环对数组
judge[]
进行异或操作,但是在后面,又以函数的形式来调用judge()
- 跟进看到
judge
的内容
形似数组一样的数据,但为什么可以作为函数调用呢?
- 其实这就是 SMC 代码自修改
这里的 judge
本来就是一个函数,只是它的函数内容需要先经过对所有 182 个元素进行异或,异或后才能得到真正的 judge()
函数
for ( i = 0; i <= 181; ++i )
judge[i] ^= 0xCu;
- 但是这种行为 IDA 是不知道的,IDA 以为异或前的
judge
只是一个普通的数组,所以识别成了char judge[182]
的数组
而随着程序执行异或之后,judge
的内容被还原,IDA 又可以将 judge
识别成函数 *(unsigned int (__fastcall **)(char *))judge
了
SMC 破解
还是以本站的《【攻防世界】BABYRE》这道题为例
- 明白了 SMC 代码自修改的原理之后,其实破解方法比较简单
直接按照程序自己解密的逻辑来对数据进行解密即可
比如这里是对 judge
所有的数据进行异或
- 但是
judge
数据量比较大,所以通过 IDA 脚本来实现
shift + F2
打开脚本编辑器,输入代码:
address = 0x600B00 # judge的首地址
for i in range(182): # 进行182次异或并修改IDA中的数据
ida_bytes.patch_byte(address + i, idc.get_wide_byte(address + i) ^ 0xC)
print("Done")
- 可以看到修改前后数据的变化
脚本执行前:
脚本执行后:
- 然后在
judge
的首地址处,使用快捷键 C
将数据生成代码
接着使用 快捷键 P
将代码生成函数
最后 F5
即可看到破解 SMC 后正常的 judge()
函数了
评论