修改指標法破解VB程式 騰圖影視'97 (14千字)

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

修改指標法破解VB程式
騰圖影視'97

作者: 囚童
課題: 解除"騰圖影視'97"五分鐘播映時間限制,清NAG
背景: VB4.0程式設計
下載:
工具: TRW2000
    Ultra Edit 32


  騰圖影視'97是一個播放VCD等數字影視節目的工具軟體,除了播放畫面流暢、色
彩逼真、介面美觀以外,還採用了獨創的“無介面”操作技術,即在影片播放過程中
進行的任何操作,都不會有操作畫面進行遮擋。此外,還增加了動態螢幕變焦(動態
的將區域性畫面進行放大、縮小)及漫遊,多畫面播放(產生電視牆的效果),動態連
續抓拍,還可以將視窗縮小後放在最上層,邊幹別的工作邊看電影,互不干擾。在播
放卡拉-OK時,可將所有曲目的畫面顯示在螢幕上,從而進行螢幕選曲,操作十分方
便。播放多種格式的影片檔案(*.FLI)、 (*.FLC)、(*.DAT)、(*.MPG)、 (*.AVI)、
(*.MOV)等。

騰圖影視'97試用版有5分鐘播映時間限制,並會彈出一個提示視窗。沒有註冊入口。

  騰圖影視'97選擇VB4.0程式設計.大家知道,VB程式的特點是既難跟又難改,這就給破解
帶來相當的難度.


下面給出用修改指標法破解VB程式的例子,供參考.

啟動TRW2000,點OK,TRW2000在螢幕右下角生成一個小圖示.右擊這個圖示,選TRmewTCB.

將一張VCD影碟放入光碟機,雙擊騰圖影視'97圖示,TRW截獲這一新執行緒.

為了讓大家瞭解什麼是VB的指標,我們先做如下操作:

下指令:    BPX THROW
按F5,程式被TRW截獲.
下指令:    BD*  ;清中斷.
按F12三次,按F10一直來到:

109F:30B6 MOV  DS,BX
109F:30B8 CALL FAR [BP+0C] //按F7、F8進入
109F:30BB MOV  [BP-04],AX  //游標停在這裡
109F:30BE MOV  [BP-02],DX
109F:30C1 MOV  CX,[BP+06]
109F:30C4 ADD  SP,CX
109F:30C6 ADD  SP,CX
109F:30C8 MOV  AX,[BP-04]
109F:30CB MOV  DX,[BP-02]
109F:30CE POP  SI
109F:30CF  POP  DI
109F:30D0 LEAVE
109F:30D1 RETF 0A

將游標上移到30B8一行,按F7、F8進入到:

418F:2CF0 MOV CX,C8   //游標停在這裡
418F:2CF3 CMP AX,C933
418F:2CF6 MOV AX,2622
418F:2CF9 MOV DX,1ADF
418F:2CFC JMP `VB40016!METHCALLENGINE`  //將游標移在這裡,按F7、F8進入
418F:2D01 ADD [BX+SI],AL
418F:2D03 ADD [BX+SI],AL
418F:2D05 DB  00
3EC7:2D06 MOV CX,D0
3EC7:2D09 CMP AX,C933
3EC7:2D0C MOV AX,1CB4
3EC7:2D0F MOV DX,3EDF
3EC7:2D12 JMP `VB40016!METHCALLENGINE`

這是典型的VB指標控制域的一個引匯入口表。
按F8跟進去,來到:

VB40016!METHCALLENGINE
1A57:0E40 MOV  BX,SP     //游標停在這裡
1A57:0E42 SUB  [SS:BX+04],CX
1A57:0E46 MOV  BX,CX
1A57:0E48 MOV  CX,3D0C
1A57:0E4B JMP  SHORT 0E50
1A57:0E4D MOV  CX,3CDD
1A57:0E50 PUSH BP
     ┇
     ┇
1ADF:0F7E MOV [ES:BX+0162],AX
1ADF:0F83 ADD SI,BYTE +02
1ADF:0F86 JMP NEAR [SI-02]   //將游標移在這裡,按F7跟到這裡

將游標下移到F86一行,按F7。
可以看到,AX的值經處理存入指標SI,DX置為DS段值。
按住F10,可以來到:

1C27:209B MOV   AX,[SI]
1C27:209D PUSH  SS
1C27:209E ADD   AX,BP
1C27:20A0 PUSH  AX
1C27:20A1 ADD   SI,BYTE +04
1C27:20A4 JMP   NEAR [SI-02]
     ┇
     ┇
