Turbo Note+ V4.4序號產生器制分析 (19千字)

看雪資料發表於2001-11-07

Turbo Note+ V4.4序號產生器制分析

作者: 囚童[FCG][BCG]
課題: Turbo Note+ V4.4序號產生器制分析
出品: South Pacific InformationServices Ltd
背景: PACKED WITH Thrink v3
平臺: win95/98, winNT/2000
下載: http://turbopress.com/tnplus44.exe
尺寸: 769KB
工具: TRW 2000
      衝擊波2000
    W32Dasm V8.93

關鍵字: 軟體破解 註冊碼


TurboNote+是一個方便的“即時帖”軟體,可以工作在Win95/98, WinNT 和 Win2000
環境下。它可以即時在自己或透過IP地址向其他人的螢幕上貼上一個可定義尺寸和顏色
的"留言條",也可以按預定的時間啟動備忘提示功能。
透過"留言條",可以方便地啟動可執行程式、網際網路址、E-mail地址,也可以把它們作
為附件傳送給指定的IP地址。它可以隱藏,也可以再現,甚至關機後資訊也不會丟失。
使用十分方便。

TurboNote V4.4未註冊版有30天的時間限制。過期後會隨時出現延時的註冊視窗,程式
仍能使用。

TurboNote+是一個被壓縮了的可執行軟體,用一般的方法無法修改。它的脫殼較簡單,
用衝擊波2000找到程式入口,在TRW2000下定位入口,再用MAKEPE命令很容易就脫殼成
功。

TurboNote+在註冊時不出現明碼,大多數情況下,輸入了錯誤的註冊碼得不到提示,
因此用動態跟蹤尋找註冊入口較困難。相反,用靜態分析卻相當簡單。

以下是對其序號產生器制的分析:

用W32Dasm開啟TurboNote+主檔案TBNOTE.EXE,以REGISTER為關鍵字搜尋,定位在:

* Possible StringData Ref from Code Obj ->"There was a problem when saving "
                                        ->"the registry key Try again "
                                        ->"please."
                                  |
:00412BF4  push 00470968
:00412BF9  push eax

向上看,可以找到:

* Reference To: KERNEL32.lstrlenA, Ord:0000h
                                  |
:00412B4D Call dword ptr [00467128]
:00412B53 cmp  eax, 00000014               <==串長≥Ox14
:00412B56 jl   00412DD8
:00412B5C push 00000064
:00412B5E lea  ecx, dword ptr [ebp-44]
:00412B61 call 0042AA60
:00412B66 xor  ebx, ebx
:00412B68 push 00000019
:00412B6A lea  ecx, dword ptr [ebp-50]
:00412B6D mov  dword ptr [ebp-04], ebx
:00412B70 call 0042AA60

嗯,有點象,註冊碼長度可能大於20個字元。怪不得輸錯了註冊碼得不到提示,因為大
多數人一開始是不會輸入那麼長的一串碼的。

啟動TRW2000,點選OK使其最小化。

雙擊TurboNote+圖示,TurboNote+在螢幕右下腳生成一個TurboNote+圖示。
右擊這個圖示,會彈出一個右鍵選單,選GENERAL SETTINGS,GENERAL SETTINGS視窗彈
出,點REGISTER TURBONOTE+選項卡,該卡被調到視窗最前面,在REGISTRATION CODE:
框中隨便輸入20個字母數字,我們後面稱它串。注意,TurboNote+的註冊碼拒絕鍵盤上
的某些字元,例如[BCG]的方括號。

按CTRL+N,啟用TRW。

下指令:BPX 412B53,按F5,TurboNote+再次被TRW截獲。

按F10,一路走一路看,來到:

* Possible StringData Ref from Code Obj ->"SOFTWARE\SPIS Ltd\TurboNote\"
                    ->"Registration"
                                  |
