首页
社区
课程
招聘
[原创]看雪CTF 2019总决赛 第六题 三道八佛
发表于: 2019-12-15 00:16 6016

[原创]看雪CTF 2019总决赛 第六题 三道八佛

2019-12-15 00:16
6016

这次的题目还是用的Q3第十题的壳

使用x32dbg调试,依然看到熟悉的操作

image-20191214205722093

image-20191214205851781

在保存完输入的用户名和序列号后便开始解密代码,在解密代码之后依然通过tib重新设置了程序的栈地址(mov dword ptr fs:[4], eaxmov dword ptr fs:[8], ebx),最后通过call eax跳转到解密后的代码

值得注意的是这一次壳自解密的过程中执行的代码都一样,因此怀疑验证算法是在壳多次自解密完成后才执行的

另外一个和上次题目不同的地方在每次跳转到解密后的代码那里,即call eax这个指令在后面有变化,因此在写脚本定位特征时需要多判断一个特征:E801000000,具体见下图:

image-20191214211039531

参考了上次比赛@注册LookLook的脚本,因为我上次写的脚本太冗长了
附件:x32dbg.txt

通过尝试发现壳一共自解密了0x578次,即1400次(比上次少了很多)。于是断到最后一次,再进行操作。因为最后一次修改fs:[8]后还有一次自解密,所以还需要gocode:这个分支中的操作才能到真正的验证算法

脚本执行完后定位到的函数头尾:

image-20191214212359171

image-20191214213435233

然后手动将dump的bin文件末尾一个字节改成c3,即ret,就可以用ida创建函数F5反编译了。附件:dump01.bin dump01.idb

image-20191214213555883

image-20191214213733124

抠出来算法,还需要知道这段算法执行的前后干了什么,调试分析一下

在进入算法前:

image-20191214214433649

esi指向的数据:

image-20191214214707416

算法完成后:

image-20191214214155208

算法完成后esi+0x1B0的位置保存了解密后的数据,然后将解密后的数据同用户名比较,若相同则打印成功

需要注意这里比较用的是repe cmpsb,判断长度为ecx = 0x11,即判断17字节的数据。然后可以发现若用户名不足16位,则默认有填充数据,也就是用户名KCTF最后验证时验证的用户名数据是:4B 43 54 46 00 1A 19 18 17 16 15 14 13 12 11 10。具体如下所示:

image-20191214214324168

附件:FixCrackMe.cpp,FixCrackMe.exe

根据以上逻辑,再将ida反编译的代码优化优化,可以做出一份可独立运行的cpp代码:

优化后的算法看起来就很清晰了,分别将序列号相邻的两个字节拼在一起,然后进行一波看不懂的运算。知道应该输出什么结果后,就可以逆推算法了。

可以发现:

所以

只需要穷举 k_6_5 与 k_8_7,速度就快很多
附件:check_cr.cpp

用z3的道路比较曲折,在后面需要注意的地方有说明
附件:key.py

用z3需要注意的地方:

首先是脱壳,参考上次的,没有什么特别的,改改脚本就完了

脱壳完成后我们先优化代码,然后尝试用z3求解,但是由于对z3的使用不够熟练总是无解

一开始也没注意到用户名KCTF\0后面有默认填充的数据,认为全是0,@ccfer就手动逆推算出来了一个序列号,结果不对,一看才知道有填充数据。因为有了填充数据,没办法手动逆推了

然后@大帅锅和@ccfer优化代码,最终发现只有 k_6_5 与 k_8_7 是变量,@ccfer就写出了爆破代码

到了第二天我们开始研究用z3求解,最终@ccfer找到了错误的原因,完成了用z3解这道题

是的,我的队友们就是这么强大!这就是传说中的带躺吧

图片描述

 
 
 
 
 
 
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2019-12-17 10:32 被KevinsBobo编辑 ,原因:
上传的附件:
收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//