【文章标题】: 破解一个骗新手的 CM(全世界高手飘过)
【文章作者】: KAN [ DCG ]
【作者邮箱】: tom7411@163.com
【作者主页】: 我都想有,可惜。。。。
【作者QQ号】: 看雪说不要留
【软件名称】: CrackMe2.exe
【软件大小】: 很小
【下载地址】: 附件
【加壳方式】: UPX
【编写语言】: Delphi 6.0 - 7.0
【使用工具】: 当然是 0D 了
【操作平台】: WIN XP
【软件介绍】: 在飘云阁下的一个 CM
【作者声明】: 只是感兴趣,为解密而学破解
--------------------------------------------------------------------------------
【详细过程】
今天在飘云阁下了一个 CM,打开一看,随意输入了用户名和假码后,下了各种断点都断不下来,烦了,打开 WIN 任务
管理器见到这个 CM 有两个进程,看来有一个是假的(也因为这样才写这篇破文(很破的文)给新手知到一些假象),还有壳太简单了,不写了。
于是就到程序载入点看看它的启动,原来问题就在开头
00454EB8 <模> $ 55 PUSH EBP ; 程序启动停在这里
00454EB9 . 8BEC MOV EBP,ESP
00454EBB . 83C4 F0 ADD ESP,-10
00454EBE . B8 D84C4500 MOV EAX,CrackMe2.00454CD8
00454EC3 . E8 380FFBFF CALL CrackMe2.00405E00
00454EC8 . E8 83FDFFFF CALL CrackMe2.00454C50 ; 这个 CALL 启动了骗人的 CM 框架,靠
00454ECD . A1 70604500 MOV EAX,DWORD PTR DS:[456070]
00454ED2 . 8B00 MOV EAX,DWORD PTR DS:[EAX]
00454ED4 . E8 2FE0FFFF CALL CrackMe2.00452F08
00454ED9 . A1 70604500 MOV EAX,DWORD PTR DS:[456070]
00454EDE . 8B00 MOV EAX,DWORD PTR DS:[EAX]
00454EE0 . BA 1C4F4500 MOV EDX,CrackMe2.00454F1C ; ASCII "CrackMe #2"
00454EE5 . E8 2EDCFFFF CALL CrackMe2.00452B18
00454EEA . 8B0D A05F4500 MOV ECX,DWORD PTR DS:[455FA0] ; CrackMe2.00457BFC
00454EF0 . A1 70604500 MOV EAX,DWORD PTR DS:[456070]
00454EF5 . 8B00 MOV EAX,DWORD PTR DS:[EAX]
00454EF7 . 8B15 A8444500 MOV EDX,DWORD PTR DS:[4544A8] ; CrackMe2.004544F4
00454EFD . E8 1EE0FFFF CALL CrackMe2.00452F20
00454F02 . A1 70604500 MOV EAX,DWORD PTR DS:[456070]
00454F07 . 8B00 MOV EAX,DWORD PTR DS:[EAX]
00454F09 . E8 92E0FFFF CALL CrackMe2.00452FA0 ; 老兄,这个 才是真命天子啊 ,F8 过 启动 CM
00454F0E . E8 E9EFFAFF CALL CrackMe2.00403EFC
――――――――――――――――――――――――――――――――――――――――――――――
F7 进入 454EBE 处把下面这条指令宰了,“痛快”
00454C7D |. /75 05 JNZ SHORT CrackMe2.00454C84 ; 把 JZ 改为 jnz 就可以了
――――――――――――――――――――――――――――――――――――――――――――――
看,这样它就不会启动那个骗我们的假货了,杀 ,然后 CTRL + B 输入 错误对话框中的 Bad Code! 关键字
就可以很容易找到下面了
0045481E |. 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C] ; 用户名地址送入 EAX ,F2 下个断点吧
00454821 |. E8 86FAFAFF CALL CrackMe2.004042AC ; 得到了用户名的位数
00454826 |. 8BD8 MOV EBX,EAX ; 将位数送入 EBX
00454828 |. 85DB TEST EBX,EBX ; 看看你大哥有没有输入用户名
0045482A |. 7E 3F JLE SHORT CrackMe2.0045486B ; 没有就不给你玩,死了吧
0045482C |. BE 01000000 MOV ESI,1
00454831 |> 8D55 DC /LEA EDX,DWORD PTR SS:[EBP-24] ;循环开始
00454834 |. 8B87 04030000 |MOV EAX,DWORD PTR DS:[EDI+304] ; 用户名地址重新还给了 EAX,
本来就是它的
0045483A |. E8 09F0FDFF |CALL CrackMe2.00433848
0045483F |. 8B45 DC |MOV EAX,DWORD PTR SS:[EBP-24]
00454842 |. 8A4430 FF |MOV AL,BYTE PTR DS:[EAX+ESI-1] ; 用户名第一字节送入了 AL
00454846 |. 50 |PUSH EAX ; /Char
00454847 |. E8 AC20FBFF |CALL <JMP.&user32.VkKeyScanA> ; \这个CALL 就把用户名字符加
工成注册码的各位数值
0045484C |. 0FBFC0 |MOVSX EAX,AX
0045484F |. 8D4D E0 |LEA ECX,DWORD PTR SS:[EBP-20] ;除了上面的一个 CALL 是由于外,
其它的基本是假货,不理
00454852 |. BA 03000000 |MOV EDX,3
00454857 |. E8 4837FBFF |CALL CrackMe2.00407FA4
0045485C |. 8B55 E0 |MOV EDX,DWORD PTR SS:[EBP-20]
0045485F |. 8D45 F8 |LEA EAX,DWORD PTR SS:[EBP-8]
00454862 |. E8 4DFAFAFF |CALL CrackMe2.004042B4
00454867 |. 46 |INC ESI
00454868 |. 4B |DEC EBX
00454869 |.^ 75 C6 \JNZ SHORT CrackMe2.00454831 ;看看 EBX 是否为 0,不是就跳回
0045486B |> 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
0045486E |. E8 39FAFAFF CALL CrackMe2.004042AC
00454873 |. 83F8 14 CMP EAX,14
00454876 |. 7E 0D JLE SHORT CrackMe2.00454885
00454878 |. 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
0045487B |. BA 14000000 MOV EDX,14
00454880 |. E8 B3FDFAFF CALL CrackMe2.00404638
00454885 |> 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
00454888 |. E8 1FFAFAFF CALL CrackMe2.004042AC
0045488D |. 83F8 14 CMP EAX,14
00454890 |. 7D 22 JGE SHORT CrackMe2.004548B4
00454892 |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
00454895 |. E8 12FAFAFF CALL CrackMe2.004042AC
0045489A |. 8BF0 MOV ESI,EAX
0045489C |. 83FE 13 CMP ESI,13
0045489F |. 7F 13 JG SHORT CrackMe2.004548B4
004548A1 |> 8D45 F8 /LEA EAX,DWORD PTR SS:[EBP-8] //这个循环就是看看上面生成的注册码有几位,不够 20 的后面加 0 补上
004548A4 |. BA 90494500 |MOV EDX,CrackMe2.00454990
004548A9 |. E8 06FAFAFF |CALL CrackMe2.004042B4
004548AE |. 46 |INC ESI
004548AF |. 83FE 14 |CMP ESI,14
004548B2 |.^ 75 ED \JNZ SHORT CrackMe2.004548A1
004548B4 |> 8D55 D8 LEA EDX,DWORD PTR SS:[EBP-28]
004548B7 |. 8B87 F8020000 MOV EAX,DWORD PTR DS:[EDI+2F8]
004548BD |. E8 86EFFDFF CALL CrackMe2.00433848
004548C2 |. 8B55 D8 MOV EDX,DWORD PTR SS:[EBP-28]
004548C5 |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
004548C8 |. E8 2BFBFAFF CALL CrackMe2.004043F8
004548CD |. 74 52 JE SHORT CrackMe2.00454921 ;关键跳转,改为 JMP 你就无敌了
;在我心中这比算法注册还完美破解,强
004548CF |. FF87 08030000 INC DWORD PTR DS:[EDI+308]
004548D5 |. 83BF 08030000>CMP DWORD PTR DS:[EDI+308],3
004548DC |. 75 05 JNZ SHORT CrackMe2.004548E3
004548DE |. E8 19F6FAFF CALL CrackMe2.00403EFC
004548E3 |> B8 03000000 MOV EAX,3
004548E8 |. 2B87 08030000 SUB EAX,DWORD PTR DS:[EDI+308]
004548EE |. 83F8 02 CMP EAX,2
004548F1 |. 75 17 JNZ SHORT CrackMe2.0045490A
004548F3 |. 6A 00 PUSH 0
004548F5 |. 66:8B0D 94494>MOV CX,WORD PTR DS:[454994]
004548FC |. 33D2 XOR EDX,EDX
004548FE |. B8 A0494500 MOV EAX,CrackMe2.004549A0 ; ASCII "Bad Code!"
,CR,"2 attempt(s) remaining..."
00454903 |. E8 582BFDFF CALL CrackMe2.00427460
00454908 |. EB 38 JMP SHORT CrackMe2.00454942
0045490A |> 6A 00 PUSH 0
0045490C |. 66:8B0D 94494>MOV CX,WORD PTR DS:[454994]
00454913 |. 33D2 XOR EDX,EDX
00454915 |. B8 CC494500 MOV EAX,CrackMe2.004549CC ; ASCII "Bad Code!",
CR,"1 attempt remaining..."
0045491A |. E8 412BFDFF CALL CrackMe2.00427460
0045491F |. EB 21 JMP SHORT CrackMe2.00454942
00454921 |> 6A 00 PUSH 0
00454923 |. 66:8B0D 94494>MOV CX,WORD PTR DS:[454994]
0045492A |. B2 02 MOV DL,2
0045492C |. B8 F8494500 MOV EAX,CrackMe2.004549F8 ; ASCII "Code is OK!",CR,"
Thanks for solving this CrackMe..."
00454931 |. E8 2A2BFDFF CALL CrackMe2.00427460
00454936 |. A1 70604500 MOV EAX,DWORD PTR DS:[456070]
0045493B |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
0045493D |. E8 4AE7FFFF CALL CrackMe2.0045308C
--------------------------------------------------------------------------------
【经验总结】
总结一下,它的注册过程:
用户名长度有 1 位也通过
你输入的用户名小写的,它硬把它改为大写(没道理)
注册码只是用?的用户名的 ASCII 码连在一起,当然如果你输入的如果是
小写的话,它会在每位前头加一个 0 ,输入的是大写的话就加个 1
你输入一百个用户名字符,它就帮你算前七个,所以你可以省些力气
没了。。。。。。。。。。结束
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
main()
{
cout<<"请输入你的用户名,程序结束计算在前第七位,你看着办吧!\n";
char temp[6];
char name[6];
cin>>temp;
int i;
for(i=0;temp[i]!='\0';i++) // 获取长度,也可以用 strlen 函数来代替
{
if(temp[i]=='\0')
break;
}
int v=0,j,b;
for(j=0;j<i;j++)
{
v=temp[j];
b=v;
if(v>90)
{
v-=32; //如果输入的是小写就把它转换为大写
}
name[j]=v;
if(b>90)
cout<<"0"; //输入用户名字符是小写的插入 0
else
cout<<"1"; //输入用户名字符是大写的插入 1
if(j==6)
{
if(b>90)
cout<<"4\n";
else
cout<<"5\n";
return 0;
}
printf("%0X",name[j]);
}
switch(j)
{
case 1:cout<<"00000000000000000\n";
break;
case 2:cout<<"00000000000000\n";
break;
case 3:cout<<"00000000000\n";
break;
case 4:cout<<"00000000\n";
break;
case 5:cout<<"00000\n";
break;
case 6:cout<<"00\n";
break;
}
cout<<endl;
} //修改了一下,昨天看漏眼了,第七位也在计算之内
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年01月27日 1:06:57
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课