1C27:20B9 MOV   DI,[SI]
1C27:20BB POP   AX
1C27:20BC MOV   [BP+DI],AL
1C27:20BE ADD   SI,BYTE +04
1C27:20C1 JMP   NEAR [SI-02]

  分析上面給出的209B和20B9兩節指令,可以看出VB指標控制域程式碼結構的明顯特
徵:指標DS:SI指向一個混合裝有指令入口和資料的指標列表,節首的傳送指令透過指
針列表下載資料;節尾的跳轉指令透過指標列表下載新的指令入口。這樣就將事先按
死順序編好在VB執行庫裡的指令程式碼和使用者所給的資料透過指標列表盤活了。因此,
下面給出的帶條件語句的TRW跟蹤指令也反映了VB指標控制域程式碼結構的這一特徵。

那麼,怎樣解除"騰圖影視'97"五分鐘播映時間限制呢?

  "騰圖影視'97"有多個時間限制機制,一個是由視窗內的滑鼠指標啟用的與系統時
鐘相關的5分鐘計時,另七個是內建的以分鐘為單位的5分鐘計時,它們各自獨立執行。

先看第一個:
A:

其指令引導表為:
1B1F:22DE MOV CX,0086
1B1F:22E1 CMP AX,C933
1B1F:22E4 MOV AX,2DA6
1B1F:22E7 MOV DX,1AC7
1B1F:22EA JMP `VB40016!METHCALLENGINE`

下指令:G 158E IF(SI==2),回車,將游標移入視窗,截獲到:

15A7:158B MOV  DI,15AF
15A7:158E CALL FAR [SI]   //游標停在這裡
15A7:1590 ADD  SI,BYTE +04
15A7:1593 JMP  DI
15A7:1595 MOV  DI,159A
15A7:1598 JMP  SHORT 158E
15A7:159A XOR  AH,AH
15A7:159C PUSH AX
15A7:159D ADD  SI,BYTE +02
15A7:15A0 JMP  NEAR [SI-02]
15A7:15A3 MOV  DI,15AE
15A7:15A6 JMP  SHORT 158E
15A7:15A8 MOV  DI,15AD
15A7:15AB SHORT 158E
15A7:15AD PUSH DX
15A7:15AE PUSH AX
15A7:15AF ADD  SI,BYTE +02
15A7:15B2 JMP  NEAR [SI-02]

  可以看到TRW反彙編視窗下面的橫線中央標有VB40016(xx)+xxx,指出當前模組名
是VB40016,括號中是子模組序號,加號後是在模組中的偏移量.

這就是VB4的指標控制域.所謂VB難追,也是指在這個域裡.

  為什麼上面的TRW跟蹤指令要附帶條件語句呢?因為VB是解釋語言,解釋語言的
一節命令可能會被反覆多次呼叫,不同的呼叫會有不同的指標。用指標做條件可以限
定在指定的呼叫環境下截獲中斷。特別在長呼叫返回時,若呼叫的節對自身再次呼叫,
無指標做條件會導致返回在下一個呼叫的返回處。

(若按F8跟進去,可以發現這是對函式RTCGetTimeBSTR的呼叫。)

下指令:D DS:0
得到指標列表(方擴號是作者加的。方擴號內是指令指標,方擴號外是資料指標):

1AC7:0000[15A8]0BCC 116F[402E]FF9A[2051]FF9A[3283]
1AC7:0010 0001 0000[332C]FF5C 0002[15A8]0AE0 3B6F
1AC7:0020[4025]FF58[394B]FF50[158B]1E18 116F[2051]
1AC7:0030 FF9A[3283]0004 0000[332C]FF30 0002[15A8]
1AC7:0040 0AE0[3B6F 4025]FF2C[394B]FF24[158B]1E18
1AC7:0050 116F[2BA0]0026 0000[321B 468C 381D]0006
1AC7:0060 005C[3283]0005 0000[3555 1876 2090]FF50
1AC7:0070[3213]003C[1869 3631 2090]FF24[3585 1965]
1AC7:0080[46E4 33B2 220B]0004 FF58 FF2C[21F7]0004
1AC7:0090 FF5C FF30[148B]000C 161E 0004 06AC 3BE0

將上表整理,可得指標、指令和資料的關係如下(每一序號包含一至多節):

