我的破解心得(5) (16千字)
破解程式:
HyperCam Version 1.20.04(for Intel processors)
破解工具:
SoftIce 3.0 for Windows95(或更高版本)
破解者:
chcw
1. 用WinICE載入HyperCam.exe
2. 在HyperCam中選擇License/Enter License Now,彈出HyperCam License對話方塊.
3. 按Ctrl-D,切換到SoftICE視窗,在SoftICE命令列設定斷點 BPX MessageBoxA
4. 再按Ctrl-D,回到執行程式HyperCam.在Register和Key中隨便填入註冊碼,如Register=chcw,Key=
9530109.並選擇一種註冊型別,如Sigle User - Number of Licensed 1,添完上述內容後,選擇
'OK', 觸發SoftICE。
5. SoftICE的光帶停留在MessageBoxA函式的入口處:
USER32!MessageBoxA
015F:BFF541BA PUSH EBP
將游標移到MessageBoxA函式的返回處
015F:BFF541D RET 0010
並鍵入命令HERE,程式執行到游標所在處。(由於函式MessageBoxA要呼叫函式MessageBoxExA,
所以在上述執行過程中會出現一個對話方塊,直接選'OK'或'確定’即可)
6. 連續按F10鍵,回到MessageBoxA函式被呼叫處:
015F:00427881 CALL [USER32!MessageBoxA]
015F:00427887 POP EDI
015F:00427888 POP ESI
015F:00427889 RET 000C
這部分程式碼在程式HyperCam.exe中,但在程式呼叫MessageBoxA後,程式立即以子程式的方式返回,
綜合在呼叫MessageBoxA前的程式碼,可以看出這是程式HyperCam中的一個子程式(入口地址為00427853),
其主要功能大致是顯示一個資訊框而已。因此,我們沒有必要把注意力放在這裡。繼續按F10,跳出這
個子程式。返回到呼叫它的上一層程式。
015F:0040A03B CALL 00427853 (呼叫上述子程式00427853)
顯然,既然CALL 00427853的功能是顯示一個註冊錯誤的資訊框,那麼在它被執行之前,一定有一些
函式或語句是用來判斷註冊正確與否,並根據判斷結果來決定是顯示錯誤資訊,還是提示註冊成功
(HyperCam在使用者輸入正確的註冊碼時,沒有任何提示資訊)。 從CALL 00427853語句向上找,在
015F:0040A020處有一條語句JMP 0040A040,跳轉地址正好是CALL 00427853的下一條語句。由於這是
一條無條件跳轉語句,我們繼續往上找能使程式流程執行到這條跳轉語句的條件跳轉語句(這裡的條
件,就是指註冊碼正確與否)。 在015F:0040A00D和015F:00409FF2處各有一條條件跳轉語句,但它
們都不影響程式的主要流程。最後在015F:00409FD8處,有一個條件跳轉:
015F:00409FD1 CALL 004092E0 ;
呼叫004092E0檢查註冊碼的有效性
015F:00409FD6 TEST EAX, EAX ;
若返回值為0,則顯示錯誤資訊。
015F:00409FD8 JE 0040A022 ;
分析以上語句,不難看處,當呼叫函式004092E0的返回值為0時,將顯示註冊錯誤的對話方塊視窗。可
見,函式4092E0應該是HyperCam檢查註冊碼是否正確的函式。鍵入命令BC *,清除原先的斷點;並
在015F:00409FD1處雙擊滑鼠,設定執行斷點。
7. 按Ctrl D回到HyperCam中,仍使用原先的註冊碼,再次選擇'OK'後。觸發SoftICE,執行亮條停留在
斷點015F:00409FD1 CALL 004092E0處,先按F10,Step Out過這個函式的呼叫。此時,EAX的值為0
並顯示高亮,顯然函式004092E0改動了EAX。在SoftICE的命令列下,鍵入r EAX=1,造成註冊成功的假
象,再按Ctrl D,繼續執行程式,返回到HyperCam。這時我們發現,提示使用者輸入註冊資訊的視窗
HyperCam License已經關閉。但在License頁中顯示的資訊還是未註冊, 這是怎麼回事呢?
我們可以作這樣一個假設,004092E0函式不僅透過返回值來表明註冊資訊正確與否,還透過傳遞
指標引數來返回註冊資訊。呼叫004092E0的函式再進一步將這些註冊資訊記錄在磁碟上。由於我們在
上面程式的執行過程中沒有填充這些資訊,因而儘管程式的流程大致是正確的,但註冊資訊卻沒有被
儲存下來。
8. 如果要用Patch方法來破解HyperCam,顯然不能只修改015F:00409FD8處的條件判斷,具體該如何破解,
我沒有仔細研究。我主要分析了獲取有效註冊碼的方法。
9. 繼續上面的破解過程,在015F:00409FD1處設定有執行斷點。按'OK'後,觸發SofeICE,執行亮條停留
在斷點處,按F8,進入函式004092E0中。
10.接下來按F10鍵,到達函式體中的兩個子函式呼叫子函式呼叫015F:00409313 CALL 和0041F3AC,
015F:00931C CALL 0041F3BF該函式的大致作用 是判斷時區和現在的時間,可能與註冊方式中的臨時
性註冊有關,由於我們選擇單使用者按份數註冊的方式。因而可以直接跳過(Step Out)這兩個函式。繼
續按F10鍵。
11.接下來進入兩個迴圈:
015F:0040932E MOV EDX, DWORD PTR [ESI]
...
015F:00409348 CALL 0040EDB0
; 字串比較(stricmp)
015F:0040934D ADD ESP, 0000000C
015F:00409350 TEST EAX, EAX
;
015F:00409352 JE 004096B5
; 若eax==0則跳轉
015F:00409358 ADD ESI, 00000004
; 指向下一個字串
015F:0040935B CMP ESI, 00436EBC
; 字串陣列都比較完了嗎?
015F:00409361 JB 0040932E
; 若未比較完,則繼續比較。
在迴圈中不斷呼叫子程式0040EDB0,該程式的功能相當於stricmp,它將使用者輸入的姓名和系統內
部的兩個陣列中的字串進行比較。字串陣列如下:
char *s1[]={"hacker","ED!SON","tHATDUDE","super user","saltine","xygorf","Borin
Thibault",
"Alexander Chen","-M-O-A-","^SaTaNa","Michael
Jackon"}
char *s2[]={"abel", "Monkey", "jackkuo", "TRACY"}
寫到這裡,也許有人會猜想,這可能是程式在比較使用者輸入的姓名是否和系統保留的幾個字串相
同,若相同,則繼續檢驗註冊碼的正確性,也就是說,這是系統留下的後門。當時我也這麼想,那麼剩
下的只有註冊碼了。於是,我按Ctrl D,回到HyperCam的註冊視窗,將名字那一欄用上述陣列中的某個
字串填寫(如"saltine"),再按Ctrl D,在命令列輸入s ds:0 l ffffffff '9530109',找到了存放註冊碼
的記憶體地址0030:80527d70, 然後設定斷點BPM 0030:80527d70,再鍵入X,執行程式。但是在攔截到對字元
串'9530109'的所有訪問中,卻沒有發現可能是檢驗註冊碼的語句。看來我們原先的猜想是錯誤的。再次
分析上述的迴圈後發現。字串陣列s1、s2實際上是兩個黑名單,當使用者輸入的註冊名是陣列中的某個
字串時,系統立即認為註冊失敗,不再檢查註冊碼。而只要你輸入的註冊名不是上面陣列中的某個字元
串後,就可以跳過這兩個迴圈,
12.繼續按F10鍵,執行到下列語句處:
015F:00409395 PUSH ECX
; 將註冊碼地址壓棧
015F:00409396 CALL 004098C0
015F:0040939B MOV EBX, EAX
; EBX <- EAX
015F:0040939D ADD ESP, 4
015F:004093A0 TEST EBX, EBX
; 返回值在EBX中
015F:004093A2 JZ 004096B5
; 若EBX為0,則程式認為註冊出錯。
由於子程式004098C0的引數為註冊碼,而該函式返回值決定註冊是否成功,因而有必要分析該子程式。按
F8,進入該程式:
...
015F:004098D6 CMP AL, 41
;
015F:004098D8 JL 004098E6
; 對註冊碼進行檢查,
015F:004098DA MOV AL, [ECX]
; 將不在'A'-'Z'範圍內的字元過濾掉。
015F:004098DC CMP AL, 5A
015F:004098DE JG 004098E6
...
015F:00409903 CMP ECX, 00000080
015F:0040990D JGE 004099A5
; 檢查註冊碼的長度(存放在ECX中),
015F:00409913 CMP ECX, 03
; 長度<=3或>=128的為非法。
015F:00409916 JLE 004099A5
...
015F:0040991C MOVSX EBP, BYTE PTR [ESP+16]
015F:00409921 SUB EBP, 00000041
; 對註冊碼進行某種換算,
...
015F:0040992C MOV AL, BYTE PTR [ESP+EBX+14]
; 得到一個新的加密碼SecretCode。
...
015F:00409947 CALL 00409A20
...
015F:00409967 INC EBX
015F:00409968 CMP EBX, ECX
015F:0040996A JL 0040992C
...
015F:0040996C MOVSX ESI, BYTE PTR [EDI+0043B77F]
; 將加密碼分成前n-1個字元和
015F:0040997B MOV BYTE PTR [EDI+0043B77F],
00 ; 最後一個字元兩部分,
015F:00409982 CALL 004099C0
; 分別作某種運算,
...
015F:0040998C CMP ESI, EAX
; 比較其結果是否相同。
015F:0040998E SETNE CL
; 若不同,則註冊為非法。
...
015F:00409992 AND ECX, 0043B780
; 將加密碼SecretCode(去掉最後一個字元)的地址返回。
015F:00409998 MOV EAX, ECX
;
子程式004098C0對註冊碼進行檢查和判斷,生成SecretCode,並將結果放在EAX返回。
13.從子程式004098C0返回後,繼續按F10鍵,下面一部分程式將再次檢查你的註冊姓名是否在黑名單s2上(看
來作者對陣列s2中的人恨之入骨)跳過這段程式。到015F:0040945B MOV EAX,[EBP+14]處。
14.接下來,程式將對使用者輸入的註冊名進行處理:
015F:004094B9 LEA EDI, DWORD PTR [ESP+20]
; 使用者輸入的註冊名所存放的地址
...
015F:004094C1 LEA EDX, DWORD PTR [ESP+00000120]
; 系統處理後得到的新串LName存放的地址
015F:004094C8 REPNZ SCASB
015F:004094CA NOT ECX
;
取得註冊名的串長度
...
015F:004094DE REPZ MOVSD
; 將註冊名複製到新串LName中
...
015F:004094F5 CMP ECX, 00000010
; 檢查使用者輸入的姓名是否小於16個字元,
015F:004094F8 JL 004094B9
; 如果是,則將姓名串不斷重複複製到
;
LName處,直到超過16個字元為止。
由於我們輸入的是"chcw", 因而系統處理後將得到串LName="CHCWCHCWCHCWCHCW"。
15.繼續按F10,直到下列語句處:
015F:004096D2 MOV AL, [EBX]
; AL <- SecretCode[0](EBX中存放的是SecretCode的地址)
015F:004096D4 MOV EBP, [ESP+00000238]
015F:004096DB CMP AL, 50
; 若AL=='P',則為第一種註冊方式(Single User)
015F:004096DD JZ 00409769
; 跳轉到第一種註冊方式的處理語句處。
015F:004096E3 CMP AL, 53
; 若AL=='S',則為第二種註冊方式(Unlimited Site License)
015F:004096E5 JZ 0040974F
; 跳轉到第二種註冊方式的處理語句處。
015F:004096E7 CMP AL, 57
; 若AL=='P',則為第三種註冊方式(Unlimited Word-Wide License)
015F:004096E9 JNZ 00409707
; 若三種都不是,則註冊出錯。
015F:004096EB MOV EDI, DWORD PTR [ESP+0000023C]
015F:004096F2 CMP EDI, 00000003
; 判斷使用者輸入的註冊方式是否為3
015F:004096F5 JNE 00409707
; 若不是,則註冊出錯。
015F:004096F7 CMP BYTE PTR [EBX+01],
4F ; 判斷SecretCode[1]是否為'O'
015F:004096FB JNE 00409707
; 若不是,則註冊出錯。
015F:004096FD CMP BYTE PTR [EBX+02],
52 ; 判斷SecretCode[1]是否為'R'
015F:00409701 JE 00409787
; 若不是,則註冊出錯。
...
015F:00409707 LEA ECX, DWORD PTR [ESP+00000230]
; 註冊出錯處理
...
015F:0040974F MOV EDI, DWORD PTR [ESP+0000023C]
015F:00409756 CMP EDI, 00000002
; 判斷使用者輸入的註冊方式是否為2
015F:00409759 JNE 00409707
; 若不是,則註冊出錯。
015F:0040975B CMP BYTE PTR [EBX+01],
49 ; 判斷SecretCode[1]是否為'I'
015F:0040975F JNE 00409707
; 若不是,則註冊出錯。
015F:00409761 CMP BYTE PTR [EBX+02],
54 ; 判斷SecretCode[1]是否為'T'
015F:00409765 JE 00409787
015F:00409767 JMP 00409707
; 若不是,則註冊出錯。
015F:00409769 LEA EAX, DWORD PTR [EBX+01]
;取得SecretCode[1]的地址
015F:0040976C PUSH 00000002
015F:0040976E PUSH EAX
; 將SecretCode[1]的地址壓棧
015F:0040976F CALL 00409A40
; 根據字元SecretCode[1]和字元SecretCode[2](大寫字元)
;計算註冊的數目。由於採用的是26進位制,因而最多可以表示26x26份複製。
015F:00409774 MOV EDI, DWORD PTR [ESP+00000244]
015F:0040977B ADD ESP, 00000008
015F:0040977E CMP EDI, 00000001
; 判斷使用者輸入的註冊方式是否為2
015F:00409781 JNE 00409707
; 若不是,則註冊出錯。
015F:00409783 CMP EBP, EAX
; 比較計算所得得註冊數是否與使用者輸入的註冊數相同
015F:00409785 JNE 00409707
; 若不是,則註冊出錯。
從上面的程式段可以看出,該段程式的主要功能是對SecretCode進行檢查,根據使用者註冊的方式不同,可
分為三種情況:
1. 第一種註冊方式(Single User),SecretCode的第一個字元必須是'P',接下來的兩個字元應為註冊數目的
26進位制值。
2. 第二種註冊方式(Unlimited Site License),該種情況下,SecretCode的頭三個字元必須是'S'、'I'、'T'。
3. 第三種註冊方式(Unlimited Word-Wide License),該種情況下,SecretCode的頭三個字元必須是'W'、'O'、
'R'。
16.在SecretCode的前三個字元與使用者的註冊方式完全相符後,繼續按F10鍵,到下列語句處:
015F:004097AB PUSH 00436F68
; 字串"HCA"的地址壓棧
015F:004097B0 PUSH EBX
; SecretCode[3]的地址壓棧
015F:004097B1 CALL 0040ED70
; 比較以SecretCode[3]為啟始地址的字串的前三個字元是否為'HCA'
015F:004097B6 ADD ESP, 0000000C
015F:004097B9 TEST EAX, EAX
; 若不是"HCA",則註冊出錯。
015F:004097BB JNE 00409707
該段程式檢查SecretCode的第三到第六個字元是否為"HCA"(就是HyperCam的縮寫),如果不是,則註冊出錯。
17.透過上述檢查後,繼續按F10鍵,到以下語句處:
015F:004097C8 MOV DL, [EAX] ;
DL <- LName[i]
015F:004097CA MOV BL, [ESI] ;
BL <- Secret[6+j]
015F:004097CC MOV CL, DL
015F:004097CE CMP DL, BL
; 比較DL,BL是否相當。
015F:004097D0 JNZ 004097F0 ;
若不相等,則註冊出錯
015F:004097D2 TEST CL, CL ;
判斷是否已經到達字串的末尾
015F:004097D4 JZ 004097EC
...
015F:004097E2 ADD EAX, 02 ;
i+=2
015F:004097E5 ADD ESI, 02 ;
j+=2
015F:004097E8 TEST CL, CL ;
判斷是否已經到達字串的末尾
015F:004097EA JNZ 004097C8 ;
若不是,則迴圈。
這部分程式段將SecretCode(Secret在第14步處呼叫程式004098C0時產生)剩餘的字元所組成的字串與字串LName進行比
較。若二者相同,則認為註冊成功。
18.至此,我們已經分析完HyperCam的註冊檢驗過程。在此過程中,程式不在記憶體中生成任何合法的註冊碼,而僅根據使用者輸入
的註冊碼產生一個SecretCode,並對此SecretCode進行後續的操作,這使得破解過程較為複雜。而且在整個註冊檢驗過程中,
程式還多次檢驗使用者輸入的註冊名是否是常用的Cracker名字,這使破解的複雜程度進一步增加。因此,我們有理由相信,
HyperCam程式在編寫過程中,曾經有意識的加入了反Crack的程式碼。
19.下面我們要為HyperCam寫一個註冊碼生成器,透過對HyperCam註冊檢驗過程的分析,我們已經知道,該註冊碼生成器的輸入
資訊為:
1.使用者註冊的姓名Name。
2.使用者註冊的方式Register type。
3.對於以第一種註冊方式(Single User)註冊的使用者,還需要輸入註冊的數目Copy Number.
根據輸入的資訊,可以生成中間程式碼SecretCode,它由三部分組成,分別對應於下列資訊:
1.第一部分為3個字元,表示註冊的方式程式碼,可以由輸入2、3換算得到。
2.第二部分為固定的三個字元"HCA"。
3.第三部分為LName,可以由輸入Name換算得到。
得到了SecretCode之後,我們可以進一步求取最終的註冊碼Register Code, 這是一個逆向的過程,由於SecretCode的每
個字元是透過Register Code的當前字元以及SecretCode的前一個字元生成的,因此,只要註冊碼的前面部分是正確的,
我們就可以採用窮舉法變換Register Code當前的字元,並檢驗由此生成的SecretCode是否合法,從而能從左自右,試探
出全部合法的註冊字元。由於每個字元只能取大寫字元,因此全部的工作量只有26 X strlen(Register Code)。另外註冊
碼Register Code除了要求能正確生成SecretCode外,其自身還要滿足一定的條件(在第12步中已經指出),這可以透過
對Register Code的最後一個字元進行檢驗來實現。
附:HyperCam的註冊碼生成器KeyMaker.C
---------------------- KeyMaker.C -----------------------------
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include <process.h>
int shiftsum(char *result, int len)
{
int fact,i,x,sum=0;
char c;
fact=1;
if (len<fact) len=strlen(result);
if (len<=0) return sum;
for (i=0; i<len; i++) {
c=result[i];
x=c-'A';
x*=fact;
sum += x;
fact = 26*fact;
}
return sum;
}
char checksum(char *regcode)
{
int sum=0,val,i;
char c,tmp;
for (i=0;i<strlen(regcode);i++) {
c=regcode[i];
val=c-'A';
if (i & 1) val=val*2;
if (val>=26) val=val-25;
sum += val;
}
tmp=sum % 26;
return tmp;
}
int genregcode(char *regcode, char *result, int *tail)
{
char *table="EHIOTBVPSFRNWYQCJAGKUZXDML";
char tmpcode[27];
int i,j,x,y;
long len;
char c;
/* Filter characters that are not in 'A' to 'Z' */
for (i=0,j=0; regcode[i]!='\0'; i++)
if (isupper(regcode[i])) tmpcode[j++]=regcode[i];
tmpcode[j]='\0';
/* Test the len of the regcode */
len=strlen(tmpcode);
if ((len>=128) || (len<=3)) {
printf("error: cannot accept a regcode with mislen");
return NULL;
}
i=j=0;
y=tmpcode[2]-'A';
for (i=0;i<len;i++)
if (i!=2) {
c=tmpcode[i];
if (c<'A') return NULL;
if (tmpcode[j]>'Z') return NULL;
x=strchr(table, c)-table;
x=x-y;
x--;
if (x<0) x+=26;
result[j++]=x+'A';
y=c-'A';
}
result[j]='\0';
*tail=result[j-1]-'A';
result[j-1]='\0';
return checksum(result);
}
void main()
{
char regcode[27];
char secretcode[27],tmp[27];
int i,j,len;
char ch;
char LName[33],Name[33];
int rtype,copy;
int chksum,tail;
int again;
for (i=0;i<26;i++)
regcode[i]='A';
regcode[i]='\0';
printf("\n\tHyper Cam Cracker\n\tWritten By Mr. Chcw\n\n");
printf("\tPlease enter your name: ");
gets(Name);
strcpy(LName, Name);
if (strlen(Name) >= 32) {
printf("Error : User Name is too long\n");
exit(1);
}
if (strlen(Name)<16) {
while (strlen(LName)<16)
strcat(LName, Name);
LName[16]='\0';
}
do {
printf("\n\tPlease choose the license type:\n");
printf("\t1. Single User\n");
printf("\t2. Unlimited Site License\n");
printf("\t3. Unlimited World Wide License\n\t");
scanf("%d", &rtype);
again=0;
switch (rtype) {
case 1:
printf("\n\tPlease enter number of lincensed: ");
scanf("%d", ©);
secretcode[0] = 'P';
secretcode[1] = 'A' + copy % 26;
secretcode[2] = 'A' + copy / 26;
break;
case 2:
strcpy(secretcode, "SIT");
break;
case 3:
strcpy(secretcode, "WOR");
break;
default:
printf("\tIncorrect option, please enter a number in
1-3");
again=1;
}
} while (again);
secretcode[3]='\0';
strcat(secretcode, "HCA"); // Add the
HCA mark
strcat(secretcode, LName); // Add the
LName String
l
相關文章
- 我的破解心得(1) (3千字)2001-03-13
- 我的破解心得(6) (3千字)2001-03-13
- 我的破解心得(8) (2千字)2001-03-13
- 我的破解心得(9) (4千字)2001-03-13
- 我的破解心得(11) (9千字)2001-03-13
- 我的破解心得(12) (1千字)2001-03-13
- 登陸奇兵3.0破解心得 (5千字)2001-05-02
- 破解心得之WinImage篇 (15千字)2001-07-01
- 破解心得之eXeScope篇 (9千字)2001-07-01
- Readbook 1.31破解心得
(3千字)2000-03-01
- PolyView 破解 (5千字)2000-12-31View
- 破解MyMahj (5千字)2001-06-20
- 破解Don't Panic! 4.0(我又來了) (5千字)2001-06-22
- 我的破解之路-BBOY (3千字)2000-07-21
- 資料大師3.17破解心得!(我對vfp的程式很頭疼呀!) (1千字)2001-12-04
- BrickShooter 2.1破解心得(新手看看吧) (18千字)2001-03-09
- 破解心得之CHMMaker(耶圃歟┢ (11千字)2002-01-27HMM
- 破解TurboLaunch 4.04 (5千字)2001-06-06
- 我的MYSQL學習心得(16) : 優化2015-06-07MySql優化
- 破解心得之CDRWin 4.0A BETA篇 (18千字)2001-04-24
- 輕鬆提取資源1.45破解心得
(7千字)2015-11-15
- jdpack的脫殼及破解 (5千字)2002-06-25
- 談談VB程式的破解 (5千字)2002-10-28
- 破解入門5 (3千字)2000-09-23
- duelist crackme 1 破解 (5千字)2000-10-16
- IPTools 1.10 破解 (5千字)2001-02-11
- see This 破解實戰! (5千字)2000-06-26
- 如何破解CuteFTP 4.0 (5千字)2000-07-20FTP
- 初學者請進(一篇破解javagirl的心得) (2千字)2000-05-09Java
- 我來寫一下LanSentry的解狗破解過程 (5千字)2002-01-19
- 《漂葉網咖管理系統4.0》破解心得: (9千字)2001-01-14
- PolyView再破解---請指教 (5千字)2001-01-02View
- 破解XFtpSvr =====> 請進 (5千字)2001-07-01FTPVR
- 破解MailScan V3.5.1.2 (5千字)2001-08-31AI
- 砸碎SLock, 我的一次破解.
(3千字)2015-11-15
- 一個超容易破解的軟體! (5千字)2001-01-21
- 破解心得之3DMark2001篇 (10千字)2001-04-183D
- FINDITNOW!1.25 or 102 中文版 破解心得 (14千字)2002-02-09