Kalua Cocktails 1.1完全破解,內附彙編序號產生器(用序號產生器編寫器,並有它的使用教程) (22千字)

看雪資料發表於2002-02-27

Kalua Cocktails 1.1完全破解,內附彙編序號產生器(用序號產生器編寫器,並有它的使用教程)

軟體名稱: Kalua Cocktails 1.1
下載地址:ftp://ftp.gekkosoft.com/pub/kalua11.exe

軟體簡介:
        是一套教你如何調配雞尾酒的食譜軟體。這套軟體收錄超過1100種雞尾酒調法,並且都附有圖片說明每種雞尾酒所含的酒精濃度和調配雞尾酒所要購買的配料,且支援列印功能,可讓你將調配雞尾酒所需的配料列印出來,方便採購這些配料。此外,也提供輸入配料來調配雞尾酒的功能,可以自行輸入配料,程式便會自動幫配料調配出哪些種類的雞尾酒供你參考。

軟體限制:未註冊只可查閱100種雞尾酒,每次退出會提示註冊.註冊後可查閱1000多種酒
破解原因:我是做飲食服務業的,它對我有用,可惜是E文的

  程式是用Delphi編的,Shrinker v3.4加的殼,因為這幾天都在想寫序號產生器的事,我記不起如何找到下面程式碼了,反正程式可以用Procdump脫殼,用Dede載入,找到註冊視窗的OK按鍵反彙編,然後用Trw200攔截,用S命令查詢輸入的假資訊,再用bpm設斷點,細心一點就能找到了.學破解以來我一直在用Trw,但是此程式最後查表時用到了浮點運算,我用了Trw的FPU外掛,可是到運算指令前一用就當機了,不知有人成功過嗎,逼得我在ME裡裝了Ice.

    這個程式的加密方法還不算很難,起碼可以逆運算來獲得註冊碼,但這個已經是我破解生涯中最難的一個了,因為它是將註冊名和註冊碼變形來比較的,看到的都是亂七八糟的16進位制數在記憶體中轉來轉去,一不留意就搞錯了.破了它以後想到寫個序號產生器,可以提高自己的水平嘛,為此我可充電了好幾天啊,在此也要謝謝"序號產生器編寫器"的作者,他在他的論壇上回答了我的不少問題,教會了我不少東西,另外還要謝謝看雪論壇!!

    提醒一句,紙和筆也是破解時的重要工具!

==SN Start==================================
這裡是我輸入的假註冊碼的變形,並不複雜,而且是可逆的,就是看到如此簡單我才想到要寫序號產生器,但當我搞清楚了註冊名的變形後,發現這裡根本就不重要.最後得到的結果不管它,生點在下面.
公式如下:

設假註冊碼前12位Xor C後的資料如下
S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11 S12

S1 xor S12 = Y1
S2 xor Y1  = Y2
.
.
S12 xor Y11=Y12

0187:004743F3  MOV      EDX,0C
0187:004743F8  LEA      EAX,[ESP+01]
0187:004743FC  MOV      CL,[EAX]    <----註冊碼的第一位
0187:004743FE  XOR      CL,0C        <----將它Xor C
0187:00474401  MOV      [EAX],CL    <----放回原位
0187:00474403  INC      EAX
0187:00474404  DEC      EDX
0187:00474405  JNZ      004743FC    <----這裡取12位,再長的註冊碼也是如此

0187:00474407  MOV      AL,[ESP+01]  <----變形後的第一位
0187:0047440B  XOR      AL,[ESP+0C]  <----與最後一位相Xor
0187:0047440F  MOV      [ESP+01],AL  <----放到第一位
0187:00474413  MOV      EDX,0B
0187:00474418  LEA      EAX,[ESP+02]
0187:0047441C  MOV      CL,[EAX]    <----變形後的第二位
0187:0047441E  XOR      CL,[EAX-01]  <----與再次變形後的第一位相Xor
0187:00474421  MOV      [EAX],CL    <----儲存在第二位
0187:00474423  INC      EAX
0187:00474424  DEC      EDX
0187:00474425  JNZ      0047441C
==SN End=====================================

