前言
今天練習脫Armadillo. 記錄下流程點.
記錄
查殼
PEID => Armadillo 1.xx - 2.xx -> Silicon Realms Toolworks [Overlay] DetectItEasy => Armadillo(6.X-9.X)[-] RDG => Armadillo 
脫殼環境
目標程序在原版WinXpSp3虛擬機中啟動不了, 可能有虛擬機檢測吧. 在真機環境(Win7X64Sp1)中可以直接啟動運行. 在52pj虛擬機(WinXpSp3)中可以直接啟動運行. 因為是X86程序, 選擇在52pj虛擬機中脫殼.
52pjOD太強了, 用異常計數法不行, 去掉OD的異常檢測后, F9直接跑起來了. 使用看雪OD+hideOD插件可以用異常計數法脫殼.
查找OEP前的設置
異常檢測的設置  重新運行程序, F9跑起來, 目標程序會不斷制造異常,這時會停在OD中, 按SHIFT+F9, 將異常返回給目標程序處理, 記錄”按SHIFT+F9”的次數, 我這里按了22次, 第23次程序跑起來了.
 重新運行程序, F9跑起來, 目標程序會不斷制造異常,這時會停在OD中, 按SHIFT+F9, 將異常返回給目標程序處理, 記錄”按SHIFT+F9”的次數, 我這里按了22次, 第23次程序跑起來了. 
