EditPlus v2.12en破解全過程
第一篇破文,還望大家多多指教!!!!
【破解作者】icytear
【作者郵箱】icytear@126.com
【使用工具】SoftIce4.3.1,IDA4.5,PEiD0.92
【破解平臺】WindowsXP Pro SP1.
【破解日期】2004.12.7 - 2004.12.22
【軟體名稱】EditPlus v2.12en
【軟體大小】913,408 BYTE
【加殼方式】無殼
【下載地址】
【軟體簡介】
EditPlus是Internet時代的32位文字編輯程式,HTML編輯及程式設計師的Windows平臺編輯器。它可以充分的替換記事本,它也提供網頁作家及程式設計師許多強悍的功能。對於HTML、CSS、PHP、ASP、Perl、C/C++、Java、JavaScript及VBScript的語法突顯。當然,它也可以在自定義語法檔案後擴充其他的程式語言。嵌合網頁瀏覽器作HTML頁的預覽,及FTP命令做本地檔案上傳到FTP伺服器。其他功能還包含HTML工具欄、使用者工具、列號、標尺、URL突顯。自動完成、剪貼文字、行列選擇、強大的搜尋與替換、多重撤消/重做、拼寫檢測、自定義鍵盤快捷鍵、以及更多。
【破解宣告】本文僅供技術交流、學習之用。
【破解內容】
1. 用PEiD開啟editplus發現無殼。
2. 開啟程式出現註冊對話方塊,點選輸入註冊碼,Username輸入"icytear",Regcode輸入"280060443",下斷點
addr editplus
bpx GetWindowTextA
單擊註冊按鈕,程式被中斷,按F12退出GetWindowTextA函式,到如下位置
001B:004BFC91 PUSH DWORD PTR [ESP+08]
001B:004BFC95 PUSH DWORD PTR [ESP+08]
001B:004BFC99 PUSH DWORD PTR [ECX+1C]
001B:004BFC9C CALL [USER32!GetWindowTextA]
001B:004BFCA2 JMP 004BFCB6 ;---->按F12後到這裡,goto #exit
...
001B:004BFCB6 RET 0008 ;#exit
按2次F10執行程式碼,程式返回到#R01
001B:0047C850 MOV EAX,[ESP+0C]
001B:0047C854 MOV ECX,[ESP+04]
001B:0047C858 PUSH ESI
001B:0047C859 MOV ESI,[ESP+0C]
001B:0047C85D PUSH EAX
001B:0047C85E PUSH ESI
001B:0047C85F CALL 004BFC8A
001B:0047C864 MOV AL,[ESI] ;#R01---->程式返回到這裡
001B:0047C866 CMP AL,20 ;---->從前向後比較字元是否為空格
001B:0047C868 JZ 0047C86E ;---->為空格則跳轉,繼續比較下一個字元
001B:0047C86A CMP AL,09 ;---->比較這個字元是否為製表符
001B:0047C86C JNZ 0047C871 ;---->如果不為空格也不是製表符則跳轉到#J01↓
001B:0047C86E INC ESI ;---->如果字元為空格或製表符則刪除
001B:0047C86F JMP 0047C864 ;---->繼續比較下一個字元(跳轉到#R01↑)
===>:0047C871 PUSH ESI ;↑#J01---->使用者名稱入棧
001B:0047C872 CALL [KERNEL32!lstrlen] ;---->不用說了吧,得到使用者名稱長度
001B:0047C878 MOV ECX,[ESP+14]
001B:0047C87C TEST EAX,EAX ;---->檢查是否輸入了使用者名稱
001B:0047C87E MOV [ECX],EAX ;---->把結果儲存起來
001B:0047C880 JLE 0047C899
001B:0047C882 MOV EAX,[ECX]
001B:0047C884 MOV DL,[ESI+EAX-01] ;---->取出最後一個字元
001B:0047C888 CMP DL,20 ;---->比較是否為空格
001B:0047C88B JZ 0047C892
001B:0047C88D CMP DL,09
001B:0047C890 JNZ 0047C899
001B:0047C892 DEC EAX ;---->繼續向前比較
001B:0047C893 TEST EAX,EAX
001B:0047C895 MOV [ECX],EAX
001B:0047C897 JG 0047C882
001B:0047C899 MOV EDX,[ECX]
001B:0047C89B MOV BYTE PTR [ESI+EDX],00 ;---->刪除末尾的空格和製表符
001B:0047C89F MOV EAX,[ECX]
001B:0047C8A1 TEST EAX,EAX ;
001B:0047C8A3 JNZ 0047C8AD
001B:0047C8A5 PUSH 40
001B:0047C8A7 CALL [USER32!MessageBeep]
001B:0047C8AD MOV EAX,ESI
001B:0047C8AF POP ESI
001B:0047C8B0 RET
上面的程式碼大概的意思就是:檢查輸入的使用者名稱開始和末尾是否為有效字元(非空格和製表符)。
然後返回到#R02:
...
001B:0047C8E1 CALL 0047C850 ;---->取輸入的使用者名稱
001B:0047C8E6 MOV EBX,EAX ;#R02---->D EAX;EAX指向的就是輸入的使用者名稱icytear
001B:0047C8E8 MOV EAX,[ESP+20] ;---->[esp+20]存的是使用者名稱的長度
001B:0047C8EC ADD ESP,10 ;---->平衡堆疊
001B:0047C8EF TEST EAX,EAX ;---->檢查輸入的用使用者名稱是否有效
001B:0047C8F1 JZ 0047C9B1
001B:0047C8F7 LEA EAX,[ESP+0C] ;---->SS:[ESP+0C] = 00000034
001B:0047C8FB LEA ECX,[ESP+14] ;---->SS:[ESP+14] = 0
001B:0047C8FF PUSH EAX
001B:0047C900 PUSH 31
001B:0047C902 LEA EDX,[ESI+5C]
001B:0047C905 PUSH ECX
001B:0047C906 PUSH EDX
001B:0047C907 CALL 0047C850 ;---->用上面同樣的方法得到輸入的註冊碼
001B:0047C90C MOV ECX,[ESP+1C] ;---->[ESP+1C]輸入的註冊碼長度
001B:0047C910 ADD ESP,10 ;---->平衡堆疊
001B:0047C913 TEST ECX,ECX ;---->檢查有效註冊碼長度
001B:0047C915 MOV EDI,EAX
001B:0047C917 JZ 0047C9B1
001B:0047C91D XOR EAX,EAX
001B:0047C91F TEST ECX,ECX
001B:0047C921 JLE 0047C93B
001B:0047C923 XOR ECX,ECX
001B:0047C925 MOV CL,[EDI+EAX] ;---->從輸入的註冊碼取一個字元
001B:0047C928 INC EAX ;---->移動指標指向下一個字元
001B:0047C929 MOV DL,[ECX+00522C90] ;---->查表,把小寫轉換成大寫
001B:0047C92F MOV [EDI+EAX-01],DL
001B:0047C933 MOV ECX,[ESP+0C]
001B:0047C937 CMP EAX,ECX
001B:0047C939 JL 0047C923
001B:0047C93B PUSH EDI ;---->把輸入的註冊碼入棧
001B:0047C93C PUSH EBX ;---->輸入的使用者名稱入棧
001B:0047C93D CALL 0047CA60 ;#C01---->關鍵呼叫
001B:0047C942 ADD ESP,08
001B:0047C945 TEST EAX,EAX
001B:0047C947 JNZ 0047C961 ;---->註冊成功的關鍵
001B:0047C949 PUSH FF
001B:0047C94B PUSH 10
001B:0047C94D PUSH 00005F81
001B:0047C952 CALL 004C7E94 ;---->這裡就彈出錯誤對話方塊了
001B:0047C957 POP EDI
001B:0047C958 POP ESI
001B:0047C959 POP EBX
001B:0047C95A ADD ESP,00000230
001B:0047C960 RET
001B:0047C961 PUSH EDI
001B:0047C962 PUSH EBX
001B:0047C963 CALL 0047C3B0
...
進入#C01 (CALL 0047CA60)繼續跟蹤
001B:0047CA60 SUB ESP,0C
001B:0047CA63 PUSH EBX ;---->使用者名稱入棧
001B:0047CA64 MOV EBX,[KERNEL32!lstrlen]
001B:0047CA6A PUSH ESI
001B:0047CA6B PUSH EDI
001B:0047CA6C MOV EDI,[ESP+1C] ;---->edi指向了使用者名稱
001B:0047CA70 PUSH EDI
001B:0047CA71 CALL EBX ;---->call [lstrlen],得到使用者名稱長度
001B:0047CA73 MOV ESI,EAX
001B:0047CA75 TEST ESI,ESI ;---->
001B:0047CA77 JNZ 0047CA80 ;---->跳到#C01.C1
001B:0047CA79 POP EDI
001B:0047CA7A POP ESI
001B:0047CA7B POP EBX
001B:0047CA7C ADD ESP,0C
001B:0047CA7F RET
001B:0047CA80 CALL 0047C9C0 ;#C01.C1---->跟進去
001B:0047CA85 PUSH ESI
001B:0047CA86 PUSH EDI
001B:0047CA87 PUSH 00
001B:0047CA89 CALL 0047CA10 ;#C01.C2---->
001B:0047CA8E ADD ESP,0C
001B:0047CA91 AND EAX,0000FFFF
001B:0047CA96 PUSH EAX
001B:0047CA97 LEA EAX,[ESP+10]
001B:0047CA9B PUSH 0051824C
001B:0047CAA0 PUSH EAX
001B:0047CAA1 CALL 004AEABC ;#C01.C3---->sprintf
001B:0047CAA6 MOV ESI,[ESP+2C]
001B:0047CAAA MOV AL,[ESP+18]
...
進入#C01.C1 (CALL 0047C9C0).
001B:0047C9C0 PUSH ESI
001B:0047C9C1 PUSH EDI
001B:0047C9C2 MOV ECX,00000080 ;---->計數 0x80
001B:0047C9C7 XOR EAX,EAX ;---->EAX清零
001B:0047C9C9 MOV EDI,00523410
001B:0047C9CE XOR ESI,ESI
001B:0047C9D0 REPZ STOSD ;---->從00523410~00523610清零
001B:0047C9D2 MOV EDX,00523410
001B:0047C9D7 MOV EAX,0000C0C1 ;#loop1--->第一層迴圈
001B:0047C9DC MOV ECX,00000001
001B:0047C9E1 TEST ESI,ECX ;#loop2--->第二層迴圈
001B:0047C9E3 JZ 0047C9E8
001B:0047C9E5 XOR [EDX],AX
001B:0047C9E8 ADD EAX,EAX
001B:0047C9EA SHL ECX,1
001B:0047C9EC XOR EAX,00004003
001B:0047C9F1 CMP ECX,00000100
001B:0047C9F7 JL 0047C9E1 ;---->跳轉到#loop2
001B:0047C9F9 ADD EDX,02
001B:0047C9FC INC ESI
001B:0047C9FD CMP EDX,00523610
001B:0047CA03 JL 0047C9D7 ;---->跳轉到#loop1
001B:0047CA05 POP EDI
001B:0047CA06 POP ESI
001B:0047CA07 RET
以上程式碼用C語言表示如下:
WORD list[0x80*2];
void sub_0047C9C0()
{
int i,j=0;
DWORD ieax,iecx,iesi=0;
WORD temp;
for(i=0;i<0x80*2;i++)
list[i] = 0;
do{
ieax = 0x0C0C1; //ieax = 49345
iecx = 1;
do{
if ((iesi&iecx)!=0)
{
temp = (WORD)(ieax&0x0FFFF);
list[j] = list[j]^temp;
}
ieax*=2;
iecx*=2;
ieax = ieax^0x04003;
}while(iecx<0x100);
j++;
iesi++;
}while(j<0x80*2);
}
從#C01.C1 CALL 出來
...
001B:0047CA85 PUSH ESI ;---->使用者名稱長度
001B:0047CA86 PUSH EDI ;---->使用者名稱指標入棧
001B:0047CA87 PUSH 00
001B:0047CA89 CALL 0047CA10 ;#C01.C2--->跟進去..
001B:0047CA8E ADD ESP,0C
...
進入#C01.C2 (CALL 0047CA10).
001B:0047CA10 MOV ECX,[ESP+08] ;---->ECX指向使用者名稱'icytear'
001B:0047CA14 MOV EAX,[ESP+0C] ;---->EAX存使用者名稱長度,
001B:0047CA18 PUSH ESI
001B:0047CA19 LEA ESI,[EAX+ECX] ;---->ESI指向了使用者名稱的末尾'\0'
001B:0047CA1C CMP ECX,ESI
001B:0047CA1E JAE 0047CA4A ;---->如果大於等於則跳轉#exit.
001B:0047CA20 MOV EAX,[ESP+08]
001B:0047CA24 PUSH EBX
001B:0047CA25 MOV EDX,EAX ;#loop3
001B:0047CA27 XOR EBX,EBX
001B:0047CA29 MOV BL,[ECX] ;---->開始逐個字元取使用者名稱
001B:0047CA2B AND EDX,000000FF
001B:0047CA31 XOR EDX,EBX
001B:0047CA33 XOR EBX,EBX
001B:0047CA35 MOV BL,AH
001B:0047CA37 MOV AX,[EDX*2+00523410] ;---->(00523410~00523610) #C01.C1 CALL 生成的東東
001B:0047CA3F XOR AX,BX
001B:0047CA42 INC ECX
001B:0047CA43 CMP ECX,ESI
001B:0047CA45 JB 0047CA25 ;---->如果小於跳轉倒#loop3↑
001B:0047CA47 POP EBX
001B:0047CA48 POP ESI
001B:0047CA49 RET
001B:0047CA4A MOV AX,[ESP+08] ;#exit.
001B:0047CA4F POP ESI
001B:0047CA50 RET
##C01.C2 (CALL 0047CA10) C語言程式碼如下:
char username[]="icytear";
int sub_0047CA10(int n,char *pname,int unamelen)
{
DWORD ieax,iebx,iedx,temp;
char *iecx;
iecx = pname;
ieax = unamelen;
if(*iecx == '\0')
return 0;
ieax = n;
do{
//MOV EDX,EAX
iedx = ieax;
//XOR EBX,EBX
iebx = 0;
//MOV BL,[ECX]
temp = *iecx;
iebx = iebx & 0xFFFFFF00;
iebx = iebx ^ temp;
//AND EDX,000000FF
iedx = iedx & 0x000000FF;
//XOR EDX,EBX
iedx = iedx ^ iebx;
//XOR EBX,EBX
iebx = 0;
//MOV BL,AH
temp = ieax;
temp = temp>>8;
temp = temp & 0x000000FF;
iebx = iebx & 0xFFFFFF00;
iebx = iebx ^ temp;
//MOV AX,[EDX*2+00523410]
temp = list[iedx];
ieax = ieax & 0xFFFF0000;
ieax = ieax ^ temp;
//XOR AX,BX
temp = iebx;
temp = temp & 0x0000FFFF;
ieax = ieax ^ temp;
iecx++;
}while(*iecx != '\0');
return ieax;
}
從#C01.C2 CALL 出來到 #C01CALL
...
001B:0047CA8E ADD ESP,0C ;---->#C01.C2 CALL 出來到這裡
001B:0047CA91 AND EAX,0000FFFF ;---->AX是用使用者名稱算出的結果
001B:0047CA96 PUSH EAX
001B:0047CA97 LEA EAX,[ESP+10]
001B:0047CA9B PUSH 0051824C ;---->;"%02X"
001B:0047CAA0 PUSH EAX ;
001B:0047CAA1 CALL 004AEABC ;---->sprintf,把使用者名稱算出的16進位制結果以字元形式儲存
001B:0047CAA6 MOV ESI,[ESP+2C]
001B:0047CAAA MOV AL,[ESP+18] ;---->[ESP+18] = "5CF",由"icytear"算出的值
001B:0047CAAE ADD ESP,0C
001B:0047CAB1 MOV CL,[ESI+02] ;---->[ESI+02] 註冊碼的第三個字元
001B:0047CAB4 LEA EDI,[ESI+02]
001B:0047CAB7 CMP CL,AL ;---->比較,在這裡比較註冊碼第三個字元是否為'5'
001B:0047CAB9 JZ 0047CAC4
001B:0047CABB POP EDI
001B:0047CABC POP ESI
001B:0047CABD XOR EAX,EAX
001B:0047CABF POP EBX
001B:0047CAC0 ADD ESP,0C
001B:0047CAC3 RET
001B:0047CAC4 MOV DL,[ESI+03] ;---->註冊碼第四個字元
001B:0047CAC7 MOV AL,[ESP+0D] ;---->"5CF"的第二個字元
001B:0047CACB CMP DL,AL ;---->比較註冊碼的第四個字元是否為'C'
001B:0047CACD JZ 0047CAD8
001B:0047CACF POP EDI
001B:0047CAD0 POP ESI
001B:0047CAD1 XOR EAX,EAX
001B:0047CAD3 POP EBX
001B:0047CAD4 ADD ESP,0C
001B:0047CAD7 RET
001B:0047CAD8 PUSH ESI ;---->註冊碼
001B:0047CAD9 CALL EBX ;---->KERNEL!lstrlen
001B:0047CADB SUB EAX,02
001B:0047CADE PUSH EAX ;---->EAX == 註冊碼長度 - 2;
001B:0047CADF PUSH EDI ;---->第三位以後的註冊碼
001B:0047CAE0 PUSH 00
001B:0047CAE2 CALL 0047CA10 ;---->前面出現過這個函式,用註冊碼第三為以後的字元計算出一個值
001B:0047CAE7 ADD ESP,0C
001B:0047CAEA AND EAX,0000FFFF
001B:0047CAEF PUSH EAX
001B:0047CAF0 LEA EAX,[ESP+10]
001B:0047CAF4 PUSH 0051824C ;---->"%02X"
001B:0047CAF9 PUSH EAX
001B:0047CAFA CALL 004AEABC ;---->sprintf
001B:0047CAFF MOV CL,[ESI] ;---->取註冊碼的第一個字元
001B:0047CB01 MOV AL,[ESP+18] ;---->由第三位以後的註冊碼計算出的值(第一個字元)
001B:0047CB05 ADD ESP,0C
001B:0047CB08 CMP CL,AL ;---->比較註冊碼的第一位
001B:0047CB0A JZ 0047CB15
001B:0047CB0C POP EDI
001B:0047CB0D POP ESI
001B:0047CB0E XOR EAX,EAX
001B:0047CB10 POP EBX
001B:0047CB11 ADD ESP,0C
001B:0047CB14 RET
001B:0047CB15 MOV DL,[ESI+01] ;---->取註冊碼的第二個字元
001B:0047CB18 MOV CL,[ESP+0D] ;---->由第三位以後的註冊碼計算出的值(第二個字元)
001B:0047CB1C XOR EAX,EAX
001B:0047CB1E CMP DL,CL ;---->比較註冊碼的第二位
001B:0047CB20 POP EDI
001B:0047CB21 POP ESI
001B:0047CB22 SETZ AL
001B:0047CB25 POP EBX
001B:0047CB26 ADD ESP,0C
001B:0047CB29 RET ;---->出#C01 CALL
3. 以上程式碼,驗證了註冊碼的前四位,以上可知註冊碼的第3、4位是由使用者名稱用sub_0047CA10(int,char*,int)函式計算出的值16進位制碼的字元格式的前兩位, 在這裡為"5C"; 註冊碼的第1、2位是由註冊碼第三位以後的字元用sub_0047CA10函式計算出的16進位制碼的字元格式的前兩位,用"5C60443"計算的結果為"EF",所以在這時註冊碼應為"ef5c60443".
回到註冊對話方塊重新輸入註冊碼"ef5c60443",提示需要重啟EditPlus啟用註冊碼,看來第一步驗證透過了.
4. 重啟EditPlus,提示"Invalid registration code.",看來其它的地方還有註冊碼的驗證過程,好我們回到程式繼續跟蹤...
這次跟蹤註冊碼用"EF5C60443".
出#C01 CALL 到...
001B:0047C942 ADD ESP,08 ;---->返回到這裡
001B:0047C945 TEST EAX,EAX ;---->
001B:0047C947 JNZ 0047C961 ;---->跳轉則第一步註冊成功
001B:0047C949 PUSH FF
001B:0047C94B PUSH 10
001B:0047C94D PUSH 00005F81
001B:0047C952 CALL 004C7E94 ;---->出錯對話方塊,
001B:0047C957 POP EDI
001B:0047C958 POP ESI
001B:0047C959 POP EBX
001B:0047C95A ADD ESP,00000230
001B:0047C960 RET
===>:0047C961 PUSH EDI ;---->註冊碼
001B:0047C962 PUSH EBX ;---->使用者名稱
001B:0047C963 CALL 0047C3B0 ;#C02---->關於登錄檔的動作????,跟進去看看..
001B:0047C968 ADD ESP,08
001B:0047C96B TEST EAX,EAX
001B:0047C96D JNZ 0047C986 ;--->輸入"ef5c60443"時,在這裡我們跳轉了..
001B:0047C96F PUSH FF
001B:0047C971 PUSH EAX
001B:0047C972 PUSH 00004E7F
001B:0047C977 CALL 004C7E94 ;--->註冊失敗!!
001B:0047C97C POP EDI
001B:0047C97D POP ESI
001B:0047C97E POP EBX
001B:0047C97F ADD ESP,00000230
001B:0047C985 RET
===>:0047C986 MOV ECX,[ESI+000000D8]
001B:0047C98C PUSH EBX ;---->使用者名稱
001B:0047C98D CALL 004C0367 ;---->CString::=
001B:0047C992 MOV ECX,[ESI+000000DC]
001B:0047C998 PUSH EDI ;---->註冊碼"EF5C60443"
001B:0047C999 CALL 004C0367 ;---->CString::=
001B:0047C99E MOV EAX,[ESI+000000E4]
001B:0047C9A4 MOV ECX,ESI
001B:0047C9A6 MOV DWORD PTR [EAX],00000000
001B:0047C9AC CALL 004BF482 ;---->CDialog::0nOK(void)
001B:0047C9B1 POP EDI
001B:0047C9B2 POP ESI
001B:0047C9B3 POP EBX
001B:0047C9B4 ADD ESP,00000230
001B:0047C9BA RET
001B:0047C9BB NOP
...
進入#C02 ...
001B:0047C3B0 SUB ESP,000000E0
001B:0047C3B6 PUSH EBX ;---->使用者名稱(保護現場)
001B:0047C3B7 PUSH EBP
001B:0047C3B8 PUSH ESI
001B:0047C3B9 MOV ESI,[ESP+000000F0] ;---->讓ESI指向使用者名稱
001B:0047C3C0 PUSH EDI ;---->註冊碼(保護現場)
001B:0047C3C1 MOV EDI,[KERNEL32!lstrlen]
001B:0047C3C7 PUSH ESI ;---->使用者名稱入棧了
001B:0047C3C8 CALL EDI ;---->得到使用者名稱長度
001B:0047C3CA MOV EBX,EAX
001B:0047C3CC MOV EAX,[ESP+000000F8]
001B:0047C3D3 PUSH EAX ;---->EAX指向註冊碼
001B:0047C3D4 CALL EDI ;---->註冊碼長度
001B:0047C3D6 LEA EBP,[EBX+EAX+02] ;---->ebp = name_len+sn_len+2;
001B:0047C3DA MOV [ESP+14],EAX
001B:0047C3DE PUSH EBP
001B:0047C3DF CALL 004AD84D ;---->malloc(size_t)分配記憶體
001B:0047C3E4 MOV ECX,EBX
001B:0047C3E6 LEA EDI,[EAX+01]
001B:0047C3E9 MOV EDX,ECX
001B:0047C3EB MOV [EAX],BL ;---->把bl(使用者名稱長度)存到新分配的空間中的第一個位元組
001B:0047C3ED SHR ECX,02
001B:0047C3F0 REPZ MOVSD ;---->把使用者名稱存到分配的空間中
001B:0047C3F2 MOV ECX,EDX
001B:0047C3F4 MOV [ESP+1C],EAX
001B:0047C3F8 AND ECX,03
001B:0047C3FB REPZ MOVSB ;---->把使用者名稱存到分配的空間中
001B:0047C3FD MOV ECX,[ESP+18] ;---->註冊碼長度
001B:0047C401 MOV ESI,[ESP+000000FC] ;---->ESI指向註冊碼
001B:0047C408 MOV [EAX+EBX+01],CL ;---->把cl(註冊碼長度)存到分配的空間中
001B:0047C40C LEA EDI,[EAX+EBX+02]
001B:0047C410 MOV EAX,ECX
001B:0047C412 SHR ECX,02
001B:0047C415 REPZ MOVSD ;---->存註冊碼
001B:0047C417 MOV ECX,EAX
001B:0047C419 MOV EAX,51EB851F
001B:0047C41E IMUL EBP ;---->EDX:EAX=0x51eb851f * 0x12 = 5C28F5C2E
001B:0047C420 AND ECX,03
001B:0047C423 REPZ MOVSB ;---->存註冊碼,此時記憶體中的資料為"\x07icytear\x09EF5C60443"
001B:0047C425 SAR EDX,05 ;---->移位操作
001B:0047C428 MOV ECX,EDX
001B:0047C42A SHR ECX,1F
001B:0047C42D ADD EDX,ECX
001B:0047C42F LEA EDX,[EBP+EDX+0C] ;---->計算要下一個操作要分配多少空間n
001B:0047C433 PUSH EDX
001B:0047C434 MOV [ESP+18],EDX ;---->把n存下來
001B:0047C438 CALL 004AD84D ;---->malloc(size_t)分配記憶體
001B:0047C43D MOV EDI,[ESP+20] ;---->EDI指向"\x07icytear\x09EF5C60443"
001B:0047C441 PUSH EBP
001B:0047C442 LEA EDX,[ESP+1C] ;---->EDX指向上次分配空間大小n
001B:0047C446 MOV ESI,EAX ;---->讓ESI指向最近分配的記憶體空間
001B:0047C448 PUSH EDI ;---->EDI指向"\x07icytear\x09EF5C60443",
001B:0047C449 PUSH EDX
001B:0047C44A PUSH ESI
001B:0047C44B MOV [ESP+38],ESI
001B:0047C44F CALL 0049F820 ;#C1---->關鍵,計算出一段值(size:1E),要寫入登錄檔License,在此處按F9下一個斷點
001B:0047C454 ADD ESP,18
001B:0047C457 TEST EAX,EAX
001B:0047C459 JZ 0047C477 ;---->跳轉到#J1
001B:0047C45B PUSH EDI
001B:0047C45C CALL 004AD764 ;---->call????
001B:0047C461 PUSH ESI
001B:0047C462 CALL 004AD764 ;---->call????
001B:0047C467 ADD ESP,08
001B:0047C46A XOR EAX,EAX
001B:0047C46C POP EDI
001B:0047C46D POP ESI
001B:0047C46E POP EBP
001B:0047C46F POP EBX
001B:0047C470 ADD ESP,0E0
001B:0047C476 RET
===>:0047C477 MOV EAX,[ESP+10] ;#J1---->
001B:0047C47B ADD EAX,08
001B:0047C47E PUSH EAX
001B:0047C47F MOV [ESP+18],EAX
001B:0047C483 CALL 004AD84D ;---->malloc(size_t)分配記憶體
001B:0047C488 MOV ECX,[0051A58] ;---->[0051A58]==DWORD 0x182989DB 定值
001B:0047C48E MOV EBX,EAX
001B:0047C490 MOV [EBX],ECX ;---->write memory...
001B:0047C492 MOV EDX,[00518A58]
001B:0047C498 PUSH EDX
001B:0047C499 CALL 004AD987 ;---->void _cdecl srand(unsigned int)
001B:0047C49E CALL 004AD994 ;---->int rand(void)產生一個偽隨機數
001B:0047C4A3 ADD EAX,EBP ;---->ebp == name_len+sn_len+2
001B:0047C4A5 MOV [EBX+04],AX ;---->write memory... to [ebx+4]
001B:0047C4A9 MOV EAX,[00518A58]
001B:0047C4AE INC EAX
001B:0047C4AF PUSH EAX
001B:0047C4B0 CALL 004A987 ;---->srand
001B:0047C4B5 ADD ESP,0C
001B:0047C4B8 CALL 004AD994 ;---->rand() 產生一個偽隨機數
001B:0047C4BD MOV ECX,[ESP+10]
001B:0047C4C1 LEA EDI,[EBX+08]
001B:0047C4C4 ADD EAX,ECX
001B:0047C4C6 MOV [EBX+06],AX ;---->write memory... to [ebx+6] = 0xb78188+6
001B:0047C4CA MOV ECX,[ESP+10]
001B:0047C4CE MOV EDX,ECX
001B:0047C4D0 SHR ECX,02
001B:0047C4D3 REPZ MOVSD
001B:0047C4D5 MOV ECX,EDX
001B:0047C4D7 AND ECX,03
001B:0047C4DA REPZ MOVSB
...
把剛才生成的16進位制碼寫登錄檔...
...
按F5執行程式,又提示重啟editplus,退出程式..在這裡程式被上面按F9下的那個斷點中斷(在#C02.#C1,001B:0047C44B),看來程式在關閉時又呼叫了一次#C02 Call,也就是又寫了一次登錄檔,好我們用D edi命令檢視edi指向的記憶體為"\x07icytear\x090F5C60443",看到區別了嗎,前面我們看到的是"\x07icytear\x09EF5C60443",看來是被程式修改了,用這個再一次計算出16進位制程式碼寫入登錄檔,重啟editplus時和第一次寫得當然就不一樣了,看來程式是在這裡做了手腳..
我們按F12退出此次呼叫(CALL 0047C3B0)
...
001B:0042E691 CALL 0047C3B0
001B:0042E696 ADD ESP,08 ;---->到這裡
...
我們向上檢視程式碼,看到
...
001B:0042E661 TEST EAX,EAX
001B:0042E663 JZ 0042E69A ;---->這裡有個跳轉,如果跳就不能執行CALL 0047C3B0了,按F9在這裡下個斷點(把其它得斷點可以先禁掉),如果跳轉我們就可以註冊成功..
重新輸入註冊碼後退出editplus程式被中斷,單步執行看看
...
001B:0042E653 MOV EAX,[ESI+B44]
001B:0042E659 MOV DWORD PTR [ESP+10],08
001B:0042E661 TEST EAX,EAX
001B:0042E663 JZ 0042E69A
001B:0042E665 MOV EAX,[ESI+0B30] ;---->D EAX,發現eax指向的還是"EF5C60443",由此判斷可能是由於下面的程式碼改變了此字串,我們保持此記憶體的視窗,繼續往下執行
001B:0042E66B PUSH EDI
001B:0042E66C LEA EDI,[ESI+0B30]
001B:0042E672 MOV AL,[EAX]
001B:0042E674 CMP AL,30
001B:0042E676 JNZ 0042E67C
001B:0042E678 PUSH 31
001B:0042E67A JMP 0042E67E
001B:0042E67C PUSH 30
001B:0042E67E PUSH 00
001B:0042E680 MOV ECX,EDI
001B:0042E682 CALL 004C069E ;#C03---->執行此呼叫後,"EF5C60443"被改為"0F5C60443",看來我們的判斷是真確的.
001B:0042E687 MOV EDI,[EDI]
001B:0042E689 MOV EAX,[ESI+B2C]
001B:0042E68F PUSH EDI
001B:0042E690 PUSH EAX
001B:0042E691 CALL 0047C3B0
...
我們再看看TEST EAX,EAX 中的EAX從那來的,向上看到MOV EAX,[ESI+B44],用D ESI+B44檢視記憶體,顯示如下
...
0023:00B7590C 01 00 00 00 .....
0023:00B7591C .......
...
那我們下一個記憶體斷點試試,BPMD 0B7590C,再次輸入註冊碼點選註冊,OK,程式被中斷在..
...
001B:0047C9A6 MOV DWORD PTR [EAX],0 ;---->這裡改變記憶體,賦值0
001B:0047C9AC CALL 004BF482 ;---->中斷在此
...
MOV DWORD PTR [EAX],0;把記憶體B7590C賦值0,我們要看看在那裡把其改為1的,按F5執行程式,再次中斷
...
001B:0047C718 MOV DWORD PTR [ECX],01 ;---->改變記憶體,賦值1
001B:0047C71E LEA ECX,[EDI+98] ;---->中斷在此
...
我們向上看程式
001B:0047C707 MOV AL,[EAX,04] ;---->把第5位註冊碼存入AL
001B:0047C70A MOV CL,[ESP+10] ;---->那[esp+10]存的是什麼呢?我們繼續向上看程式
001B:0047C670 PUSH FF
001B:0047C672 PUSH 004E6183
001B:0047C677 MOV EAX,FS:[00000000]
001B:0047C67D PUSH EAX
001B:0047C67E MOV FS:[0],ESP
001B:0047C685 SUB ESP,10
001B:0047C688 PUSH EBP
001B:0047C689 PUSH ESI
001B:0047C68A PUSH EDI
001B:0047C68B MOV EDI,ECX
001B:0047C691 MOV DWORD PTR [EDI],004F41E0
001B:0047C697 MOV EAX,[EDI+D8]
001B:0047C69D MOV DWORD PTR [ESP+24],01
001B:0047C6A5 MOV EBP,[EAX] ;---->讓EBP指向使用者名稱"icytear"
001B:0047C6A7 MOV ESI,[EBP-08] ;---->ESI存使用者名稱長度
001B:0047C6AA TEST ESI,ESI
001B:0047C6AC JLE 0047C71E ;---->跳過賦值1的那個指令
001B:0047C6AE XOR EAX,EAX
001B:0047C6B0 MOV ECX,01 ;---->ECX賦值1
001B:0047C6B5 TEST ESI,ESI
001B:0047C6B7 JLE 0047C6C5
===>:0047C6B9 XOR EDX,EDX ;#LOOP
001B:0047C6BB MOV DL,[EBP+EAX]
001B:0047C6BE ADD ECX,EDX
001B:0047C6C0 INC EAX
001B:0047C6C1 CMP EAX,ESI
001B:0047C6C3 JL 0047C6B9 ;---->跳到#LOOP,使用者名稱每一位的值相加再加1;
001B:0047C6C5 LEA ECX,[ECX*8+ECX+0A]
001B:0047C6C9 MOV EAX,55555556
001B:0047C6CE IMUL ECX
001B:0047C6D0 MOV EAX,EDX
001B:0047C6D2 SHR EAX,1F
001B:0047C6D5 LEA ECX,[EAX+EDX+24]
001B:0047C6D9 AND ECX,8000000F
001B:0047C6DF JNS 0047C6E6
001B:0047C6E1 DEC ECX
001B:0047C6E2 OR ECX,-10
001B:0047C6E5 INC ECX
===>:0047C6E6 PUSH ECX
001B:0047C6E7 LEA EDX,[ESP+14]
001B:0047C6EB PUSH 0051700C ;---->"%1X"
001B:0047C6F0 PUSH EDX
001B:0047C6F1 CALL 004AEABC ;---->sprintf
001B:0047C6F6 MOV EAX,[EDI+DC]
001B:0047C6FC ADD ESP,0C
001B:0047C6FF MOV EAX,[EAX] ;---->EAX指向註冊碼
001B:0047C701 CMP DWORD PTR[EAX-8],05 ;---->[EAX-8]存著註冊碼長度,也就是說註冊碼長度應該大於5
001B:0047C605 JL 0047C712
001B:0047C607 MOV AL,[EAX,04] ;---->註冊碼第5位
001B:0047C60A MOV CL,[ESP+10] ;---->很顯然是我們用使用者名稱算出的那個值
001B:0047C60E CMP AL,CL ;---->驗證第5位註冊碼,在這裡我們計算出的是'D'
001B:0047C610 JZ 0047C71E ;---->第二次驗證透過則註冊成功..^_^,勝利!!
001B:0047C612 MOV ECX,[EDI+E4]
001B:0047C618 MOV DWORD PTR[ECX],01
...
5. 用我的使用者名稱'icytear'計算出的值是'D'所以我的第5位註冊碼應為'D',前2位應用'5CD0443'由sub_0047CA10重新計算為'E4',重新輸入註冊碼'E45CD0443',哈哈,註冊成功!!
6. 好累,序號產生器大家寫吧,別忘了給我發一份!!
####################
username: icytear
Regcode: E45CD0443
####################
相關文章
- MySQL下載安裝全過程(包含Navicat破解)2017-05-26MySql
- GaitCD破解全過程(installshield) (3千字)2015-11-15AI
- PowerArchiver破解過程。2015-11-15Hive
- 破解 OverNimble Localize Plus 1.04
全過程! (13千字)2015-11-15
- 破解<<破解堅盾磁碟加密系統 V4.0>>的全過程 (10千字)2001-10-23加密
- 貫通詞典破解過程2004-12-20
- 破解FlashGet1.65的過程2015-11-15
- 設定autotrace全過程2008-07-29
- Hydro OJ搭建全過程2024-05-03
- RegSnap 2.6破解過程 (610字)2001-02-17
- 破解Ghost多媒體視訊點播系統全過程 (9千字)2002-07-29
- MapReduce 執行全過程解析2019-08-05
- 頁面載入全過程2018-11-27
- DNS解析全過程及原理2013-07-15DNS
- centos 安裝MySQL全過程2014-09-10CentOSMySql
- 記憶體訪問全過程2020-05-10記憶體
- Git伺服器搭建全過程2015-07-07Git伺服器
- C語言編譯全過程2010-10-19C語言編譯
- oracle for redhat as4.0 cluster 全過程2007-03-01OracleRedhat
- TDP for SQL安裝配置全過程2008-01-30SQL
- linux iSCSI target配置全過程2007-10-25Linux
- LLM本地部署全過程記錄2024-05-10
- OICQ HACK 1.0 破解過程 (9千字)2001-04-23
- Nullz CrackMe 1.1破解過程 (13千字)2001-09-18Null
- WebTimeSync 5.2.0 破解過程 (14千字)2001-10-05Web
- 凱撒密碼加解密過程與破解原理2024-07-10密碼解密
- 【Elasticsearch學習】文件搜尋全過程2020-05-10Elasticsearch
- redhat 5.4下安裝MYSQL全過程2021-09-09RedhatMySql
- innobackupex命令備份全過程圖解2018-11-30圖解
- 在青雲上部署oracle rac全過程2018-04-09Oracle
- Oracle RAC+ASM 關閉全過程2009-03-16OracleASM
- solaris 10 網路配置全過程(轉)2011-04-27
- 建立一個standby database的全過程2005-04-08Database
- Oracle-解析啟動的全過程2012-01-12Oracle
- 全表複製過程建立指令碼2007-12-17指令碼
- 我終於破解了魔裝網神了,破解過程!!,不過是用2.70破解的。 (1千字)2001-10-15
- 中興ZXV10B860AV2.1-A破解過程2019-02-02
- dfx V4.0破解過程 (10千字)2000-09-24