==Step 1=====================================
以下是註冊名的變形,很長,要有耐性.除了我特別宣告,下面的數都是16進位制的.
我輸入的是註冊名是www.Sam.com

0167:0047449D  LEA      EAX,[ESP+12]  <-----eax指向註冊名的首地址
0167:004744A1  XOR      ECX,ECX
0167:004744A3  MOV      CL,[EAX]      <-----註冊名首位"w"放入ecx
0167:004744A5  ADD      EDI,ECX      <-----edi為0
0167:004744A7  INC      EAX
0167:004744A8  DEC      EDX          <-----edx是註冊名的位數
0167:004744A9  JNZ      004744A1      <-----往上跳,這裡其實是將註冊名的每一位依次相加,結果放入edi
0167:004744AB  MOV      EAX,EDI
0167:004744AD  MOV      ECX,FF
0167:004744B2  CDQ   
0167:004744B3  IDIV    ECX          <-----上面相加的結果除以FF
0167:004744B5  MOV      EDI,EDX      <-----餘數放到edi,這個數很重要,記住它,我這裡是25,設為Z1
0167:004744B7  LEA      EAX,[ESP+84]
0167:004744BE  PUSH    EAX
0167:004744BF  LEA      EDX,[ESP+15]
0167:004744C3  LEA      EAX,[ESP+FC]

==Step 2======================================
下面的是一個Call內的內容,留意一下之前程式在記憶體裡產生了一個字串"Kalua2000Kal",下面就是將註冊名加上此字尾,變為"www.Sam.comKalua2000Kal",然後取12位進行運算,即為"www.Sam.comK",這裡我沒把程式碼貼齊,只要留意一下就能看到的.

0167:00402CC0  PUSH    ESI
0167:00402CC1  PUSH    EDI
0167:00402CC2  MOV      EDI,EAX
0167:00402CC4  XOR      EAX,EAX
0167:00402CC6  MOV      AL,[EDI]
0167:00402CC8  MOV      ESI,EDX
0167:00402CCA  XOR      EDX,EDX
0167:00402CCC  MOV      DL,[ESI]
0167:00402CCE  INC      ESI
0167:00402CCF  ADD      AL,DL
0167:00402CD1  JC      00402CE5
0167:00402CD3  CMP      AL,CL
0167:00402CD5  JA      00402CE5
0167:00402CD7  MOV      ECX,EDX
0167:00402CD9  MOV      DL,[EDI]
0167:00402CDB  MOV      [EDI],AL
0167:00402CDD  INC      EDI
0167:00402CDE  ADD      EDI,EDX
0167:00402CE0  REP MOVSB
0167:00402CE2  POP      EDI
0167:00402CE3  POP      ESI
0167:00402CE4  RET

==Step 3====================================   
這裡才是重要的,註冊名在這裡開始要變化了,怎樣變我很難表達,反正結果如下(注意此時註冊名為12位的"www.Sam.comK"):

w  w  w  .  S  a  m  .  c  o  m  K          K  w  m  w  o  w  c  .  .  S  m  a
|  |  |  |  |  |  |  |  |  |  |  |    ===>  |  |  |  |  |  |  |  |  |  |  |  |
1  2  3  4  5  6  7  8  9  10 11 12        12 1  11 2  10 3  9  4  8  5  7  6

我們得到字串"Kwmwowc..Sma"

0167:00474518  MOV      EBX,01
0167:0047451D  LEA      EAX,[ESP+12]
0167:00474521  MOV      ECX,EBX
0167:00474523  ADD      ECX,ECX
0167:00474525  DEC      ECX
0167:00474526  MOV      EDX,0D
0167:0047452B  SUB      EDX,EBX
0167:0047452D  MOV      DL,[ESP+EDX+11]
0167:00474531  MOV      [ESP+ECX+76],DL
0167:00474535  MOV      DL,[EAX]
0167:00474537  MOV      [ESP+ECX+77],DL
0167:0047453B  INC      EBX
0167:0047453C  INC      EAX
0167:0047453D  CMP      EBX,BYTE +07
0167:00474540  JNZ      00474521