查找OEP的流程記錄
0115CA3E    8900            mov     dWord ptr [eax], eax             ; F9后,按下22次(SHIFT+F9), 來到這里這里寫上22次來這了,重新運行程序,下次來這里,就可以在Memory代碼區下F2斷點了.第23次(SHIFT+F9), 程序就跑起來了第22次(SHIFT+F9)返回后,再Memory代碼區下F2斷點, F9跑起來.Memory map, 條目 24 地址=00914000 大小=00040000 (262144.) 屬主=RegMech  00400000 區段=.text1 包含=代碼 類型=Imag 01001002 訪問=R 初始訪問=RWE還會有第23次(異常來),再按下(SHIFT+F9)繼續,這時會來到代碼區中(因為對代碼區下了F2斷點).0092A202    83C4 04         add     esp, 4                           ; 第23次SHIFT+F9后, 中斷在代碼區F8往下走, 看看OEP在哪?0092B76C    FF15 54AA9600   call    dword ptr [96AA54]               ; F8到這里, 程序跑起來了在0092B76C這里,下一個硬執行斷點,重新跑程序,斷在這后,F7進入看OEP在哪?F7進入了call    dword ptr [96AA54], 再F8找OEP在哪?0115BF62    FFD7            call    edi                              ; F8程序跑起來了去掉硬斷點, 在0115BF62處下一個硬執行斷點, 重新跑程序來到這.F7進入 CALL edi, F8往下走.0041262C    68 1C364100     push    0041361C00412631    E8 EEFFFFFF     call    00412624                         ; F8卡住了, F7進去去掉硬斷點, 在00412631下一個硬執行斷點, 重新跑程序來到這(F9一次,23次SHIFT+F9)F7進入call    00412624, F8往下走. 最后又走進7xx函數去了(見下面的2個片段<<0041262C Eip處F7經過的2個代碼片段>>), 像是進了一個框架的接口.看看push    0041361C是壓入得什么?0041361C  56 42 35 21 F0 1F 2A 00 00 00 00 00 00 00 00 00  VB5!?*.........在memory小窗口看到, 壓入了"VB5!"給一個函數, 在VB程序里,只有OEP處是這樣的.看看call    00412624調用的是哪個函數?dword ptr [401358] = 733935A4看看733935A4在哪個DLL里面,是哪個函數?在可執行模塊列表中, 可以看到733935A4在MSVBVM60.DLL中。Executable modules, 條目 10 基址=73390000 大小=00153000 (1388544.) 入口=73391AF8 MSVBVM60.<模塊入口點> 名稱=MSVBVM60 (系統) 文件版本=6.00.9802 路徑=C:/WINDOWS/system32/MSVBVM60.DLL用IDA將MsVBVM60.dll拖進來,看看733935A4是啥函數?在IDA中看到, 733935A4 是 ThunRTMain.text:733935A4                 public ThunRTMain.text:733935A4 ThunRTMain      PRoc near               ; DATA XREF: .text:off_733B2D78o.text:733935A4.text:733935A4 var_64          = dword ptr -64h.text:733935A4 StartupInfo     = _STARTUPINFOA ptr -60h.text:733935A4 var_1C          = dword ptr -1Ch.text:733935A4 var_18          = dword ptr -18h.text:733935A4 var_4           = dword ptr -4.text:733935A4 arg_0           = dword ptr  8.text:733935A4.text:733935A4 ; FUNCTION CHUNK AT .text:733AF9B7 SIZE 0000000B BYTES.text:733935A4.text:733935A4                 push    ebp.text:733935A5                 mov     ebp, esp.text:733935A7                 push    0FFFFFFFFh.text:733935A9                 push    offset dword_733A97D0push "VB5!"call MSVBVM60.ThunRTMain這是VB程序的OEP代碼了.0041262C    68 1C364100     push    0041361C00412631    E8 EEFFFFFF     call    00412624                         ; F8卡住了, F7進去最后得到結論 0041262C 是OEP.去掉所有斷點(硬件斷點和F2斷點), 在0041262C處下硬件執行斷點, 重新運行程序(F9 + 23次SHIFT+F), 來到OEP = 0041262C////////////////////////////////////////////////////////////0041262C EIP處F7經過的2個代碼片段////////////////////////////////////////////////////////////00412624  - FF25 58134000   jmp     dword ptr [401358]733935A4    55              push    ebp733935A5    8BEC            mov     ebp, esp733935A7    6A FF           push    -1733935A9    68 D0973A73     push    733A97D0733935AE    68 FDBA4773     push    7347BAFD733935B3    64:A1 00000000  mov     eax, dword ptr fs:[0]733935B9    50              push    eax733935BA    64:8925 0000000>mov     dword ptr fs:[0], esp733935C1    51              push    ecx733935C2    51              push    ecx733935C3    83EC 4C         sub     esp, 4C733935C6    53              push    ebx733935C7    56              push    esi733935C8    57              push    edi733935C9    8965 E8         mov     dword ptr [ebp-18], esp733935CC    8B75 08         mov     esi, dword ptr [ebp+8]733935CF    8935 70E84973   mov     dword ptr [7349E870], esi733935D5    8365 FC 00      and     dword ptr [ebp-4], 0733935D9    8D45 A0         lea     eax, dword ptr [ebp-60]733935DC    50              push    eax733935DD    FF15 A0103973   call    dword ptr [733910A0]             ; kernel32.GetStartupInfoA733935E3    0FB745 D0       movzx   eax, word ptr [ebp-30]733935E7    A3 6CE84973     mov     dword ptr [7349E86C], eax733935EC    FF35 D8E74973   push    dword ptr [7349E7D8]             ; RegMech.00400000733935F2    56              push    esi733935F3    BE 70E44973     mov     esi, 7349E470733935F8    8BCE            mov     ecx, esi733935FA    90              nop733935FB    E8 5C000000     call    7339365C                         ; F8卡住了脫殼
脫殼前的設置:* 將異常檢測選項恢復,都打上勾.* 將hideod開啟* 在內存列表中,將目標程序的區段,全部改為全部可訪問的屬性.用OllyDump脫2個版本(不帶引入表修復和帶引入表修復).發現帶引入表修復的dump操作運行后, OD的UI掛掉了(沒反應)根據這種場景,到了OEP之后, 只dump一個不帶引入表修復的版本出來, 或者將OD最小化之后,等一會(1分鐘左右), 等OD醒過來.直接運行脫殼后的程序,報錯:"不是有效的Win32程序"修復導入表使用ImpREC* OEP填入 0001262C, 點擊AutoSearch.得到 RVA = 00001000, SIZE = 0000041C---------------------------Found something!---------------------------Found address which may be in the Original IAT. Try 'Get Import'.(If it is not correct, try RVA: 00001000 Size:00504538)---------------------------確定   ---------------------------* 點擊"Get Imports"發現 rva = 00001048處的函數不識別, 其他函數都正常.無效函數上面的函數是 : __vbaStrVarMove無效函數下面的函數是 : __vbaFreeVarList綜合上面文的msvbvm60的API ord, 并不是按照順序排列的, 也不好猜這個API的序號.右擊這個無效函數, 在菜單中選擇反匯編, 看反匯編,也看不出是什么API.選擇HexView, 將函數的字節碼抄下來,在msvbvm60.dll中搜索,看看是哪個函數?有可能殼, 將這個API代碼偷去了, 他不可能是自己寫吧?0113F261   55 8B EC 6A FF 68 D8 26 16 01 68 50 0D 16 01 640113F271   A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 10在OD中切換到msvbvm60.dll中,搜索這32個字節碼(2進制字符串查找)沒找到這32個特征碼在目標程序中找到了幾個vb函數的調用點008F2C7E     .  FF15 14144000 call    dword ptr [401414]               ;  MSVBVM60.__vbaFreeStr008F2C84     .  C745 FC 04000>mov     dword ptr [ebp-4], 4008F2C8B     .  68 00080000   push    800008F2C90     .  FF15 8C114000 call    dword ptr [40118C]               ;  MSVBVM60.rtcSpaceBstr008F2C96     .  8BD0          mov     edx, eax008F2C98     .  8D4D C4       lea     ecx, dword ptr [ebp-3C]008F2C9B     .  FF15 D0134000 call    dword ptr [4013D0]               ;  MSVBVM60.__vbaStrMove去IAT看一下.00401040  734768DF  MSVBVM60.__vbaLenBstr00401044  73471766  MSVBVM60.__vbaStrVarMove00401048  0113F2610040104C  73497262  MSVBVM60.__vbaFreeVarList00401050  734800FA  MSVBVM60._adj_fdiv_m64果真,00401048就是被偷了一個Vb的API.重新跑程序,在00401048下硬件寫入斷點,看看被偷走之前,寫的是哪個API?現在只有2個斷點* OEP 硬件執行斷點* 00401048 硬件寫入斷點(DWORD)重新跑程序.no.1    00401048  660CBDA8no.2    00401048  0113F261當被寫時,跟出去,發現了寫IAT的代碼.01157ACD      E8 14920000     call    01160CE6                                       ; jmp 到 msvcrt.memcpy01157AD2      83C4 0C         add     esp, 0C01157AD5      8D85 B4C4FFFF   lea     eax, dword ptr [ebp-3B4C]01157ADB      50              push    eax01157ADC      FFB5 B4C4FFFF   push    dword ptr [ebp-3B4C]01157AE2      FFB5 BCC4FFFF   push    dword ptr [ebp-3B44]01157AE8      8B85 00C7FFFF   mov     eax, dword ptr [ebp-3900]01157AEE      0385 B8C4FFFF   add     eax, dword ptr [ebp-3B48]01157AF4      50              push    eax01157AF5      FF15 5C211601   call    dword ptr [116215C]                            ; kernel32.VirtualProtect01157AFB      8B85 C0C4FFFF   mov     eax, dword ptr [ebp-3B40]01157B01      8985 C09EFFFF   mov     dword ptr [ebp+FFFF9EC0], eax01157B07      FFB5 C09EFFFF   push    dword ptr [ebp+FFFF9EC0]01157B0D      E8 CE910000     call    01160CE0                                       ; jmp 到 msvcrt.Operator delete// 這里開始寫IAT了, 011575AC處下硬件執行斷點011575AC      6A 01           push    1為了跟蹤00401048誰寫的, 對00401044下硬件寫入斷點. 等00401044被寫入時, 再仔細跟蹤00401048怎么寫.01158D02               8B8D 58B9FFFF   mov     ecx, dword ptr [ebp+FFFFB958]                  ; 這里是系統API地址堆棧 ss:[00128638]=0113F261ecx=00127D28, (ASCII "__vbaEnd")00127D28  5F 5F 76 62 61 45 6E 64 00 00 00 00 00 00 00 00  __vbaEnd........00128638  61 F2 13 01 00 00 00 00 5F 5F 76 62 61 45 6E 64  a?....__vbaEnd00128648  00 00 00 00 00 00 00 00 72 00 00 00 00 00 00 00  ........r.......IAT中最終填的值是0113F261, 經過這里猜測, 對應的功能是__vbaEnd00128638這里好像一個結構體, 前面放著函數指針,后面放著這個指針對應的函數名稱.先按IAT項 0113F261 為__vbaEnd,修復IAT試試.在ImpREC中, 雙擊無效項,在彈出的API列表中選擇__vbaEnd, 點擊確定, 導入函數都有效了.用ImpREC修復前面dump出來的2個版本.ImpREC提示, 不能添加任何節.用PETools重建PE(前面dump出來的2個版本).再用ImpREC進行IAT修復, IAT修復成功.測試脫殼后的程序2個版本都可用, 開心啊:)簡便脫殼方法-CreateThread硬件執行斷點
有的cm, 用異常計數法,次數非常多(e.g. 將近100次), 需要換CreateThread硬斷點法. 這時, 對CreatThreaad下硬件斷點, 返回用戶凌空后, 下面不遠處,就是進入OEP的call.
做試驗, 還是用的同一個cm, 注釋都標注好了(做異常計數法時標注好的) 可以驗證, 這種方法找OEP同樣正確.
將OD異常檢測選項都勾上, 對CreateThread下硬件執行斷點. F9將程序跑起來, 斷在CreateThread.
7C8106C7 kernel32.CreateThread      8BFF            mov     edi, edi               ; ALT+F9返回返回用戶領空7C8106C9                            55              push    ebp7C8106CA                            8BEC            mov     ebp, esp7C8106CC                            FF75 1C         push    dword ptr [ebp+1C]7C8106CF                            FF75 18         push    dword ptr [ebp+18]7C8106D2                            FF75 14         push    dword ptr [ebp+14]7C8106D5                            FF75 10         push    dword ptr [ebp+10]7C8106D8                            FF75 0C         push    dword ptr [ebp+C]7C8106DB                            FF75 08         push    dword ptr [ebp+8]7C8106DE                            6A FF           push    -17C8106E0                            E8 D7FDFFFF     call    CreateRemoteThread7C8106E5                            5D              pop     ebp7C8106E6                            C2 1800         retn    18011410FC       FF15 A0211601   call    dword ptr [11621A0]    ; kernel32.CreateThread01141102       5E              pop     esi                    ; RegMech.0096AA30 一路F8返回到調用點01141103       C9              leave01141104       C3              retn0115BEC7       A1 D81E1701     mov     eax, dword ptr [1171ED8]0115BECC       59              pop     ecx0115BECD       8B48 68         mov     ecx, dword ptr [eax+68]0115BED0       3348 64         xor     ecx, dword ptr [eax+64]0115BED3       3348 5C         xor     ecx, dword ptr [eax+5C]0115BED6       F6C1 40         test    cl, 400115BED9       75 08           jnz     short 0115BEE30115BEDB       6A 01           push    10115BEDD       E8 15BEFDFF     call    01137CF70115BEE2       59              pop     ecx0115BEE3       53              push    ebx0115BEE4       C705 E0791601 A>mov     dword ptr [11679E0], 11687A4   ; ASCII "RC"0115BEEE       E8 22EAFDFF     call    0113A9150115BEF3       59              pop     ecx0115BEF4       E8 8BE7FEFF     call    0114A6840115BEF9       8BF8            mov     edi, eax0115BEFB       A1 D81E1701     mov     eax, dword ptr [1171ED8]0115BF00       8B48 7C         mov     ecx, dword ptr [eax+7C]0115BF03       3348 68         xor     ecx, dword ptr [eax+68]0115BF06       3348 10         xor     ecx, dword ptr [eax+10]0115BF09       03F9            add     edi, ecx0115BF0B       8B0E            mov     ecx, dword ptr [esi]0115BF0D       3BCB            cmp     ecx, ebx0115BF0F       75 2F           jnz     short 0115BF400115BF11       8B78 68         mov     edi, dword ptr [eax+68]0115BF14       E8 6BE7FEFF     call    0114A6840115BF19       8B0D D81E1701   mov     ecx, dword ptr [1171ED8]       ; RegMech.009643700115BF1F       FF76 14         push    dword ptr [esi+14]0115BF22       8B51 7C         mov     edx, dword ptr [ecx+7C]0115BF25       FF76 10         push    dword ptr [esi+10]0115BF28       3351 10         xor     edx, dword ptr [ecx+10]0115BF2B       FF76 0C         push    dword ptr [esi+C]0115BF2E       33D7            xor     edx, edi0115BF30       03C2            add     eax, edx0115BF32       8B51 34         mov     edx, dword ptr [ecx+34]0115BF35       3351 20         xor     edx, dword ptr [ecx+20]0115BF38       33D7            xor     edx, edi0115BF3A       2BC2            sub     eax, edx0115BF3C       FFD0            call    eax0115BF3E       EB 24           jmp     short 0115BF640115BF40       83F9 01         cmp     ecx, 10115BF43       75 22           jnz     short 0115BF670115BF45       FF76 04         push    dword ptr [esi+4]0115BF48       FF76 08         push    dword ptr [esi+8]0115BF4B       53              push    ebx0115BF4C       E8 33E7FEFF     call    0114A6840115BF51       50              push    eax0115BF52       A1 D81E1701     mov     eax, dword ptr [1171ED8]0115BF57       8B48 68         mov     ecx, dword ptr [eax+68]0115BF5A       3348 34         xor     ecx, dword ptr [eax+34]0115BF5D       3348 20         xor     ecx, dword ptr [eax+20]0115BF60       2BF9            sub     edi, ecx0115BF62       FFD7            call    edi                            ; F8程序跑起來了0115BF64       8945 FC         mov     dword ptr [ebp-4], eax0115BF67       8B45 FC         mov     eax, dword ptr [ebp-4]0115BF6A       5F              pop     edi0115BF6B       5E              pop     esi0115BF6C       5B              pop     ebx0115BF6D       C9              leave0115BF6E       C3              retn0115BF62處的call edi, F7進去后就是OEP
0041262C       68 1C364100     push    0041361C                       ; OEP00412631       E8 EEFFFFFF     call    00412624                       ; F8卡住了, F7進去00412636       0000            add     byte ptr [eax], al后面的IAT修復,PE重建過程同異常計數法. 這殼用OllyDump脫的時候, 只能選非修復引用表方式. 如果選修復引用表方式, OD會掛掉, 不一定能恢復正常. 當ImpREC得到的導入函數沒得到時,可以嘗試在無效項上右擊菜單 => Trace_Level1(Disasm)  
  ImpREC按照導入函數反匯編去找導入函數名稱時, 有時能找對幾個. 像這個cm, 則找的不對(將vbApi找成了GetModuleHandleA),遇到這種情況, 那就要自己去找缺失的導入函數名稱(異常計數法里,找缺失的導入函數的方法,是通過追蹤IAT里填導入函數地址的反匯編實現來做的,這是最樸素,最靠譜的方法).
 ImpREC按照導入函數反匯編去找導入函數名稱時, 有時能找對幾個. 像這個cm, 則找的不對(將vbApi找成了GetModuleHandleA),遇到這種情況, 那就要自己去找缺失的導入函數名稱(異常計數法里,找缺失的導入函數的方法,是通過追蹤IAT里填導入函數地址的反匯編實現來做的,這是最樸素,最靠譜的方法).