简单DDos木马的样本分析

没有介绍

0x01 详细分析

首先还是先看该PE文件的导入表,可以看到它导入了 ADVAPI32这个dll,调用的函数有 CreateServiceA/ StartServiceCtrlDispatcherA/OpenSCManagerA ,这三个函数对于初学者来说还是比较陌生的

1
2
3
CreateServiceA:创建服务对象并将其添加到指定的服务控制管理器数据库。创建成功,返回该服务的句柄,失败返回NULL
StartServiceCtrlDispatcherA:将服务进程的主线程连接到服务控制管理器,使得线程成为调用进程的服务控制调度程序线程。成功返回非0,否则返回0
OpenSCManagerA:建立与服务控制管理器的连接,并打开指定的服务控制管理器数据库

image-20211029003952951

这两个函数就耳熟能详了。

image-20211029004703633

大致看下它的字符串,大概可以猜测出是请求该域名并下载数据流,还可能用IE8.0的代理

image-20211029005721849

下面就去分析 main 函数

401028处调用了StartServiceCtrlDispatcherA函数,通常这个函数会立即被调用,前面是传入的参数,其中传入了 401040,这是StartServiceCtrlDispatcherA指定的服务控制管理器会调用的服务控制函数。整个主函数的流程是这样,貌似只创建了一个服务,别急,我们接着继续分析

image-20211029011021411

接着去调用 401040处的函数,在这里面又调用了 OpenMutexA函数,清空eax寄存器,跳转到401064处。OpenMutexA会打开一个已有的互斥量句柄,看前面传入的参数,互斥量的名字是“HGL345”,如果函数调用成功,程序退出。

1
互斥量是windows的一个内核对象,互斥量与关键段的作用相似,可以用来确保全局资源的互斥访问。并且互斥量可以用在不同的进程中的线程互斥访问全局资源。更多关于互斥量,自行了解操作系统的进程与线程管理

image-20211029011001886

来看下401064这段汇编代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
loc_401064:                             ; CODE XREF: sub_401040+1A↑j
.text:00401064 push esi
.text:00401065 push offset Name ; "HGL345"
.text:0040106A push 0 ; bInitialOwner
.text:0040106C push 0 ; lpMutexAttributes
.text:0040106E call ds:CreateMutexA
.text:00401074 push 3 ; dwDesiredAccess
.text:00401076 push 0 ; lpDatabaseName
.text:00401078 push 0 ; lpMachineName
.text:0040107A call ds:OpenSCManagerA
.text:00401080 mov esi, eax
.text:00401082 call ds:GetCurrentProcess
.text:00401088 lea eax, [esp+404h+Filename]
.text:0040108C push 3E8h ; nSize
.text:00401091 push eax ; lpFilename
.text:00401092 push 0 ; hModule
.text:00401094 call ds:GetModuleFileNameA
.text:0040109A push 0 ; lpPassword
.text:0040109C push 0 ; lpServiceStartName
.text:0040109E push 0 ; lpDependencies
.text:004010A0 push 0 ; lpdwTagId
.text:004010A2 lea ecx, [esp+414h+Filename]
.text:004010A6 push 0 ; lpLoadOrderGroup
.text:004010A8 push ecx ; lpBinaryPathName
.text:004010A9 push 0 ; dwErrorControl
.text:004010AB push 2 ; dwStartType
.text:004010AD push 10h ; dwServiceType
.text:004010AF push 2 ; dwDesiredAccess
.text:004010B1 push offset DisplayName ; "Malservice"
.text:004010B6 push offset DisplayName ; "Malservice"
.text:004010BB push esi ; hSCManager
.text:004010BC call ds:CreateServiceA
.text:004010C2 xor edx, edx
.text:004010C4 lea eax, [esp+404h+FileTime]
.text:004010C8 mov dword ptr [esp+404h+SystemTime.wYear], edx
.text:004010CC lea ecx, [esp+404h+SystemTime]
.text:004010D0 mov dword ptr [esp+404h+SystemTime.wDayOfWeek], edx
.text:004010D4 push eax ; lpFileTime
.text:004010D5 mov dword ptr [esp+408h+SystemTime.wHour], edx
.text:004010D9 push ecx ; lpSystemTime
.text:004010DA mov dword ptr [esp+40Ch+SystemTime.wSecond], edx
.text:004010DE mov [esp+40Ch+SystemTime.wYear], 834h
.text:004010E5 call ds:SystemTimeToFileTime
.text:004010EB push 0 ; lpTimerName
.text:004010ED push 0 ; bManualReset
.text:004010EF push 0 ; lpTimerAttributes
.text:004010F1 call ds:CreateWaitableTimerA
.text:004010F7 push 0 ; fResume
.text:004010F9 push 0 ; lpArgToCompletionRoutine
.text:004010FB push 0 ; pfnCompletionRoutine
.text:004010FD lea edx, [esp+410h+FileTime]
.text:00401101 mov esi, eax
.text:00401103 push 0 ; lPeriod
.text:00401105 push edx ; lpDueTime
.text:00401106 push esi ; hTimer
.text:00401107 call ds:SetWaitableTimer
.text:0040110D push 0FFFFFFFFh ; dwMilliseconds
.text:0040110F push esi ; hHandle
.text:00401110 call ds:WaitForSingleObject
.text:00401116 test eax, eax
.text:00401118 jnz short loc_40113B
.text:0040111A push edi
.text:0040111B mov edi, ds:CreateThread
.text:00401121 mov esi, 14h
.text:00401126