==Step 4=====================================
這步也比較複雜,用"Kalua2000Kal"和"Kwmwowc..Sma"兩個字串進行運算,運算完後在記憶體裡就看不到明碼的東西了.運算的公式如下:
K  w  m  w  o  w  c  .  .  S  m  a
|  |  |  |  |  |  |  |  |  |  |  |
A1  A2  A3  A4  A5  A6  A7  A8  A9  A10 A11 A12

K  a  l  u  a  2  0  0  0  K  a  l
|  |  |  |  |  |  |  |  |  |  |  |
B1  B2  B3  B4  B5  B6  B7  B8  B9  B10 B11 B12

A1+B1=T1
A2+Z1=T2
T1+T2=T3
T3÷FF==>edx==C1

A2+B2=T1
A3+Z2=T2
T1+T2=T3
T3÷FF==>edx==C2
.
.
.
A12+B12=T1
T1+Z2=T3
T3÷FF==>edx==C12

最後得到一組資料:
33 E2 5B DD 39 75 8D 86 D9 87 19 18

0167:00474551  MOV      EBX,01        <----計數器
0167:00474556  LEA      ESI,[ESP+12]  <----指向"Kwmwowc..Sma"
0167:0047455A  LEA      EBP,[ESP+05]  <----指向"Kalua2000Kal"
0167:0047455E  XOR      ECX,ECX
0167:00474560  MOV      CL,[ESI]      <----ecx="K"
0167:00474562  XOR      EAX,EAX
0167:00474564  MOV      AL,[EBP+00]    <----eax="K"
0167:00474567  ADD      ECX,EAX        <----"K"+"K"結果設為T1
0167:00474569  CMP      EBX,BYTE +0C  <----如果到了第12位就跳
0167:0047456C  JNL      00474575
0167:0047456E  XOR      EAX,EAX
0167:00474570  MOV      AL,[ESI+01]    <----eax="w"
0167:00474573  ADD      EDI,EAX        <----edi=25,結果設為T2,25是Step 1裡的結果,edi是累加的結果,設為Z2
0167:00474575  ADD      ECX,EDI        <----兩個結果相加T1+T2=T3,如果是第12位就免了上面一步
0167:00474577  MOV      EAX,ECX
0167:00474579  MOV      ECX,FF
0167:0047457E  CDQ   
0167:0047457F  IDIV    ECX            <----T3除以FF,餘數=edx=C1
0167:00474581  MOV      ECX,EDX
0167:00474583  CMP      ECX,BYTE +01
0167:00474586  JNL      0047458E
0167:00474588  ADD      ECX,FF        <----如果餘數小於1就加上FF
0167:0047458E  MOV      [ESI],CL      <----將餘數儲存
0167:00474590  INC      EBX
0167:00474591  INC      EBP
0167:00474592  INC      ESI
0167:00474593  CMP      EBX,BYTE +0D
0167:00474596  JNZ      0047455E      <----這裡迴圈完後指向"Kwmwowc..Sma"的地址就儲存了變形後的資料


下面的程式碼是否很眼熟,其實它和Step 3是一樣的,得到的資料再次移位,得到另一組資料:
18 33 19 E2 87 5B D9 DD 86 39 8D 75

0167:00474598  MOV      EBX,01
0167:0047459D  LEA      EAX,[ESP+12]
0167:004745A1  MOV      ECX,EBX
0167:004745A3  ADD      ECX,ECX
0167:004745A5  DEC      ECX
0167:004745A6  MOV      EDX,0D
0167:004745AB  SUB      EDX,EBX
0167:004745AD  MOV      DL,[ESP+EDX+11]
0167:004745B1  MOV      [ESP+ECX+76],DL
0167:004745B5  MOV      DL,[EAX]
0167:004745B7  MOV      [ESP+ECX+77],DL
0167:004745BB  INC      EBX
0167:004745BC  INC      EAX
0167:004745BD  CMP      EBX,BYTE +07
0167:004745C0  JNZ      004745A1

