【吾爱2013CM大赛解答】----驱动crackme -- 网际座山雕 CM解题过程+KEYGEN源码
本帖最后由 Sandman 于 2013-12-14 12:00 编辑【文章标题】 【吾爱2013CM大赛解答】----驱动crackme -- 网际座山雕 CM解题过程+KEYGEN源码
【文章作者】 Sandman
【作者邮箱】
【作者主页】 无~
【软件名称】 CrackMe
【下载地址】 http://www.52pojie.cn/thread-228427-1-1.html
【加壳方式】 无~
【保护方式】 无~
【编写语言】 VC
【使用工具】 OD+IDA
【操作平台】 XPSP3
【软件介绍】 吾爱2013CM大赛题目
由于本题目涉及到RING3程序与RING0程序通信,考虑到常见的应用程序与驱动程序通信方式为CreateFileA+DeviceIoControl方式,使用OD将程序载入后,在CreateFileA与DeviceIoControl函数上下断点。F9运行后,在序列号输入Edit输入任意字符串后,回车,程序在CreateFileA和DeviceIoControl函数上断下。
由OD断点可知,驱动程序创建一个\\.\crackme的符号链接用于与应用程序通信。其中DeviceIoControl函数对驱动程序的控制码为0x222004,查看InBuffer内容,可知程序送往RING0的Buffer内容为机器码+用户设置的序列号,Buffer长度为0x103字节。
将DeviceIoControl函数执行到返回,查看返回Buffer,发现返回Buffer前10字节发生了变化,肯定是驱动程序对这个Buffer做了什么。
将SYS拖到IDA反编译,发现只有6个函数,分别为驱动程序的各个派遣函数,其中sub_10748为驱动程序的DeviceIoControl的处理例程,选择此函数进行F5,找到对驱动控制码0x222004相应的部分,结果如下:
由上述伪代码可知,注册码长度为9位,返回应用程序的格式为:pIoBuffer = RegCode - MachineCode + 1;现在继续回到OD,在DeviceIoControl的OutputBuffer上下硬件访问断点,长度为1。因为后面的注册码验证部分肯定是要读取这部分数据的。F9后,断下。进入如下循环体
其中ECX控制循环计数。下面的代码实际上是EAX = EAX * ECX其中EAX为结果的低32位,EDX为结果的高32位。00401B7B.B8 398EE338 mov eax, 38E38E3900401B80.F7E1 mul ecx00401B82.D1EA shr edx, 1EDX左移一位,总体上来看,实际是ECX * 0x38E38E39 的结果右移了33位:EDX = (ECX * 0x38E38E39) shr 33
M= (ECX * 0x38E38E39) / 2n其中n=33ECX > 0 M>0 且ECX和M均为整数因此,EDX = ECX / 9
上述代码段从0x4438F8处读取1字节的数据,与0xE0比较,如果小于等于则与驱动返回数据中的一个字节做减法,这个字节是谁取决于ECX除以9的结果(并且9次一个循环),并将结果保存至0x446780处,一共循环0xA3次。上述代码对应的C语言表示为:
VOID DecryptCode(PUCHAR SrcBuffer,PUCHAR KeyBuffer)
{
int i;
unsigned char j;
for(i=0;i<0xA3;i++)
{
if(Buffer<=0xE0)
{
j = i / 9;
j += j*8;
j = i -j;
DstBuffer = SrcBuffer - KeyBuffer;
}
}
}
待上述代码解密完成后,继续跟。
其中有2段代码引起注意:cmp byte ptr ,0x21.............................1还有mov eax,00406780...........................................2call eax
其中代码1判断0x00406780 + 0xA2的位置是否为0x21 如果不是则跳转到弹出错误的窗口。如果是则执行代码2.代码2是将解密后的数据作为代码进行调用。程序根据代码的调用结果来判断是否注册成功的。这就引来一个问题:如果代码解密不正确的话,这些代码是不能被CPU成功执行的,将会触发异常。因此解密的关键在于那个KeyBuffer的数据。仔细整理一下已有的思路:原始数据地址 = 0x004438F8解密后数据地址= 0x00406780成功解密的一个前提条件是0x00406780 +0xA2处的数据是0x21。而0x004438F8 + 0xA2= 0x22,而解密算法是由原始数据做减法得出的,由DecryptCode函数可知:DstBuffer = SrcBuffer -KeyBuffer可以推出KeyBuffer = 1。第一个值我们算出来了。那么后面的8个值怎么办呢?综合上面的结果可以知道,驱动程序做的只是做一个减法而已,根据不同电脑的分析结果发现,原始数据是不变的,与机器码无关,而解密后的代码具有可执行的属性,也就是说解密后的代码也是不变的,具有唯一性。此时可以得到一个结论:注册码 - 机器码是一个固定值,并且 注册码第一位 - 机器码第一位 + 1的结果是1.此时我做了一个大胆的推测,那个KeyBuffer的内容可能是KeyBuffer = {1,2,3,4,5,6,7,8}; 因为上面的解密循环是9次一个循环。所以我写了一段注册机代码:#include <stdio.h>
void KeyGen(unsigned char *MachineID)
{
unsigned int i;
unsigned char Key = {0};
for(i=0;i<9;i++)
{
Key = MachineID + i;
}
printf("KeyCode:%s\n",Key);
}
void main()
{
unsigned char MachineID = {0};
scanf("%s",&MachineID);
KeyGen(MachineID);
}
经过验证,上面的注册算法是可用的。结果如下图:
这个分析过程最后有点不太完美,不是说完整分析出来的,有猜的成分在里面。希望有人能有更好的解决方法贴出来。是怎么得出那个KeyBuffer = {1,2,3,4,5,6,7,8},这个只是我的一个猜测,最终得到了验证而已。
这个弄完实在太晚了,第一次写,时间匆忙,写的不是很好。并且后面的KEYBuffer是我猜出来的,如果论坛有人有更好的解法,希望贴出来一起交流。有错误之处,还请各位高手指正。
不会破解的小菜 只能膜拜! 个人认为没有好办法 我搞到这里也是猜的Key是 {0 1 2 3 4 5 6 7 8 9}
因为只有第一个key能确定下来
如果他密钥复杂 我觉得这东西根本没办法分析了就
另外 这个CM的 shellcode在WIN7下有问题 主要是在PEB遍历DL双向链表有问题 路过,学习。 谢谢分享 没时间玩了,来顶顶人气 你为什么这么牛逼 Orz 跪拜!前来学习! 本帖最后由 Sandman 于 2013-12-14 11:06 编辑
baby 发表于 2013-12-14 05:20 static/image/common/back.gif
个人认为没有好办法 我搞到这里也是猜的Key是 {0 1 2 3 4 5 6 7 8 9}
因为只有第一个key能确定下来
如 ...
我没在Win7下做调试,我是在XP虚拟机下搞的
他那个KeyBuffer = {0,1,2,3,4,5,6,7,8}这个没有见到有哪里能跟出来的,个人认为只能猜了。因为整个题目贯穿着就是一个0-8的9个数字的循环。。。似乎就是告诉你KEY跟0-8有关。。。
要是搞得复杂了,确实没办法了
{:1_931:}好文章
给你32个赞~
页:
[1]
2