SpeedFlash註冊演算法分析(VB)

看雪資料發表於2015-11-15

一個VB程式SpeedFlash的破解

下載地址:http://www.relaxsoft.net/SoftDown/SoftView.asp?SoftID=25

有同學請我幫忙破這個軟體(可惜不是MM ),當時我二話沒說答應了,結果花了二十分鐘才把個這個4M的大傢伙DOWN下來(我只有56K小貓).先用PEiD檢測,是ASPACK2.11,手頭正好有這個版本的脫殼機,輕鬆搞定.再檢測,是VB6.0 .以前我對VB程式一直是敬而遠之的,但這次為了在哥們面前顯露一把,只好硬著頭皮試試了.

這個軟體很狡猾,點註冊後根本沒有任何提示.先下斷點BPX HMEMCPY看看,點選,斷了下來,按了五十來次F12還在VB DLL裡轉悠,只好換人: BPX MSVBVM60!__vbaVarTstEq .第二次中斷後再走一段就來到這裡: 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004982F2(C)
|
:00498251 8B03                    mov eaxdword ptr [ebx]
:00498253 50                      push eax
:00498254 8B4D14                  mov ecxdword ptr [ebp+14]
:00498257 8B11                    mov edxdword ptr [ecx]
:00498259 52                      push edx

* Reference To: MSVBVM60.__vbaStrCat, Ord:0000h
                                  |
:0049825A FF1580104000            Call dword ptr [00401080] <--把機器碼和NAME合併為串S
:00498260 8945A4                  mov dword ptr [ebp-5C], eax
:00498263 C7459C08000000          mov [ebp-64], 00000008
:0049826A 0FBFC6                  movsx eaxsi
:0049826D 50                      push eax
:0049826E 8D4D9C                  lea ecxdword ptr [ebp-64]
:00498271 51                      push ecx
:00498272 8D558C                  lea edxdword ptr [ebp-74]
:00498275 52                      push edx

* Reference To: MSVBVM60.rtcLeftCharVar, Ord:0269h
                                  |
:00498276 FF15B4124000            Call dword ptr [004012B4]
:0049827C 6A01                    push 00000001
:0049827E 8D458C                  lea eaxdword ptr [ebp-74]
:00498281 50                      push eax
:00498282 8D8D7CFFFFFF            lea ecxdword ptr [ebp+FFFFFF7C]
:00498288 51                      push ecx

* Reference To: MSVBVM60.rtcRightCharVar, Ord:026Bh
                                  |
:00498289 FF15D0124000            Call dword ptr [004012D0]
:0049828F 8D957CFFFFFF            lea edxdword ptr [ebp+FFFFFF7C]
:00498295 52                      push edx
:00498296 8D45C8                  lea eaxdword ptr [ebp-38]
:00498299 50                      push eax

* Reference To: MSVBVM60.__vbaStrVarVal, Ord:0000h
                                  |
:0049829A FF15EC114000            Call dword ptr [004011EC] <--依次得到S中的字元
:004982A0 50                      push eax

* Reference To: MSVBVM60.rtcAnsiValueBstr, Ord:0204h
                                  |
:004982A1 FF1560104000            Call dword ptr [00401060] <--把字元轉為ASCII碼
:004982A7 0FBFC8                  movsx ecxax
:004982AA 03CF                    add ecxedi <--把結果累加起來
:004982AC 0F80BB0D0000            jo 0049906D
:004982B2 8BF9                    mov ediecx
:004982B4 8D4DC8                  lea ecxdword ptr [ebp-38]

* Reference To: MSVBVM60.__vbaFreeStr, Ord:0000h
                                  |
:004982B7 FF1508134000            Call dword ptr [00401308]
:004982BD 8D957CFFFFFF            lea edxdword ptr [ebp+FFFFFF7C]
:004982C3 52                      push edx
:004982C4 8D458C                  lea eaxdword ptr [ebp-74]
:004982C7 50                      push eax
:004982C8 8D4D9C                  lea ecxdword ptr [ebp-64]
:004982CB 51                      push ecx
:004982CC 6A03                    push 00000003