==Step 5=========================================
這裡是核心部分了,下面其實是一個查表的過程,用上面得到的資料逐位查表,得到的字元就和真正的註冊碼差不多了.不過程式用了浮點運算,為了搞清楚它我還查了不少資料.

0167:004745D1  MOV      EBX,09
0167:004745D6  LEA      EDI,[ESP+12]    <----指向上面的資料18 33 19 E2 87 5B D9 DD 86 39 8D 75
0167:004745DA  LEA      ESI,[ESP+77]
0167:004745DE  XOR      ECX,ECX
0167:004745E0  MOV      CL,[EDI]        <----ecx=18,這裡查第1位
0167:004745E2  MOV      EDX,1A          <----這個1A也是個重要的東西,記住它
0167:004745E7  MOV      EAX,ECX
0167:004745E9  CALL    0047432C        <----這個Call裡很多浮點運算,核心部分,下有解釋(Main Call)
0167:004745EE  MOV      ECX,EAX        <----ecx<==eax=17,這個數就是我們想要的了
0167:004745F0  MOV      EAX,00474724    <----eax指向字串"abcdefghijklmnopqrstuvwxyz"
0167:004745F5  MOV      AL,[EAX+ECX-01] <----查表得eax="w",注意這裡的17是16進位制的,十進位制是23,其實就是指26個英文字母的第23位

0167:004745F9  MOV      [ESI],AL        <----儲存結果
0167:004745FB  CMP      BYTE [005A424C],00  <---游標執行到此句時下d esi就可看到查到的字元,逐位把它記下來,我得到的是"wsxrkpoqj"

0167:00474602  JZ      0047460A
0167:00474604  MOV      AL,[ESI]
0167:00474606  XOR      AL,0C          <----這裡是不是也很眼熟,查到的字元馬上被Xor了
0167:00474608  MOV      [ESI],AL
0167:0047460A  INC      ESI
0167:0047460B  INC      EDI
0167:0047460C  DEC      EBX            <----ebx是計數器,這裡只查了前9位
0167:0047460D  JNZ      004745DE

0167:0047460F  MOV      EBX,03          <----下面是查後3位的
0167:00474614  LEA      EDI,[ESP+1B]
0167:00474618  LEA      ESI,[ESP+80]
0167:0047461F  XOR      ECX,ECX
0167:00474621  MOV      CL,[EDI]
0167:00474623  MOV      EDX,0A          <----這個換成A了
0167:00474628  MOV      EAX,ECX
0167:0047462A  CALL    0047432C
0167:0047462F  MOV      ECX,EAX
0167:00474631  MOV      EAX,00474748
0167:00474636  MOV      AL,[EAX+ECX-01]
0167:0047463A  MOV      [ESI],AL
0167:0047463C  CMP      BYTE [005A424C],00  <----這裡再下d esi,得到"951"
0167:00474643  JZ      0047464B
0167:00474645  MOV      AL,[ESI]
0167:00474647  XOR      AL,0C
0167:00474649  MOV      [ESI],AL
0167:0047464B  INC      ESI
0167:0047464C  INC      EDI
0167:0047464D  DEC      EBX
0167:0047464E  JNZ      0047461F
呵!好累,這一大段其實我們得到了一個字串"wsxrkpoqj951",不過馬上被Xor C了,所以得到了:
7B 7F 74 7E 67 7C 63 7D 66 35 39 3D
~~~~~~~~                  ````````

