2022全国大学生信息安全竞赛决赛 Re —— analgo
前言
本来想练习一下Go
的有关题目的,不知不觉就找到了这个…被硬生生暴打,坐牢几天后想到为什么不可以直接使用爆破反正也就42
位flag
,最坏的情况下也就是98的42次方
(不会真的有人打开输入关闭去这样爆破吧…),简单的找了点参考,发现和今年还是去年的一个hgame
的题目有点相似,hgame
的那个题目叫hardasm
,看官方的wp
看的头大…但是校外的一个师傅给出了subprocess
进行爆破的一种方法,相当于用python
模拟我们输入并获取结果…网上没找到太多的关于这个的资料,于是只好对着校外师傅的脚本简单改改
简单分析
刚拿到题目,光是看名字似乎就知道是分析Go
了,建议使用IDA 7.6
及以上的IDA
进行反编译,GO
的主函数与我们常接触到的C/C++
不太一样,有一些奇妙的特性,像是主函数是main_mian
,传入字符串时是一个结构体,结构体里面是一个指针和一个int
类型的字符串长度,也因为这些奇妙的特性导致GO
逆向向来不太好进行
输入字符串
找到main_main
,就可以推断出来我们需要输入的长度
加密部分
可以看到程序使用一个qmemcpy
将对应的opcode
赋值给了v27
,同时下面启动main_anal
函数,不难猜测出其就是我们的主要加密部分,进入该函数可以看到多个if
块,一会if
这个if
那个同时还有v10
这些控制if
块是否执行,整个虚拟机运行部分十分混杂,特别难看(也有可能是我太菜了)
对此我们结合之前所提到的subprocess
想是否我们可以直接对每一位进行爆破?因为程序下面有对应的比较语句,我们是否能像hgame
的程序一样将对应的程序部分patch
,将我们加密后的数据输出,然后与正确的进行比较,当输出正确一个时会对应上一个加密后的数据,通过这个方式进行有目的性的爆破处理
爆破测试
我们可以多次进行尝试输入,因为flag
头可以确定是flag{}
,长度要求为42
,多次的调试进行测试下来我们可以发现一个规律,程序将我们的输入进行两两加密
在发现上述规律后我们便要开始尝试进行patch
对应的输出
修改程序
我们观察到输出是用lea
将对应的偏移地址进行保存到rdx
,我们需要做的便是修改对应的off_XXX
处内的值,起初打算是将这个换成一个寄存器,因为我们可以通过调试发现加密后的输入保存在某一个寄存器上,修改了半天Keypatch
崩了,带着IDA
一起走了…要么就是Keypatch
总是自己将我们改的一个地址修改到另一个地址,好奇怪?
最后我们将目标锁定在了比较的过程中,因为比较中肯定会同时出现flag
加密后的数据和我们输入加密后的数据,在这个地方我们也可以尝试将对应的输入加密保存到一个固定的位置
在之前的if
块中,我们可以发现比较的函数是runtime_memequal()
我们进入函数进行查找对应的比较部分在哪里,最后可以锁定在一个if
块上
切换到对应的汇编
我们将其进行修改后为:
需要注意的是Wrong!
字符串是保存在.rdata
段上的,需要注意一下其是否可写,将对应的段的权限进行修改
修改完毕后我们进行简单的测试一下看看能不能完成输入
可以发现可以将我们的输入加密后进行输出后我们可以开始写对应的爆破脚本了
编写脚本
此处借用hgame
比赛时外校师傅使用的脚本进行魔改
1 |
|
因为前面提到的Wrong!
处的字符串似乎只能存储8
个字节,因此我们需要每次爆破出来后将源程序继续进行patch
,将对应的rsi+8
,同时改变脚本中的ans
最后即可爆破出flag
flag
1 |
|