这场比赛的质量还是不错的,这是肝了一天才做出来的题目,感觉能学到东西,好好记录一下,题目和exp放到附件里面了。
用 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~
如有写的不对的地方,欢迎师傅们留言指正!!