0167:00474650  LEA      EAX,[ESP+016C]
0167:00474657  PUSH    EAX
0167:00474658  MOV      ECX,03
0167:0047465D  MOV      EDX,01
0167:00474662  LEA      EAX,[ESP+7A]
0167:00474666  CALL    0040291C
0167:0047466B  LEA      EDX,[ESP+016C]
0167:00474672  LEA      EAX,[ESP+017C]
0167:00474679  CALL    00402CF0
0167:0047467E  LEA      EAX,[ESP+0198]
0167:00474685  PUSH    EAX
0167:00474686  MOV      ECX,03
0167:0047468B  MOV      EDX,0A
0167:00474690  LEA      EAX,[ESP+7A]
0167:00474694  CALL    0040291C
0167:00474699  LEA      EDX,[ESP+0198]
0167:004746A0  LEA      EAX,[ESP+017C]
0167:004746A7  MOV      CL,18
0167:004746A9  CALL    00402CC0
0167:004746AE  LEA      EDX,[ESP+017C]
0167:004746B5  LEA      EAX,[ESP+01A8]
0167:004746BC  CALL    00402CF0
0167:004746C1  LEA      EAX,[ESP+0198]
0167:004746C8  PUSH    EAX
0167:004746C9  MOV      ECX,06
0167:004746CE  MOV      EDX,04
0167:004746D3  LEA      EAX,[ESP+7A]
0167:004746D7  CALL    0040291C
0167:004746DC  LEA      EDX,[ESP+0198]
0167:004746E3  LEA      EAX,[ESP+01A8]
0167:004746EA  MOV      CL,24
0167:004746EC  CALL    00402CC0
0167:004746F1  LEA      EDX,[ESP+01A8]
上面這段將剛才那組資料移來移去,過了這一條,d edx看看,它將上面資料的位置換了換,變成:
7B 7F 74 35 39 3D 7E 67 7C 63 7D 66
~~~~~~~~ ````````
也就是說我們查表最後得到的一個字串是"wsx951rkpoqj",

==Step 6========================================
這裡已經算是最後一步了,是不是發現下面的運算和最上面註冊碼的變形是一樣的,其實對於我們來說這裡已經不重要了,因為真正的註冊碼已經出現了只不過如果第一次除錯時找不到這一步就根本找不到重點.因為程式在Step 5裡得到的字串"wsxrkpoqj951"每一位一出現就被Xor C,所以看不到明碼,而且程式還將它的中間6位移到字串的最後,再經過下面運算的結果和我假註冊碼的變形相比較,所以馬上可以斷定"wsx951rkpoqj"就是我的真正註冊碼.

0167:00474407  MOV      AL,[ESP+01]
0167:0047440B  XOR      AL,[ESP+0C]
0167:0047440F  MOV      [ESP+01],AL
0167:00474413  MOV      EDX,0B
0167:00474418  LEA      EAX,[ESP+02]
0167:0047441C  MOV      CL,[EAX]
0167:0047441E  XOR      CL,[EAX-01]
0167:00474421  MOV      [EAX],CL
0167:00474423  INC      EAX
0167:00474424  DEC      EDX
==Step Over=====================================





下面是查表時核心Call的部分,關於浮點運算,可以查閱看雪的Crack Tutorial,因為我也不是很懂.
==Main Call=====================================
它的過程大概是這樣的:
18  33  19  E2  87  5B  D9  DD  86  39  8D  75
|  |  |  |  |  |  |  |  |  |  |  |
D1  D2  D3  D4  D5  D6  D7  D8  D9  D10 D11 D12

D1除以40E00000  ==>ST(0)
求ST(0)的平方根  ==>ST(0)
ST(0)==>ST(1)
ST(0)取整
ST(0)-ST(1)      ==>ST(0)
ST(0)乘以1A(or A)==>ST(0)
ST(0)+3F800000  ==>ST(0)
ST(0)取整
如果看不懂,可以看看我寫的序號產生器,我省略了很多無用的步驟,最好用ICE除錯一下就能搞懂了


0167:0047432C  PUSH    EBX
0167:0047432D  PUSH    ESI
0167:0047432E  ADD      ESP,BYTE -14
0167:00474331  MOV      ESI,EDX
0167:00474333  MOV      EBX,EAX
0167:00474335  CALL    0040BBC8          <----這個Call不用理它,下面還有一個
寫序號產生器時寫到此我就被卡住了,因為此Call裡呼叫了GetLocalTime的函式,還進行了一大堆的運算,可能是為了生成下面記憶體中的一些資料的,剛開始我還以為註冊碼會和時間相關,但搞清楚後基本確定生成註冊碼不用呼叫這個Call.


