Pexplorer 1.70 完全破解(KeyFile&Name+Code),附序號產生器~~~~~~~~~ (17千字)

看雪資料發表於2002-04-03

名稱:Pexplorer 1.70 中文版
下載:漢化新世紀

簡介:一個強大的漢化工具,可以直接檢視、修改軟體的資源,包括選單、對話方塊、字串表等;另外,還具備有 W32DASM 軟體的反編譯能力和PEditor 軟體的PE檔案頭編輯功能;該軟體支援外掛,你可以透過增加外掛加強該軟體的功能,該工具中捆綁了一個可以解開用 UPX 0.8-UPX 1.20版本加殼的軟體的外掛.

保護:KeyFile&Name+Code
原因:純屬練習
工具:Trw,DeDe 2.5中文版,WinHex,D_Peeper(可檢視Delphi程式的控制元件等資訊)


經過:此軟體下載後是已經註冊了的,剛開始我是拿1.60來開刀的,因為當時1.70我還沒安裝,確定了它的KeyFile找到演算法後安裝了1.7,發現它的KeyFile沒變,而且還在幫助選單多了個註冊項,於是研究它的Name+Code演算法,所以推遲幾天釋出此文.我們先來研究它的KeyFile,這樣到研究註冊碼時就會很好理解.它的主程式是Delphi寫的,沒加殼,在安裝目錄下發現pexdata.rdat檔案,改名後變成未註冊版,KeyFile只有512位元組,不算大,用WinHex開啟它

00000000:  43 2C 0F C4-C5 49 1D 4F-38 40 33 D0-86 9E DA 48  C,吶IO8@3H
00000010:  72 CB 97 B9-AE 25 60 42-53 DB 1F 7D-4C 54 D8 1E  r鞏%`BS?}LT?
00000020:  6D B5 5F 08-65 16 A8 9D-91 4B A0 77-5A 89 67 7A  m_eKwZgz
00000030:  62 B2 DC 49-45 86 E0 39-43 A2 54 8D-A7 F7 58 65  b曹IE9CTXe

00000040:  43 2C 0F C4-C5 49 1D 4F-38 40 33 D0-86 9E DA 48  C,吶IO8@3H
00000050:  72 CB 97 B9-AE 25 60 42-53 DB 1F 7D-4C 54 D8 1E  r鞏%`BS?}LT?
00000060:  6D B5 5F 08-65 16 A8 9D-91 4B A0 77-5A 89 67 7A  m_eKwZgz
00000070:  62 B2 DC 49-45 86 E0 39-43 A2 54 8D-A7 F7 58 65  b曹IE9CTXe
.
.

.
000001F0:  62 B2 DC 49-45 86 E0 39-43 A2 54 8D-A7 F7 58 1E  b曹IE9CTX

----------------------------------------------------------------------------
發現了什麼??其實它的內容只有前64個位元組,後面的都是重複的,重複8次,共512位元組,有點不同的是第512位元組應該是65,但KeyFile裡是1E,這個有用嗎,請往後看,呵呵~~~看來我們分析的範圍又縮小了一點.既然它要讀KeyFile,那我們就下bpx readfile好了,為了不受其它程式的影響,我們用Trw載入pexplorer.exe,停在程式的入口,這時才下斷點,按F5,攔下了,我們非常走運,第一次攔下的地方就是我們要找的,請看下面程式碼.建議參考一下API的說明,下面的edi就是readfile的引數---檔案大小

==Step 1=======================================================
技巧:過了ReadFile一行就要用bpm來設斷點了,然後可以用F5,只要程式一讀記憶體的資料就會攔下來了,通常程式還會將這些資料複製到其它的地方,所以發現一個就下一個bpm斷點(有限的!),不要有漏網之魚了.

