一个简单cm的分析
{:5_118:}今天。风清扬大大甩给我一个cm让我干了。。。然后就有了这个文章=-=
地址先丢出来:链接: http://pan.baidu.com/s/1kT2zj6J 密码: 7ikh
废话不多说了。。。开始了。。。
先载入od
然后查找字符串
发现OK 和 Wrong(错误)
这两个关键字符串。。
于是双击进入OK。
然后找到断首
这里在用户名里输入rain
在密码里输入123
00401410 53 push ebx 断首下断
00401411 55 push ebp
00401412 56 push esi
00401413 57 push edi
00401414 8BF9 mov edi,ecx
00401416 6A 01 push 1
00401418 E8 93030000 call <jmp.&MFC42.#operator new_823>
0040141D 83C4 04 add esp,4
00401420 85C0 test eax,eax
00401422 74 07 je short 0040142B
00401424 C600 18 mov byte ptr ds:,18
00401427 8BD8 mov ebx,eax
00401429 EB 02 jmp short 0040142D
0040142B 33DB xor ebx,ebx
0040142D 6A 01 push 1
0040142F E8 7C030000 call <jmp.&MFC42.#operator new_823>
00401434 83C4 04 add esp,4
00401437 85C0 test eax,eax
00401439 74 07 je short 00401442
0040143B C600 18 mov byte ptr ds:,18
0040143E 8BF0 mov esi,eax
00401440 EB 02 jmp short 00401444
00401442 33F6 xor esi,esi
00401444 6A 14 push 14
00401446 53 push ebx
00401447 8D8F A0000000 lea ecx,dword ptr ds:
0040144D E8 58030000 call <jmp.&MFC42.#CWnd::GetWindowTextA_3> 获取用户名
00401452 6A 14 push 14
00401454 56 push esi
00401455 8D4F 60 lea ecx,dword ptr ds:
00401458 E8 4D030000 call <jmp.&MFC42.#CWnd::GetWindowTextA_3> 获取注册码
这是前面的一部分
然后现在讲下怎么爆破。。
先运行起来把。。
然后点一下验证。
发现断下来了
于是F8单步到这里。
(编辑框1和2不能大于10个字节,如果大于就nop把。。)
我这里填的没有大于10字节所以默认的就没跳。
继续F8单步把。。。
现在先讲爆破。。分析就直接略过把。。
然后继续单步。。
单步到这里004014BD
然后按照恒大教给我们的。
nop了。。。。
下面的那个004014C1的跳转没跳。。。
于是不管他。
直接点运行。
哇!成功了!!!!!
咦。。不对啊。。怎么什么都没显示。。。
于是别着急。
仔细看看这两处的代码
004014C3 50 push eax
004014C4 68 50304000 push 00403050 ; Ok
004014C9 68 2C304000 push 0040302C ; Congratulations!This is the key!
004014CE 50 push eax
004014CF FF15 D8214000 call dword ptr ds:[<&USER32.MessageBoxA>>; USER32.MessageBoxA
004014D5 5F pop edi
004014D6 5E pop esi
004014D7 5D pop ebp
004014D8 5B pop ebx
004014D9 C3 retn
004014DA 6A 00 push 0
004014DC 68 28304000 push 00403028 ; Msg
004014E1 68 20304000 push 00403020 ; Wrong!
004014E6 6A 00 push 0
004014E8 FF15 D8214000 call dword ptr ds:[<&USER32.MessageBoxA>>; USER32.MessageBoxA
004014EE 5F pop edi
004014EF 5E pop esi
004014F0 5D pop ebp
004014F1 5B pop ebx
004014F2 C3 retn
发现除了内容不同 还有1个地方不同
那就是成功地方是
push eax
push 成功内容
push eax
而失败地方是
push 0
push 失败内容
push 0
发现了什么?。。。
就是成功地方是由eax来确定是不是创建这个窗口的(小菜是这么理解的。。。如有错误 请指出来把。)。。。
下面的失败内容中
push 的是0
而上面的eax
我们单步到那里
发现eax=1
那么我们只要在这把eax赋值为0
就好了把?。
于是就在
004014C3 50 push eax
的前面
004014B8 83D8 FF sbb eax,-1
修改代码为mov eax,1
在运行看看。是不是成功了?
啊啊啊啊,好开心。。。
下面进入注册码分析:
00401410 53 push ebx
00401411 55 push ebp
00401412 56 push esi
00401413 57 push edi
00401414 8BF9 mov edi,ecx
00401416 6A 01 push 1
00401418 E8 93030000 call <jmp.&MFC42.#operator new_823>
0040141D 83C4 04 add esp,4
00401420 85C0 test eax,eax
00401422 74 07 je short 0040142B
00401424 C600 18 mov byte ptr ds:,18
00401427 8BD8 mov ebx,eax
00401429 EB 02 jmp short 0040142D
0040142B 33DB xor ebx,ebx
0040142D 6A 01 push 1
0040142F E8 7C030000 call <jmp.&MFC42.#operator new_823>
00401434 83C4 04 add esp,4
00401437 85C0 test eax,eax
00401439 74 07 je short 00401442
0040143B C600 18 mov byte ptr ds:,18
0040143E 8BF0 mov esi,eax
00401440 EB 02 jmp short 00401444
00401442 33F6 xor esi,esi
00401444 6A 14 push 14
00401446 53 push ebx
00401447 8D8F A0000000 lea ecx,dword ptr ds:
0040144D E8 58030000 call <jmp.&MFC42.#CWnd::GetWindowTextA_3>; 取编辑框1.内容 也就是用户名
00401452 6A 14 push 14
00401454 56 push esi
00401455 8D4F 60 lea ecx,dword ptr ds:
00401458 E8 4D030000 call <jmp.&MFC42.#CWnd::GetWindowTextA_3>; 取编辑框2.内容 也就是密码
0040145D 8BFB mov edi,ebx
0040145F 83C9 FF or ecx,FFFFFFFF
00401462 33C0 xor eax,eax
00401464 F2:AE repne scas byte ptr es:
00401466 F7D1 not ecx
00401468 49 dec ecx
00401469 8BFE mov edi,esi ; 以上代码是取编辑框1的长度
0040146B 8BE9 mov ebp,ecx ; 4位
0040146D 83C9 FF or ecx,FFFFFFFF
00401470 F2:AE repne scas byte ptr es:
00401472 F7D1 not ecx
00401474 49 dec ecx ; 取编辑框2的长度
00401475 83FD 0A cmp ebp,0A
00401478 77 60 ja short 004014DA ; 编辑框1.长度大于10就错误
0040147A 83F9 0A cmp ecx,0A
0040147D 77 5B ja short 004014DA ; 编辑框2.长度大于10也错误
0040147F 53 push ebx
00401480 E8 7B000000 call 00401500 ; 算法call1
00401485 56 push esi
00401486 E8 A5000000 call 00401530 ; 算法call2
0040148B 83C4 08 add esp,8
0040148E 8A0B mov cl,byte ptr ds: ; 运算完成的第一个用户名ASCII
00401490 8A16 mov dl,byte ptr ds: ; 运算完成的第一个密码ASCII
00401492 8AC1 mov al,cl
00401494 3ACA cmp cl,dl ; 互相比较是不是一样
00401496 75 1E jnz short 004014B6 ; 如果一样就不跳
00401498 84C0 test al,al
0040149A 74 16 je short 004014B2
0040149C 8A53 01 mov dl,byte ptr ds: ; 运算完成的第二个用户名ASCII
0040149F 8A4E 01 mov cl,byte ptr ds: ; 运算完成的第二个密码ASCII
004014A2 8AC2 mov al,dl
004014A4 3AD1 cmp dl,cl ; 比较一样不
004014A6 75 0E jnz short 004014B6 ; 一样就不跳 不一样就跳
004014A8 83C3 02 add ebx,2 ; 舍去2个用户名ASCII码 到第三个
004014AB 83C6 02 add esi,2 ; 舍去2个密码ASCII码 到第三个
004014AE 84C0 test al,al
004014B0^ 75 DC jnz short 0040148E
004014B2 33C0 xor eax,eax
004014B4 EB 05 jmp short 004014BB ; 于是就成功了=-=
004014B6 1BC0 sbb eax,eax
004014B8 83D8 FF sbb eax,-1
004014BB 85C0 test eax,eax
004014BD 75 1B jnz short 004014DA
004014BF 85ED test ebp,ebp
004014C1 74 17 je short 004014DA
004014C3 50 push eax
004014C4 68 50304000 push 00403050 ; Ok
004014C9 68 2C304000 push 0040302C ; Congratulations!This is the key!
004014CE 50 push eax
004014CF FF15 D8214000 call dword ptr ds:[<&USER32.MessageBoxA>>; USER32.MessageBoxA
004014D5 5F pop edi
004014D6 5E pop esi
004014D7 5D pop ebp
004014D8 5B pop ebx
004014D9 C3 retn
004014DA 6A 00 push 0
004014DC 68 28304000 push 00403028 ; Msg
004014E1 68 20304000 push 00403020 ; Wrong!
004014E6 6A 00 push 0
004014E8 FF15 D8214000 call dword ptr ds:[<&USER32.MessageBoxA>>; USER32.MessageBoxA
004014EE 5F pop edi
004014EF 5E pop esi
004014F0 5D pop ebp
004014F1 5B pop ebx
004014F2 C3 retn
算法call1:
00401500 8B5424 04 mov edx,dword ptr ss: ; 算法call1
00401504 56 push esi
00401505 57 push edi
00401506 8BFA mov edi,edx
00401508 83C9 FF or ecx,FFFFFFFF
0040150B 33C0 xor eax,eax
0040150D F2:AE repne scas byte ptr es:
0040150F F7D1 not ecx
00401511 49 dec ecx ; rain的长度4
00401512 8BF1 mov esi,ecx
00401514 74 11 je short 00401527
00401516 8A0C10 mov cl,byte ptr ds: ; 循环读取ASCII
00401519 80F1 03 xor cl,3 ; ASCII码与3异或
0040151C 80E9 14 sub cl,14 ; -20
0040151F 880C10 mov byte ptr ds:,cl
00401522 40 inc eax
00401523 3BC6 cmp eax,esi
00401525^ 72 EF jb short 00401516
00401527 5F pop edi
00401528 5E pop esi
00401529 C3 retn
算法call2:
00401530 8B5424 04 mov edx,dword ptr ss: ; 算法call 2
00401534 56 push esi
00401535 57 push edi
00401536 8BFA mov edi,edx
00401538 83C9 FF or ecx,FFFFFFFF
0040153B 33C0 xor eax,eax
0040153D F2:AE repne scas byte ptr es:
0040153F F7D1 not ecx
00401541 49 dec ecx ; 4
00401542 8BF1 mov esi,ecx
00401544 74 11 je short 00401557
00401546 8A0C10 mov cl,byte ptr ds: ; 循环取ASCII
00401549 80C1 02 add cl,2 ; ASCII+2
0040154C 80F1 10 xor cl,10 ; 和10异或
0040154F 880C10 mov byte ptr ds:,cl
00401552 40 inc eax
00401553 3BC6 cmp eax,esi
00401555^ 72 EF jb short 00401546
00401557 5F pop edi
00401558 5E pop esi
00401559 C3 retn
总结一下流程:
一上来读取编辑框1.内容的长度
然后计次循环
{
取出ASCII码
然后和3异或-14
}
然后编辑框2.内容的长度
计次循环
{
取出ASCII码
然后+2异或10
}
然后和第一个比较
计算出来的相同就正确
那么下面开始
(注意都是十六进制的运算)
我的用户名是rain
密码未知。
rain通过取ASCII码是72、61、69、6E。
然后和3异或是71、62、6A、6D。
然后-14是5D、4E、56、59
然后因为计算要是同样的
所以既然用户名是4个。
那密码也要是4个。
这个都知道。
然后开始计算
异或有个运算顺序:
A运算B=C
A=B运算C
可以用生哥OD里面的逆向计算器
来运算一下。 先勾上16进制
然后5D XOR 10=4D
现在来检验一下。。
10 XOR 4D =5D 检验成功
然后继续运算。 运算4个之后。
密码的ASCII码=4D、5E、46、49
然后别忘了减去2哦。
因为这是算法,+2最后就要-2:
(取出ASCII码
然后+2异或10)
减去2之后密码的ASCII=4B、5C、44、47
然后查ASCII码表 得出
密码=K/DG
填进去。发现正确了=-=
于是就到这里了。。结束
希望所有看过帖子的人回复一个正确的key!
肯定会评分的!!!
膜拜支持感谢
学霸啊,学习了,感谢lz发帖
随便甩几个教程出来,就这么霸气~{:6_202:}
一下子接受不了,留下来慢慢学习,谢谢分享
学习了..
...
非常感谢分享教程
好技术都是分享心得总结经验得来的!
感谢分享~~
_KaQqi
V"\,LD
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
char Name;
char key;
int SizeOfName;
scanf("%s",Name);
SizeOfName = strlen(Name);
if(SizeOfName > 10)
return 0;
for(int i = 0;i < SizeOfName;i++)
{
Name ^= 3;
Name -= 0x14;
key = Name;
key ^= 0x10;
key -= 2;
}
for(int i = 0;i < SizeOfName;i++)
printf("%c",key);
while(1);
return 0;
}