前言:

​ 这场比赛的质量还是不错的,这是肝了一天才做出来的题目,感觉能学到东西,好好记录一下,题目和exp放到附件里面了。

一、分析main函数逻辑

用 ida7.5 定位 main 函数,先分析程序的主要逻辑

特别难看,完全不像一道正常的逆向题,还是先看看运行的

结果,通过字符串定位法看函数

然后 ida 发现压根没有这些字符串???

盲猜应该是运行时动态解密出来的字符串(以前遇到过通过 异或自解密的字符串)
没关系,继续看 main 函数,尝试优化一下,搞清楚逻辑 Jmpout 红色字体那里我们看汇编

c 一下转成代码,然后再 f5 看看

解析出来了一部分了,还有 jumpout,同样的做法继续......... 最后得到完整的 main 函数代码:

这里有很多常量运算没有被优化的,可能是出题人故意这么 搞的,加大分析难度,比如第一个 if 那里:

可以通过动态调试直接看==比较的是什么值,也可以直接将 qword 那个常量值改成 const 类型,让 ida 自动优化:

发现效果很不错哦!后面的 for 循环那些同样用 const 的方 法继续搞一波操作............

然后通过 ida 动态调试看结果的方式,分析函数的功能并做 好函数名的注释,最后得到完整的能看的程序,截图如下:

继续

二、加密算法分析

这里 aes 算法是通过 sbox 的特征看出来的,在 data 开始的 位置那里找到的 sbox:

这里先说下我是怎么看出来那个 sha256 的,其实一开始也没看出来,因为找 table 也没找到,不像 aes,然后我就一步步动态跟了下函数的具体实现(确实需要耐心):

发现那个某个加密算法有点可疑,继续跟踪(然后就是一句好家伙!看不懂):

差点直接关闭 ida,这移位运算移来移去,还有&,还有异或, 还有 for 循环一直内卷,啥玩意?没见过这个算法,盲猜 tea、 sm4、md5.....结果都不是(自闭)。 然后动态调试过程中,我无意间看到了一个 table 的初始化:

于是跟踪进去看了下,解密出来的 table 数据(v51 那个 table) 拿去谷歌了一下(可以自己动态跟踪下数据),于是发现是

sha256,好家伙!学到了学到了,居然来个隐藏 table 的骚操作~

于是这块算是解决了,第一部分就是输入 64 位 flag,然后每 4 位进行 sha256 得到 32 字节,总共 512 个字节。下面继续 分析:

这里的是 random 的初始化,可以动态调试获取数据,但是 发现没卵用。。。继续分析

这里 table 的初始化,动态直接提取加密完的 table值。

继续分析:

这里有个 buf1 的赋值,用到了前面的 table,动态发现其实

就是:

buf1[ii+0x100*m]=table[buf[ii+0x100*m]]

继续:

这里根据上面初始化的 random 数据,进行了 v28 的 table 数据赋值,可以看成常量也可以动态提取 v28 那里的东西, 但是我没管了,因为常量最后都可以在最关键的地方用上, 继续分析:

这里就是最关键的逻辑了,对 buf1 再次进行赋值,用到了 v28 那块的内容,所以这里我们可以动态调试直接提取出来 v28 那边的内容,因为每次 for 循环,v28 偏移处都会生成一 个表,所以这里需要提 16 次(恶心的提取,我用 lazyida 动态手动提取的,每次 256 个字符,师傅们可以试试 idapython 应该会快一些?)
我把 v28 那块的数据命名为 Another_array,在 python 脚本里面有。 然后同样动态优化一下这块的操作:

buf1[ll+0x100*m]=2*((buf1[ll+0x100*m]^0xff)&another_array [n][ll])+buf1[ll+0x100*m]-another_array[n][ll]
buf1[ll+0x100*m]+=ll

继续分析:

最后就是 memcmp 比较 buf1 和 buf2,很明显 buf2 就是密文, 直接动态调试 aes 自解密得到。
最后相同就会输出 you get the flag。这里为了方便看。我把整个逻辑和过程放到了 fake.c 中,附件里面有,自己写的伪代码,方便分析而已,然后开始解密。

三、解密脚本书写

从后往前分析,得到了密文,也就是加密后的 buf1 的值已 经知道,看下算法:

不难看出来,这是点对点加密,也就是单一加密互不影响, 这时我想到了爆破法!
我先写了这个算法的 python 实现:

然后根据这个进行爆破脚本书写:

第一轮 256 是 crypto[i]==k,第二轮 256 是 crypto[i+256]==k, 这里是因为当时已经算到了第二步了没改,可以自己调回去, 通过密文,我们可以得到两部分的 kkk,合并就是进行 buf1赋值前的值了,这里需要将其转成字符串形式,同时将单个的补 0,处理一 下:

得到的是一长串的字符串,然后利用正则表达式进行每 64 个字符(32 个字节)切割:

得到 sha256 加密后的密文,最后每 4 个 flag 的字节进行 sha256 的爆破(可见字符域):

脚本大概要跑个 7 分钟,最后成功拿到 flag~

四、总结

1、身为一个pwn手,要补补自己的逆向基础(我连sha256都没直接看出来.......)
2、做逆向非常需要耐心,动态调试结合静态分析时做题的关键,有时也需要猜的成分
3、出题人的思路不错,将关键性信息,例如字符串和table表格通过先加密的方式隐藏起来,然后动态运行时自解密,可以达到抗逆向分析的目的
4、这题采用了一些混淆的方式加大了分析的难度,需要手动一步步改好代码
5、伪代码+函数注释的方式可以加快逆向分析的速度

如有写的不对的地方,欢迎师傅们留言指正!!

white give.zip (1.437 MB) 下载附件
点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