[原創]heXer老兄的telock0.98脫殼機原理

看雪資料發表於2004-06-16

物件:heXer老兄的telock0.98脫殼機
作者:lordor
QQ:88378557
mail:lordor#163.com
From:

用ASM編寫,沒加殼,很容易會來到處理"Unpack"按鍵的程式碼:

004021C8  PUSHAD                                            ; |
004021C9  PUSH untelock.00404428                            ;  ASCII "C:\Program Files\starTV\starTV.exe"
004021CE  CALL untelock.00401B45                            ; \untelock.00401B45
004021D3  CMP DWORD PTR DS:[405744],1
004021DA  JNZ untelock.004022C8
004021E0  PUSH untelock.00404428                            ; /String2 = "C:\Program Files\starTV\starTV.exe"
004021E5  PUSH untelock.0040452C                            ; |String1 = untelock.0040452C
004021EA  CALL <JMP.&KERNEL32.lstrcpyA>                     ; \lstrcpyA
004021EF  PUSH untelock.00404428                            ; /String2 = "C:\Program Files\starTV\starTV.exe"
004021F4  PUSH untelock.00404630                            ; |String1 = untelock.00404630
004021F9  CALL <JMP.&KERNEL32.lstrcpyA>                     ; \lstrcpyA
004021FE  PUSH untelock.00404288                            ; /StringToAdd = ".BAK"
00402203  PUSH untelock.0040452C                            ; |ConcatString = "C:\Program Files\starTV\starTV.exe.BAK"
00402208  CALL <JMP.&KERNEL32.lstrcatA>                     ; \lstrcatA
0040220D  PUSH untelock.0040428D                            ; /StringToAdd = ".TMP"
00402212  PUSH untelock.00404630                            ; |ConcatString = "C:\Program Files\starTV\starTV.exe.TMP"
00402217  CALL <JMP.&KERNEL32.lstrcatA>                     ; \lstrcatA
0040221C  PUSH 0                                            ; /FailIfExists = FALSE
0040221E  PUSH untelock.0040452C                            ; |NewFileName = "C:\Program Files\starTV\starTV.exe.BAK"
00402223  PUSH untelock.00404428                            ; |ExistingFileName = "C:\Program Files\starTV\starTV.exe"
00402228  CALL <JMP.&KERNEL32.CopyFileA>                    ; \CopyFileA
0040222D  CALL untelock.00401DA2
00402232  CMP DWORD PTR DS:[405740],0
00402239  JE untelock.004022C8                              ;  上面是備份,並把檔案對映到記憶體,判斷是否為有效pe檔案
0040223F  CALL untelock.00401CAD                            ;  判斷是否為telock加密
00402244  CALL untelock.004016F1                            ;  這個很長,這裡是模擬telock的解壓程式碼,解到記憶體中
00402249  CALL untelock.004020A5                            ;  對記憶體中的資料,生成脫殼檔案
0040224E  PUSH DWORD PTR DS:[405740]                        ; /BaseAddress = 01270000
00402254  CALL <JMP.&KERNEL32.UnmapViewOfFile>              ; \UnmapViewOfFile
00402259  PUSH DWORD PTR DS:[40573C]                        ; /hObject = 00000108 (window)
0040225F  CALL <JMP.&KERNEL32.CloseHandle>                  ; \CloseHandle
00402264  PUSH DWORD PTR DS:[405734]                        ; /hObject = 0000015C (window)
0040226A  CALL <JMP.&KERNEL32.CloseHandle>                  ; \CloseHandle
0040226F  PUSH 0                                            ; /FailIfExists = FALSE
00402271  PUSH untelock.00404428                            ; |NewFileName = "C:\Program Files\starTV\starTV.exe"
00402276  PUSH untelock.00404630                            ; |ExistingFileName = "C:\Program Files\starTV\starTV.exe.TMP"
0040227B  CALL <JMP.&KERNEL32.CopyFileA>                    ; \CopyFileA
00402280  PUSH untelock.00404630                            ; /FileName = "C:\Program Files\starTV\starTV.exe.TMP"
00402285  CALL <JMP.&KERNEL32.DeleteFileA>                  ; \DeleteFileA
0040228A  CALL untelock.00401DA2
0040228F  CALL untelock.00401D31
00402294  PUSH DWORD PTR DS:[405740]                        ; /BaseAddress = 01270000
0040229A  CALL <JMP.&KERNEL32.UnmapViewOfFile>              ; \UnmapViewOfFile
0040229F  PUSH DWORD PTR DS:[40573C]                        ; /hObject = 00000108 (window)
004022A5  CALL <JMP.&KERNEL32.CloseHandle>                  ; \CloseHandle
004022AA  PUSH DWORD PTR DS:[405734]                        ; /hObject = 0000015C (window)
004022B0  CALL <JMP.&KERNEL32.CloseHandle>                  ; \CloseHandle
004022B5  PUSH 0                                            ; /Style = MB_OK|MB_APPLMODAL
004022B7  PUSH untelock.004040C6                            ; |Title = " tElock v0.98+ unpacker Special   "
004022BC  PUSH untelock.00404241                            ; |Text = "         Success unpacked!"
004022C1  PUSH 0                                            ; |hOwner = NULL
004022C3  CALL <JMP.&USER32.MessageBoxA>                    ; \MessageBoxA
004022C8  POPAD
004022C9  RETN

