查看程序
1. 题目提示要在xp下运行,看了看资源,发现有驱动,将文件提取出来,用PEID的算法插件KANAL扫描驱动,发现有MD5算法:
2. 用OD加载程序CrakeME,下断点CreateFileA,一次断在释放驱动的时候,另一次断在加载驱动的时候:
在CreateFileA 的下一条指令下断点,运行程序,程序直接出错退出。
有反调试,用IDA打开程序,发现了IsDebuggerPresent,这个应该不会导致程序崩溃。
接着找,发现了一个线程:
线程中死循环在发送控制码,打开驱动,找到对应的控制码:
嘿嘿,EPROCESS,最后有个清零的动作,这里就是反调试了吧。没有查这个结构体,据猜测应该是把调试端口清零了。
解决办法:
1.
通过资源工具导出驱动,然后修改驱动中的sub_10486函数(即上图的fantishi_10486):
这样就不会清空端口了。
然后用loadpe修改驱动的校验和。修改方法详见:http://bbs.pediy.com/thread-185490.htm
用winhex修复crakeme,修复后的程序见附件。
2.跟踪流程
跟踪了几次之后,理出来的流程大致如下:
1.sub_4013E0 主要负责释放驱动,启动驱动,还有反调试
2.sub_4013E0 是按下enter之后的处理函数
主要流程:
1)sub_4182FA((CString *)&v7); // 获取注册码
2)sub_4182FA((CString *)&v7); //注册码转小写 CString::MakeLower
3)sub_41830C((CString *)&v7); //注册码倒序 CString::MakeReverse
4) if ( *(_DWORD *)(v7 - 8) != 6 || IsDebuggerPresent() ) 判断注册码长度是否等于6 加反调试
5)Sub_401D50(v1, v3, (size_t)v5); 这个函数主要功能:把获取到的注册码发送到驱动层,计算 hash后载读取回来。
DeviceIoControl 这个地方是个坑,原来以为只是用来反调试的,后续发现它会设置一个全局变量dword_114D8 = 1;
这个变量在驱动层计算md5中要使用,没有这个,每次不管输入的是什么,驱动层返回的md5都一样。
WriteFile 用来发送我们输入的注册码。
ReadFile 用来读取计算出来的hash.
接着说说计算hash(md5)的算法--驱动中:
圆圈中圈住的就是上边说的全局变量。
方框中圈的也与正规的md5算法不同:
多了一些莫名其妙的操作。是一个变形的MD5算法。
6)获取到驱动返回的MD5之后:
(1).sub_417D43((CString *)&v4, (LPCSTR *)v1 + 23);
返回类似md5值的字符串形式 md5_like=md5_(userInput)
(2).sub_401920(v4, (CString *)v5); 将上述md5字符串再计算一次md5
Md5=sub_401920(md5_like)
(3).mid_415A78((LPCSTR *)&v8, (int)&v9, 2, 0xAu);
subMd5=mid(md5,2,10)
将md5字符串从位置2处截取10个字符。
(4)if ( _mbsicmp(v8, a888aeda4ab) )
截取的字符串与888aeda4ab 比较。
(5)show_success_402030 拼接字符串Success^^! 并显示在窗体上。
整个算法用伪代码描述就是:
subString=string_substr(md5(md5_like(CString::MakeReverse(CString::MakeLower(userInPut)))),2,10)
已知条件,输入字符串长度为6最终的subString 为888aeda4ab 。求输入字符串。
所以只能乖乖的爆破。
由于驱动中的md5是非标准版算法,这里也不再详细跟了,直接自己写程序调用他的驱动,Crakeme内的驱动为标准算法,直接找一个md5源码就可以了。
找一个加载驱动的工具加载导出的驱动,然后运行下面的算法:
代码如下:
最终:
程序中没有出来倒序的问题,因此这里反过来输入就可以了。