CTF Reverse逆向学习之SMC动态代码加密技术,题目复现(NSSCTF)([网鼎杯 2020 青龙组]jocker)

SMC简介

SMC,即Self Modifying Code,动态代码加密技术,指通过修改代码或数据,阻止别人直接静态分析,然后在动态运行程序时对代码进行解密,达到程序正常运行的效果。

SMC的实现方式有很多种,可以通过修改PE文件的Section Header、使用API Hook实现代码加密和解密、使用VMProtect等第三方加密工具等。关于具体的实现方式可以参考合天的文章:探究SMC局部代码加密技术以及在CTF中的运用 - SecPulse.COM | 安全脉搏

CTF中的SMC

SMC一般有俩种破解方法,第一种是找到对代码或数据加密的函数后通过idapython写解密脚本。第二种是动态调试到SMC解密结束的地方dump出来。

SMC的实现是需要对目标内存进行修改的,.text一般是没有写权限的。那么就需要拥有修改目标内存的权限:

  • 在linux系统中,可以通过mprotect函数修改目标内存的权限
  • 在Windows系统中,VirtualProtect函数实现内存权限的修改

因此也可以观察是否有这俩个函数来判断是否进行了SMC。 

CTF 题目复现

[网鼎杯 2020 青龙组]jocker

文件先查壳,无壳,32bit文件,一打开就可以发现VitualProtect函数,这里对内存权限进行了修改,大概率是SMC。

这里的逻辑大致看下,通过scanf让我们输入一个长度为24的flag,再wrong函数和omg。


key = 0x66, 0x6B, 0x63, 0x64, 0x7F, 0x61, 0x67, 0x64, 0x3B, 0x56, 0x6B, 0x61, 0x7B, 0x26, 0x3B, 0x50, 0x63, 0x5F, 0x4D, 0x5A, 0x71, 0x0C, 0x37, 0x66
flag = ''
 
 
for i in range(24):
    if i % 2 == 1:
        flag += chr(key[i] + i)
    else:
        flag += chr(key[i] ^ i)
 
 
print(flag)

这里解出一个flag{fak3_alw35_sp_me!!} 是个假flag。

接着往下看,可以看到encrypt,并且encrypt函数打开出错了。

可以判断是在encrypt处进行了SMC加密,随便下个断点,用 Local windows debugger调试

根据前面得判断,输入长度为24得flag 123456789123456789123456

这里,F7单步走到00401833的call处,单步进入_Z7函数内

点击__Z7encryptPc 先用U将其设为无定义

接着选中下面所有数据内容,按C转换为代码。

选择Force,再点击yes

之后再点击_Z7进行P定义为函数,再用F5反编译。这里可以得到encrypt函数

下面还有一个函数不要忽略了,同样P定义为函数,再F5反编译。

通过第一个encrpyt函数 逆向一下,


hh = 'hahahaha_do_you_find_me?'
v2 = [0x0E, 0x0D, 0x9, 0x6, 0x13, 0x5, 0x58, 0x56, 0x3E, 0x6,
      0x0C, 0x3C, 0x1F, 0x57, 0x14, 0x6B, 0x57, 0x59, 0x0D]
flag = []
 
 
for i in range(19):
    flag.append(chr(v2[i] ^ ord(hh[i])))

解出flag{d07abccf8a410c   明显还有后半部分,看第二个函数,大致的意思就是%tp&:这五个字符和某个数字异或得到最后的flag,已知是flag的最后一位一定是},那么就很好求了。


v3 = [37, 116, 112, 38, 58]
key = ord('}') ^ 58
 
for i in range(5):
    flag.append(chr(v3[i] ^ key))
 
print(''.join(flag))

这样就可以解出flag{d07abccf8a410cb37a}

[羊城杯 2021]BabySmc

题目打开

在导入表中看到VirtualProtect函数

在最下面可以看到一个错误地址。点进去 看汇编,

大量的数据,可以直接尝试下断点动态调试。用本地win就好

F8步过,进入数据处,这里会提示是否让IDA自己根据RIP生成代码,选no,因为这里IDA已经不能自主分辨主函数的结构了。

No了后,从上方的main头一直选到第一个retn处,按C后选择Force强制转换为代码,之后直接F5反编译就好了。 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sciurdae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值