0187:004074A2  PUSH    BYTE +00
0187:004074A4  LEA      EAX,[ESP+04]
0187:004074A8  PUSH    EAX
0187:004074A9  PUSH    EDI      <-------200h=512
0187:004074AA  PUSH    ESI
0187:004074AB  PUSH    EBX
0187:004074AC  CALL    `KERNEL32!ReadFile`
0187:004074B1  TEST    EAX,EAX  <-------d esi可看到pexdata.rdat的內容已經讀到記憶體裡了
0187:004074B3  JNZ      004074BC
0187:004074B5  MOV      DWORD [ESP],FFFFFFFF
0187:004074BC  MOV      EAX,[ESP]
0187:004074BF  POP      EDX
0187:004074C0  POP      EDI
0187:004074C1  POP      ESI
0187:004074C2  POP      EBX
0187:004074C3  RET

==Step 2======================================================
程式在這之前會將pexdata.rdat的內容複製到幾個地方,還會比較讀出來的檔案長度是否是512位元組,以上程式碼略,最後我們來到以下地方,因為pexdata.rdat裡的資料都是重複前64位元組的,所以後面的資料略,因為經過運算它們的結果都是一樣的.

0187:00523322  MOV      DWORD [EBP-08],01FF <---1FFh=511
0187:00523329  PUSHA 
0187:0052332A  MOV      ESI,[EBP-04] <---esi指向KeyFile資料
0187:0052332D  MOV      ECX,[EBP-08]
0187:00523330  XOR      EDX,EDX      <---計數器
0187:00523332  MOV      EBX,3617E418 <---!!
0187:00523337  MOV      EAX,EBX
0187:00523339  XOR      [ESI+EDX],AL <---用AL和第一位元組Xor
0187:0052333C  ROR      EBX,1        <---3617E418迴圈右移
0187:0052333E  XOR      EBX,A5A5A5A5 <---再Xor
0187:00523344  INC      EDX
0187:00523345  DEC      ECX
0187:00523346  JNZ      00523337    <---迴圈511次,這樣pexdata.rdat的資料就面目全非了