可以看到主要處理過程:備份->判斷特徵碼->解壓->據解壓生成未加殼的檔案
下面是三個主要的call程式碼

--------------------------------
第一個:0040223F  CALL untelock.00401CAD

00401CAD  PUSHAD
00401CAE  MOV EDI,DWORD PTR DS:[405740]
00401CB4  ADD EDI,DWORD PTR DS:[EDI+3C]                     ;  pe頭
00401CB7  MOV EAX,DWORD PTR DS:[EDI+28]                     ;  取oep值
00401CBA  PUSH EAX                                          ;  1bdbd6
00401CBB  PUSH DWORD PTR DS:[405740]
00401CC1  CALL untelock.0040117E                            ;  取rva在檔案中的相對位移offset
-------------------
  0040117E  />PUSH EBP
  0040117F  |>MOV EBP,ESP
  00401181  |>PUSH EDI
  00401182  |>PUSH ESI
  00401183  |>PUSH EDX
  00401184  |>PUSH ECX
  00401185  |>MOV ESI,DWORD PTR SS:[EBP+8]                      ;  基址
  00401188  |>ADD ESI,DWORD PTR DS:[ESI+3C]                     ;  pe頭
  0040118B  |>MOV EDI,DWORD PTR SS:[EBP+C]                      ;  eep
  0040118E  |>MOV EDX,ESI
  00401190  |>ADD EDX,0F8                                       ;  定位第一個段
  00401196  |>MOV CX,WORD PTR DS:[ESI+6]                        ;  有多少個節
  0040119A  |>MOVZX ECX,CX
  0040119D  |>JMP SHORT untelock.004011CC
  0040119F  |>/CMP EDI,DWORD PTR DS:[EDX+C]                     ;  oep與當前節的voffset比較
  004011A2  |>|JB SHORT untelock.004011C8
  004011A4  |>|MOV EAX,DWORD PTR DS:[EDX+C]
  004011A7  |>|ADD EAX,DWORD PTR DS:[EDX+10]                    ;  voffset+rawsize
  004011AA  |>|CMP EDI,EAX
  004011AC  |>|JNB SHORT untelock.004011C8
  004011AE  |>|MOV EAX,DWORD PTR DS:[EDX+10]                    ;  rawsize
  004011B1  |>|MOV DWORD PTR DS:[405768],EAX
  004011B6  |>|MOV EAX,DWORD PTR DS:[EDX+C]
  004011B9  |>|SUB EDI,EAX
  004011BB  |>|MOV EAX,DWORD PTR DS:[EDX+14]
  004011BE  |>|ADD EAX,EDI
  004011C0  |>|POP ECX
  004011C1  |>|POP EDX
  004011C2  |>|POP ESI
  004011C3  |>|POP EDI
  004011C4  |>|LEAVE
  004011C5  |>|RETN 8
  004011C8  |>|ADD EDX,28                                       ;  下一節
  004011CB  |>|DEC ECX
  004011CC  |> CMP ECX,0
  004011CF  |>\JA SHORT untelock.0040119F                       ;  判斷oep是落在那一節上
  004011D1  |>MOV EAX,-1
  004011D6  |>POP ECX
  004011D7  |>POP EDX
  004011D8  |>POP ESI
  004011D9  |>POP EDI
  004011DA  |>LEAVE
  004011DB  \>RETN 8
--------------------------


00401CC6  MOV EDI,EAX                                       ;  取得oep的檔案偏移be1d6
00401CC8  ADD EDI,DWORD PTR DS:[405740]                     ;  加上基址
00401CCE  MOV EAX,DWORD PTR DS:[405768]                     ;  eop所在段的大小2800
00401CD3  MOV EAX,-1
00401CD8  CMP DWORD PTR DS:[EDI-A],237
00401CDF  JNZ SHORT untelock.00401D0F                       ;  入口地址前第9及10位元組(Word型)是否為237
00401CE1  CMP BYTE PTR DS:[EDI],0E9                         ;  入口處第一個位元組是否為e9
00401CE4  JNZ SHORT untelock.00401D0F
00401CE6  CMP WORD PTR DS:[EDI+3],0FFFF                     ;  入口處第4、5個位元組是否為0ffff
00401CEB  JNZ SHORT untelock.00401D0F
00401CED  MOV EDX,DWORD PTR DS:[EDI+1]          ==>取入口第二位元組開始共4個位元組,即取jmp後的地址
00401CF0  ADD EDI,5              ==>加上第一條指令的長度    
00401CF3  ADD EDI,EDX                          ==>edi再加上跳轉的地址,即取得jmp後的地址 
00401CF5  CMP BYTE PTR DS:[EDI+16],0B9                      ;  判斷第23位元組是否為b9
00401CF9  JNZ SHORT untelock.00401D0F
00401CFB  CMP WORD PTR DS:[EDI+19],0        ==>26位元組
00401D00  JNZ SHORT untelock.00401D0F
00401D02  CMP DWORD PTR DS:[EDI+25],6781448D      
==>38位元組(005BC025    8D4481 67       LEA EAX,DWORD PTR DS:[ECX+EAX*4+67])    
00401D09  JNZ SHORT untelock.00401D0F
00401D0B  XOR EAX,EAX
00401D0D  JMP SHORT untelock.00401D10
00401D0F  NOP
00401D10  NOP
00401D11  CMP EAX,-1
00401D14  JNZ SHORT untelock.00401D2F
00401D16  PUSH 10                                           ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401D18  PUSH untelock.004040C6                            ; |Title = " tElock v0.98+ unpacker Special   "
00401D1D  PUSH untelock.004041F5                            ; |Text = "This file is not packed by tElock v0.98+"
00401D22  PUSH 0                                            ; |hOwner = NULL
00401D24  CALL <JMP.&USER32.MessageBoxA>                    ; \MessageBoxA
00401D29  PUSH EAX                                          ; /ExitCode
00401D2A  CALL <JMP.&KERNEL32.ExitProcess>                  ; \ExitProcess
00401D2F  POPAD
00401D30  RETN

可以看到這是判斷入口程式碼的特徵字



----------------------------------------
第二個:0402244  CALL untelock.004016F1:這裡是模擬telock的解壓程式碼,解到記憶體中