:00412B86 push 004709B4
:00412B8B push 80000002
:00412B90 lea  ecx, dword ptr [ebp-6C]
:00412B93 mov  [ebp-04], 02
:00412B97 call 0044CA50
:00412B9C push 0000012C
:00412BA1 lea  ecx, dword ptr [ebp-20]
:00412BA4 mov  [ebp-04], 03
:00412BA8 call 0042AA60
:00412BAD push edi
:00412BAE lea  ecx, dword ptr [ebp-20]
:00412BB1 mov  [ebp-04], 04
:00412BB5 call 0042AF00
:00412BBA mov  eax, dword ptr [ebp-4C]
:00412BBD mov  ecx, dword ptr [ebp-40]
:00412BC0 mov  edx, dword ptr [ebp-1C]
:00412BC3 mov  eax, dword ptr [eax]
:00412BC5 mov  ecx, dword ptr [ecx]
:00412BC7 mov  edx, dword ptr [edx]
:00412BC9 push eax
:00412BCA push ecx
:00412BCB push edx
:00412BCC call 0044B470            <==註冊模組入口,按F8進入
:00412BD1 add  esp, 0000000C
:00412BD4 test eax, eax
:00412BD6 je 0 0412D2A
:00412BDC mov  ecx, esi
:00412BDE call 00412DF0
:00412BE3 test eax, eax
:00412BE5 jne  00412C05
:00412BE7 mov  eax, dword ptr [esi+000001B0]
:00412BED push 00000010

412BCC是註冊模組入口,按F8進入,來到:

* Referenced by a CALL at Addresses:
|:00412BCC, :0044AC60, :0044AEE5
|
:0044B470 sub  esp, 00000304
:0044B476 lea  eax, dword ptr [esp+00000080]
:0044B47D push ebx
:0044B47E push ebp
:0044B47F push esi
:0044B480 push edi

* Possible StringData Ref from Code Obj ->"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"
                    ->"fghijklmnopqrst"
                                        ->"uvwxyz0123456789+/="
                                  |
:0044B481 push 00473000
:0044B486 push eax

* Reference To: KERNEL32.lstrcpyA, Ord:0000h
                                  |
:0044B487 Call dword ptr [0046712C]
:0044B48D mov  ecx, 00000040          <==從這裡開始建密匙對照表
:0044B492 or e ax, FFFFFFFF
:0044B495 lea  edi, dword ptr [esp+000000D2]
:0044B49C repz
:0044B49D stosd
:0044B49E mov  eax, 00000041
        
        
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044B513(C)
|
:0044B4FF mov  byte ptr [esp+eax+000001DC], 00
:0044B507 mov  byte ptr [esp+eax+00000241], 00
:0044B50F inc  eax
:0044B510 cmp  eax, 00000064
:0044B513 jl   0044B4FF
:0044B515 mov  esi, dword ptr [esp+00000318]
:0044B51C mov  dword ptr [esp+000002A8], 3F7FDEFF
:0044B527 push esi
:0044B528 mov  byte ptr [esp+000001DC], FF  <==第二遍運算時使用的密匙表
:0044B530 mov  byte ptr [esp+000001DD], DE
:0044B538 mov  byte ptr [esp+000001DE], 7F
:0044B540 mov  byte ptr [esp+000001DF], cl