節序        ①      ②      ③      ④      ⑤
指標SI     2       C          1C         40        5C
指令入口[SI-2]    15A8     2051      15A8     15A8     468C
資料內容[SI]  0BCC     FF9A      0AE0     0AE0     ―
資料內容描述  函式地址偏移 資料地址偏移 函式地址偏移 函式地址偏移 ― 
該節功能    獲取當前時間 傳送時間   處理小時   處理分鐘    判小時


節序        ⑥      ⑦      ⑧
指標SI     5E      82      84
指令入口[SI-2]    381D     46E4     33B2
資料內容[SI]  0006     ―      ―
資料內容描述  浮點處理引數 ―      ―
該節功能    進入浮點處理 判分鐘        終判、置標誌

節① SI=2
1A8F:158E CALL FAR [SI]  //SI指向函式RTCGETTIMEBSTR入口,獲取當前時間
1A8F:1590 ADD  SI,BYTE +04
1A8F:1593 JMP  DI
1A8F:1595 MOV  DI,159A
1A8F:1598 JMP  SHORT 158E
1A8F:159A XOR  AH,AH
1A8F:159C PUSH AX
1A8F:159D ADD  SI,BYTE +02
1A8F:15A0 JMP  NEAR [SI-02]
1A8F:15A3 MOV  DI,15AE
1A8F:15A6 JMP  SHORT 158E
1A8F:15A8 MOV  DI,15AD   //該節入口
1A8F:15AB JMP  SHORT 158E
1A8F:15AD PUSH DX
1A8F:15AE PUSH AX
1A8F:15AF ADD  SI,BYTE +02  //指向下一節
1A8F:15B2 JMP  NEAR [SI-02] //跳到下一節入口

節② SI=C
1A8F:2051 MOV  DI,[SI]
1A8F:2053 PUSH WORD [BP+DI+02] //將指向當前時間的地址壓入堆疊
1A8F:2056 PUSH WORD [BP+DI]
1A8F:2058 ADD  SI,BYTE +04   //指向下一節
1A8F:205B JMP  NEAR [SI-02]  //跳到下一節入口

節③ SI=1C
同節①,SI指向函式RTCMIDCHARBSTR入口,取小時值供後續處理。

節④ SI=40
同節③,SI指向函式RTCMIDCHARBSTR入口,取分鐘值供後續處理。

節⑤ SI=5C
1A8F:468C POP  DX     //彈出參照標量
1A8F:468D POP  CX     //彈出小時處理結果
1A8F:468E CMP  CX,DX    //判斷
1A8F:4690 MOV  AX,00    //清小時超時標誌
1A8F:4693 JNZ  4696     //未超時,跳
1A8F:4695 DEC  AX     //超時,置小時超時標誌FFFF
1A8F:4696 PUSH AX      //壓入堆疊
1A8F:4697 ADD  SI,BYTE +02 //指向下一節
1A8F:469A JMP  NEAR [SI-02]//跳到下一節入口

節⑥ SI=5E
1A8F:381D MOV  DI,[SI]
1A8F:381F LES  DI,[BP+DI]
1A8F:3821 MOV  AX,ES
1A8F:3823 OR   AX,AX
1A8F:3825 JZ   3870
1A8F:3827 ADD  DI,[SI+02]
1A8F:382A PUSH WORD [ES:DI+02]  //將浮點處理引數壓入堆疊
1A8F:382E PUSH WORD [ES:DI]   //供浮點系統處理
1A8F:3831 ADD  SI,BYTE +06
1A8F:3834 JMP  NEAR [SI-02]

節⑦ SI=82
3A7F:46E4 CALL C777    //在浮點系統中先將十六進位制分鐘資料轉換為80位的數
3A7F:46E7 JMP  SHORT 46F6  //據,再判斷是否超時,將結果送入AH,再將AH中的內
3A7F:46E9 CALL C785    //容送標誌位。
3A7F:46EC JMP  SHORT 46F6
3A7F:46EE CALL C74C
3A7F:46F1 JMP  SHORT 46F6
3A7F:46F3 CALL C732
3A7F:46F6 SBB  AX,AX    //根據標誌位置分鐘超時標誌,0為未超時,FFFF為超時。
3A7F:46F8 PUSH AX      //壓入堆疊
3A7F:46F9 ADD  SI,BYTE +02 //指向下一節
3A7F:46FC JMP  NEAR [SI-02] //跳到下一節入口

節⑧ SI=84
31B7:33B2 POP  AX     //彈出小時超時標誌
31B7:33B3 POP  CX     //彈出分鐘超時標誌
31B7:33B4 AND  AX,CX    //終判,其一為超時則判為超時
31B7:33B6 PUSH AX     //置終判標誌於棧頂
31B7:33B7 ADD  SI,BYTE +02 //指向下一節
31B7:33BA JMP  NEAR [SI-02]//跳到下一節入口

  可見,只要在節⑧位置向棧頂壓入標誌字0,就可以不去理會浮點運算有多麼復