0167:0047433A  FSTP    QWORD [ESP+08]
0167:0047433E  WAIT   
0167:0047433F  MOV      [ESP+10],EBX      <----這裡開始了,ebx=18,查第一位
0167:00474343  FILD    DWORD [ESP+10]    <----注意在ICE中看到的ST(i)中的數是10進位制的,如此時ST(0)=24
0167:00474347  FSTP    QWORD [ESP]
0167:0047434A  WAIT   
0167:0047434B  FLD      QWORD [ESP]
0167:0047434E  FDIV    DWORD [004743B8]  <----[004743B8]裡的值是40E00000,這個數是固定的,下面的[004743BC]都一樣,程式還沒進入這個Call時就已經是這個數了,所以做序號產生器時這兩個地址的資料就很重要了

0167:00474354  FSQRT 
0167:00474356  FSTP    QWORD [ESP]
0167:00474359  WAIT   
0167:0047435A  FLD      QWORD [ESP]
0167:0047435D  CALL    00402C38          <----Call (1)
0167:00474362  MOV      [ESP+10],ESI      <----esi=1A,這個記得吧,如果是查後3位的話esi=A
0167:00474366  FILD    DWORD [ESP+10]
0167:0047436A  FMULP    ST1                <----因為用Trw的原故,這裡顯示不完整,寫序號產生器時這裡應寫成fmulp st(1),st(0)
0167:0047436C  FADD    DWORD [004743BC]  <----[004743BC]=3F800000
0167:00474372  FSTP    QWORD [ESP]
0167:00474375  WAIT   
0167:00474376  FLD      QWORD [ESP]
0167:00474379  CALL    00402C10          <----Call (2)
0167:0047437E  FSTP    QWORD [ESP]
0167:00474381  WAIT   
0167:00474382  FLD      QWORD [ESP]
0167:00474385  CALL    00402C54          <----Call (3)
0167:0047438A  MOV      EBX,EAX            <----到這裡eax已經是我們想要的17啦,暫放到ebx中
0167:0047438C  CALL    0040BBC8          <----Forgot it!
0167:00474391  FSUBR    QWORD [ESP+08]
0167:00474395  FSTP    QWORD [ESP+08]
0167:00474399  WAIT   
0167:0047439A  FLD      TWORD [004743C0]
0167:004743A0  FCOMP    QWORD [ESP+08]
0167:004743A4  FNSTSW  AX
0167:004743A6  SAHF   
0167:004743A7  JNC      004743AE
0167:004743A9  MOV      EBX,01
0167:004743AE  MOV      EAX,EBX            <----把17放回eax中,出了這個Call就用它來查表了
0167:004743B0  ADD      ESP,BYTE +14
0167:004743B3  POP      ESI
0167:004743B4  POP      EBX
0167:004743B5  RET   
==Call (1)========================================
0167:00402C38  FLD      ST0
0167:00402C3A  SUB      ESP,BYTE +04
0167:00402C3D  FSTCW    [ESP]
0167:00402C41  WAIT   
0167:00402C42  FLDCW    [005A2028]        <----[005A2028]=1F32
說明一下FSTCW和FLDCW命令,因為我在查這兩個命令的資料時找不到詳細的說明,搞不懂它們是怎麼用的,後來經過我的實驗才搞懂的.FSTCW [ESP]是將現在的浮點標誌暫存器狀態寫入[ESP]中,浮點標誌暫存器是用來控制浮點運算的舍入、精度之類的,它的狀態會影響浮點運算結果的精確度,我這裡寫入的是1272,二進位制是1001001110010,分別對應暫存器的各欄位.而FLDCW則相反,它是將記憶體中的一個字寫入到暫存器中,這樣就可以按自己的要求來控制浮點運算的結果.這是我個人理解,請指正.