:0044B547 Call  dword ptr [00467128]
:0044B54D mov  edx, eax
:0044B54F cmp  edx, 00000014
:0044B552 jl   0044B6D5
:0044B558 mov  dword ptr [esp+18], edi
:0044B55C mov  ecx, 00000019
:0044B561 xor  eax, eax
:0044B563 lea  edi, dword ptr [esp+28]
:0044B567 lea  ebp, dword ptr [edx+esi-04]
:0044B56B lea  ebx, dword ptr [edx+esi-03]
:0044B56F repz
:0044B570 stosd
:0044B571 mov  al, byte ptr [ebp+00]
:0044B574 lea  edi, dword ptr [edx+esi-02]
:0044B578 mov  byte ptr [esp+10], al
:0044B57C mov  cl, byte ptr [ebx]
:0044B57E mov  byte ptr [esp+11], cl
:0044B582 mov  al, byte ptr [edi]
:0044B584 lea  edx, dword ptr [edx+esi-01]
:0044B588 mov  byte ptr [esp+12], al
:0044B58C mov  dword ptr [esp+24], edx
:0044B590 push 0016EB35
:0044B595 mov  cl, byte ptr [edx]
:0044B597 lea  edx, dword ptr [esp+1C]
:0044B59B mov  byte ptr [esp+17], cl
:0044B59F push edx
:0044B5A0 lea  eax, dword ptr [esp+18]
:0044B5A4 push 00000004           <==先處理末4位
:0044B5A6 lea  ecx, dword ptr [esp+34]
:0044B5AA push eax
:0044B5AB push ecx
:0044B5AC lea  ecx, dword ptr [esp+000000A4]
:0044B5B3 mov  dword ptr [esp+34], edi
:0044B5B7 mov  [esp+28], 00
:0044B5BC call 00406F20            <==末4位處理模組,按F8進入
:0044B5C1 test eax, eax
:0044B5C3 jne  0044B5D8
:0044B5C5 mov  edx, dword ptr [esp+18]
:0044B5C9 pop  edi
:0044B5CA pop  esi
:0044B5CB pop  ebp
:0044B5CC mov  byte ptr [esp+edx+1C], al
:0044B5D0 pop  ebx
:0044B5D1 add  esp, 00000304
:0044B5D7 ret

透過後面對序號產生器制的分析,可以從上面建立的密匙對照表總結出,TurboNote+的注
冊碼只接受0-9、A-Z、a-z、“+”和“/”,其它為無效字元。

在44B5BC按F8進入,來到406F20,這是對串尾末4位的處理。我們可以看兩種串尾的結
構,一種串尾為任意碼,另一種串尾為"==",兩種演算法的效果基本是一樣的,這裡我
們來看第一種。

* Referenced by a CALL at Addresses:
|:004074D6, :0044B5BC
|
:00406F20 sub  esp, 000000D0
:00406F26 xor  eax, eax
:00406F28 push ebx
:00406F29 mov  ebx, dword ptr [esp+000000DC]
:00406F30 push ebp
:00406F31 push esi
:00406F32 mov  esi, dword ptr [esp+000000E8]
:00406F39 mov  ebp, ecx
:00406F3B push edi
:00406F3C mov  ecx, 00000019
:00406F41 lea  edi, dword ptr [esp+78]
:00406F45 repz
:00406F46 stosd
:00406F47 cmp  byte ptr [ebx+esi-01], 3D    <==注意這裡,串尾一個"="號
:00406F4C je 0 0406FC9
:00406F4E mov  ecx, 00000019          <==串尾為任意碼的處理
:00406F53 xor  eax, eax
:00406F55 lea  edi, dword ptr [esp+10]
:00406F59 push esi
:00406F5A repz
:00406F5B stosd
:00406F5C lea  eax, dword ptr [esi+2*esi]           <==串長x3
:00406F5F mov  edi, dword ptr [esp+000000F4]
:00406F66 shl  eax, 1                     <==結果x2
:00406F68 cdq
:00406F69 and  edx, 00000007
:00406F6C push ebx
:00406F6D add  eax, edx
:00406F6F mov  ecx, ebp
:00406F71 sar  eax, 03                     <==結果/8
:00406F74 mov  dword ptr [edi], eax      <==碼長關鍵字,記下這個地址
:00406F76 lea  eax, dword ptr [esp+18]
:00406F7A push eax
:00406F7B call 00407220                <==對串尾進行處理
:00406F80 test eax, eax
:00406F82 jne  00406F91                <==成功則跳
:00406F84 pop  edi
:00406F85 pop  esi
:00406F86 pop  ebp
:00406F87 pop  ebx
:00406F88 add  esp, 000000D0
:00406F8E ret  0014

