破解一个骗新手的 CM(全世界高手飘过)
【文章标题】: 破解一个骗新手的 CM(全世界高手飘过)【文章作者】: KAN [ DCG ]
【作者邮箱】: [email protected]
【作者主页】: 我都想有,可惜。。。。
【作者QQ号】: 看雪说不要留
【软件名称】: CrackMe2.exe
【软件大小】: 很小
【下载地址】: https://www.chinapyg.com/viewthread.php?tid=11454&extra=page%3D1
【加壳方式】: 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:
00454ED2 .8B00 MOV EAX,DWORD PTR DS:
00454ED4 .E8 2FE0FFFF CALL CrackMe2.00452F08
00454ED9 .A1 70604500 MOV EAX,DWORD PTR DS:
00454EDE .8B00 MOV EAX,DWORD PTR DS:
00454EE0 .BA 1C4F4500 MOV EDX,CrackMe2.00454F1C ;ASCII "CrackMe #2"
00454EE5 .E8 2EDCFFFF CALL CrackMe2.00452B18
00454EEA .8B0D A05F4500 MOV ECX,DWORD PTR DS: ;CrackMe2.00457BFC
00454EF0 .A1 70604500 MOV EAX,DWORD PTR DS:
00454EF5 .8B00 MOV EAX,DWORD PTR DS:
00454EF7 .8B15 A8444500 MOV EDX,DWORD PTR DS: ;CrackMe2.004544F4
00454EFD .E8 1EE0FFFF CALL CrackMe2.00452F20
00454F02 .A1 70604500 MOV EAX,DWORD PTR DS:
00454F07 .8B00 MOV EAX,DWORD PTR DS:
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: ;用户名地址送入 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: ;循环开始
00454834 |.8B87 04030000 |MOV EAX,DWORD PTR DS: ;用户名地址重新还给了 EAX,
本来就是它的
0045483A |.E8 09F0FDFF |CALL CrackMe2.00433848
0045483F |.8B45 DC |MOV EAX,DWORD PTR SS:
00454842 |.8A4430 FF |MOV AL,BYTE PTR DS: ;用户名第一字节送入了 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: ;除了上面的一个 CALL 是由于外,
其它的基本是假货,不理
00454852 |.BA 03000000 |MOV EDX,3
00454857 |.E8 4837FBFF |CALL CrackMe2.00407FA4
0045485C |.8B55 E0 |MOV EDX,DWORD PTR SS:
0045485F |.8D45 F8 |LEA EAX,DWORD PTR SS:
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:
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:
0045487B |.BA 14000000 MOV EDX,14
00454880 |.E8 B3FDFAFF CALL CrackMe2.00404638
00454885 |>8B45 F8 MOV EAX,DWORD PTR SS:
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:
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:
004548A4 |.BA 90494500 |MOV EDX,CrackMe2.00454990
004548A9 |.E8 06FAFAFF |CALL CrackMe2.004042B4 //这里看看你上面的注册码几位,不够20位的后面用0来补上
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:
004548B7 |.8B87 F8020000 MOV EAX,DWORD PTR DS:
004548BD |.E8 86EFFDFF CALL CrackMe2.00433848
004548C2 |.8B55 D8 MOV EDX,DWORD PTR SS:
004548C5 |.8B45 F8 MOV EAX,DWORD PTR SS:
004548C8 |.E8 2BFBFAFF CALL CrackMe2.004043F8
004548CD |.74 52 JE SHORT CrackMe2.00454921 ;关键跳转,改为 JMP 你就无敌了
;在我心中这比算法注册还完美破解,强
004548CF |.FF87 08030000 INC DWORD PTR DS:
004548D5 |.83BF 08030000>CMP DWORD PTR DS:,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:
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:
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:
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:
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:
0045493B |.8B00 MOV EAX,DWORD PTR DS:
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;
char name;
cin>>temp;
int i;
for(i=0;temp!='\0';i++) // 获取长度,也可以用 strlen 函数来代替
{
if(temp=='\0')
break;
}
int v=0,j,b;
for(j=0;j<i;j++)
{
v=temp;
b=v;
if(v>90)
{
v-=32; //如果输入的是小写就把它转换为大写
}
name=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);
}
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
[ 本帖最后由 lgjxj 于 2007-1-27 10:38 编辑 ] 分析的不错啊!继续进行CM3 真假窗口是怎么样传递注册码的..有点搞不明白...:L 漂亮…学习了!!! 不错不错~~~
呵呵!
页:
[1]