004016F1  PUSHAD
004016F2  MOV EDI,DWORD PTR DS:[405740]            ;  基址
004016F8  ADD EDI,DWORD PTR DS:[EDI+3C]            ;  pe
004016FB  MOV EAX,DWORD PTR DS:[EDI+28]            ;  eop
004016FE  PUSH EAX
004016FF  PUSH DWORD PTR DS:[405740]
00401705  CALL untelock.0040117E                   ;  fileoffset
0040170A  MOV EDI,EAX
0040170C  ADD EDI,DWORD PTR DS:[405740]
00401712  MOV EAX,DWORD PTR DS:[EDI+1]             ;  jmp後的地址
00401715  ADD EDI,5
00401718  ADD EDI,EAX
0040171A  MOV DWORD PTR DS:[40574C],EDI            ;  儲存跳轉後的地址
00401720  MOV EBP,EDI
00401722  MOV ESI,EDI
00401724  ADD ESI,41                               ;  add 41
00401727  MOV ECX,DWORD PTR DS:[EDI+17]            ;  14
0040172A  MOV EAX,ECX
0040172C  PUSH ESI
0040172D  /LEA EAX,DWORD PTR DS:[ECX+EAX*4+67]
00401731  |XOR BYTE PTR DS:[ESI],AL
00401733  |INC ESI
00401734  |AAM 9
00401736  |DEC ECX
00401737  \JG SHORT untelock.0040172D              ;  模擬解壓
00401739  POP ESI
0040173A  PUSH ESI
0040173B  MOV EAX,DWORD PTR DS:[ESI+1]                         ;  esi為解後的地址
0040173E  ADD ESI,5
00401741  ADD ESI,EAX                                          ;  跳轉的地址
00401743  MOV EAX,DWORD PTR DS:[ESI+8]
00401746  ADD ESI,5
00401749  SUB ESI,EAX
0040174B  MOV ECX,0D
00401750  CALL untelock.004013D2
00401755  MOV CL,BYTE PTR DS:[ESI-1D]
00401758  MOV CH,BYTE PTR DS:[ESI-16]
0040175B  MOV EBX,DWORD PTR DS:[ESI-2C]
0040175E  MOV ESI,EDI
00401760  POP ESI
00401761  ADD ESI,6
00401764  /ROL BYTE PTR DS:[ESI+EBX],CL
00401767  |ADD BYTE PTR DS:[ESI+EBX],BL
0040176A  |XOR BYTE PTR DS:[ESI+EBX],CH
0040176D  |INC BYTE PTR DS:[ESI+EBX]
00401770  |DEC EBX
00401771  \JG SHORT untelock.00401764    ;  模擬解壓


--------------------
第三個:儲存檔案的模組:

004020A5  PUSH 0                                            ; /hTemplateFile = NULL
004020A7  PUSH 80                                           ; |Attributes = NORMAL
004020AC  PUSH 2                                            ; |Mode = CREATE_ALWAYS
004020AE  PUSH 0                                            ; |pSecurity = NULL
004020B0  PUSH 1                                            ; |ShareMode = FILE_SHARE_READ
004020B2  PUSH C0000000                                     ; |Access = GENERIC_READ|GENERIC_WRITE
004020B7  PUSH untelock.00404630                            ; |FileName = "C:\Program Files\starTV\starTV.exe.TMP"
004020BC  CALL <JMP.&KERNEL32.CreateFileA>                  ; \CreateFileA
004020C1  MOV DWORD PTR DS:[405738],EAX
004020C6  XOR EBX,EBX
004020C8  MOV DWORD PTR DS:[405774],EBX
004020CE  PUSH 0
004020D0  PUSH DWORD PTR DS:[405740]
004020D6  CALL untelock.0040110D
004020DB  PUSH 0                                            ; /pOverlapped = NULL
004020DD  PUSH untelock.00405748                            ; |pBytesWritten = untelock.00405748
004020E2  PUSH EBX                                          ; |nBytesToWrite
004020E3  PUSH DWORD PTR DS:[405740]                        ; |Buffer = 01270000
004020E9  PUSH DWORD PTR DS:[405738]                        ; |hFile = 00000120 (window)
004020EF  CALL <JMP.&KERNEL32.WriteFile>                    ; \WriteFile
004020F4  MOV EAX,DWORD PTR DS:[405748]
004020F9  MOV DWORD PTR DS:[405778],EAX
004020FE  PUSH ESI
004020FF  PUSH EDI
00402100  PUSH ECX
00402101  MOV ECX,EAX
00402103  MOV ESI,DWORD PTR DS:[405740]
00402109  LEA EDI,DWORD PTR DS:[404734]
0040210F  REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
00402111  POP ECX
00402112  POP EDI
00402113  POP ESI
00402114  ADD DWORD PTR DS:[405774],EAX
0040211A  CALL untelock.00401E4F
0040211F  MOV DWORD PTR DS:[40576C],EAX
00402124  XOR ESI,ESI
00402126  JMP SHORT untelock.00402186
00402128  /PUSH ESI
00402129  |PUSH DWORD PTR DS:[405740]
0040212F  |CALL untelock.0040110D  ==>節
00402134  |MOV ECX,EAX
00402136  |MOV DWORD PTR DS:[405748],0
00402140  |CMP DWORD PTR DS:[405760],0
00402147  |JE SHORT untelock.00402167
00402149  |CALL untelock.00401FEB  ==>寫入檔案
0040214E  |PUSH EAX
0040214F  |PUSH DWORD PTR DS:[405774]
00402155  |CALL untelock.0040115B
0040215A  |MOV EAX,DWORD PTR DS:[405748]
0040215F  |ADD DWORD PTR DS:[405774],EAX
00402165  |JMP SHORT untelock.00402185
00402167  |XOR EAX,EAX
00402169  |MOV DWORD PTR DS:[405748],EAX
0040216E  |PUSH EAX
0040216F  |PUSH DWORD PTR DS:[405774]
00402175  |CALL untelock.0040115B
0040217A  |MOV EAX,DWORD PTR DS:[405748]
0040217F  |ADD DWORD PTR DS:[405774],EAX
00402185  |INC ESI
00402186   CMP ESI,DWORD PTR DS:[40576C]
0040218C  \JNZ SHORT untelock.00402128
0040218E  PUSH 0                                            ; /Origin = FILE_BEGIN
00402190  PUSH 0                                            ; |pOffsetHi = NULL
00402192  PUSH 0                                            ; |OffsetLo = 0
00402194  PUSH DWORD PTR DS:[405738]                        ; |hFile = 00000120 (window)
0040219A  CALL <JMP.&KERNEL32.SetFilePointer>               ; \SetFilePointer
0040219F  PUSH 0                                            ; /pOverlapped = NULL
004021A1  PUSH untelock.00405748                            ; |pBytesWritten = untelock.00405748
004021A6  PUSH DWORD PTR DS:[405778]                        ; |nBytesToWrite = 400 (1024.)
004021AC  PUSH untelock.00404734                            ; |Buffer = untelock.00404734
004021B1  PUSH DWORD PTR DS:[405738]                        ; |hFile = 00000120 (window)
004021B7  CALL <JMP.&KERNEL32.WriteFile>                    ; \WriteFile
004021BC  PUSH DWORD PTR DS:[405738]                        ; /hObject = 00000120 (window)
004021C2  CALL <JMP.&KERNEL32.CloseHandle>                  ; \CloseHandle
004021C7  RETN

總結:
可以看到脫殼機是模擬telock的原理進行脫殼的,heXer編寫了大量的解壓程式碼,直接對檔案程式碼進行解壓出正確的程式碼。
防範:對於這種脫殼機,防範的方法是針對兩種:一中它在判斷特徵碼是作修改,另一個是它在解壓時的資料作修改。如用telock加殼後,對入口程式碼作一些變形,這樣特徵碼不起作用,也就脫不了。


by lordor  04.6.16

相關文章