* Referenced by a CALL at Address:
|:00406F7B 
|
:00407220  push ebx
:00407221  push ebp
:00407222  mov ebp, dword ptr [esp+14]
:00407226  push esi
:00407227  push edi
:00407228  xor edi, edi
:0040722A  xor edx, edx
:0040722C  test ebp, ebp
:0040722E  jle 004072D2

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004072CC(C)
|
:00407234  mov ebx, dword ptr [esp+18]
:00407238  lea esi, dword ptr [edx+01]
:0040723B  movsx eax, byte ptr [ebx+esi-01]   <==四位數一組,取第1位數
:00407240  mov al, byte ptr [eax+ecx+42]          <==查表取值
:00407244  test al, al
:00407246  jl 004072DE
:0040724C  and eax, 0000003F                <==3f內有效
:0040724F  shl eax, 06                   <==結果=值*Ox40
:00407252  cmp esi, ebp
:00407254  jge 0040726C
:00407256  movsx ebx, byte ptr [edx+ebx+01]         <==取下一位數
:0040725B  mov bl, byte ptr [ebx+ecx+42]          <==查表取值
:0040725F  test bl, bl
:00407261  jl 004072DE
:00407263  and ebx, 0000003F                <==3f內有效
:00407266  or eax, ebx                  <==加這個值到結果
:00407268  mov ebx, dword ptr [esp+18]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407254(C)
|
:0040726C  lea ebp, dword ptr [esi+01]
:0040726F  shl eax, 06                   <==結果=值*Ox40
:00407272  cmp ebp, dword ptr [esp+1C]
:00407276  jge 0040728E
:00407278  movsx ebx, byte ptr [edx+ebx+02]        <==取下一位數
:0040727D  mov bl, byte ptr [ebx+ecx+42]         <==查表取值
:00407281  test bl, bl
:00407283  jl 004072DE
:00407285  and ebx, 0000003F               <==3f內有效
:00407288  or eax, ebx                  <==加這個值到結果
:0040728A  mov ebx, dword ptr [esp+18]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407276(C)
|
:0040728E  mov ebp, dword ptr [esp+1C]
:00407292  add esi, 00000002
:00407295  shl eax, 06                   <==結果=值*Ox40
:00407298  cmp esi, ebp
:0040729A  jge 004072AE
:0040729C  movsx esi, byte ptr [edx+ebx+03]        <==取最後一位數
:004072A1  mov bl, byte ptr [esi+ecx+42]          <==查表取值
:004072A5  test bl, bl
:004072A7  jl 004072DE
:004072A9  and ebx, 0000003F                <==3f內有效
:004072AC  or eax, ebx                   <==加這個值到結果

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040729A(C)
|
:004072AE  mov esi, dword ptr [esp+14]
:004072B2  add edx, 00000004
:004072B5  mov byte ptr [edi+esi+02], al      <==結果為三位,存為新串
:004072B9  add edi, 00000003
:004072BC  shr eax, 08               <==結果/Ox100
:004072BF  mov byte ptr [edi+esi-02], al      <==取餘
:004072C3  shr eax, 08               <==結果/Ox100
:004072C6  mov byte ptr [edi+esi-03], al      <==取商
:004072CA  cmp edx, ebp
:004072CC  jl 00407234

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040722E(C)
|
:004072D2  pop edi
:004072D3  pop esi
:004072D4  pop ebp
:004072D5  mov eax, 00000001
:004072DA  pop ebx
:004072DB  ret 000C


406F7B的call若運算成功,退出後會跳到406F91:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00406F82(C)
|
:00406F91  mov eax, dword ptr [edi]
:00406F93  xor ecx, ecx
:00406F95  test eax, eax
:00406F97  jle 004070F9
:00406F9D  mov eax, dword ptr [esp+000000E4]
:00406FA4  lea esi, dword ptr [esp+10]
:00406FA8  sub esi, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00406FB5(C)
|
:00406FAA  mov dl, byte ptr [esi+eax]   <==取第一遍的運算結果,存為新串
:00406FAD  inc ecx
:00406FAE  mov byte ptr [eax], dl     <==校驗關鍵字,記下這個地址
:00406FB0  mov edx, dword ptr [edi]
:00406FB2  inc eax
:00406FB3  cmp ecx, edx
:00406FB5  jl 00406FAA
:00406FB7  pop edi
:00406FB8  pop esi
:00406FB9  pop ebp
:00406FBA  mov eax, 00000001
:00406FBF  pop ebx
:00406FC0  add esp, 000000D0
:00406FC6  ret 0014

