前两天TAE!让我看看KEYGENNING4BEWBIES 的#3,那个东西很简单,做了它的注册机
KEYGENNING4NEWBIES有7个KEYGENME(其中第二个有问题),这些KEYGENME的
作用就是让初学者练习写KEYGEN,其中有的是比较简单的(如#1,#3)
这次我要写的KEYGENME #7用了MD5算法(相应的资料可以在http://www.rsa.com找到)
下载地址:http://www.leelouonline.com/users/bofh/k4n/k4n7.zip
使用
工具:TRW2000
难度 :5(10为最难,0为最易)
CRACKER :伪装者[BCG&&CCG]
目的 :
学习破解一周年纪念
目标 : 做出这个的注册机,并且使初学者看完之后能有所收获
过程如下:
运行KEYGENNING4NEWBIES #7(以下简称"#7")
输入用户名,注册码
用户名:cracknow
注册码:121212
启动TRW2000
BPX HMEMCPY
按"OK"键,被
拦截 一次PMODULE后来到0167:00401B8A这里
BC *并用F9在这里下新的断点
0167:00401B8A CMP EAX,BYTE +10 -------------->输入的注册码的位数和16比较
0167:00401B8D JNZ 00401BA8 不是16就跳(呵呵~~想起一位大客的口诀
0167:00401B8F PUSH BYTE +64 "一条就死,九筒便和"不过如果这样的话
0167:00401B91 PUSH DWORD 0040603C 就不能叫KEYGEN ME了~~)所以从新输入注
0167:00401B96 PUSH DWORD 03E8 册码,新注册码为:1212121212121212
0167:00401B9B PUSH ESI
0167:00401B9C CALL EDI
0167:00401B9E CALL 00401D90------------------>将输入的注册码转成十六进制
0167:00401BA3 CALL 00401C70------------------>关键的CALL 了,一定要进去!
0167:00401BA8 POP EDI
0167:00401BA9 XOR EAX,EAX
0167:00401BAB POP ESI
0167:00401BAC RET 10
***********************************************
0167:00401CAF LEA EAX,[EBP-78]-------------->进入之后不是到这里,但上面的我觉得
0167:00401CB2 PUSH EAX 都不重要,所以没有U下来
0167:00401CB3 CALL 00401A10 将用户名进行进行标准的MD5转换(不重要
0167:00401CB8 ADD ESP,BYTE +08 不用跟,跟也看不明白~~呵呵~~~)
0167:00401CBB MOV EBX,[EBP-14]-------------->从这里开始你必须要集中精力了,因为如
0167:00401CBE MOV [EBP-04],EBX | 果你要做这个的注册机,那么底下的每一
0167:00401CC1 XOR EBX,[EBP-0C] | 行你都要明白是做什么用的!
0167:00401CC4 MOV [00406CE4],EBX | 我们设用户名经过MD5转换后的结果为S
0167:00401CCA MOV EBX,[EBP-10] | S[0]~~S[3]分别表示S的4个部分,这些
0167:00401CCD MOV [EBP-18],EBX | 行的作用就是使[ebp-4]=[ebp-14]=s[0]
0167:00401CD0 MOV EBX,[EBP-0C] | [ebp-10]=[ebp-18]=s[1],[ebp-c]=[ebp-
0167:00401CD3 MOV [EBP-1C],EBX | 1c]=s[2],[ebp-8]=[ebp-20]=s[3],另外
0167:00401CD6 MOV EBX,[EBP-08] | 再设一个N,N=S[0]^S[2];
0167:00401CD9 MOV [EBP-20],EBX-------------
0167:00401CDC MOV EBX,[004060A0]----->注册码的前8个和后8个分别放入ebp-80,ebp-7c
0167:00401CE2 MOV [EBP-7C],EBX | 这时你会发现如果注册码用1212121212121212这
0167:00401CE5 MOV EBX,[004060A4] | 样前后相同的数回造成不方便观察,所以退出,将
0167:00401CEB MOV [EBP-80],EBX------->注册码改成1212121234343434 继续
0167:00401CEE MOV ECX,[EBP-7C]------------->从这里开始是关键中的关键!!!!!!
0167:00401CF1 SHL ECX,04 | 最好用笔抄下来慢慢分析
0167:00401CF4 ADD ECX,[EBP-1C] | 这些行将输入的注册码和字符串s做
0167:00401CF7 MOV EDX,[EBP-7C] | 运算,最后的结果分别和0x6779656b
0167:00401CFA ADD EDX,[00406CE4] | 0x656d6e65比较(呵呵~~就是keygenme)
0167:00401D00 XOR ECX,EDX |
0167:00401D02 MOV EAX,[EBP-7C] |
0167:00401D05 SHR EAX,05 |
0167:00401D08 ADD EAX,[EBP-20] |
0167:00401D0B XOR ECX,EAX |
0167:00401D0D MOV EDX,[EBP-80] |
0167:00401D10 SUB EDX,ECX |
0167:00401D12 MOV [EBP-80],EDX | ********注意这里!!!********
0167:00401D15 MOV EAX,[EBP-80] |
0167:00401D18 SHL EAX,04 |
0167:00401D1B ADD EAX,[EBP-04] |
0167:00401D1E MOV ECX,[EBP-80] |
0167:00401D21 ADD ECX,[00406CE4] |
0167:00401D27 XOR EAX,ECX |
0167:00401D29 MOV EDX,[EBP-80] |
0167:00401D2C SHR EDX,05 |
0167:00401D2F ADD EDX,[EBP-18] |
0167:00401D32 XOR EAX,EDX |
0167:00401D34 MOV ECX,[EBP-7C] |
0167:00401D37 SUB ECX,EAX |
0167:00401D39 MOV [EBP-7C],ECX------------->
0167:00401D3C CMP DWORD [EBP-7C],6779656B-->跳就死!
0167:00401D43 JNZ 00401D69 |
0167:00401D45 CMP DWORD [EBP-80],656D6E65 |
0167:00401D4b JNZ 00401D69----------------->跳就死!
现在开始对那个"关键中的关键"分析
比较的是[ebp-7c]与0x6779656B,[ebp-80]与0x656D6E65,所以如果注册码正确那么这两处在比较的时候
就分别应该为0x6779656B,0x656D6E65,看看上面的这行0167:00401D12 MOV [EBP-80],EDX
将edx放入[ebp-80]中,那么这个EDX就应该等于0x656D6E65,并且这行0167:00401D12以后的[ebp-80]
都要等于0x656D6E65!利用这点我们可以反推出401D34行中的ecx,它就是正确的注册码的第二部分,
然后再利用这个反推出401D0D中的edx,这个就是正确注册码的第一部分
得到结果
用户名:cracknow
注册码:f7afdc2f25d32e18
注册机如下(VC)
#include
#include
#include "md5lib.h"
void main()
{unsigned long s[4],k[2],ea,eb,ec,ed,n,sn1,sn2;
char *text;
int i,j;
int tmp[16],d[2];
printf("*********KEYGENME #7*********\nThis keygen is made by Pretender\nPlease input your name : ");
k[0]=0x656d6e65;k[1]=0x6779656b;
gets(text);
text=MDString(text); //用户名做MD5
for(i=0;i<16;i++) //将结果分为s[0]~s[3]
{d[0]=text[i*2];d[1]=text[i*2+1]; //四个部分
for(j=0;j<2;j++)
{if(d[j]>47&&d[j]<58) d[j]=d[j]-48;
if(d[j]>64&&d[j]<71) d[j]=d[j]-55;
if(d[j]>96&&d[j]<103) d[j]=d[j]-87;
}
tmp[i]=d[0]*16+d[1];
if(i%4==3)
s[i/4]=tmp[i]*65536*256+tmp[i-1]*65536+tmp[i-2]*256+tmp[i-3];
}
n=s[0]^s[2];
//printf("%lx\n",n); //反推的过程
ea=k[0];
ea<<=4;
ea+=s[0];
ec=k[0];
ec+=n;
//printf("%lx",ea);
ea^=ec;
ed=k[0];
ed>>=5;
ed+=s[1];
ea^=ed;
ec=ea+k[1];
sn2=ec;
ec<<=4;
ec+=s[2];
ed=sn2;
ed+=n;
ec^=ed;
ea=sn2;
//printf("%lx",ea);
ea/=32;
ea+=s[3];
ec^=ea;
ed=ec+k[0];
printf("Your Register code is : %08lx%08lx",ed,sn2); //输出结果
printf("\n ***************************** --- --- ---\n *Welcome to WWW.CRACKNOW.COM* / / / --\n ***************************** --- --- --/\n");
}
|