0167:00402C48  FRNDINT
0167:00402C4A  WAIT   
0167:00402C4B  FLDCW    [ESP]
0167:00402C4E  ADD      ESP,BYTE +04
0167:00402C51  FSUBP    ST1        <-----這個應為fsubp st(1),st(0)
0167:00402C53  RET   
==Call (2)========================================
0167:00402C10  SUB      ESP,BYTE +04
0167:00402C13  FSTCW    [ESP]
0167:00402C17  WAIT   
0167:00402C18  FLDCW    [005A2028]
0167:00402C1E  FRNDINT
0167:00402C20  WAIT   
0167:00402C21  FLDCW    [ESP]
0167:00402C24  ADD      ESP,BYTE +04
0167:00402C27  RET   
==Call (3)=========================================
0167:00402C54  SUB      ESP,BYTE +08
0167:00402C57  FISTP    QWORD [ESP]
0167:00402C5A  WAIT   
0167:00402C5B  POP      EAX
0167:00402C5C  POP      EDX
0167:00402C5D  RET   
==Call End=========================================

總結:累死了!已經太羅嗦了,把每個步驟前的說明加起來就是總結了.我怕論壇貼不完!呵呵~~~~~




~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
下面附上序號產生器,彙編寫的,C語言我已經忘記了,我不知道這個序號產生器能否用C語言寫出來,主要是指浮點運算那部分.當然我寫得不好,基本上我是將機器碼照搬上來的,我想應該可以寫得更加簡潔些.將下面的程式碼儲存為*.rek檔案,用序號產生器編寫器(v1.51以上除錯透過)開啟,編譯後就可以了,支援中文註冊名.另外序號產生器編寫器在編譯的時候大家最好編譯兩次,如果我們改了原始碼,只編譯一次的話生成的檔案和沒改的一樣,就算你把舊檔案刪掉也是如此,此問題我已向作者提出,希望他能改正.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.data
szHomePage db "http://www.365hz.net",0
szEmail    db "mailto:ljyljx@mail.china.com",0
szErrMess  db "註冊名不能大於34位!",0    ;/經過除錯註冊名大於34位後結果不正確
DATA1 db "Kalua2000Kal",0                ;/字尾字串
DATA2 db 50 dup(0)
DATA3 db 13 dup(0)
DATA4 db 0,0,0e0h,40h,0,0,80h,3fh        ;/[004743B8]和[004743BC]裡的資料
DATA5 db "abcdefghijklmnopqrstuvwxyz",0  ;/兩個表
DATA6 db "1234567890",0
DATA7 db 13 dup(0)
FDATA db 72h,12h,32h,1fh                  ;/浮點暫存器的狀態
.code
mov esi,eax                ;/先將一些重要的資料儲存
    invoke lstrlen,eax
    cmp eax,34
    jg ERR
    mov edx,eax
    mov ebx,eax
    mov eax,esi
    xor edi,edi

PRO1:
    xor ecx,ecx
    mov cl,[eax]            ;/Step 1
    add edi,ecx
    inc eax
    dec edx
    jnz PRO1
    mov eax,edi
    mov ecx,000000FFh
    cdq
    idiv ecx
    push edx                ;/儲存結果
    mov eax,esi
    mov ecx,ebx
    lea edi,DATA2          ;/Step 2
    rep movsb
    lea esi,DATA1
    mov ecx,12
    rep movsb

    mov ebx,1              ;/Step 3
    lea eax,DATA2
    lea edi,DATA3
    mov esi,eax
PRO2:
    mov ecx,ebx
    add ecx,ecx
    dec ecx
    mov edx,12
    sub edx,ebx
    mov dl,byte ptr [esi+edx]
    mov [edi],dl
    mov dl,[eax]
    mov [edi+1],dl
    inc ebx
    inc eax
    add edi,2
    cmp ebx,7
    jnz PRO2

    mov ebx,1              ;/Step 4
    lea esi,DATA3
    lea ebp,DATA1
    pop edi                ;/Step 1中的結果
PRO3:
    xor ecx,ecx
    mov cl,[esi]
    xor eax,eax
    mov al,byte ptr [ebp]
    add ecx,eax
    cmp ebx,12
    jnl PRO4
    xor eax,eax
    mov al,byte ptr [esi+1]
    add edi,eax
