雷石|病毒样本分析
2024-1-12 09:3:30 Author: 雷石安全实验室(查看原文) 阅读量:15 收藏

一个简单的病毒样本,病毒样本呈现了相对基础但具有潜在危害的汇编代码结构。从逐句分析汇编代码的角度来看,病毒的主要行为主要包括以下几个方面:

01.

内存操作

接下来的汇编代码分析表明,通过将值1C(28)压入堆栈,可能为缓冲区的大小,然后将 ebp-1C 的值赋给 eax 寄存器,病毒准备调用 VirtualQuery 函数来获取指定地址的内存信息。这一步是病毒行为的关键部分,其目的可能是为了探查系统内存的状态以执行后续的操作。

00401B9A  |.  6A 1C         push    1C                               ; /BufSize = 1C (28.)00401B9C  |.  8D45 E4       lea     eax, dword ptr [ebp-1C]          ; |00401B9F  |.  50            push    eax                              ; |Buffer00401BA0  |.  FF75 E0       push    dword ptr [ebp-20]               ; |Address0401BA3  |.  FF15 2C914000 call    dword ptr [<&KERNEL32.VirtualQue>; \VirtualQuery00401BA9  |.  8B45 E8       mov     eax, dword ptr [ebp-18]          ;  VirTualQuery获取内存信息

这里是微软的接口文档对他的解释:

https://learn.microsoft.com/zh-cn/windows/win32/api/memoryapi/nf-memoryapi-virtualquery

结构如下:

SIZE_T VirtualQuery(  LPCVOID                   lpAddress,  PMEMORY_BASIC_INFORMATION lpBuffer,  SIZE_T                    dwLength);

     在 VirtualQuery 函数的参数中,lpAddress 通常是待查询的内存地址,lpBuffer 是用于存储返回信息的缓冲区,而 dwLength 表示缓冲区的长度。病毒代码中将 ebp-1C 的值(可能是缓冲区的指针)传递给 VirtualQuery 函数,以便获取特定内存地址的详细信息。这种行为可能有助于病毒了解系统内存结构,识别可用的空间,或者为进一步的攻击做准备。这种手法表明病毒利用操作系统提供的 API 来执行具体的系统调用,这种方式通常能够绕过一些安全防御机制。

02.

模块基址检查

     随后的汇编代码显示,将 eax 寄存器的值移动到内存地址 40DC38 处,可能是为了将先前获取的内存信息进行缓存。同时,将值 0 压入堆栈,然后调用 GetModuleHandleA 函数。此函数在系统中扮演着获取模块句柄的角色,用于判断程序是否发生了重载、卸载等情况。

     详细而言,通过 GetModuleHandleA 函数,病毒获取当前程序的模块句柄。这个模块句柄可以用于识别程序的加载状态。如果获取到的模块句柄与之前缓存的内存信息不相等,这可能意味着程序已经发生了变化,可能会触发一些退出线程或重新加载的操作。这种检测程序状态的方式有助于病毒适应环境的变化,可能是为了提高存活性或逃避检测。

     接下来的代码段中,病毒使用了 GetInputState 函数,该函数确定当前线程的消息队列中是否有需要处理的鼠标和键盘消息。通过调用 PostThreadMessageA 函数,发送 WM_NULL 消息给当前线程,可能是为了唤醒线程以执行消息队列中的任务。这种操作可能是为了在后续的代码中实施更高级的行为。

00401BAC  |.  A3 38DC4000   mov     dword ptr [40DC38], eax00401BB1  |.  6A 00         push    0                                ; /pModule = NULL00401BB3  |.  FF15 04914000 call    dword ptr [<&KERNEL32.GetModuleH>; \GetModuleHandleA00401BB9  |.  3B05 38DC4000 cmp     eax, dword ptr [40DC38]          ;  GetModuleHandle获取当前模块基址00401BBF  |.  75 16         jnz     short 00401BD7                   ;  两者比较,不要相等则退出线程00402056   .  FF15 14924000 call    dword ptr [<&USER32.GetInputStat>; [GetInputState0040205C   .  6A 00         push    0                                ; /lParam = 00040205E   .  6A 00         push    0                                ; |wParam = 000402060   .  6A 00         push    0                                ; |Message = WM_NULL00402062   .  FF15 48914000 call    dword ptr [<&KERNEL32.GetCurrent>; |[GetCurrentThreadId00402068   .  50            push    eax                              ; |ThreadId00402069   .  FF15 18924000 call    dword ptr [<&USER32.PostThreadMe>; \PostThreadMessageA0040206F   .  6A 00         push    0                                ; /MsgFilterMax = 000402071   .  6A 00         push    0                                ; |MsgFilterMin = 000402073   .  6A 00         push    0                                ; |hWnd = NULL00402075   .  8D85 BCFDFFFF lea     eax, dword ptr [ebp-244]         ; |0040207B   .  50            push    eax                              ; |pMsg0040207C   .  FF15 0C924000 call    dword ptr [<&USER32.GetMessageA>>; \GetMessageA004064B4  |.  68 04010000   push    104                              ; /BufSize = 104 (260.)004064B9  |.  8D85 D8FDFFFF lea     eax, dword ptr [ebp-228]         ; |004064BF  |.  50            push    eax                              ; |PathBuffer004064C0  |.  6A 00         push    0                                ; |hModule = NULL004064C2  |.  FF15 00914000 call    dword ptr [<&KERNEL32.GetModuleF>; \GetModuleFileNameA004064C8  |.  68 04010000   push    104                              ; /获取当前路径004064CD  |.  6A 00         push    0                                ; |c = 00004064CF  |.  8D85 E0FEFFFF lea     eax, dword ptr [ebp-120]         ; |004064D5  |.  50            push    eax                              ; |s004064D6  |.  E8 67290000   call    <jmp.&MSVCRT.memset>             ; \memset

 最后,通过调用GetModuleFileNameA 函数获取了当前程序的路径,这可能用于病毒的信息搜集或隐藏。整体而言,这段代码表明病毒通过操作系统 API 来监控程序状态、处理消息队列,以及获取当前程序的路径信息,这些都是其后续行为的基础。

03.

病毒破坏阶段

     接下来的汇编代码揭示了程序使用 memset 分配了一个大小为 3 字节的内存,并通过 API 将内存内容提取出来,同时保留了原来路径的三个字节。这个过程实际上是提取之前获取的路径信息中的前三个字节,即磁盘的盘符。这一步的目的可能是为了对路径信息进行进一步的处理和识别。

004064D6  |.  E8 67290000   call    <jmp.&MSVCRT.memset>             ; \memset004064DB  |.  83C4 0C       add     esp, 0C004064DE  |.  8D85 D8FDFFFF lea     eax, dword ptr [ebp-228]004064E4  |.  50            push    eax                              ; /String2004064E5  |.  8D85 E0FEFFFF lea     eax, dword ptr [ebp-120]         ; |004064EB  |.  50            push    eax                              ; |String1004064EC  |.  FF15 1C914000 call    dword ptr [<&KERNEL32.lstrcpyA>] ; \lstrcpyA004064F2  |.  68 01010000   push    101                              ; /n = 101 (257.)004064F7  |.  6A 00         push    0                                ; |c = 00004064F9  |.  8D85 E3FEFFFF lea     eax, dword ptr [ebp-11D]         ; |004064FF  |.  50            push    eax                              ; |s00406500  |.  E8 3D290000   call    <jmp.&MSVCRT.memset>             ; \memset00406505  |.  83C4 0C       add     esp, 0C                          ;  保留路径前三个字节

     随后,病毒通过对这个路径信息进行解析,并调用 GetDriveType 函数来判断磁盘的类型。这个函数用于确定磁盘驱动器是可移动的、固定的、CD-ROM、RAM 磁盘,还是网络驱动器。如果磁盘类型为2(可移动磁盘),则程序跳转到地址 00406553。

     在 00406553 地址处,代码片段通过调用 wsprintfA 函数进行字符串的格式化,其中包含 explorer.exe 的路径。wsprintfA 函数用于将格式化的数据写入字符缓冲区。在这里,通过将路径信息和其他字符串组合成一个新的字符串,病毒可能在后续操作中使用这个新的路径字符串。

0040650F  |.  FF15 A4904000 call    dword ptr [<&KERNEL32.GetDriveTy>; \GetDriveTypeA00406515  |.  83F8 02       cmp     eax, 2                           ;  判断当前磁盘类型00406518  |.  75 39         jnz     short 00406553                   ;  -------------------------------------------0040651A  |.  8D85 E0FEFFFF lea     eax, dword ptr [ebp-120]00406520  |.  50            push    eax                              ; /<%s>00406521  |.  68 A09A4000   push    00409AA0                         ; |Format = "/n,%s"00406526  |.  8D85 98FDFFFF lea     eax, dword ptr [ebp-268]         ; |0040652C  |.  50            push    eax                              ; |s0040652D  |.  FF15 10924000 call    dword ptr [<&USER32.wsprintfA>]  ; \wsprintfA00406533  |.  83C4 0C       add     esp, 0C00406536  |.  6A 05         push    5                                ; /IsShown = 500406538  |.  6A 00         push    0                                ; |DefDir = NULL0040653A  |.  8D85 98FDFFFF lea     eax, dword ptr [ebp-268]         ; |00406540  |.  50            push    eax                              ; |Parameters00406541  |.  68 A89A4000   push    00409AA8                         ; |FileName = "explorer.exe"00406546  |.  68 B89A4000   push    00409AB8                         ; |Operation = "open"0040654B  |.  6A 00         push    0                                ; |hWnd = NULL0040654D  |.  FF15 E4914000 call    dword ptr [<&SHELL32.ShellExecut>; \ShellExecuteA00406553  |>  C745 EC C09A4>mov     dword ptr [ebp-14], 00409AC0     ;  ------------如果为移动磁盘则打开explorer-----00401681  |> \6A 00         push    0                                ; /hTemplateFile = NULL00401683  |.  68 80000000   push    80                               ; |Attributes = NORMAL00401688  |.  FFB5 E8FEFFFF push    dword ptr [ebp-118]              ; |Mode0040168E  |.  6A 00         push    0                                ; |pSecurity = NULL

    最后,通过调用 ShellExecuteA 函数,程序打开了资源管理器(explorer.exe)。这个步骤引起了关注,因为通常普通程序通过操作系统提供的 API 或其他适当的手段来实现其功能,而不直接调用 explorer.exe。这种直接调用系统资源管理器的方式可能是可疑的,因为它可能允许程序执行一些具有破坏性的操作,例如结束或修改进程,对主机进行文件写入等操作。

本文作者:西瓜麻辣烫

雷石安全实验室

商务咨询:

0571-87031601

商务邮箱:

[email protected]


文章来源: http://mp.weixin.qq.com/s?__biz=MzI5MDE0MjQ1NQ==&mid=2247525920&idx=1&sn=d757b7c9ba3250357503cdeef42ab684&chksm=ed43bc474317b7cec6cf23d80424edc5f43f6f775339fc63a51d4e4ee528e4c89c478de94b96&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh