160个CrackMe之51
本帖最后由 zbnysjwsnd8 于 2017-10-15 13:04 编辑我不是大神,所以文章哪里写的不对的地方还请各位大佬指出。
直接来到算法部分0x0040104B处,分析发现算法很简短,主要分成了两部分。
第一部分:
```
0040105C A1 21214000 mov eax, dword ptr ; 注册码的前四个字节
00401061 B9 02000000 mov ecx, 0x2
00401066 99 cdq
00401067 F7F1 div ecx ; 除以2
00401069 8BF0 mov esi, eax ; 保存商
0040106B B8 44554536 mov eax, 0x36455544
00401070 8B0D 21214000 mov ecx, dword ptr ; 注册码的前四个字节当做循环次数
00401076 C1C0 06 rol eax, 0x6 ; 循环左移六位
00401079 32E0 xor ah, al
0040107B 02C1 add al, cl
0040107D 49 dec ecx
0040107E^ 75 F6 jnz short 00401076
00401080 3D 85180704 cmp eax, 0x4071885 ; 最后的结果是0x04071885则通过,否则失败
```
第二部分:
```
00401094 A1 25214000 mov eax, dword ptr ; 注册码的后四个字节
00401099 B9 02000000 mov ecx, 0x2
0040109E 99 cdq
0040109F F7F1 div ecx ; 除以2
004010A1 8BF0 mov esi, eax ; 保存商
004010A3 B8 52495343 mov eax, 0x43534952
004010A8 8B0D 25214000 mov ecx, dword ptr ; 注册码的后四个字节当做循环次数
004010AE C1C0 06 rol eax, 0x6 ; 循环左移六位
004010B1 32E0 xor ah, al
004010B3 02C1 add al, cl
004010B5 49 dec ecx
004010B6^ 75 F6 jnz short 004010AE
004010B8 3D 27D1004B cmp eax, 0x4B00D127 ; 最后的结果是0x4B00D127则通过,否则失败
```
不难发现这两个部分的算法几乎是一致的,只是每次操作的数据不一样。所以只要逆向出第一个算法,就可以轻易逆向出第二个算法了。
这里直接枚举并不合适,因为这个至少要循环0x20202020次,每次枚举的时间复杂度都是成倍增加的,直接枚举不知道得枚举到什么时候呢。
所以就需要有个快速的方法逆向出注册码。
分析这个代码的时候,画了一个流程图。
![这里写图片描述](http://img.blog.csdn.net/20171015125039252?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
于是就可以根据最后比较的数据来反推循环次数,因为反推的时候循环次数要从1开始递增,所以这些运算都应该写成逆运算的形式,即把后面的代码放到前面去,add换成sub,xor不变,rol换成ror,最后将被比较的数据和待运算的数据互换位置。
于是就可以写出如下的代码:
```
mov eax,0x04071885
xor ecx,ecx
LOOP_:
inc ecx
sub al,cl
xor ah,al
ror eax,6
cmp eax,0x36455544
jnz LOOP_
mov Time,ecx
```
结果出的很快,第一次出来的结果是0x0DBD76F6。因为有不可显示的字符,所以我加了一个判断,如果计算出来的是这个,就继续计算。
最后能得到注册码的前四位"isd4"。当然也可以继续往下,不止一组。
计算后四位的思路也是一样的,代码如下:
```
mov eax,0x4B00D127
xor ecx,ecx
LOOP_1:
inc ecx
sub al,cl
xor ah,al
ror eax,6
cmp eax,0x43534952
jnz LOOP_1
mov Time,ecx
```
这段代码能算出注册码的后四位"ever"。
最后合在一起得到注册码为"isd4ever"。
![这里写图片描述](http://img.blog.csdn.net/20171015125614253?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
最后放一个完整的计算代码吧。
代码写的很挫,大佬们不要喷我 = =
可以在这个代码的基础上加上循环来计算出所有满足条件的值。
```
#include <stdio.h>
int main(int argc,char *argv[])
{
int Time = 0;
_asm
{
mov eax,0x04071885
xor ecx,ecx
LOOP_:
inc ecx
sub al,cl
xor ah,al
ror eax,6
cmp eax,0x36455544
jnz LOOP_
cmp ecx,0x0DBD76F6
je LOOP_
mov Time,ecx
}
printf("%0.4s",&Time);
_asm
{
mov eax,0x4B00D127
xor ecx,ecx
LOOP_1:
inc ecx
sub al,cl
xor ah,al
ror eax,6
cmp eax,0x43534952
jnz LOOP_1
mov Time,ecx
}
printf("%0.4s",&Time);
while(1);
return 0;
}
``` 第50个分析了吗?去NAG窗口改JMP跳转地址,可我找不到算法部分,除非在SendDlgItemMessage前将压栈Unregistered字符偏移+2,其它没什么别的收获,不知道大神可有其它方法。 感谢师傅分享
Ps:终于有一章是菜逼我看得懂的了~ 感谢分享,辛苦了 学习了,辛苦楼主 尝试练习下技术 学习了,谢谢 好厉害的感觉啊 49那个帖子还在么 好牛!!学习了~ 支持下,的
页:
[1]
2