最後得到以下資料:
------------------------------------------------------------------------------
018F:016A70CC 5B 85 7E 59 2E 99 50 CC-DC 17 BD 32 52 D1 58 2C [~Y.P謄.?RX,
018F:016A70DC 65 65 65 65 65 65 65 65-65 65 65 65 65 65 65 65 eeeeeeeeeeeeeeee
018F:016A70EC 75 1C 2E 95 8E C6 E5 1E-75 1C 2E 95 8E C6 E5 1E u...u...
018F:016A70FC 75 1C 2E 95 8E C6 E5 1E-75 1C 2E 95 8E C6 E5 1E u...u...
------------------------------------------------------------------------------

0187:00523348  POPA   
0187:00523349  LEA      EDX,[EBP-41]
0187:0052334C  MOV      EAX,[EBP-20]
0187:0052334F  ADD      EAX,BYTE +2C
0187:00523352  MOV      ECX,20
0187:00523357  CALL    0040279C    <---這裡將上面資料的前32位元組複製到記憶體
0187:0052335C  PUSHA 
0187:0052335D  MOV      EDI,[EBP-0C]
0187:00523360  MOV      ESI,[EBP-10]
0187:00523363  MOV      EAX,[EDI]
0187:00523365  XOR      EAX,[EDI+04]
0187:00523368  MOV      EBX,[EDI+08]
0187:0052336B  XOR      EBX,[EDI+0C] <---這兩個Xor可以先不理它
0187:0052336E  MOV      EAX,3617E418
0187:00523373  XOR      [EDI],EAX    <---edi指向資料首位
0187:00523375  MOV      EAX,A935FC2E
0187:0052337A  XOR      [EDI+04],EAX
0187:0052337D  MOV      EAX,57D872B9
0187:00523382  XOR      [EDI+08],EAX
0187:00523385  MOV      EAX,493DB437
0187:0052338A  XOR      [EDI+0C],EAX <---經過這四個數Xor後,資料又變化了

看看我們得到了什麼??Caio不就是那個註冊使用者嗎,呵呵呵呵~~~~看來程式的保護還很一般喲
------------------------------------------------------------------------------
018F:0086F81B 43 61 69 6F 00 65 65 65-65 65 65 65 65 65 65 65 Caio.eeeeeeeeeee
018F:0086F82B 65 65 65 65 65 65 65 65-65 65 65 65 65 65 65 65 eeeeeeeeeeeeeeee
------------------------------------------------------------------------------

0187:0052338D  MOV      EAX,[EDI]
0187:0052338F  MOV      [ESI],EAX
0187:00523391  MOV      EAX,[EDI+04]
0187:00523394  MOV      [ESI+04],EAX
0187:00523397  MOV      EAX,[EDI+08]
0187:0052339A  MOV      [ESI+08],EAX
0187:0052339D  MOV      EAX,[EDI+0C]
0187:005233A0  MOV      [ESI+0C],EAX
0187:005233A3  MOV      EAX,[EDI+10]
0187:005233A6  MOV      [ESI+10],EAX
0187:005233A9  MOV      EAX,[EDI+14]
0187:005233AC  MOV      [ESI+14],EAX
0187:005233AF  MOV      EAX,[EDI+18]
0187:005233B2  MOV      [ESI+18],EAX
0187:005233B5  MOV      EAX,[EDI+1C]
0187:005233B8  MOV      [ESI+1C],EAX
0187:005233BB  MOV      EDI,[EBP-04]
0187:005233BE  MOV      EAX,[EDI+20]
0187:005233C1  MOV      [EBP-08],EAX
0187:005233C4  MOV      EAX,[EDI+24]
0187:005233C7  MOV      [EBP-14],EAX <---上面複製資料
0187:005233CA  MOV      EDI,[EBP-0C]
0187:005233CD  MOV      EAX,3617E418
0187:005233D2  XOR      [EDI],EAX
0187:005233D4  MOV      EAX,A935FC2E
0187:005233D9  XOR      [EDI+04],EAX
0187:005233DC  MOV      EAX,57D872B9
0187:005233E1  XOR      [EDI+08],EAX
0187:005233E4  MOV      EAX,493DB437
0187:005233E9  XOR      [EDI+0C],EAX

將資料打回原形,
------------------------------------------------------------------------------
018F:016A70CC 5B 85 7E 59 2E 99 50 CC-DC 17 BD 32 52 D1 58 2C [~Y.P謄.?RX,
018F:016A70DC 65 65 65 65 65 65 65 65-65 65 65 65 65 65 65 65 eeeeeeeeeeeeeeee
018F:016A70EC 75 1C 2E 95 8E C6 E5 1E-75 1C 2E 95 8E C6 E5 1E u...u...
018F:016A70FC 75 1C 2E 95 8E C6 E5 1E-75 1C 2E 95 8E C6 E5 1E u...u...
------------------------------------------------------------------------------

0187:005233EC  MOV      EAX,[EDI]    <---這裡注意了,程式拿前16位元組的資料做運算
0187:005233EE  XOR      EAX,[EDI+04]    用第1和第2個dword相Xor
0187:005233F1  MOV      EBX,[EDI+08]    用第3和第4個dowrd相Xor
0187:005233F4  XOR      EBX,[EDI+0C]    也就是:597E855B xor CC50992E=952E1C75
0187:005233F7  MOV      [EBP-18],EAX            32BD17DC xor 2C58D152=1EE5C68E
0187:005233FA  MOV      [EBP-1C],EBX
0187:005233FD  POPA   
0187:005233FE  MOV      EAX,[EBP-18] <---取出來與[ebp-8]來比較
0187:00523401  CMP      EAX,[EBP-08] <---[ebp-8]裡其實就是上面資料第3行的第1個dword
0187:00523404  JNZ      00523454
0187:00523406  MOV      EAX,[EBP-1C]
0187:00523409  CMP      EAX,[EBP-14] <---[ebp-14]裡其實就是上面資料第3行的第2個dword
0187:0052340C  JNZ      00523454    <---象這樣跳得比較遠的應該都是出錯的地方
0187:0052340E  MOV      EAX,00549C14
0187:00523413  LEA      EDX,[EBP-62]
0187:00523416  MOV      ECX,21
0187:0052341B  CALL    00403B90    <---這個Call將下面資料中的註冊名讀出來

註冊名以0結尾,這時如果你將Caio改成你自己的名字,程式執行時註冊使用者就是你了
------------------------------------------------------------------------------
018F:0086F81B 43 61 69 6F 00 65 65 65-65 65 65 65 65 65 65 65 Caio.eeeeeeeeeee
018F:0086F82B 65 65 65 65 65 65 65 65-65 65 65 65 65 65 65 65 eeeeeeeeeeeeeeee
------------------------------------------------------------------------------

0187:00523420  LEA      ECX,[EBP-68]
0187:00523423  MOV      EDX,08
0187:00523428  MOV      EAX,[EBP-1C]

總結:後面的程式根本就沒用到KeyFile裡40位元組後的資料,所以KeyFile的內容只有40位元組是有用的,其它的都是垃圾,你可以試一下將其它資料改成其它,程式照樣是已註冊的.有用資料的關係也很簡單,前32位元組是存放註冊名的,只要前16位元組和第33到40位元組的關係成立,而KeyFile的大小是512位元組的話這個KeyFile就是合法的,因為它的運算過程只用了Xor(例:A xor B=C , C xor B=A),所以我們可以寫個序號產生器來生成一個KeyFile,不然用人工算可就麻煩了,趕快做一個屬於你自己的KeyFile吧,哈哈~~~~~~~~~


下面我們來看看註冊碼的部分~~~~~
==============================================================================
因為1.7可以透過輸入註冊碼來註冊,所以也來研究研究吧.按慣例先填入註冊名Sam Von和假註冊碼6767676767676767(注意:輸入註冊資訊後不要直接按Enter鍵,因為游標正處於取消鍵上,要用滑鼠點選或用TAB鍵,不然你無論如何都攔不下來),為什麼是16位,因為下面有比較呀,呵呵.接著就下斷點bpx hmemcpy,F5,誰知程式給我來個藍色畫面,但下其它斷點程式卻又正常,照我推斷程式應該沒有防Debug的地方,可能是程式下面視窗的提示資訊在作怪吧.不怕,我們還有其它的工具嘛,先用D_peeper檢視它的註冊視窗是TrForm,順便看看它的一些控制元件以方便作判斷,用DeDe開啟主程式,過程很順利,在DeDe的"程式"視窗裡點選TrForm,然後在右邊的"事件"裡雙擊第一行的Button1Click,可看到下面程式碼:

***** TRY
|
004B3375  64FF30                push    dword ptr fs:[eax]
004B3378  648920                mov    fs:[eax], esp
004B337B  8D55F4                lea    edx, [ebp-$0C]
004B337E  8B45FC                mov    eax, [ebp-$04]

* Reference to control TrForm.Edit1 : TEdit
|
004B3381  8B8000020000          mov    eax, [eax+$0200]

|
004B3387  E8DCE5F6FF            call    00421968
004B338C  8B55F4                mov    edx, [ebp-$0C] <---過此行打d edx是註冊名的儲存地址
004B338F  A118A75400            mov    eax, dword ptr [$54A718]

|
004B3394  E81F06F5FF            call    004039B8
004B3399  8D55F4                lea    edx, [ebp-$0C]
004B339C  8B45FC                mov    eax, [ebp-$04]

* Reference to control TrForm.Edit2 : TEdit
|
004B339F  8B8004020000          mov    eax, [eax+$0204]

|
004B33A5  E8BEE5F6FF            call    00421968
004B33AA  8B55F4                mov    edx, [ebp-$0C] <---過此行打d edx是假註冊碼的儲存地址
004B33AD  A1E0A95400            mov    eax, dword ptr [$54A9E0]

|
004B33B2  E80106F5FF            call    004039B8
004B33B7  33C0                  xor    eax, eax
004B33B9  5A                    pop    edx
004B33BA  59                    pop    ecx
004B33BB  59                    pop    ecx
004B33BC  648910                mov    fs:[eax], edx

****** FINALLY

找到程式儲存資料的地方後,用bpm來設斷點,不一定能攔下,還可能會藍色畫面,如果攔不下但沒藍色畫面退出的話請再次輸入註冊資訊,保持bpm的兩個斷點(如果失敗,請重複上面過程以確定註冊資訊的儲存地址,因為程式退出後地址就會改變了),注意觀察記憶體,最後可發現下面程式碼,是否很眼熟:-)

0187:0052302E  MOV      CL,65
0187:00523030  MOV      EDX,21
0187:00523035  CALL    00402A8C        <---在記憶體中放入32個"e"
0187:0052303A  XOR      EAX,EAX
0187:0052303C  MOV      [EBP-08],EAX
0187:0052303F  XOR      EAX,EAX
0187:00523041  MOV      [EBP-0C],EAX
0187:00523044  LEA      EAX,[EBP-45]
0187:00523047  MOV      EDX,[00549C24]
0187:0052304D  CALL    00407954        <---將使用者名稱複製到32個"e"最前端
0187:00523052  LEA      EAX,[EBP-45]
0187:00523055  MOV      [EBP-04],EAX    <---d eax可看到下面內容

018F:0086F81B 53 61 6D 20 56 6F 6E 00-65 65 65 65 65 65 65 65 Sam Von.eeeeeeee
018F:0086F82B 65 65 65 65 65 65 65 65-65 65 65 65 65 65 65 65 eeeeeeeeeeeeeeee

0187:00523058  PUSHA 
0187:00523059  MOV      EDI,[EBP-04]
0187:0052305C  MOV      EAX,3617E418
0187:00523061  XOR      [EDI],EAX
0187:00523063  MOV      EAX,A935FC2E
0187:00523068  XOR      [EDI+04],EAX
0187:0052306B  MOV      EAX,57D872B9
0187:00523070  XOR      [EDI+08],EAX
0187:00523073  MOV      EAX,493DB437  <---其實這裡就是讀KeyFile的逆過程
0187:00523078  XOR      [EDI+0C],EAX
0187:0052307B  MOV      EAX,[EDI]      <---又來了
0187:0052307D  XOR      EAX,[EDI+04]
0187:00523080  MOV      EBX,[EDI+08]
0187:00523083  XOR      EBX,[EDI+0C]
0187:00523086  MOV      [EBP-08],EAX  <---注意它儲存的地址
0187:00523089  MOV      [EBP-0C],EBX      eax=952E1C75
0187:0052308C  POPA                        ebx=1EE5C68E
0187:0052308D  MOV      EAX,[00549C28]
0187:00523092  CALL    00403BE0
0187:00523097  CMP      EAX,BYTE +10  <---比較註冊碼長度是否為16位
0187:0052309A  JL      NEAR 0052328A      現在讓你猜,你能猜出正確的註冊碼是什麼嗎?
0187:005230A0  LEA      EAX,[EBP-18]
0187:005230A3  PUSH    EAX
0187:005230A4  MOV      ECX,08
0187:005230A9  MOV      EDX,01
0187:005230AE  MOV      EAX,[00549C28]
0187:005230B3  CALL    00403DE4
0187:005230B8  LEA      EAX,[EBP-1C]
0187:005230BB  PUSH    EAX
0187:005230BC  MOV      ECX,08
0187:005230C1  MOV      EDX,09
0187:005230C6  MOV      EAX,[00549C28]
0187:005230CB  CALL    00403DE4
0187:005230D0  LEA      ECX,[EBP-4C]
0187:005230D3  MOV      EDX,08
0187:005230D8  MOV      EAX,[EBP-08]
0187:005230DB  CALL    004072E8
0187:005230E0  MOV      EDX,[EBP-4C]
0187:005230E3  MOV      EAX,[EBP-18]
0187:005230E6  CALL    00403CF0      <---下面有個跳轉,說明這個Call有問題了,上面的幾個
0187:005230EB  JNZ      NEAR 0052326A      Call將eax和ebx的數變成ASC碼也就是說我們得到
0187:005230F1  LEA      ECX,[EBP-4C]      了2個字串"952E1C75"和"1EE5C68E",而這個Call
0187:005230F4  MOV      EDX,08            就是用這兩個字串與我輸入的假註冊碼比較,相等
0187:005230F9  MOV      EAX,[EBP-0C]      的話就註冊成功了,程式會自動生成一個新的KeyFile
0187:005230FC  CALL    004072E8          如果這裡不明白的話請看KeyFile部分
0187:00523101  MOV      EDX,[EBP-4C]
0187:00523104  MOV      EAX,[EBP-1C]
0187:00523107  CALL    00403CF0      <---比較第2部分,和上面是同一個Call
0187:0052310C  JNZ      NEAR 0052326A

-=End=-

==============================================================
下面是KeyFile的序號產生器,輸入註冊名後自動生成pexdata.rdat檔案,將檔案複製到程式的安裝目錄即可,註冊名支援中文名.請將下面源程式儲存為.rek檔案,用序號產生器編寫器編譯,序號產生器編寫器1.69測試透過!序號產生器的演算法很簡單,寫這個序號產生器有點困難的是API的呼叫,API的原型請查詢相關資料


.data
szHomePage db "http://www.365hz.net",0
szEmail    db "mailto:ljyljx@163.com",0
szErrMess  db "輸入的序列號不正確!",0
szFileName db "pexdata.rdat",0
SizeReadWrite dd ?
szTemp    db 512 dup(0)
.code

;請在宣告中加入以下兩句
;CreateFileA proto :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
;WriteFile proto :DWORD,:DWORD,:DWORD,:DWORD,:DWORD

mov esi,eax
mov eax,65656565h
mov ecx,8
lea edi,szTemp
push edi
rep stosd
pop edi
invoke lstrlen,esi
mov ecx,eax
rep movsb
mov [edi],byte ptr 0
lea edi,szTemp
mov eax,3617E418h
xor [edi],eax
mov eax,0A935FC2Eh
xor [edi+4],eax
mov eax,57D872B9h
xor [edi+8],eax
mov eax,493DB437h
xor [edi+0Ch],eax
mov eax,[edi]
xor eax,[edi+4]
mov ebx,[edi+8]
xor ebx,[edi+0Ch]
mov [edi+32],eax
mov [edi+36],ebx
mov [edi+40],eax
mov [edi+44],ebx
mov [edi+48],eax
mov [edi+52],ebx
mov [edi+56],eax
mov [edi+60],ebx

invoke lstrcpynA,addr szTemp+64,addr szTemp,65
invoke lstrcpynA,addr szTemp+128,addr szTemp,129
invoke lstrcpynA,addr szTemp+256,addr szTemp,257

mov ecx,511
xor edx,edx
mov ebx,3617E418h
PRO1:
mov eax,ebx
xor [edi+edx],al
ror ebx,1
xor ebx,0A5A5A5A5h
inc edx
dec ecx
jnz PRO1

invoke CreateFileA,addr szFileName,0C0000000h,3,0,2,0,0
invoke WriteFile,eax,edi,200h,addr SizeReadWrite,0


=================================================================
下面是生成註冊碼的序號產生器,註冊名支援中文名.請將下面源程式儲存為.rek檔案,用序號產生器編寫器編譯,序號產生器編寫器1.69測試透過!


.data
szHomePage db "http://www.365hz.net",0
szEmail    db "mailto:ljyljx@163.com",0
szErrMess  db "輸入的序列號不正確!",0
szErr      db "註冊名不能大於32位!",0
szFmt      db "%lX",0
szTemp    db 32 dup(0)
szBuffer  db 17 dup(0)
.code
mov esi,eax
mov eax,65656565h
mov ecx,4
lea edi,szTemp
push edi
rep stosd
pop edi
invoke lstrlen,esi
cmp eax,32
jg ERR

mov ecx,eax
rep movsb
mov [edi],byte ptr 0
lea edi,szTemp
mov eax,3617E418h
xor [edi],eax
mov eax,0A935FC2Eh
xor [edi+4],eax
mov eax,57D872B9h
xor [edi+8],eax
mov eax,493DB437h
xor [edi+0Ch],eax
mov eax,[edi]
xor eax,[edi+4]
mov ebx,[edi+8]
xor ebx,[edi+0Ch]
invoke wsprintf,addr szBuffer,addr szFmt,eax
invoke wsprintf,addr szBuffer+8,addr szFmt,ebx
lea eax,szBuffer
jmp Sam

ERR:
lea eax,szErr

Sam:

-=End=-

      _/_/_/
    _/          _/_/_/  _/_/_/  _/_/
    _/_/    _/    _/  _/    _/    _/
        _/  _/    _/  _/    _/    _/
_/_/_/      _/_/_/  _/    _/    _/

                                              Sam.com
                                          5:04 2002-4-3

相關文章