雜,使程式始終處於未超時狀態。
      
  但是,上面提到的全部資料傳輸和處理過程都是在vb40016.dll中完成的,無法將
33B6處改寫為例如PUSH BYTE +00這樣的指令(改寫公共DLL檔案是對使用者極不負責
的表現).

  而指標表是程式在編譯過程中生成的,是可以改寫的。只要記住這樣的規則,就
不怕改寫VB程式了:不要指望改寫語句,要設法改變呼叫。

改變呼叫的方法就是修改指標表。

在當前指令程式碼段中找了一下,有下面2節大約可用於新的呼叫:


31D7:1746 SBB  AX,AX
31D7:1748 PUSH AX
31D7:1749 ADD  SI,BYTE +02
31D7:174C JMP  NEAR [SI-02]


31D7:321B PUSH BYTE +00
31D7:321D ADD  SI,BYTE +02
31D7:3220 JMP  NEAR [SI-02]

試選⑵,做一個新的指標方案:

節序        ⑧
指標SI     84
指令入口[SI-2]    321B
資料內容[SI]  ―
資料內容描述  ―
該節功能    強制設定未超時標誌0

  抄下指標表中指標84前後的十六進位制碼,使用Ultra Edit 32,按下面的方法做第
一步的修改:

46 B2 33 0B
― 1B 32 ―

下面來看另七個內建的以分鐘為單位的5分鐘計時。
B-1:

其指令引導表為:
346F:0F40 MOV CX,66
346F:0F43 CMP AX,C933
346F:0F46 MOV AX,370C
346F:0F49 MOV DX,346F
346F:0F4C JMP `VB40016!METHCALLENGINE`

下指令:G 3807 IF(SI==31F2),回車,來到:

1A8F:3807 MOV  DI,[SI]   //游標停在這裡
1A8F:3809 LES  DI,[BP+DI]
1A8F:380B MOV  AX,ES
1A8F:380D OR   AX,AX
1A8F:380F JZ   3870
1A8F:3811 ADD  DI,[SI+02]
1A8F:3814 PUSH WORD [ES:DI]
1A8F:3817 ADD  SI,BYTE +06
1A8F:381A JMP  NEAR [SI-02]

下指令:D DS:31E0


得到指標列表(方擴號是作者加的。方擴號內是指令指標,方擴號外是資料指標):

346F:31E0[0F92]0004[0F92]0008[3D49]0512[0F92]0012
346F:31F0[3807]0006 0034[321B 47C5 148B]0018[0F92]
346F:3200 0014[3807]0006 0034[3223 359C 38BA]0006
346F:3210 0034[1474]04E4[0F92]0004[0F92]0034[321B]

將上表整理,可得指標、指令和資料的關係如下(每一序號包含一至多節):

節序        ①      ②     ③      ④  
指標SI     31F2     31F8    31FA     31FC 
指令入口[SI-2]    3807     321B     47C5     148B 
資料內容[SI]  0006     ―     ―      ―  
資料內容描述  資料地址偏移 ―     ―      ―  
該節功能    獲取剩餘分鐘 給出參照值 比較、置標誌 判斷 

節序      ⑤      ⑥     ⑦     ⑧
指標SI     3204     320A    320C    320E
指令入口[SI-2]    3087     3223    359C    38BA
資料內容[SI]  0006     ―     ―     0006    
資料內容描述  資料地址偏移 ―     ―     非超時增跳節數
該節功能    獲取剩餘分鐘 給出遞減值 剩餘分鐘減1 回置儲存單元

節① SI=31F2

1A8F:3807 MOV  DI,[SI]   //取資料地址偏移
1A8F:3809 LES  DI,[BP+DI]
1A8F:380B MOV  AX,ES
1A8F:380D OR   AX,AX    //校驗地址有效性
1A8F:380F JZ   3870
1A8F:3811 ADD  DI,[SI+02] //取下一個資料地址偏移
1A8F:3814 PUSH WORD [ES:DI]//將剩餘分鐘壓入堆疊
1A8F:3817 ADD  SI,BYTE +06 //指向下一節
1A8F:381A JMP  NEAR [SI-02]//跳到下一節入口

節② SI=31F8

