-
-
[原创]看雪.Wifi万能钥匙 CTF 2017 第5题Writeup
-
2017-6-11 22:07 2932
-
说是一个驱动题,那肯定要释放文件加载驱动。ida载入,查找writefile
的调用,找到sub_401F20
,再向上找下就发现sub_4013E0
(后来发现直接通过字符串就能找到位置),此函数应该是OnInitDiaglog
的重载函数,驱动就是从这里开始释放安装的,先拼接文件名,申请堆空间,调用sub_401F20
从程序资源里加载驱动并写文件,调用sub_401AA0
安装驱动启动驱动最后删除驱动文件。
于是乎直接使用资源查看软件导出驱动文件,ida加载分析。 驱动初始化过程中注册了这第几个函数
memset32(DriverObject->MajorFunction, (int)Dispatch_106EC, 0x1Bu); DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)null_106C8; DriverObject->MajorFunction[3] = (PDRIVER_DISPATCH)read_105A8; DriverObject->MajorFunction[4] = (PDRIVER_DISPATCH)write_1061C; DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)control_1071A; DriverObject->MajorFunction[18] = (PDRIVER_DISPATCH)null_106C8; DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)null_106C8; DriverObject->DriverUnload = (PDRIVER_UNLOAD)unload_10564;
名字我改了,其中control_1071A
作用两个,一个是算法流程控制标志置位,一个是反调试。本来我将此处作了patch,把驱动入口的检验也作了更改,就是过不了检验,不知道为什么,也不知道怎么改,所以我的整个过程,没有完整的动态调试过。
其实驱动真正和程序交互的是read_105A8
和write_1061C
,不知道这两个名是不是和惯例一样,一个是将结果输出给程序,一个是接收程序写入,并作算法运算。
write_1061C
是未变形的md5算法,不用过多分析,只不过在md5算法运算前将输入第0位加1,后面依次加上i(i为字串脚标)。而且这里用了上面说的算法流程控制标志。如置位则进行hash运算,并将输出标志置位。 read_105A8
根据输出标志是否置位分别输出hash结果和定值结果。
再继续往下看程序。
刚才说了驱动和程序的交互方式,所以继续从writefile
或readfile
调用找起,两步就能找到sub_401760
,通过分析,此函数为验证主流程。 主要过程中取输入小写再反序,检查输入为6位,传给驱动,再读回16字节的hash,str2hex,再进行md5计算,结果str2hex,取[2:12]与888aeda4ab
比较。在与驱动交互前也有个DeviceIoControl
调用前面说的control_1071A
,如果驱动不patch,这个调用起了作用,那动态时驱动算法就不计算了,同样输出结果为定值。
后来在验证算法的过程中发现sub_402250
创建了几个线程,定时地进行DeviceIoControl
。
因为驱动没搞好,其它地方patch了也没用。哎。 我将线程patch掉了之后,采取让程序运行,输入6位字串,回车。再用od载入,在与驱动交互的地方DeviceIoControl
前下断,恢复运行,停下后,从栈区找堆地址,然后就能看到上一次的结果,从而验证算法的正确性。
最后就是写脚本跑输入了。这个地方我犯了两次错,白跑了4个小时。后面又有小失误,跑了两小时才出结果,一共21亿的,跑了19亿,失误大了。附上脚本,应该把数字放前面的,这是最快出结果的顺序,或者是先逆序再跑,这也比现在的强。
# -*- coding=utf-8 -*-
from hashlib
import md5
import string
def crack():
table = [i for i in range(0x61,0x7b)]+[i for i in range(0x30,0x3a)]
check = '888aeda4ab'
count = 0
for i1 in table:
for i2 in table:
for i3 in table:
for i4 in table:
for i5 in table:
for i6 in table:
str = chr(i1+1)+chr(i2+1)+chr(i3+2)+chr(i4+3)+chr(i5+4)+chr(i6+5)
if md5(md5(str).hexdigest()).hexdigest()[2:12] == check:
result = chr(i6)+chr(i5)+chr(i4)+chr(i3)+chr(i2)+chr(i1)
print result
return
count +=1
if count % 10000000 == 0:
print coun
if __name__ == '__main__':
crack()
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界