首页
社区
课程
招聘
[原创]看雪CTF2017第五题 独行孤客CrackMe的writeup
发表于: 2017-6-11 07:28 3901

[原创]看雪CTF2017第五题 独行孤客CrackMe的writeup

2017-6-11 07:28
3901

驱动不大,才20多个函数。

从入口开始分析。

用来与应用层通信

主要有三个,read/write/ioctl。

先看f_DrvWrite_1061C,通过irp获取到上层传入的数据,然后通过104b6获取某个输出存入全局变量g_READCC(根据read的分析,可以知道长度为4的4字节数组)。

进入104b6内部,key是个16字节数组,初始化0。然后将上面传下的数据拷贝到key中,长度需要小于16。然后将key进行一下变换。 key[0] ++(反调试标志为1,后面再说),其他key[i] += i

接着通过下面三个函数对key进行计算,输出结果

进入108b2一看就猜测是md5计算,f_Md5_hexdigest将计算结果(32字节字符)保存到md 5字段中输出,设置计算标志。也就是大致确认write是计算md5,然后保存到g_READCC

接着看f_DrvRead_105A8,看刚才的计算标志是否为0,为0就初始化g_READCC一段值(不知道作者意图,迷惑cracker?),如果计算标志是1,就直接返回计算的结果,然后该值返回到用户空间。也就是如果通过write计算了md5,这里就是获取md5计算结果。

最后看f_DrvControl_1071A,支持多个命令号,但只有222004h有用。设置反调试标志为1,然后进入10486看看

枚举进程找到当前进程的eprocess(其实没必要枚举把),置eprocess->DebugPort = NULL,让应用层调试器失效,达到反跳试效果。

这里猜想一下,如果破解者通过应用层patch,不发送222004h命令来解除反跳试的话,那么这里的反跳试标志就是0,然后在write中计算md5时,对key[0]就不会做++操作,那么上层就会获取到一个错误的值,从而影响破解。

首先想到的是将驱动文件patch,也就是DebugPort置零的指令nop掉

通过reshacker将驱动资源导出来,然后hex编辑工具修改104A9的内容(文件内存对齐一样)为7个NOP,然后再将patch驱动文件导入到exe中。

会提示驱动加载失败,可能有校验,不再细跟。

没办法,为了让od能够调试,我写了个简单驱动,在本驱动加载时,将104A进行patch,通过反跳试。

既然知道有驱动了,先找找释放和加载驱动的代码,通过 FindResourceA和CreateService即可定位(不再详述),注意到的是,驱动加载成功会设置一个标志,用于后面验证的判断

然后再找和驱动通信的代码,通过DeviceIoControl找到调用222004命令好的代码。通过创建一个线程,循环调用该接口来清零DebugPort

按理说这里可以patch掉来去掉反跳试,但就会出现我前面分析提到的问题。

通过WriteFile找到调用read/write的位置,也就是计算md5和获取md5的位置。

f_CalcKeyMd5_401D50回溯一层就是输入key回车的响应函数。 这里先通过UpdateData(1)获取输入数据,然后拷贝到局部变量

然后输入进行小写和反转变换

判断输入长度是否为6,不是退出,清除输入,并通过IsDebuggerPresent检查是否在调试(OD直接过),是调试也退出,清理出输入。

满足长度要求,再看驱动是否加载,再调用f_CalcKeyMd5_401D50计算md5. 也就是调用驱动获取md5,记为KeyMd51.

接着下面两个函数,先调用f_GetStrMd5_401920(应用层的Md5,通过调试可以很快确认,内部也有md5特征)计算KeyMd51的Md5,记为KeyMd52,然后调用sub_415A78截取KeyMd52从第3为开始的10字符,记为KeyMd53。

最后KeyMd53与888aeda4ab比较,成功提示Success^^!

总结算法:

由于MD5hash无法逆运算,只能爆破了,刚开始忘了题目key只能是数字和字母,结果我跑了全字符,跑了1天多....没出来,卡hi是怀疑自己

后来改成了数字字母,终于得到答案 su1987

爆破代码如下:

最后结果


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回