* Reference To: MSVBVM60.__vbaFreeVarList, Ord:0000h
                                  |
:004982CE FF1540104000            Call dword ptr [00401040]
:004982D4 83C410                  add esp, 00000010
:004982D7 6683C601                add si, 0001
:004982DB 0F808C0D0000            jo 0049906D
:004982E1 668B55E0                mov dxword ptr [ebp-20]
:004982E5 6683C201                add dx, 0001 
:004982E9 0F807E0D0000            jo 0049906D
:004982EF 663BF2                  cmp sidx
:004982F2 0F8559FFFFFF            jne 00498251 <--這裡迴圈結束;EDI處是各個字元累加的結果
:004982F8 6800000840              push 40080000
:004982FD 6A00                    push 00000000
:004982FF 6BFF05                  imul edi, 00000005 <--EDI=EDI*5
:00498302 0F80650D0000            jo 0049906D
:00498308 B856555555              mov eax, 55555556 <--EAX=55555556$
:0049830D F7EF                    imul edi <--EAX=EAX*EDI的低32位,EDX=EAX*EDI的高32位
:0049830F 8BC2                    mov eaxedx
:00498311 C1E81F                  shr eax, 1F       <--得到高32位的最高1位
:00498314 03D0                    add edxeax      <--加到原來的高32位上去
:00498316 83C201                  add edx, 00000001 <--結果再加1,我們把結果記為R
:00498319 0F804E0D0000            jo 0049906D <--上面這一段還是比較好懂的

到了這裡以後,我以為已經接近目標了,沒想到後面一直風平浪靜,到下面那個vbaStrR8處突然嘩啦一下出來一個老長的數轉成了字串,而後面的vbaStrCmp也是把假碼與這個字串比較,可見這就是真正的註冊碼了.唯一一個可疑的就是49833F處的CALL MSVBVM60!__vbaPowerR8,但我又跟了好幾遍也不知道那個大數是怎麼算出來的.趕緊再翻開<<Crack Tutorial>>,這才明白下面那些f開頭的命令都是浮點計算,也就是說根本不在我們可愛的通用暫存器EAX,EBX中 . OK!明白以後我們在SOFTICE中輸入WF開啟浮點顯示視窗,裡面ST0,ST1,ST2之類就是浮點暫存器了.仔細盯著點,我們繼續...

:0049831F 899500FFFFFF            mov dword ptr [ebp+FFFFFF00], edx
:00498325 DB8500FFFFFF            fild dword ptr [ebp+FFFFFF00]
:0049832B DD9DF8FEFFFF            fstp qword ptr [ebp+FFFFFEF8]
:00498331 8B8DFCFEFFFF            mov ecxdword ptr [ebp+FFFFFEFC]
:00498337 51                      push ecx
:00498338 8B95F8FEFFFF            mov edxdword ptr [ebp+FFFFFEF8]
:0049833E 52                      push edx

* Reference To: MSVBVM60.__vbaPowerR8, Ord:0000h
                                  |
:0049833F FF1558124000            Call dword ptr [00401258] <--這個CALL就是計算了
:00498345 DC05C0284000            fadd qword ptr [004028C0] <--這句會把ST0+1(見後面)
:0049834B DFE0                    fstsw ax
:0049834D A80D                    test al, 0D
:0049834F 0F85130D0000            jne 00499068
:00498355 83EC08                  sub esp, 00000008
:00498358 DD1C24                  fstp qword ptr [esp]

* Reference To: MSVBVM60.__vbaStrR8, Ord:0000h
                                  |
:0049835B FF1580114000            Call dword ptr [00401180] <--這裡是把上面的ST0+1變為字串
:00498361 8BD0                    mov edxeax
:00498363 8D4DC8                  lea ecxdword ptr [ebp-38]