PRO4:
    add ecx,edi
    mov eax,ecx
    mov ecx,000000FFh
    cdq
    idiv ecx
    mov ecx,edx
    cmp ecx,1
    jnl PRO5
    add ecx,000000FFh
PRO5:
    mov [esi],cl
    inc ebx
    inc ebp
    inc esi
    cmp ebx,13
    jnz PRO3

    mov ebx,1
    lea eax,DATA3
    lea edi,DATA2
    mov esi,eax
PRO6:
    mov ecx,ebx
    add ecx,ecx
    dec ecx
    mov edx,12
    sub edx,ebx
    mov dl,byte ptr [esi+edx]
    mov [edi],dl
    mov dl,[eax]
    mov [edi+1],dl
    inc ebx
    inc eax
    add edi,2
    cmp ebx,7
    jnz PRO6          ;/這裡完成Step 4得到我們要的查表資料放在DATA2中

    mov ebx,9          ;/PRO7和PRO8分別查表
    lea edi,DATA2
    lea esi,DATA3
PRO7:
    xor ecx,ecx
    mov cl,byte ptr [edi]
    mov edx,0000001Ah   
    call Sam
    lea eax,DATA5
    mov al,byte ptr [eax+ecx-1]
    mov [esi],byte ptr al
    inc esi
    inc edi
    dec ebx
    jnz PRO7
   
    mov ebx,3
    lea edi,DATA2+9
    lea esi,DATA3+9
PRO8:
    xor ecx,ecx
    mov cl,byte ptr [edi]
    mov edx,0000000Ah
    call Sam
    lea eax,DATA6
    mov al,byte ptr [eax+ecx-1]
    mov [esi],byte ptr al
    inc esi
    inc edi
    dec ebx
    jnz PRO8

    lea esi,DATA3        ;/將查表後的註冊碼擺好位置
    lea edi,DATA7
    mov ecx,3
    rep movsb
    lea esi,DATA3+9
    mov ecx,3
    rep movsb
    lea esi,DATA3+3
    mov ecx,6
    rep movsb
    lea eax,DATA7
    jmp PRO9

Sam:
    push ebp          ;/這裡儲存現場,為了這個子程式,我的機死了n次,主要是不懂儲存
    mov ebp,esp        ;/現場,下面三個push如果去掉也會出錯,除錯一下就知
    push ebx
    push edi
    push esi
    push 0            ;/這裡push了兩個0因為下面要用到qword
    push 0
    mov [esp],ecx
    lea eax,FDATA
    fldcw [eax]          ;/因為在破解時程式在執行浮點運算前的浮點暫存器狀態是1272H,
    fild dword ptr [esp] ;/而我試過序號產生器執行時的狀態不同,為了保證序號產生器的準確性,所
    fstp qword ptr [esp] ;/以儘量讓序號產生器與原程式的暫存器狀態保持一致
    fld qword ptr [esp]
    lea eax,DATA4
    fdiv dword ptr [eax]
    fsqrt
    fstp qword ptr [esp]
    fld qword ptr [esp]
    fld st
    lea eax,FDATA
    fldcw [eax+2]
    frndint
    fldcw [eax]
    fsubp st(1),st(0)  ;/這個開始我寫成fsubp st1,st 因為我在Trw中U出來的是
    mov [esp],edx      ;/FSUBP ST1,害我查了很久書
    fild dword ptr [esp]
    fmulp st(1),st(0)
    lea eax,DATA4
    fadd dword ptr [eax+4]
    fstp qword ptr [esp]
    fld qword ptr [esp]
    lea eax,FDATA
    fldcw [eax+2]
    frndint
    fldcw [eax]
    fstp qword ptr [esp]
    fld qword ptr [esp]
    fistp qword ptr [esp]
    pop ecx
    pop ebx   
    ret 0              ;/這裡返回一定要加0,不然就~~~~~

ERR:
    lea eax,szErrMess
PRO9:




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

                                                  Sam.com
                                                18:34 2002-2-27

相關文章