9

[原创]看雪.Wifi万能钥匙 CTF 2017 第5题Writeup

poyoten 2017-6-11 22:07 745


说是一个驱动题,那肯定要释放文件加载驱动。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_105A8write_1061C,不知道这两个名是不是和惯例一样,一个是将结果输出给程序,一个是接收程序写入,并作算法运算。

write_1061C是未变形的md5算法,不用过多分析,只不过在md5算法运算前将输入第0位加1,后面依次加上i(i为字串脚标)。而且这里用了上面说的算法流程控制标志。如置位则进行hash运算,并将输出标志置位。 read_105A8根据输出标志是否置位分别输出hash结果和定值结果。

再继续往下看程序。

刚才说了驱动和程序的交互方式,所以继续从writefilereadfile调用找起,两步就能找到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()


最新回复 (0)
返回