* Reference To: MSVBVM60.__vbaStrMove, Ord:0000h
                                  |
:00498366 FF15C4124000            Call dword ptr [004012C4]
:0049836C 50                      push eax   <--EAX為真碼
:0049836D 8B4510                  mov eaxdword ptr [ebp+10]
:00498370 8B08                    mov ecxdword ptr [eax]
:00498372 51                      push ecx   <--ECX為假碼

* Reference To: MSVBVM60.__vbaStrCmp, Ord:0000h
                                  |
:00498373 FF153C114000            Call dword ptr [0040113C] <--這個CALL就是比較了
:00498379 8BF0                    mov esieax
:0049837B F7DE                    neg esi
:0049837D 1BF6                    sbb esiesi
:0049837F 46                      inc esi
:00498380 F7DE                    neg esi

在CALL __vbaPowerR8處進入: (現在我們到了MSVBVM60.DLL裡面)

MSVBVM60!__vbaPowerR8
0167:73475767  PUSH      EBP
0167:73475768  MOV       EBP,ESP
0167:7347576A  FLD       REAL8 PTR [733C0700]
0167:73475770  FLD       REAL8 PTR [EBP+08]
0167:73475773  FCOMP     ST(1)
0167:73475775  FSTSW   AX
0167:73475777  SAHF
0167:73475778  JNZ       73475790
0167:7347577A  FLD       REAL8 PTR [EBP+10]
0167:7347577D  FCOMP     ST(1)
0167:7347577F  FSTSW   AX
0167:73475781  SAHF
0167:73475782  JNZ       73475790
0167:73475784  FSTP      ST(0)
0167:73475786  FLD       REAL8 PTR [733C0718]
0167:7347578C  POP       EBP
0167:7347578D  RET       0010
0167:73475790  FLD       REAL8 PTR [EBP+08]
0167:73475793  FCOMP     ST(1)
0167:73475795  FSTSW   AX
0167:73475797  SAHF
0167:73475798  JNZ       734757A4
0167:7347579A  FLD       REAL8 PTR [EBP+10]
0167:7347579D  FCOMP     ST(1)
0167:7347579F  FSTSW   AX
0167:734757A1  SAHF
0167:734757A2  JB        734757CE
0167:734757A4  FLD       REAL8 PTR [EBP+08]
0167:734757A7  FCOMP     ST(1)
0167:734757A9  FSTSW   AX
0167:734757AB  SAHF
0167:734757AC  FSTP      ST(0)
0167:734757AE  JAE       734757D2
0167:734757B0  FLD       REAL8 PTR [EBP+10]
0167:734757B3  PUSH      ECX
0167:734757B4  PUSH      ECX
0167:734757B5  FSTP      REAL8 PTR [ESP]
0167:734757B8  CALL      73480307
0167:734757BD  FCOMP     REAL8 PTR [EBP+10]
0167:734757C0  POP       ECX
0167:734757C1  POP       ECX
0167:734757C2  FSTSW   AX
0167:734757C4  SAHF
0167:734757C5  JZ        734757D2
0167:734757C7  PUSH      05
0167:734757C9  CALL      733B5359
0167:734757CE  FSTP      ST(0)
0167:734757D0  JMP       734757C7
0167:734757D2  CALL      733A68B8
0167:734757D7  FLD       REAL8 PTR [EBP+08]
0167:734757DA  FLD       REAL8 PTR [EBP+10]
0167:734757DD  AND       DWORD PTR [EAX],00 
0167:734757E0  CALL      73480400   <--上面的一堆都沒什麼用,不過是把上面的EDX結果放入ST0中,但帶過這個CALL後發現那個大數出現了,所以要進入這個CALL
0167:734757E5  FST       REAL8 PTR [EBP+10]
0167:734757E8  PUSH      ECX
0167:734757E9  PUSH      ECX

進入734757E0處的CALL:

0167:73480400  SUB       ESP,10
0167:73480403  FXCH      ST(1)
0167:73480405  FSTP      REAL8 PTR [ESP]
0167:73480408  FST       REAL8 PTR [ESP+08]
0167:7348040C  MOV       EAX,[ESP+0C]
0167:73480410  CALL      73480419  <--進入這個CALL
0167:73480415  ADD       ESP,10
0167:73480418  RET

進入73480419處的CALL:

0167:73480419  MOV       ECX,EAX
0167:7348041B  PUSH      EAX
0167:7348041C  WAIT
0167:7348041D  FSTCW     WORD PTR [ESP]
0167:73480420  CMP       WORD PTR [ESP],027F
0167:73480426  JZ        7348042D
0167:73480428  CALL      73483C17
0167:7348042D  AND       ECX,7FF00000
0167:73480433  LEA       EDX,[ESP+08]
0167:73480437  CMP       ECX,7FF00000
0167:7348043D  JZ        7348058D
0167:73480443  CALL      73483C47
0167:73480448  JZ        73480586
0167:7348044E  TEST      EAX,7FF00000
0167:73480453  JZ        734805AC
0167:73480459  MOV       CL,[ESP+0F]
0167:7348045D  AND       CL,80
0167:73480460  JNZ       73480622
0167:73480466  FYL2X <--前面ST0=R(上面的結果),ST1=3(好像是常數) 
                     <--該句是ST0<-ST1*(log2(ST0))
0167:73480468  CALL      73483C02  <--進入這個CALL
0167:7348046D  CMP       CL,01
0167:73480470  JNZ       73480474


0167:73483C02  FLD       ST(0) 
0167:73483C04  FRNDINT             <--將ST0取整
0167:73483C06  FSUBR     ST(1),ST  <--相減求出小數部分
0167:73483C08  FXCH      ST(1)     <--ST0與ST1交換
0167:73483C0A  FCHS <--ST0變為正數.此時ST0=上面結果的小數部分,ST1=整數部分
0167:73483C0C  F2XM1               <-- ST0<-(2^ST0)+1
0167:73483C0E  FLD1                <-- ST0<-ST0-1
0167:73483C10  FADDP     ST(1),ST  <-- ST0<-ST0+ST1
0167:73483C12  FSCALE  <-- ST0<-ST0*(2^ST1) 到這裡終於計算完了
0167:73483C14  FSTP      ST(1)
0167:73483C16  RET

本來想寫個序號產生器,在彙編裡挺清楚的語句,到了高階語言裡面一堆資料型別全亂了 .請各位高手寫個序號產生器貼出來學習一下,我的程式設計實在太爛了...

後記:

因為從來沒有見到過浮點計算的指令,上面的許多運算都是在看雪老師的<<Crack Tutorial>>中浮點運算一節中查到的,但裡面對FSCALE命令的解釋有誤,說是求2的ST(0)次方,即ST(0) <- 2^ST(0). 而我卻怎麼也算不對,在網上查了一下,發現應該是ST(0) <- ST(0)*(2^ST(1)). 下面是我找到的資料,請各位看一下對不對.

<tr> tr> <tr> tr>
引用:
_____________________________________________________________________________

FSCALE          Scale by a power of 2                Exceptions: I O U
                                                     C3 C2 C1 C0: ? ? * ?
FSCALE

        Logic   ST . ST * 2**ST(1)

    FSCALE interprets the contents of ST(1) as an integer, and uses it
    as an exponent of 2 with which to multiply the contents of ST. Thus,
    FSCALE provides a quick way to multiply or divide by a power of 2.

    The number in ST(1) must be -2**15 <= ST(1) < 2**15. It is truncated
    before the operation is performed. If 0 < ST(1) < 1, the result is
    undefined (and no exception is generated).

    Opcode      Format
    D9 FD       FSCALE

    Timing
    Operand       8087         287        387      486     Pentium
    -            32-38        32-38      67-86    30-32    20-31   NP
_____________________________________________________________________________


相關文章