破解DebugApiSpy v3.2.1.56

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

破解DebugApiSpy v3.2.1.56 

上次trw2000兄的貼子裡提到這個軟體,我研究了一陣,現把結果呈給大家,請大家指正。我先扔一塊石頭,有玉的儘管朝我砸來。

原貼:http://bbs2.pediy.com/viewtopic.php?t=5531&highlight=%CB%AB%B2%E3%BF%C7

這是一個雙層殼,比較簡單。雖然可以一步一步跟,但trw2000兄的方法簡潔實用,所以這兒用他的方法(謝謝trw2000兄)


【轉】

一、脫殼

    一執行,要註冊。很久沒搞破解啦,就拿它開刀溫習一下功課吧。 
    因為在od中找不到可用的中文字串,所以考慮用w32dasm反彙編,但要求先脫殼。 
    用FI2.5檢視,是用AsPack2.1加的殼,很久沒有手工跟啦,手工跟一把吧。用od剛一載入,停在: 

00469001 PUSHAD 

    Ctrl-F查詢popad指令,去掉“整個區段”選項,找到這裡: 

004694F3  POPAD 
004694F4  JNZ SHORT 004694FE 
004694F6  MOV EAX,1 
004694FB  RETN 0C 
004694FE  PUSH 00464000 
00469503  RETN        

    讓游標停在上面一段的最後一行,按F4一次,再F8一次,即可到達第一層殼的OEP。這時如果轉存程式的話,用fi檢視還有一層PeCompact的殼,並且不能執行(用工具自動脫也不能執行,不知怎樣修改)。因此繼續脫第二層殼,起始一段如下,有特徵命令pushfd和pushad,是殼的開始: 

00464000  JMP SHORT 00464008 
00464002  PUSH 2E9E8     這就是程式的原始OEP的RVA地址  
00464007  RETN 
00464008  PUSHFD 
00464009  PUSHAD 
0046400A  CALL 00464011 

    跟到下面一段,有特徵命令popad和popfd,是殼的結束: 

0046554E  POPAD 
0046554F  POPFD 
00465550  PUSH EAX 
00465551  PUSH 0042E9E8 
00465556  RETN 4 

    到達00465556一行,再F8一次,返回到真正入口點: 

0042E9E8  PUSH EBP 
0042E9E9  MOV EBP,ESP 

    游標停在入口點後轉存該程式,再用fi檢視無殼,是用Visual C++ 6.0編寫的。但是用od直接轉存的程式不能執行。重跟到入口點,用別的方法轉存。重跟就沒有必要細跟啦,只要在下面幾個關鍵點設斷即可: 

1. 停在入口點時,在00469503處設斷,中斷後單步一下,即到達第二層殼的入口點。 

2. 在第二層殼的入口點時,殼的結尾00465556處還沒有程式碼,因此無法把斷點設在這裡,要分幾步到才能到達這裡。第一步可以斷點可以設在0046407B,執行到這兒後,向結尾處寫程式碼的程式碼才出現: 

00464077  REP MOVS DWORD PTR ES:[EDI],DWORD PTR [ESI
00464079  MOV EDI,EBX 
0046407B  RETN 

3. 第二步,在0046407B處中斷後,斷點可以設在004651A7,執行到這兒以後殼結尾程式碼才形成: 

004651A5  REP MOVS BYTE PTR ES:[EDI],BYTE PTR [ESI
004651A7  JMP SHORT 004651CF 

4. 第三步,在004651A7處中斷後,在殼結尾程式碼00465556處設斷,中斷後單步走到真正的OEP。 

    用PEditor來dump程式,並修正入口點,測試,程式不能執行,用別的方法dump,也不能執行。


【結束】


當然在最後需要用ImportREC來修復輸入表(未加密)。



下面我們來修復dump出來的程式。


二、修復

1.去掉ZwSetInformationThread

00409BD1   PUSH DebugApi.0044DD34                   ; ASCII "ZwSetInformationThread"
00409BD6   PUSH DebugApi.0044DD28                   ; ASCII "ntdll.dll"
00409BDB   CALL DWORD PTR DS:[4361D8]               ; kernel32.GetModuleHandleA
00409BE1   PUSH EAX
00409BE2   CALL DWORD PTR DS:[4361E8]               ; kernel32.GetProcAddress
00409BE8   MOV ESIEAX
00409BEA   CMP ESIEDI
00409BEC   JE SHORT DebugApi.00409BFB
00409BEE   PUSH EDI
00409BEF   PUSH EDI
00409BF0   PUSH 11
00409BF2   CALL DWORD PTR DS:[436150]               ; kernel32.GetCurrentThread
00409BF8   PUSH EAX                        //nop
00409BF9   CALL ESI                        //nop


    脫殼程式在00409BF9處呼叫ZwSetInformationThread函式來反除錯,這個函式除了反除錯以外沒其他用途,因此可以把00409BF8和00409BF9處nop掉。


2.解決動態解碼

執行程式到424d0f處出錯,上一句為CALL 0042407C,進去看看,發現程式碼顯然不對,這是程式動態自解碼,脫殼後解碼出錯,因此執行也出錯。

在OD中開啟原程式在00409BF8處下一個硬體執行斷點,執行停住,在00409BFB處new origin here。在0042407C處下硬體執行斷點,執行停住,0042407C處已正確解碼,0042407C~0042447B。可以直接用OD的Binary copy和Binary paste複製到脫殼程式中。但要注意,這樣複製過去後,程式還是要對該段程式碼進行解碼,因此要對解碼函式處理。

下面尋找解碼函式,執行到00409BFB後,在0042407C處下一硬體訪問斷點,再執行,中斷:

0042CEA3     REP MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]  //斷下

這是把0042407C開始處的程式碼複製到一記憶體空間,準備解碼。假設記憶體空間為0fc0570,則在0fc0570處再下一硬體訪問斷點,執行。

0040542D       XOR EAXEAX
0040542F       CMP DWORD PTR SS:[EBP-8], EAX
00405432       JE SHORT DebugApi.00405449
00405434       PUSH DWORD PTR SS:[EBP+8]
00405437       MOV ECXDWORD PTR SS:[EBP-4]
0040543A       PUSH ESI
0040543B       CALL DebugApi.00404E68            //解碼函式
00405440       ADD ESI, 8
00405443       ADD DWORD PTR SS:[EBP+8], 8
00405447       JMP SHORT DebugApi.0040546E
00405449       MOV CLBYTE PTR DS:[EAX+ESI]
0040544C       MOV BYTE PTR DS:[EAX+EDI], CL     //斷在這
0040544F       INC EAX
00405450       CMP EAX, 8
00405453       JL SHORT DebugApi.00405449
00405455       PUSH DWORD PTR SS:[EBP+C]
00405458       MOV ECXDWORD PTR SS:[EBP-4]
0040545B       PUSH EDI
0040545C       CALL DebugApi.00404E68            //解碼函式
00405461       PUSH 8
00405463       POP EAX
00405464       ADD DWORD PTR SS:[EBP+8], EAX
00405467       ADD ESIEAX
00405469       ADD EDIEAX
0040546B       ADD DWORD PTR SS:[EBP+C], EAX
0040546E       DEC EBX
0040546F       JNZ SHORT DebugApi.0040542D


進入CALL DebugApi.00404E68看看,好長一段程式碼,沒去研究解碼演算法。改成在00404E68直接返回,即改成:
00404E68  RETN 8

修改完成。我們回到呼叫0042CEA3複製語句的上一層函式看看:


00424CCC      PUSH ESI
00424CCD      PUSH DWORD PTR SS:[EBP+C]
00424CD0      PUSH EDI
00424CD1      CALL DebugApi.0042CE70               //複製
00424CD6      ADD ESP, 0C
00424CD9      MOV ECXEBX
00424CDB      PUSH ESI
00424CDC      PUSH DWORD PTR SS:[EBP-10]
00424CDF      PUSH EDI
00424CE0      CALL DebugApi.004053F9               //解碼
00424CE5      TEST EBXEBX
00424CE7      JE SHORT DebugApi.00424CF7
00424CE9      MOV ECXEBX
00424CEB      CALL DebugApi.00404AE1
00424CF0      PUSH EBX
00424CF1      CALL DebugApi.0042D1A5
00424CF6      POP ECX
00424CF7      PUSH ESI
00424CF8      PUSH DWORD PTR SS:[EBP-10]
00424CFB      PUSH DWORD PTR SS:[EBP+C]
00424CFE      CALL DebugApi.0042CE70              //把正確程式碼複製到42407c
00424D03      PUSH DWORD PTR SS:[EBP-10]
00424D06      PUSH EDI
00424D07      PUSH DWORD PTR SS:[EBP+10]
00424D0A      CALL DebugApi.0042407C              //執行42407c
00424D0F      PUSH ESI
00424D10      PUSH EDI
00424D11      PUSH DWORD PTR SS:[EBP+C]
00424D14      CALL DebugApi.0042CE70              //執行完後,把錯誤程式碼複製回42407c
00424D19      PUSH DWORD PTR SS:[EBP-10]


另外4144e2~4158e1也是類似的動態解碼。程式中有兩處解碼函式:
 
0042429E    CALL dumped_6.004053F9
00424CE0    CALL dumped_6.004053F9

就是這兩個地方的解碼。也有可能還有其他地方是動態解碼,我沒有再找。



3.解決自效驗

這個問題一開始我的方法是正面去找,即執行脫殼程式一處一處找,找到了一些地方,但太麻煩,後來看到程式中有這樣的語句:

CALL DWORD PTR DS:[<&kernel32.ExitProces>; ExitProcess

這不就是退出函式嗎,因此查詢所有命令:CALL DWORD PTR DS:[4361F4],然後在每處都設斷,執行,停住:

(1)
00414589    CMP EAXDWORD PTR SS:[ESP+14]
0041458D    JE SHORT dumped_4.00414597      //JE改成JMP
0041458F    PUSH 0                                   ; /ExitCode = 0
00414591    CALL DWORD PTR DS:[<&kernel32.ExitProces>; ExitProcess    //停在這

00414589處就是一個自效驗,把0041458D處的je改成jmp。好,其他的也類似修改:

(2)
004167E3    CMP EAXDWORD PTR SS:[ESP+14]
004167E7    JE SHORT dumped_4.004167F1      //JE改成JMP
004167E9    PUSH 0                                   ; /ExitCode = 0
004167EB    CALL DWORD PTR DS:[<&kernel32.ExitProces>; ExitProcess


修改好這兩處後,程式可以執行了,但執行一段時間後還會退出,因此還有自效驗:

(3)
004168D3    CMP ECXEDX
004168D5    MOV DWORD PTR SS:[EBP+8], ECX
004168D8    JE SHORT dumped_4.004168E2      //JE改成JMP
004168DA    PUSH 0                                   ; /ExitCode = 0
004168DC    CALL DWORD PTR DS:[<&kernel32.ExitProces>; ExitProcess

(4)
00416907    CMP EAXDWORD PTR SS:[EBP-4]
0041690A    MOV DWORD PTR SS:[EBP+8], EAX
0041690D    JE SHORT dumped_4.0041691A      //JE改成JMP
0041690F    PUSH 0                                   ; /ExitCode = 0
00416911    CALL DWORD PTR DS:[<&kernel32.ExitProces>; ExitProcess

(5)
00416928    CMP EAXDWORD PTR DS:[ECX+8]
0041692B    JE SHORT dumped_4.00416935      //JE改成JMP
0041692D    PUSH 0                                   ; /ExitCode = 0
0041692F    CALL DWORD PTR DS:[<&kernel32.ExitProces>; ExitProcess


修改好這些地方以後,程式正常執行。如果使用時還會退出,用同樣的方法解決。



三、破解

(1)爆破:

從登錄檔中取假註冊碼:

0042497C     PUSH EAX                 //註冊碼字元長度儲存地址
0042497D     PUSH EBX                 //註冊碼儲存地址
0042497E     PUSH dumped_6.00452818                   ;  ASCII "RegInfoBin"
00424983     CALL dumped_6.00424A5E

........

假註冊碼計算:

004249B1      PUSH EAX                                 ; /Arg6
004249B2      PUSH 0                                   ; |Arg5 = 00000000
004249B4      PUSH 10                                  ; |Arg4 = 00000010
004249B6      PUSH DWORD PTR DS:[ESI+A4]               ; |Arg3
004249BC      PUSH 10                                  ; |Arg2 = 00000010
004249BE      PUSH EBX                                 ; |Arg1
004249BF      CALL dumped_6.0041EF76                   ; dumped_6.0041EF76


比較:

004249CE     E8 58000000   CALL dumped_6.00424A2B             //比較call
004249D3     85C0          TEST EAXEAX                      //=0錯,=1對  
004249D5     74 1B         JE SHORT dumped_6.004249F2


因此要爆破,只要把 004249D5處改成JMP SHORT dumped_6.004249E2即可。 這段程式碼中沒出現真註冊碼的明碼,是計算後的結果比較。



(1)尋找註冊碼:

這個軟體註冊演算法很複雜,我沒看明白,也不清楚找到的是不是真的註冊碼,但好像可以用,有興趣的可以自己試試:

004244BE   PUSH EBX                                 ; /Arg6
004244BF   PUSH ECX                                 ; |Arg5
004244C0   OR DWORD PTR SS:[EBP-4], FFFFFFFF        ; |
004244C4   PUSH 10                                  ; |
004244C6   LEA ECXDWORD PTR DS:[ESI+90]           ; |
004244CC   POP EDI                                  ; |
004244CD   LEA EAXDWORD PTR DS:[ESI+24]           ; |
004244D0   PUSH EDI                                 ; |Arg4 => 00000010
004244D1   PUSH ECX                                 ; |Arg3
004244D2   PUSH 8                                   ; |Arg2 = 00000008
004244D4   PUSH EAX                                 ; |Arg1
004244D5   CALL dumped_6.0041F14C                   ; dumped_6.0041F14C


關鍵call:04244D5  CALL dumped_6.0041F14C,Arg5為儲存儲存註冊碼的地址。 


執行過這個call,得到註冊碼:AACBF24A6CE25E89AE6643DDC496502B

對應的註冊ID:A7E4EB4B4A683C9E10ED6CF866F5188E   


pyzpyz
2004.3.31

相關文章