TA的每日心情 | 奋斗 2017-1-16 20:03 |
---|
签到天数: 116 天 [LV.6]常住居民II
|
===================================
红客联盟&Milw0rm有奖活动
===================================
看90办个活动不容易,发个帖子表示支持.
这只是个简单的CrackMe,不加壳,属于那种只要会用OD和IDA就能分析的东西,但是既然把这个过程发出来,表示它还是有一点值得学习的东西在里面.
废话就不多说了,先运行一遍软件,发现直接弹出个“注册失败”的对话框,然后用IDA加载,发现这个CM代码不多,而“注册失败”字符差串则是保存在Text中,选择Text,在键盘上按下“x”键,在弹出来的交叉参考对话框发现有一处代码修改了这个Text的值,如下图:
于是想到这里可能是把“注册失败”改为“注册成功”。先做个测试,用OD加载软件,按下“ctrl”+“G”,输入0x00111045(这个地址要根据实际情况来确定,这里这个CrackMe的基地址是0x00111000),按下回车,来到下图所示的位置:
说明:上图是IDA中的位置,在OD中是0x00111045
这里调用CreateFile函数来打开一个文件,因为目前没有这个文件,所以这个函数注定会失败,所以那个jz就会跳转.于是就在OD中把
(IDA中反汇编出来的是jz,OD中是je)的跳转地址改为0x001111fd,这样当这个函数调用失败后,程序就直来跳转到修改注册结果的地方,如下图所示:
上图所示的是程序中“注册失败”改为“注册成功”的地方,在这里我们看到是用edx+eax+0x23e525dc,然后将这个结果写入到字符串中,我们先猜一下这个结果可能就是字符串“成功”的值,通过测试可知“成功”的值为0xa6b9c9b3,我们就先把ecx的值改为0xa6b9c9b3,把edx的值改为4(“注册”占4个字节),然后按F8,发现程序跑到
这里就跑飞了,说明现在这个内存是不能改写的。不过既然要注册成功,那么这个内存就应该是要能改写的,这就说明前面有地方要修改这个内存地址的属性。
根据IDA中Text的交叉参考可知,除了这里和MessageBox用到了Text之外,还有一处地方用到这个地址,如下图:
在这里把Text当成一个参数传进函数中,而这个函数的参数显然不是MessageBox,这时就想到这里把Text的属性改了,这样后面才能改写Text。而能修改内存属性的API,VirtualProtect就跳出来了,而且上面这个函数的参数和VirtualProtect一样,基本上能确定这里就是调用了VirtualProtect。只不过这里是一个函数指针,这个指针由上面得来:
这里需要确定这个模块名和函数名的来源,继续向上看发现:
在往上看发现这个buffer中的数据是从一个名为“CrackMeA.key”的文件中读取出来的:
这样我们就可以知道,这个CM需要个注册文件,而这个注册文件中的第一个字符串是一个模块名,第二个字符串是一个函数名。然后继续分析接下来需要的一些数据。
上图显示的是注册成功要用到的一些数据, 在这里把数据都取出来了之后,接下来就是校验了。先判断生成“成功”的值是否为空,通过上图可知,除了这两个值外,校验中还用到了另外两个值,所以在接下来的程序中,就先要判断这四个值是否为空,若是有一个为空则注册失败,代码如下:
上面这里检测完了之后,栈中的数据如下图所示:
接下来再进行一次压栈操作,代码如下:
这时栈中的数据如下图:
然后是注册验证,代码如下:
00E111AE |. D9CF fxch st(7) ; 交换st0与st7的值,这时st0为第二组值的长度
00E111B0 |. DECD fmulp st(5),st ; fLen1 * fLen2,结果保存在st4
00E111B2 |. D9CB fxch st(3)
00E111B4 |. DECD fmulp st(5),st ; fStr1 * fStr2,结果保存在st4,之前st4的值上移到st3
00E111B6 |. D9CB fxch st(3)
00E111B8 |. DEC4 faddp st(4),st ; fStr1 * fStr2 + fLen1 * fLen2,结果保存在st3
00E111BA |. D9C4 fld st(4) ; 压入fStr1
00E111BC |. DECD fmulp st(5),st ; st5中的值也是fStr1,所以这里是fStr1 * fStr1,结果保存在st4
00E111BE |. D9C1 fld st(1) ; 将fLen1压栈
00E111C0 |. DECA fmulp st(2),st ; st2也是fLen1,这里是fLen1 * fLen1,结果保存在st1
00E111C2 |. D9CC fxch st(4)
00E111C4 |. DEC1 faddp st(1),st ; 这里是fStr1 * fStr1 + fLen1 * fLen1
00E111C6 |. D9C1 fld st(1)
00E111C8 |. DECA fmulp st(2),st ; 这里是fStr2 * fStr2
00E111CA |. D9C3 fld st(3)
00E111CC |. DECC fmulp st(4),st ; 这里是fLen2 * fLen2
00E111CE |. D9C9 fxch st(1)
00E111D0 |. DEC3 faddp st(3),st ; fStr2 * fStr2 + fLen2 * fLen2
00E111D2 |. DECA fmulp st(2),st ; (fStr1 * fStr1 + fLen1 * fLen1) * (fStr2 * fStr2 + fLen2 * fLen2)
00E111D4 |. DCC8 fmul st,st ; (fStr1 * fStr2 + fLen1 * fLen2) * (fStr1 * fStr2 + fLen1 * fLen2)
00E111D6 |. DEE9 fsubp st(1),st ; (fStr1 * fStr1 + fLen1 * fLen1) * (fStr2 * fStr2 + fLen2 * fLen2) - (fStr1 * fStr2 + fLen1 * fLen2) * (fStr1 * fStr2 + fLen1 * fLen2)
00E111D8 |. DC25 C0C2E100 fsub qword ptr ds:[E1C2C0] ; 将上面得到的结果减去1,这里和接下去的这几行代码是判断上面的结果是否为1
00E111DE |. D95C24 10 fstp dword ptr ss:[esp+10]
00E111E2 |. D94424 10 fld dword ptr ss:[esp+10]
00E111E6 |. D9E1 fabs
00E111E8 |. D95C24 10 fstp dword ptr ss:[esp+10]
00E111EC |. D94424 10 fld dword ptr ss:[esp+10]
00E111F0 |. DC1D B8C2E100 fcomp qword ptr ds:[E1C2B8]
00E111F6 |. DFE0 fstsw ax
00E111F8 |. F6C4 05 test ah,5
00E111FB |. 7A 20 jpe short crackmea.00E1121D ; 结果不为1则跳转
00E111FD |. 8B55 00 mov edx,dword ptr ss:[ebp]
00E11200 |. 8B07 mov eax,dword ptr ds:[edi]
00E11202 |. 8D8C02 DC25E5>lea ecx,dword ptr ds:[edx+eax+23E525DC] ; 生成“成功”字符串
00E11209 |. 8B5424 20 mov edx,dword ptr ss:[esp+20]
00E1120D |. 898A 9CC2E100 mov dword ptr ds:[edx+E1C29C],ecx ; 用“成功”替换“失败”
上面这段代码中,设第一个值为发fStr1,其长度为fLen1,第二个值为fStr2,其长度为fLen2。通过上面的计算,我们可以总结出这么一个方程:
(fStr1^2 + fLen1^2)*(fStr2^2 + fLen2^2) – (fStr1*fStr2 + fLen1*fLen2)^2 = 1……(1)
fStr1 + fStr2 = 0xa6b9c9b3 - 0x23e525dc……(2)
到这里,第一个CrackMe的分析也就结束了,要想做注册机,则在注册算法中解出上面的方程组,然后把得到的数据填入CrackMeA.key文件中的响应位置即可.
这个CrackMe破解的关键是能不能想到用VirtualProtect这个函数来修改内存属性,从而达到破解的目的.附件中有我逆出来的代码和编写好的注册机代码,以及注册文件和原文件,想练手的同学可以玩玩.
|
|