能力值:
( LV2,RANK:10 )
|
-
-
9 楼
转贴:
标 题:[原创]heXer老兄的telock0.98脱壳机原理
发信人:lordor
时 间:2004-06-16,15:44
详细信息:
对象: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加壳后,对入口代码作一些变形,这样特征码不起作用,也就脱不了。
|