1A8F:321B PUSH BYTE +00  //給出參照值,0為計時結束。
1A8F:321D ADD  SI,BYTE +02 //指向下一節
1A8F:3220 JMP  NEAR [SI-02]//跳到下一節入口

節③ SI=31FA

1A8F:47C5 POP  DX     //彈出參照值
1A8F:47C6 POP  CX     //彈出剩餘分鐘值
1A8F:47C7 XOR  AX,AX    //清超時標誌
1A8F:47C9 CMP  CX,DX    //比較
1A8F:47CB JNG  47CE    //非超時,跳;標誌為0
1A8F:47CD DEC  AX     //超時,不跳;標誌為FFFF
1A8F:47CE PUSH AX     //儲存標誌
1A8F:47CF ADD  SI,BYTE +02 //指向下一節
1A8F:47D2 JMP  NEAR [SI-02]//跳到下一節入口

節④ SI=31FC

1A8F:148B POP CX      //彈出超時標誌
1A8F:148C MOV AX,[SI]   //取非超時增跳節數
1A8F:148E OR  CX,CX    //判斷
1A8F:1490 JNZ 1494     //超時,保持原節程式
1A8F:1492 ADD SI,AX    //非超時,增跳指定指令節數
1A8F:1494 ADD SI,BYTE +04 //指向下一節
1A8F:1497 JMP NEAR [SI-02] //跳到下一節入口

節⑤ SI=3204
同節①

節⑥ SI=320A

1A8F:3223 PUSH BYTE +01  //取遞減值
1A8F:3225 ADD  SI,BYTE +02 //指向下一節
1A8F:3228 JMP  NEAR [SI-02]//跳到下一節入口

節⑦ SI=320C

1A8F:359C POP AX      //彈出遞減值
1A8F:359D MOV BX,SP
1A8F:359F SUB [SS:BX],AX  //剩餘分鐘值減1
1A8F:35A2 JO  35BD
1A8F:35A4 ADD SI,BYTE +02 //指向下一節
1A8F:35A7 JMP NEAR [SI-02]//跳到下一節入口

節⑧ SI=320E

1A8F:38BA MOV DI,[SI]   //取資料地址偏移
1A8F:38BC LES DI,[BP+DI]
1A8F:38BE MOV AX,ES
1A8F:38C0 OR  AX,AX    //校驗地址有效性
1A8F:38C2 JZ  3870
1A8F:38C4 ADD DI,[SI+02] //取下一個資料地址偏移
1A8F:38C7 POP WORD [ES:DI]//將更新的剩餘分鐘值回置原儲存單元
1A8F:38CA ADD SI,BYTE +06 //指向下一節
1A8F:38CD JMP NEAR [SI-02]//跳到下一節入口

  從節④可以看出,在VB中,指令的跳轉不是按指令位元組數來跳轉的,而是按指令
的節數來跳轉的。

  從節⑦可以看出,若時間遞減值為0,則剩餘分鐘值永不為0,程式就可以不受限
制地執行下去了。這可以透過改變節⑥的呼叫來實現。我們仍可以用前面用到過的321B
來替換節⑥。

新的呼叫:

31D7:321B PUSH BYTE +00
31D7:321D ADD  SI,BYTE +02
31D7:3220 JMP  NEAR [SI-02]

新的指標方案:

節序        ⑥
指標SI     320A
指令入口[SI-2]    321B
資料內容[SI]  ―
資料內容描述  ―
該節功能    強制設定時間遞減值為0

另外6個計時器大同小異,但指標表的位置不一樣,列表如下:

計時器號    B-1   B-2   B-3   B-4   B-5   B-6   B-7
入口引導表入口 F40   23BA  28F8  30B8  3560  389C  3A98
首節指標SI   31E2  56E   270A  374E  2C76  2    ADA
首節入口    F92   F92   F92   F92   F92   F92   F92
指令指標SI   31F8  57E   271A  375E  2C86  12   AEA
指令入口    3807  3807  3807  3807  3807  3807  3807
需要改值的指標 3208  594   2730  3774  2C9C  28   B00
UltraEdit32偏移 44440  45510  43970  449A0  43ED0  44F90  45A80

  抄下指標表中需要改值的指標前後的十六進位制碼(它們大致相同),使用Ultra
Edit 32,按下面的方法做最後的修改:

00 23 32 9C 35 BA 38
-- 1B -- -- -- -- --

  與此程式碼相同的不止7處,可參考上表最下面一行UltraEdit32偏移,它是一組行
號,需要改值的指標在此行內。

存檔。
試執行。哇,成功!
VB是以修改的!

相關文章