最近做题做到这题,发现不是很难,逻辑很简单,但是对我来说看别人得Writeup学到了非常多。
得到可执行文件.exe,直接用IDA打开,得到如下图,代码已经进行了部分重命名.
其中关键得三个函数已经标出来了,首先是要求我们输入一个长度为6的字符,然后有一个atoi的函数,对第一次的输入进行操作。这个函数是C语言中的一个标准库函数,作用是将一个表示数字的字符串转换为对应的整型数值,也就是说我们一开始应该是输入一个长度为6的数字字符串。
再看下面的if判断语句,如果经过atoi函数处理之后变成数字小于100000,则会结束进程,所以输入的数字必须大于100000。
之后strcat函数是一个C语言中的字符串拼接函数,用于将一个字符串追加到另一个字符串的末尾。所以是输入的6个数字后面拼接@DBApp,之后进行sub_40100A函数的处理,我们进入这个函数看一看。如图
然后是一堆看不懂的代码,调用了一堆估计是Windows API函数,看了别人的Writeup,最关键的函数已经框出来了,我们查阅微软的文档,看一下这个函数的具体用法。
重点关注第二个传入的参数Algid,这里说用于标识要使用的哈希算法,问了AI,Algid的全称是Algorithm identifiers,即算法标识符,开发人员和系统管理员就可以用它来指定在不同的上下文中使用哪些密码学算法,该函数传入了0x8004u,我们点ALG_ID,进去看微软的文档,找到了
是SHA的哈希算法,也是SHA1。所以我们猜测这个sub_40100A函数就是对第一次输入后再拼接的数据进行了SHA哈希加密。加密后与一段长字符串进行比较。这里自然而然就想到了爆破,但是我很少写爆破脚本,不知道该怎么爆破,看看别人的脚本。
import hashlib
string='@DBApp'
for i in range(100000,999999):
#输入大于100000的六位数字
flag=str(i)+string
x = hashlib.sha1(flag.encode("utf8"))
#使用utf-8编码将字符串转换为字节
y = x.hexdigest()
#获取十六进制的散列值
if "6e32d0943418c2c33385bc35a1470250dd8923a9" == y:
print(flag)
break
#输出结果为123321@DBApp
那么第一步我们就搞定了,进入第二部分密码的分析。
第二部分密码的长度也为6,但没有数字方面的要求。然后会将123321@DBApp拼接在第二次输入的后面,然后被sub_401019函数处理,点进去看看。
和上面那个SHA1加密函数相似,但是这里的算法标识符变成了0x8003u,再查阅微软的文档
是MD5哈希算法,而且比较的字符串的长度也为32,符合MD5哈希算法的特征。第一想法当然是直接拿去进行解密,但是解密不了。我们再看下面那一个sub_40100F的函数,点进去如图
又是一堆看不懂的Windows API函数,去微软给的文档再去学习一下,这些代码的含义就是从AAA文件中查找字符,如果函数成功,则返回值是指定资源的信息块的句柄。如果函数失败,则返回值为 NULL。若要获取资源的句柄,请将此句柄传递给 LoadResource 函数。,而SizeofResource应该是计算大小的。
LockResource接收要访问的资源的句柄,如果加载的资源可用,则返回值是指向资源第一个字节的指针;否则为 NULL。然后函数sub_401005接收了主函数里面的拼接完后的总密码,AAA文件第一个字节的指针,和该指针的大小。然后生成dbapp.rtf,我们再点进去看看这个sub_401005函数。
也就是说文件AAA的每一位和总密码的每一位进行循环异或,我们要得到的是总密码的前6位,也就是说总密码的前6位和文件AAA的前6位进行异或之后会得到生成的RTF文件的前六位,看这道题的题目,再联想到Misc方向,经常有关于文件头的题目,我们就去找一下RTF的文件头是什么,先了解一下什么是RTF文件。
RTF,全称为Rich Text Format,即富文本格式,是一种由微软公司开发的跨平台文档格式。它支持在不同的设备和操作系统之间传输和查看,同时能够保留文本的格式和嵌入的图形内容。
在网上找半天找不到一个RTF文件,只能自己用Word文档转成一个RTF,打开看到文件头
所以文件头前六个就是{\rtf1。但是还有个疑问,AAA文件在哪里呢?这里也是学到了一个新工具Resource Hacker,直接把该可执行程序拖进去,如图
然后编写脚本,解出最后的6位答案
rtf = '{\\rtf1'
#注意这里的反斜杠要进行转义
A = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
password = ''
for i in range(len(rtf)):
x = ord(rtf[i]) ^ A[i]
password += chr(x)
print(password)
#输出~!3a@0
然后再打开可执行程序,输入两个密码,会在它所在的文件夹生成一个dbapp.rtf文件,就是在代码中的CreateFileA()函数的实现,如图
我操,真的有点神奇,所以flag就是Flag{N0_M0re_Free_Bugs}
BUUCTF要把Flag改为flag。