ArtCursors 3.03 ASPR殼軟體脫殼後修整記 (10千字)

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

首先宣告:本文寫的是脫殼後的修整,而不是脫殼。用Stripper脫aspr的殼還是挺方便的:P

目標軟體:滑鼠游標編輯軟體ArtCursors 3.03,可製作32位色的cur、ani檔案,並可以匯入、匯出多種圖象格式
相關網址: http://www.aha-soft.com/artcursors/index.htm
編寫語言:Delphi編寫,Aspr1.22殼。
版本:3.03

工具:Stripper,DEDE,OllyDBg,Trw2000,superBPM,TOPO,LordPE,ResHack,WinHex

---------------------------------------------------------------------------------------------
脫完殼,軟體一執行就退出,用trw2000+SuperBPM跟蹤版比較,發現

005363E0   . FF15 F0CB5300  CALL DWORD PTR DS:[53CBF0]

有問題,原版call進去後來到535dc0,而脫殼版call進去後來到5363d1。試著把這一句改成

005363E0   . E8 DBF9FFFF    CALL UNPACKED_.00535DC0
005363E5   . 90             NOP

正常執行,但為未註冊版,執行前彈出NAG,說30天期限已經用了1天。。。
不對啊,我明明用了不止一天啊?莫非。。。?我把時間調後了一年,執行,他還是說只用了一天。。。
原來,時間限制已經解除!只要去掉NAG,改掉"未註冊"的字樣,不就搞定了?然而,事情沒那麼簡單。。。

先用DEDE分析,點選 File -> load symbo file 載入除錯符號vcl60.dsf、vclx60.dsf、rtl60.dsf
(可以用dumpers -> dsf Builder來建立,但必須先安裝delphi),
在主視窗的create事件裡發現

* Reference to: dmu.Proc_00534C60

00517B40   E81BD10100             call    00534C60
00517B45   837DF400               cmp     dword ptr [ebp-$0C], +$00
00517B49   7505                   jnz     00517B50  <----關鍵跳

* Reference to: about.Proc_005084E4

00517B4B   E89409FFFF             call    005084E4 <---顯示NAG

* Reference to: kernel32.GetTickCount()

00517B50   E8F3F0EEFF             call    00406C48

用原版跟蹤,發現517B49在原版跳,在脫殼版不跳,於是把脫殼版中的改成強行跳,
NAG沒了,但是主視窗竟不能完整顯示,整天異常。。。。。。
天啊,難道他NAG裡對主視窗進行了一些初始化的工作(猜測)?怎麼辦。。。。連個NAG都搞不定?
把我這隻菜鳥惹急了,我什麼土辦法都做的出來的。。。

我決定,用最土的辦法幹掉NAG:用TOPO插入程式碼,在合適的時機給NAG發一個WM_CLOSE訊息。

首先要找到相關API的呼叫方法:
用LordPE的PE Editor開啟脫殼版程式,點選Directories,再點選Import Table一欄的"..."按鈕,
在上面的列表裡找到User32.dll(好幾個),在下面的列表裡找到PostMessageA,
看看他的ThunkRVA的值(最左邊),是13f6b4,那麼PostMessageA的呼叫方法就是call [53f6b4]。
(53f6b4=13f6b4+400000)

然後Topo插入大概200位元組空間,記下空間首地址:544019,然後在在DEDE裡,找到NAG所在的單元:
TfmAbout,看到有FormShow事件,恩,好,就在這裡動手腳!

接下來,要找到得到NAG的視窗控制程式碼的辦法,在DEDE裡,我看到

00508BD5   8B00                   mov     eax, [eax]

* Reference to: Controls.TWinControl.GetHandle()  <---DSF檔案的妙用

00508BD7   E8B42DF3FF             call    0043B990  <---可以得到視窗控制程式碼
00508BDC   50                     push    eax       <---返回值,視窗控制程式碼

Controls.TWinControl.GetHandle()是得到特定視窗控制程式碼的方法,
也就是說,在TfmAbout的視窗事件裡,只要呼叫call 0043B990,
EAX裡返回的就是TfmAbout的控制程式碼!哈哈哈!這就是DSF檔案的妙用,他可以認出不少VCL類的方法!
開始做手腳!

FormShow的首地址是508ad4,先記下開始的5個位元組的指令(其對應的機器碼是55,8b,ec,6a,00):

00508AD4   55                     push    ebp        <-- 記下
00508AD5   8BEC                   mov     ebpesp   <-- 這三個
00508AD7   6A00                   push    $00    <-- 指令

00508AD9   6A00                   push    $00   <-- 手腳做完從這裡執行

然後開啟OllyDBG,(我不習慣用HIEW)載入脫殼版程式,把508AD4處程式碼改成

00508AD4   E940B50300             jmp     00544019 <---跳到我們插入的程式碼空間

然後按Ctrl-G來到544019處,開始寫入做手腳的程式碼:
                                          _____________________
00544019   55               PUSH EBP     |  這裡先執行508AD4處 |
0054401A   8BEC             MOV EBP,ESP  |  被改掉的程式碼       |
0054401C   6A 00            PUSH 0       |_____________________|
                                       
0054401E   50               PUSH EAX  <---保護EAX暫存器
0054401F   E8 6C79EFFF      CALL UNPACKED_.0043B990   <----Controls.TWinControl.GetHandle()
00544024   6A 00            PUSH 0      <---lParam
00544026   6A 00            PUSH 0      <---wParam
00544028   6A 10            PUSH 10     <---WM_CLOSE
0054402A   50               PUSH EAX    <---NAG的視窗控制程式碼
0054402B   FF15 B4F65300    CALL DWORD PTR DS:[53F6B4] <---PostMessageA
00544031   58               POP EAX    <---恢復EAX暫存器
00544032   E9 A24AFCFF      JMP UNPACKED_.00508AD9   <---手腳做完,回到原處

然後選中被修改過的指令,單擊右鍵,選"Copy to executable file"(別忘了508AD4處),
再單擊右鍵,選"Save File",儲存成新檔案,執行,NAG視窗一閃而過,成功了。

雖然成功了,但又出來了新的麻煩:沒辦法顯示"關於"對話筐了,因為那正是NAG視窗!
怎麼辦?把我這隻菜鳥逼急了。。。(省略)
我醞釀了一個更土的計劃:用ResHack插入一個對話筐資源,並插入程式碼來顯示他!

我找了個用Vc寫的有著不錯的"關於"對話筐的程式,用ResHack開啟,把"關於"對話筐另存為.res檔案,
在用ResHack開啟這個.res檔案,把這個對話筐的資源名稱改個象樣的名字,叫什麼好呢?
既然原來的"關於"對話筐的RCDate的名稱叫TfmAbout,就把新對話筐的資源名稱也改成"TFMABOUT"吧:P
在用ResHack開啟動過手腳後的程式,插入res檔案裡的對話筐,儲存,接下來就是寫程式碼顯示他了。

要顯示對話筐,需要DialogBoxParamA、EndDialog、GetModuleHandleA三個API函式,
但是DialogBoxParamA、EndDialog兩個是原程式裡沒有的,
不過不要緊,用LordPE可以在輸入表裡增加API函式。用LordPE開啟動過手腳的程式,
點選Directories,再點選Import Table一欄的"..."按鈕,在上面的列表裡單擊右鍵,選"add import",
在Dll文字筐裡寫入User32.dll,在API文字筐裡寫入EndDialog,單擊"+" 號,
在API文字筐裡再寫入DialogBoxParamA,再單擊"+" 號,這樣就加入了這兩個API函式。
記下他們的ThunkRVA:

EndDialog : 1A800B
DialogBoxParamA : 1A8017
GetModuleHandleA : 13F210
那麼,
EndDialog的呼叫方法就是 call [5A800B]
DialogBoxParamA的呼叫方法就是 call [5A8017]
同理,
GetModuleHandleA的呼叫方法就是 call [53F210]
記得儲存修改。

顯示"關於"對話筐的事件是主窗體TfmMain的aHelpAboutExecute事件,這是一個TAction物件的事件,
不能象以前那樣用call 43B990得到主視窗的控制程式碼了,只能另尋他法。

在DEDE裡,TfmAbout的FormActive事件裡我找到了這麼一段程式碼:

* Reference to : TfmMain._PROC_0051A9BC()  <---在NAG裡呼叫主視窗的過程

00508BC4   E8F31D0100             call    0051A9BC
00508BC9   E856AB0200             call    00533724
00508BCE   6AFF                   push    $FF
00508BD0   A108CF5300             mov     eaxdword ptr [$0053CF08]
00508BD5   8B00                   mov     eax, [eax]

* Reference to: Controls.TWinControl.GetHandle()  

00508BD7   E8B42DF3FF             call    0043B990  <--取主視窗控制程式碼?
00508BDC   50                     push    eax       <--主視窗控制程式碼?

* Reference to : TApplication._PROC_00455A04()

00508BDD   E822CEF4FF             call    00455A04  <--改成 jmp 0054403B

00508BE2   5F                     pop     edi
00508BE3   5E                     pop     esi
00508BE4   5B                     pop     ebx
00508BE5   5D                     pop     ebp
00508BE6   C3                     ret


猜測與實踐證明,在508BDC一處,eax儲存的是主視窗的控制程式碼,我們乾脆在這裡也動點手腳,
讓他把主視窗控制程式碼儲存起來算了,就儲存在504437處吧,那裡處於用topo增加的空間。

