【标题】:破解某keyfile CM
【作者】:riusksk(泉哥)
【主页】:http://riusksk.blogbus.com
【软件】: CM.rar
【加壳】:无
【邮箱】:riusksk@qq.com
【时间】:2009/8/30
【声明】:纯属兴趣而已,无其它目的,如果失误之处望赐教!
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
【详细过程】:
用OD载入后,下断点:bpx CreateFileA, 运行后断在如下地址:
0040415A 6A 00 PUSH 0
0040415C 68 80000000 PUSH 80
00404161 51 PUSH ECX
00404162 6A 00 PUSH 0
00404164 52 PUSH EDX
00404165 50 PUSH EAX
00404166 8D43 48 LEA EAX,DWORD PTR DS:[EBX+48] ; fcrackme.key
00404169 50 PUSH EAX
0040416A E8 9DD0FFFF CALL <JMP.&KERNEL32.CreateFileA> ;断在这里
0040416F 83F8 FF CMP EAX,-1 ;打开失败则跳转
00404172 74 29 JE SHORT crme.0040419D
00404174 8903 MOV DWORD PTR DS:[EBX],EAX ; 保存文件句柄
00404176 5F POP EDI
00404177 5E POP ESI
00404178 5B POP EBX
00404179 C3 RETN
因此我们这里先建立一个名为“fcrackme.key”的文件名作为keyfile,
F8下去,执行RETN后,来到下列地址:
00426592 E8 4DC1FDFF CALL crme.004026E4
00426597 85C0 TEST EAX,EAX
00426599 0F85 66010000 JNZ crme.00426705
0042659F 8D85 A8FEFEFF LEA EAX,DWORD PTR SS:[EBP+FFFEFEA8]
004265A5 E8 5AD9FDFF CALL crme.00403F04
004265AA E8 F9C0FDFF CALL crme.004026A8
004265AF 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
004265B2 837D FC 00 CMP DWORD PTR SS:[EBP-4],0 ; 判断文件内容是否为空,不为空则跳转
004265B6 75 15 JNZ SHORT crme.004265CD
004265B8 BA 64674200 MOV EDX,crme.00426764 ; ASCII "Key file is empty!"
004265BD 8B83 B0010000 MOV EAX,DWORD PTR DS:[EBX+1B0]
004265C3 E8 CCB6FEFF CALL crme.00411C94 ;设置窗口中的文本内容
004265C8 E9 28010000 JMP crme.004266F5
004265CD 817D FC 0000010>CMP DWORD PTR SS:[EBP-4],10000 ; 比较fcrackme.key文件中的字符串长度
004265D4 7E 07 JLE SHORT crme.004265DD
004265D6 C745 FC 0000010>MOV DWORD PTR SS:[EBP-4],10000
004265DD 6A 00 PUSH 0
004265DF 8D95 FCFFFEFF LEA EDX,DWORD PTR SS:[EBP+FFFEFFFC]
004265E5 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4] ; 保存keyfile中字符串的长度
004265E8 8D85 A8FEFEFF LEA EAX,DWORD PTR SS:[EBP+FFFEFEA8]
004265EE E8 71D8FDFF CALL crme.00403E64
004265F3 E8 B0C0FDFF CALL crme.004026A8
004265F8 53 PUSH EBX
004265F9 57 PUSH EDI
004265FA 56 PUSH ESI
004265FB 8D75 FC LEA ESI,DWORD PTR SS:[EBP-4]
004265FE 8B0E MOV ECX,DWORD PTR DS:[ESI] ; 字符串长度
00426600 8DB5 FCFFFEFF LEA ESI,DWORD PTR SS:[EBP+FFFEFFFC] ; 字符串
00426606 8DBD FBFFFEFF LEA EDI,DWORD PTR SS:[EBP+FFFEFFFB]
0042660C 31C0 XOR EAX,EAX
0042660E 83CA FF OR EDX,FFFFFFFF
00426611 31DB XOR EBX,EBX
00426613 40 INC EAX
00426614 F7D2 NOT EDX
00426616 8A1C16 MOV BL,BYTE PTR DS:[ESI+EDX] ; 依次取keyfile中的字符进行以下计算
00426619 84DB TEST BL,BL ; 为0则跳转,注意这里是十六进制00,应用十六进制编辑器编辑
0042661B 74 29 JE SHORT crme.00426646
0042661D E8 16000000 CALL crme.00426638
00426622 52 PUSH EDX ; 字符位数,从0开始
00426623 F7E3 MUL EBX ; 字符与上一循环中的值相乘
00426625 5A POP EDX
00426626 35 326D5463 XOR EAX,63546D32 ; 与63546D32异或
0042662B FEC2 INC DL ; 计数器
0042662D 39CA CMP EDX,ECX ; 执行完所有字符则跳转
0042662F 74 42 JE SHORT crme.00426673 ; 这里让它跳转就失败了,我就是在这边卡住的,如果不跳转那么就必须执行到00426646,于是我就在这边下断点,但发现OD根本就没执行到这边,由此推断,在此之前应该有个分支跳转语句来判断是否应该执行到00426646,因此我就借助了一下IDA的交叉参考功能,终于发现在00426619就有此判断语句,如下图所示:
00426631 80FA FF CMP DL,0FF ; 如果DL=FF就跳转
00426634 74 3D JE SHORT crme.00426673
00426636 ^ EB DE JMP SHORT crme.00426616 ; 循环以上操作
00426638 57 PUSH EDI
00426639 8DBD F4FFFEFF LEA EDI,DWORD PTR SS:[EBP+FFFEFFF4]
0042663F 8B3F MOV EDI,DWORD PTR DS:[EDI]
00426641 881C17 MOV BYTE PTR DS:[EDI+EDX],BL
00426644 5F POP EDI
00426645 C3 RETN
00426646 E8 EDFFFFFF CALL crme.00426638
0042664B 42 INC EDX ; EDX=EDX+1
0042664C 83C2 04 ADD EDX,4 ; EDX=EDX+4
0042664F 39D1 CMP ECX,EDX ; 将EDX与文件内容长度比较
00426651 75 20 JNZ SHORT crme.00426673 ; 不相等则跳转,跳了就完蛋了,因此必须在00之后再加四个字符
00426653 83EA 04 SUB EDX,4 ; EDX=EDX-4
00426656 85C0 TEST EAX,EAX
00426658 76 02 JBE SHORT crme.0042665C
0042665A D1E8 SHR EAX,1 ; 将之前EAX的运算结果右移一位
0042665C 3B0416 CMP EAX,DWORD PTR DS:[ESI+EDX] ; 将右移后的EAX与00之后的四位字符相比较,也就是说00之后就是经00前面的用户名计算出来的注册码
0042665F 75 09 JNZ SHORT crme.0042666A ; 相等则注册成功
00426661 B8 00000000 MOV EAX,0
00426666 8907 MOV DWORD PTR DS:[EDI],EAX
00426668 EB 10 JMP SHORT crme.0042667A
0042666A B8 01000000 MOV EAX,1
0042666F 8907 MOV DWORD PTR DS:[EDI],EAX
00426671 EB 07 JMP SHORT crme.0042667A
00426673 B8 02000000 MOV EAX,2
00426678 8907 MOV DWORD PTR DS:[EDI],EAX
0042667A 5E POP ESI
0042667B 5F POP EDI
0042667C 5B POP EBX
0042667D 8A85 FBFFFEFF MOV AL,BYTE PTR SS:[EBP+FFFEFFFB]
00426683 2C 01 SUB AL,1
00426685 72 08 JB SHORT crme.0042668F
00426687 74 4A JE SHORT crme.004266D3
00426689 FEC8 DEC AL
0042668B 74 58 JE SHORT crme.004266E5
0042668D EB 66 JMP SHORT crme.004266F5
0042668F BA 80674200 MOV EDX,crme.00426780 ; ASCII "Valid Key file found!"
00426694 8B83 B0010000 MOV EAX,DWORD PTR DS:[EBX+1B0]
0042669A E8 F5B5FEFF CALL crme.00411C94
0042669F BA A0674200 MOV EDX,crme.004267A0 ; ASCII "Registered to: "
004266A4 8D85 A4FEFEFF LEA EAX,DWORD PTR SS:[EBP+FFFEFEA4]
004266AA E8 05CCFDFF CALL crme.004032B4
004266AF 8D85 A4FEFEFF LEA EAX,DWORD PTR SS:[EBP+FFFEFEA4]
004266B5 8B95 F4FFFEFF MOV EDX,DWORD PTR SS:[EBP+FFFEFFF4]
004266BB E8 DCCCFDFF CALL crme.0040339C
004266C0 8B95 A4FEFEFF MOV EDX,DWORD PTR SS:[EBP+FFFEFEA4]
004266C6 8B83 C0010000 MOV EAX,DWORD PTR DS:[EBX+1C0]
004266CC E8 C3B5FEFF CALL crme.00411C94
004266D1 EB 22 JMP SHORT crme.004266F5
004266D3 BA B8674200 MOV EDX,crme.004267B8 ; ASCII "Key file contains wrong serial!"
004266D8 8B83 B0010000 MOV EAX,DWORD PTR DS:[EBX+1B0]
004266DE E8 B1B5FEFF CALL crme.00411C94
004266E3 EB 10 JMP SHORT crme.004266F5
004266E5 BA E0674200 MOV EDX,crme.004267E0 ; ASCII "Key file is not valid!"
004266EA 8B83 B0010000 MOV EAX,DWORD PTR DS:[EBX+1B0]
004266F0 E8 9FB5FEFF CALL crme.00411C94
004266F5 8D85 A8FEFEFF LEA EAX,DWORD PTR SS:[EBP+FFFEFEA8]
004266FB E8 C8D7FDFF CALL crme.00403EC8
00426700 E8 A3BFFDFF CALL crme.004026A8
00426705 33C0 XOR EAX,EAX
00426707 5A POP EDX
00426708 59 POP ECX
00426709 59 POP ECX
0042670A 64:8910 MOV DWORD PTR FS:[EAX],EDX
0042670D 68 30674200 PUSH crme.00426730
00426712 8D85 A4FEFEFF LEA EAX,DWORD PTR SS:[EBP+FFFEFEA4]
00426718 E8 03CBFDFF CALL crme.00403220
0042671D 8D85 F4FFFEFF LEA EAX,DWORD PTR SS:[EBP+FFFEFFF4]
00426723 E8 F8CAFDFF CALL crme.00403220
00426728 C3 RETN
00426729 ^ E9 56C7FDFF JMP crme.00402E84
0042672E ^ EB E2 JMP SHORT crme.00426712
00426730 5F POP EDI
00426731 5E POP ESI
00426732 5B POP EBX
00426733 8BE5 MOV ESP,EBP
00426735 5D POP EBP
00426736 C3 RETN
【算法总结】:
1. 先读取文件名为“fcrackme.key”的keyfile
2. 计算keyfile中00之前的用户名(其实也可不写,直接用十六进制编辑器写个00 00 00 00 00五字节的内容即可),
serial=1;
for (i=0;i<lstrlen(username);i++)
{
serial=(username[i]*serial)^ 63546D32h
}
serial=serial >> 1
3. 文件中00之后的注册码即是上面计算出来值,这里提供两组正确的keyfile(十六进制编辑器下的情况):
[第一组]00000000:00 00 00 00 00
[第二组]00000000:72 69 75 73 6B 73 6B 00 C8 CB DB 79 (“riusksk 人踶”)
【注册机】:
#include "stdio.h"
#include "string.h"
void main()
{
unsigned long temp=1;
char serial[5];
char username[50];
int i;
int userlen;
FILE *keyfile;
printf("please input your name:\n");
gets(username);
userlen=strlen(username);
for (i=0;i<userlen;i++)
{
temp=(username[i]*temp)^0x63546D32;
}
temp=temp >> 1;
strcat(username," ");
if((keyfile=fopen("fcrackme.key","wt"))==NULL)
{
printf("keyfile creating errer!");
return;
}
else
{
fwrite(username,userlen,1,keyfile);
serial[0]=0;
serial[1]=temp;
serial[2]=temp>>8;
serial[3]=temp>>16;
serial[4]=temp>>24;
for(i=0;i<5;i++)
fputc(serial[i],keyfile);
printf("\nkeyfile has created successful!!\n");
printf("Make By riusksk\n");
}
return;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)