KEYGENNING4NEWBIES #7破解過程+序號產生器
前兩天TAE!讓我看看KEYGENNING4BEWBIES 的#3,那個東西很簡單,做了它的序號產生器
後來看雪給了我一個代理伺服器地址,使我能夠到國外的一些破解站轉轉,於是我找
到了這個NUMBER 7
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 <stdio.h>
#include <stdlib.h>
#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");
}