用OllyDBG載入修改後的程式
先把508BDD一處改成jmp 0054403B,
然後到54403b處寫入如下程式碼,儲存主視窗的控制程式碼:

00544037   0000             ADD BYTE PTR DS:[EAX],AL
00544039   0000             ADD BYTE PTR DS:[EAX],AL

;------------- 544037 ~ 544039 的空間是用來儲存主視窗控制程式碼的---------------

0054403B   A3 37405400      MOV DWORD PTR DS:[544037],EAX <--儲存住視窗控制程式碼
00544040   E8 BF19F1FF      CALL 00455A04                 <--執行508bdd處原來的程式碼
00544045   E9 984BFCFF      JMP UNPACKED1_.00508BE2        <--手腳做完,返回原處

現在可以寫入程式碼顯示新的對話筐了,嘿嘿。。。
以下是主窗體TfmMain的aHelpAboutExecute事件的程式碼:

005163E8   E8F720FFFF             call    005084E4 <--改成 jmp 00544053
005163ED   C3                     ret

把5163E8處改成jmp 00544053以後,來到54404a處,寫入以下程式碼:

0054404a   <--此處寫入 "TFMABOUT" 的ASCII碼,是新插入的對話筐的資源名稱

00544053   E8 8C44FCFF      CALL UNPACKED_.005084E4  <---執行5163e8處原有程式碼
00544058   50               PUSH EAX                <--保護EAX暫存器
00544059   6A 00            PUSH 0                  <---dwInitParam
0054405B   68 7C405400      PUSH UNPACKED_.0054407C  <---對話筐過程
00544060   FF35 37405400    PUSH DWORD PTR DS:[544037]  <--父視窗控制程式碼
00544066   68 4A405400      PUSH UNPACKED_.0054404A <--對話筐資源名稱"TFMABOUT"
0054406B   6A 00            PUSH 0
0054406D   FF15 10F25300    CALL DWORD PTR DS:[53F210] <--GetModuleHandleA
00544073   50               PUSH EAX                   <--程式例項控制程式碼 hInstance
00544074   FF15 2D805A00    CALL DWORD PTR DS:[5A802D] <--DialogBoxParamA
0054407A   58               POP EAX                    <--恢復EAX值
0054407B   C3               RETN                       <--直接返回,不必jmp回原處了

緊接著寫對話筐過程,直接寫有點困難,我是用MASM32寫了一個小程式,反彙編以後照抄的:

0054407C   55               PUSH EBP
0054407D   8BEC             MOV EBP,ESP
0054407F   8B45 0C          MOV EAX,DWORD PTR SS:[EBP+C]  <--把訊息儲存在 EAX
00544082   3D 11010000      CMP EAX,111                   <--WM_COMMAND
00544087   74 0B            JE SHORT UNPACKED_.00544094
00544089   83F8 10          CMP EAX,10                    <--WM_CLOSE
0054408C   74 06            JE SHORT UNPACKED_.00544094
0054408E   33C0             XOR EAX,EAX
00544090   C9               LEAVE
00544091   C2 1000          RETN 10

00544094   6A 00            PUSH 0
00544096   FF75 08          PUSH DWORD PTR SS:[EBP+8]
00544099   FF15 29805A00    CALL DWORD PTR DS:[5A8029] <--EndDialog
0054409F   33C0             XOR EAX,EAX
005440A1   C9               LEAVE
005440A2   C2 1000          RETN 10

----------------------------------------------------------------------------------------------
這是我寫的對話筐過程的原始碼:

DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

mov eax,uMsg

cmp eax,WM_COMMAND
jz quit
cmp eax,WM_CLOSE
jz quit

xor eax,eax
ret
quit:
invoke EndDialog, hWnd,NULL
xor eax,eax
ret

DlgProc endp
----------------------------------------------------------------------------------------------
別忘了儲存修改結果。
試試看?點選help -> About,啊,成功了,顯示的是我們自己做的About對話筐!!!

還有個惱人的地方:主視窗標題上有個可恨的"EXPIRED!"字樣,在資源裡找不到。
於是動用winHex尋找該字串,竟找不到!天啊,難道又要逼我用土辦法。。。?
還是他把字母拆開了?絕望中,我在winHex裡尋找"D!"字串,還真找到了!
在檔案F565c處,有個"D!PRDIXE"字串,果然,他把"EXPIRED!"這個字串進行了變換(加密?),實在暈菜~
這下簡單了,改成空格好了。

在工具欄上有個紅紅的"REGISTER"大字,很噁心,不過很好辦,在RCDate資源裡找的到,把大小改成0就好了。
大功告成,再修改資源,把NAG視窗的大小改成0,把插入的關於對話筐改的好看一點,哈哈,天衣無縫的說~~~~~~~~~~~~

相關文章