校驗關鍵字是由串的末四位運算而來的,它實際上是註冊使用者名稱累加和的尾數。

對串的前半部分,要做兩遍運算處理,其第一遍運算同樣呼叫的是上面的模組,這裡
不再贅述。

第二遍運算,是在407553的呼叫中進行的,我們來看一下:

* Referenced by a CALL at Address:
|:00407553 
|
:00407580 mov  eax, dword ptr [ecx+00000144] <==從串首取第一遍的運算結果
:00407586 mov  dl, byte ptr [ecx+eax+00000148]
:0040758D mov  al, byte ptr [esp+04]     <==取4個字的密匙表
:00407591 xor  dl, al             <==4位一組,做XOR運算
:00407593 mov  eax, dword ptr [esp+08]
:00407597 mov  byte ptr [eax], dl
:00407599 mov  edx, dword ptr [ecx+00000144]
:0040759F inc  edx
:004075A0 and  edx, 80000003
:004075A6 jns  004075AD
:004075A8 dec  edx
:004075A9 or  edx, FFFFFFFC
:004075AC inc  edx
           
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004075A6(C)
|
:004075AD mov dword ptr [ecx+00000144], edx
:004075B3 mov eax, 00000001
:004075B8 ret 0008

下面進行註冊碼效驗:

* Referenced by a CALL at Address:
|:0040751C 
|
:004075C0 sub  esp, 0000001C
:004075C3 mov  eax, 00000009
:004075C8 push ebp
:004075C9 push esi
:004075CA mov  esi, ecx
:004075CC xor  ebp, ebp
:004075CE mov  ecx, dword ptr [esp+2C]     <==取前面記下的碼長關鍵字
:004075D2 push edi
:004075D3 mov  edi, dword ptr [esp+2C]   <==取第二遍運算結果的串首地址
:004075D7 add  ecx, FFFFFFFC          <==減4
:004075DA cmp  ecx, eax             <==大於等於9?
:004075DC jl  004075F0
:004075DE lea  ebp, dword ptr [ecx-08]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004075EE(C)
|
:004075E1 mov dl, byte ptr [eax+edi]       <==從第9個數取值
:004075E4 mov byte ptr [esi+eax+00000143], dl   <==存入儲存單元
:004075EB inc eax
:004075EC cmp eax, ecx            <==取N個,N=碼長關鍵字-4-9
:004075EE jle 004075E1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004075DC(C)
|
:004075F0 mov  byte ptr [esi+ebp+0000014C], 00
:004075F8 mov  di, word ptr [edi+03]
:004075FC and  edi, 0000FFFF
:00407602 lea  eax, dword ptr [esp+0C]
:00407606 push edi

* Possible StringData Ref from Code Obj ->"N=%d"
                                  |
:00407607 push  0046F31C
:0040760C push  eax

* Reference To: USER32.wsprintfA, Ord:0000h
                                  |
:0040760D Call dword ptr [004672B4]
:00407613 add  esi, 000001B1
:00407619 push 0000000A
:0040761B push esi
:0040761C push edi
:0040761D call 004628BC
:00407622 add  esp, 00000018
:00407625 mov  dword ptr [004771BC], 00262D75
:0040762F mov  eax, 00000001
:00407634 pop  edi
:00407635 pop  esi
:00407636 pop  ebp
:00407637 add  esp, 0000001C
:0040763A ret  0008

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044B633(C)
|
:0044B655 mov  ecx, dword ptr [esp+1C]
:0044B659 mov  byte ptr [esp+ecx+000002AC], 00
:0044B661 lea  ecx, dword ptr [esp+00000090]
:0044B668 call 00407640          <==在EAX中返回4075E4處儲存的值
:0044B66D mov  edx, dword ptr [esp+28]   <==取406FAE處儲存的校驗關鍵字
:0044B671 and  edx, 000000FF
:0044B677 cmp  eax, edx          

相關文章