您现在的位置: > 首页 > 软件应用 > 系统安全
>> 最新教程
>> 热门教程
>> 最新游戏资讯
>> 热门游戏资讯
病毒“wuauclt.exe”所加未知壳的手脱方法
作者:本站                来自:安迪教程网                 加入时间:08-10-16                进入论坛讨论

  前言:

  本想努力工作来着,好把日程进度再往前赶赶。但很不幸,一不小心发现了个比较诱人的壳,看来今天又要把大部分时间压在它的身上了。

  其实这个病毒的其它变种样本我在很早以前就见过多次,也分析过多次了。只是它所加的壳实在是变态得很,以至于我一直都没能把它完全征服,所以在每次分析它的时候都只能是取其运行后的内存映像来进行研究。

  使用PEID对样本进行扫描,显示出的壳名为“PEtite 2.1 -> Ian Luck”。我脱完壳后在网上搜索了一下,发现有好多该壳的脱文,并且内容都是寥寥几句,一个ESP定律就把壳给搞定了。仔细看了一下,怎么感觉完全不是同一个壳呢?也不知道问题出在哪里了。“PEtite 2.1 -> Ian Luck”这个壳以前我没接触过,具体什么样子我也不知道,这里就把它当未知壳来讲吧。

  该壳应该是一个加密壳,里边有3处异常(通向光明的关键,其中的后2处异常加了暗桩手段)、输入表加密、代码动态解密执行,有N多迷惑性的花指令代码、压缩算法、反动态跟踪调试等技术。如果想脱掉这个壳的话,别说刚入门的新手了,就算是有经验的人都未必能很快的搞定。

  今天仔细分析了下,用了2个小时左右,终于把这个壳的框架思路分析清楚了。下面准备分两部分来讲述:第一部分-手脱方法、第二部分-难点分析。

  ---------------------------------------------------------------------------------------------

  第一部分:手脱方法:

  说明:([F2]:下软断点、[F4]:执行到当前代码处、[F7]:单步步入、[F8]:单步步过、[F9]:运行。)

  (01):使用“Ollydbg”打开病毒主程序,设置“Ollydbg”为“不忽略任何异常”,然后[F9]运行。

  (02):“Ollydbg”提示“访问违规”,然后停在代码“MOV BYTE PTR DS:[EDI],AL”处(代码如下)。

  13149217 8807 MOV BYTE PTR DS:[EDI],AL ; 访问违规

  13149219 81EC D8BA0000 SUB ESP,0BAD8

  1314921F 8D8D 887FFFFF LEA ECX,DWORD PTR SS:[EBP+FFFF7F88]

  13149225 834D EC FF OR DWORD PTR SS:[EBP-14],FFFFFFFF

  13149229 894D 90 MOV DWORD PTR SS:[EBP-70],ECX

  1314922C 8D8D 887FFFFF LEA ECX,DWORD PTR SS:[EBP+FFFF7F88]

  13149232 894D 8C MOV DWORD PTR SS:[EBP-74],ECX

  13149235 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8]

  13149238 8D45 88 LEA EAX,DWORD PTR SS:[EBP-78]

  1314923B 53 PUSH EBX

  (03):使用[Shift + F9]来忽略异常,“Ollydbg”停在下一个异常代码“POP EDX”处,并提示“单步异常”(代码如下)。

  131438F1 5A POP EDX ; 单步异常

  131438F2 64:8F05 0000000>POP DWORD PTR FS:[0]

  131438F9 58 POP EAX

  131438FA 6A 00 PUSH 0

  131438FC 53 PUSH EBX

  131438FD 33DB XOR EBX,EBX

  131438FF 68 4C030000 PUSH 34C

  13143904 8B0C24 MOV ECX,DWORD PTR SS:[ESP]

  13143907 0FBAE3 00 BT EBX,0

  1314390B 72 16 JB SHORT virus.13143923

  (04):在代码“POP DWORD PTR FS:[0]”处下软断点(如地址“131438F2”)。使用[Shift + F9]来忽略异常,停在代码“POP DWORD PTR FS:[0]”处(代码如下)。

  131438F1 5A POP EDX ; 断点

  131438F2 64:8F05 0000000>POP DWORD PTR FS:[0]

  131438F9 58 POP EAX

  131438FA 6A 00 PUSH 0

  131438FC 53 PUSH EBX

  131438FD 33DB XOR EBX,EBX

  131438FF 68 4C030000 PUSH 34C

  13143904 8B0C24 MOV ECX,DWORD PTR SS:[ESP]

  13143907 0FBAE3 00 BT EBX,0

  1314390B 72 16 JB SHORT virus.13143923

  (05):向下翻阅代码,你会找到具有明显特征的如下代码,然后在代码“CALL 74DBD43D”处下断点(如地址“13143BB2”),[F9]运行(代码如下)。

  13143BA8 59 POP ECX

  13143BA9 5E POP ESI

  13143BAA FD STD

  13143BAB 33C0 XOR EAX,EAX

  13143BAD B9 65030000 MOV ECX,365

  13143BB2 E8 8698C761 CALL 74DBD43D ; 下断点

  13143BB7 0000 ADD BYTE PTR DS:[EAX],AL

  13143BB9 0000 ADD BYTE PTR DS:[EAX],AL

  13143BBB 0000 ADD BYTE PTR DS:[EAX],AL

  13143BBD 0000 ADD BYTE PTR DS:[EAX],AL

  13143BBF 0000 ADD BYTE PTR DS:[EAX],AL

  13143BC1 0000 ADD BYTE PTR DS:[EAX],AL

  .

  .

  13143FF5 0000 ADD BYTE PTR DS:[EAX],AL

  13143FF7 0000 ADD BYTE PTR DS:[EAX],AL

  13143FF9 0000 ADD BYTE PTR DS:[EAX],AL

  13143FFB 0000 ADD BYTE PTR DS:[EAX],AL

  13143FFD 0000 ADD BYTE PTR DS:[EAX],AL

  (06):停在代码“CALL 74DBD43D”处后,使用[F7]跟进去。进去后来到这里。然后一直[F8]单步向下走,在代码“JMP”处跳(如地址“1314910B”)(代码如下)。

  13149102 5F POP EDI

  13149103 F3:AA REP STOS BYTE PTR ES:[EDI]

  13149105 61 POPAD

  13149106 66:9D POPFW

  13149108 83C4 0C ADD ESP,0C

  1314910B >- E9 F2EEFFFF JMP virus.13148002 ; 跳转(这里是分界线。听一位网友说前面属于PEtite壳的部分,那么后面的代码可能就属于另一个壳,或是该壳以被改为变形壳了。)

  13149110 - E9 1A6B6C69 JMP kernel32.GlobalFree

  13149115 - E9 5D796C69 JMP kernel32.GetFileSize

  1314911A - E9 44826D69 JMP kernel32.GetWindowsDirectoryA

  1314911F - E9 540C7169 JMP kernel32.OutputDebugStringA

  13149124 - E9 E6906B69 JMP kernel32.WriteProcessMemory

  13149129 - E9 F7846B69 JMP kernel32.DeviceIoControl

  1314912E - E9 A73C6D69 JMP kernel32.ExitProcess

  13149133 - E9 69256C69 JMP kernel32.GetModuleHandleA

  13149138 - E9 631C6C69 JMP kernel32.GetProcAddress

  1314913D - E9 16AE7169 JMP kernel32.Process32Next

  13149142 - E9 E48FBE64 JMP USER32.GetWindowTextA

  13149147 - E9 ECA0C764 JMP ADVAPI32.StartServiceA

  1314914C - E9 02E6C564 JMP ADVAPI32.OpenProcessToken

  13149151 - E9 DE33C864 JMP ADVAPI32.AdjustTokenPrivileges

  13149156 - E9 857D4C6A JMP SHELL32.ShellExecuteA

  1314915B - E9 98BCAB64 JMP msvcrt._onexit

  13149160 - E9 CC67AC64 JMP msvcrt.sprintf

  (07):跳到这里后,一直[F8]单步向下走,走到代码“INT 2D”处时停下,看堆栈,在堆栈中找到所要执行的异常处理代码位置(代码如下)。

  13148002 3BC0 CMP EAX,EAX ; 跳到这里

  13148004 9B WAIT

  13148005 43 INC EBX

  13148006 4B DEC EBX

  13148007 87E6 XCHG ESI,ESP

  13148009 87E6 XCHG ESI,ESP

  1314800B 60 PUSHAD

  1314800C 8B7424 20 MOV ESI,DWORD PTR SS:[ESP+20]

  13148010 BF 5F801413 MOV EDI,virus.1314805F

  13148015 A4 MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]

  13148016 4F DEC EDI

  13148017 87FA XCHG EDX,EDI

  13148019 87FA XCHG EDX,EDI

  1314801B 8037 6E XOR BYTE PTR DS:[EDI],6E

  1314801E 68 42801413 PUSH virus.13148042

  13148023 64:FF35 0000000>PUSH DWORD PTR FS:[0]

  1314802A 64:8925 0000000>MOV DWORD PTR FS:[0],ESP

  13148031 CD 2D INT 2D ; 停在这里看堆栈,寻找异常处理代码,该处的异常“Ollydbg”不能自动处理。

  13148033 C3 RETN

  (08):例如找到的异常处理代码所在的位置是“13148042”,那么我们就需要手动把当前调试的EIP值重新设置为“13148042”(需要手动设置的原因是OD没有识别这个异常,我们只能自己去定向这个跳转)。EIP设置完毕后,一直[F8]单步向下走,在代码“RETN”处返回(代码如下)。

  13148042 3BFF CMP EDI,EDI

  13148044 9B WAIT

  13148045 90 NOP

  13148046 3BFF CMP EDI,EDI

  13148048 3BFF CMP EDI,EDI

  1314804A 8BC0 MOV EAX,EAX

  1314804C B8 65801413 MOV EAX,virus.13148065

  13148051 50 PUSH EAX

  13148052 C2 0000 RETN 0

  (09):返回后来到这里,然后一直[F8]单步向下走,在代码“RETN”处返回(代码如下)。

  13148065 B9 00101413 MOV ECX,virus.13141000

  1314806A BB 00200000 MOV EBX,2000

  1314806F 68 7C801413 PUSH virus.1314807C

  13148074 68 59801413 PUSH virus.13148059

  13148079 C2 0000 RETN 0

  (10):返回后来到这里,向下翻阅代码,找到无效指定代码“ADD BYTE PTR DS:[EAX],AL”前的最后一个返回跳转代码“RETN”,这个返回跳转就是壳的结尾处了(代码如下)。

  13148059 85DB TEST EBX,EBX

  1314805B 74 07 JE SHORT virus.13148064

  1314805D 8031 3E XOR BYTE PTR DS:[ECX],3E

  13148060 4B DEC EBX

  13148061 41 INC ECX

  13148062 ^ EB F5 JMP SHORT virus.13148059

  13148064 C3 RETN

  13148065 B9 00101413 MOV ECX,virus.13141000

  1314806A BB 00200000 MOV EBX,2000

  1314806F 68 7C801413 PUSH virus.1314807C

  13148074 68 59801413 PUSH virus.13148059

  13148079 C2 0000 RETN 0

  1314807C 42 INC EDX

  1314807D 4A DEC EDX

  1314807E B9 00401413 MOV ECX,virus.13144000

  13148083 BB 00200000 MOV EBX,2000

  13148088 68 95801413 PUSH virus.13148095

  1314808D 68 59801413 PUSH virus.13148059

  13148092 C2 0000 RETN 0

  13148095 83EB 01 SUB EBX,1

  13148098 43 INC EBX

  13148099 9B WAIT

  1314809A 60 PUSHAD

  1314809B 61 POPAD

  1314809C 9B WAIT

  1314809D B9 00601413 MOV ECX,virus.13146000

  131480A2 BB 00100000 MOV EBX,1000

  131480A7 68 B4801413 PUSH virus.131480B4 ; ASCII "ah"

  131480AC 68 59801413 PUSH virus.13148059

  131480B1 C2 0000 RETN 0

  131480B4 61 POPAD

  131480B5 68 00221413 PUSH virus.13142200

  131480BA 47 INC EDI

  131480BB 4F DEC EDI

  131480BC C3 RETN

  131480BD 0000 ADD BYTE PTR DS:[EAX],AL

  131480BF 0000 ADD BYTE PTR DS:[EAX],AL

  131480C1 0000 ADD BYTE PTR DS:[EAX],AL

  131480C3 0000 ADD BYTE PTR DS:[EAX],AL

  131480C5 0000 ADD BYTE PTR DS:[EAX],AL

  131480C7 0000 ADD BYTE PTR DS:[EAX],AL

  131480C9 0000 ADD BYTE PTR DS:[EAX],AL

  .

  .

  13148FF8 0000 ADD BYTE PTR DS:[EAX],AL

  13148FFA 0000 ADD BYTE PTR DS:[EAX],AL

  13148FFC 0000 ADD BYTE PTR DS:[EAX],AL

  13148FFE 0000 ADD BYTE PTR DS:[EAX],AL

  (11):返回后来到这里,这个就是病毒样本的真正OEP入口了,看入口代码的结构像汇编写的。使用OD插件DUMP出来就可以了,输入表在DUMP过程中被脱壳插件自动修复了,脱壳后的样本可以正常运行(代码如下)。

  13142200 55 PUSH EBP ; ntdll.7C930738

  13142201 8BEC MOV EBP,ESP

  13142203 81EC 0C050000 SUB ESP,50C

  13142209 57 PUSH EDI

  1314220A 6A 00 PUSH 0

  1314220C 68 68531413 PUSH virus.13145368 ; ASCII "YINWSAFDWPEIRPWIEIHENANRENQUANSHILAJIHAOGUOAZHINALDAOJFAGZHIXIANLFALFJAAUFOPWLAJLFJALJFA"

  13142211 68 34531413 PUSH virus.13145334 ; ASCII "TIANYAWEISHENMEHENANLAOCHUPIANZIPEPWUAPREPAJIERPW"

  13142216 6A FF PUSH -1

  13142218 FF15 28311413 CALL DWORD PTR DS:[13143128] ; USER32.MessageBoxA

  1314221E E8 4DFFFFFF CALL virus.13142170

  13142223 85C0 TEST EAX,EAX

  13142225 74 13 JE SHORT virus.1314223A

  13142227 68 00531413 PUSH virus.13145300 ; ASCII "FINDINFILESFINDINFILESFNAJIUGANDIAOTAMENBAHEHEHE"

  1314222C FF15 84301413 CALL DWORD PTR DS:[13143084] ; virus.1314911F

  13142232 6A 00 PUSH 0

  13142234 FF15 BC301413 CALL DWORD PTR DS:[131430BC] ; virus.1314912E

  ---------------------------------------------------------------------------------------------

  第二部分:难点分析

  其实这个壳只要了解了其原理,脱起来就简单多了。关键点就是要找出它内部出现的三处异常处理代码的位置,这是脱整个壳的关键。

  大概说下“PEtite”壳的原理:

  (1):壳在一开始运行时先是在内存中解密要执行的代码,解密完毕后使用“内存访问异常”(第一处异常)来离开解密循环,然后在异常处理代码中执行后面的所有操作。

  (2):接着壳大概设置了一部分堆栈和寄存器环境变量,然后创建了一个“单步异常”(第二处异常)。这个异常的异常处理代码中有另一部分对堆栈和寄存器环境变量的设置,而“单步异常”可以使用[F8]单步直接执行过去,并且不会执行内部的异常处理代码,所以这样就做到反动态单步跟踪了。如果这样执行过去的话,由于一部分堆栈和寄存器环境变量没有得到有效的设置,所以就无法对程序去进行正确的动态跟踪了。

  (3):在内存中动态解密并修复输入表。

  (4):创建一个“INT 2D异常”(第三处异常),这个异常不会被“Ollydbg”自动识别并执行。也就是说不管你怎么做,“Ollydbg”都不会去自动寻找并执行“INT 2D异常”所产生的异常处理代码。这里就需要我们自己去看堆栈并寻找异常处理代码位置,自己去设置代码当前的EIP地址,然后从“INT 2D异常”的异常处理代码入口处开始执行剩下的操作,这样这个壳就脱完了(好象只有1到3点属于“PEtite”壳,这个第4点是被后加进来的)。

  原理看似简单,但如果自己去跟的话,如果不细心或经验不足,很多细节都会被忽略掉的。其中,“单步异常”的异常处理代码我是用内存断点定位出来的,不知道堆栈中为什么就看不到对它设置的地址呢?可能同样是在某处被秘密的隐藏起来了。就像第一处异常的异常处理代码就是在壳入口的附近创建的,看样子作者在设计这个壳时可是花去了不少的心思啊,呵呵!

联系方式:QQ:6084884 email:agwcn@126.com 粤ICP备05055782号
本网站中发布的文章只代表发表人的个人观点,不代表安迪教程网网站的立场
copyright© 2000-2004 安迪教程网 All rights reserved agwcn.com