可以看到这段地址调用了很多函数

1
2
3
4
5
6
7
8
9
10
CreateMutexA:创建互斥量
OpenSCManagerA:建立与服务控制管理器的连接,并打开指定的服务控制管理器数据库
GetCurrentProcess:返回当前进程的伪句柄,也可以理解为过渡句柄
GetModuleFileNameA:获取包含一个特定模块的文件的全路径,这个模块必须是由当前运行的进程
CreateServiceA:创建服务对象
SystemTimeToFileTime:将系统时间转换为UTC文件时间
CreateWaitableTimerA:创建计时器对象,与下个函数结合使用
SetWaitableTimer:启动计时器对象
WaitForSingleObject:多线程的情况下,等待其他线程执行完后再执行
CreateThread:创建线程

整体分析这段地址, 在40106E处创建了一个名为”HGL345”的互斥量。所以现在有一对两个互斥量,分别是OpenMutexCreateMutex 获取的,这两个互斥量被设计用来保证这个程序在任意时刻只有一份实例在内存中运行,如果已经在运行,那么对 OpenMutex 的第一次调用成功,程序退出。

接着调用 OpenSCManagerA 函数,打开一个服务控制管理器的句柄,为了让该程序可以添加或修改服务。然后调用 GetModuleFileNameA,返回当前PE文件(该exe或者被加载的dll文件)的路径,这个路径接下来被CreateServiceA调用,来创建一个服务对象。CreateServiceA的关键参数是 4010A8处的BinaryPathName4010AB处的dwStartType4010AD处的 dwServiceType。对于 dwStartType来说,它的值可能是下面几个。而在这个程序中,push 入栈的是 2,对应的 SERVICE_AUTO_START,即开机自启。

image-20211029100527973

关于为什么需要调用 GetModuleFileName,获得当前程序的路径,因为它想要创建服务对象,需要一个路径,而该程序并不知道自己的路径在哪,所以需要动态的获取当前路径,来创建服务,这样就不用考虑该恶意程序的执行路径了。

SystemTimeToFileTime:这是一个关于时间的结构体。注意到在 4010DE处,表示年的值被设置为 0x0834即2100年。

接着调用 CreateWaitableTimerA/ SetWaitableTimer/ WaitForSingleObject函数,注意到传给 SetWaitableTimer的参数是 lpDueTime,溯源下这个参数,是SystemTimeToFileTime返回的 FileTime,也就是转换后的2100年。所以传给WaitForSingleObject的参数是2100年,也就是说程序会等待到2100年。

下面到 401126这里,很明显的看出这是一个循环函数。在进入 401126之前,esi 的值被设置为14h(20d),接着调用 CreateThread函数,然后 esi递减,直到 esi 为0时才会退出,否则一直循环,也就是说会创建20个线程。还注意到 CreateTHread函数的参数有6个,其中5个被设置为空,只有 lpStartAddress被传入了 StartAddress

image-20211030013644987

f5看下伪代码,是个do-while循环

image-20211030020205336

跳转到 StartAddress这里,看到它调用了 InTernetOpenA 函数用来初始化网络连接,并且使用IE8代理。并且接下来还会循环调用 InternetOpenUrlA,传入的参数是 401178处的域名。并且这个跳转的指令是 jmp 无条件跳转,也就是说这段循环不会终止,会一直去访问 http://www.malwareanalysisbook.com。还有前面创建了20个线程,一直持续的访问一个网站,造成资源拥堵……到这里木马的行为已经很明显了吧,就是DDos攻击。

image-20211030015044384

总结

这个程序创建一个互斥量来保证同一时刻只有一个实例在运行,然后创建一个自启动服务,接着进入等待到2100年,开始创建20个线程访问目标站点,造成DDos攻击。

Peace.