大华摄像头-CVE-2021-33044漏洞研究

固件下载地址:Firmwares (dahuasecurity.com)

下载固件的时候,提及一下这几种类别:

1、IPC:IPC即IP-CAMERA,是集成视频服务器和摄像机的功能为一体的数字视频设备;IP-CAMERA网络摄像机一般有内置Web服务的数字摄像机和录音设备,直接与以太网(有线、无线)相连。用户可通过标准Web浏览器观看和收听网络摄像机传送过来的视频和声音。

2、视频服务器(DVS):采用数字压缩算法,实现音视频信息的数字压缩和网络传输与控制设备。视频服务器一般为嵌入式视频服务器设备,采用嵌入式CPU的硬件设计,体积小,结构方便,一般有为1路、2路和4路音视频输入,有些可以实现双向对讲功能。目前有些DVS设备也可以内置小容量的硬盘。

3、数字视频录像机(DVR): DVR即是Digital Video Recorder,数字视频录像机或数字硬盘录像机,我们习惯上称为硬盘录像机。结合标准接口的数字存储介质,采用数字压缩算法,实现音视频信息的数字记录、监视与回放,并可带有系统控制功能的视频设备或视频网络传输与监控的设备(一般带有独有的功能操控面板)。目前韩国、台湾的DVR产品在全球市场上占有很高的市场份额,有PC工控机式的,也有嵌入式的,高路数方面PC的多以些,低路数上嵌入式的多一些。韩国以PC为主,台湾以低路数的嵌入式为主。中国大陆的DVR也有PC式和嵌入式的。以前的DVR是不带联网功能的,以本地监控为主。根据用户的要求和技术的发展,目前不少厂家的DVR设备也具有了联网能力,根据用户的要求,带联网功能的DVR一般在本地观看和存储的是D1格式的图像,上传到中心的图像是CIF格式的。一般DVR输入不超过16路,尽量不要让DVR同时工作在不间断录像和网络传输应用之中。

4、网络数字硬盘录像机(NVR):NVR即是Network Video Recorder,网络数字硬盘录像机,与DVR的不同点在于,DVR前端是接模拟摄像头,而NVR前端是接网络摄像头;在图像压缩传输方面,NVR比DVR要清晰的多,可以达到高清,信号传输也比DVR流畅;有些NVR也兼容DVR的功能。

image-20211015110352756

选择IPC,2021年6月份之前的(后面才知道官网已经下架旧固件的下载地址了,我这里是先找的修复过的固件,看看)

image-20211012102225244

对web-x.squashfs.bin提取

binwalk -Me web-x.squashfs.bin

image-20211012155634680

对下面列表得文件进行逆向分析

image-20211012160057872

因为我也是第一次接触js,看js的代码,不太了解web开发,所以全部看我肯定更懵了,我就按照CVE所说的clientType有问题,直接搜索clientType,发现只有三个文件是带有这个字符串的

image-20211013095730155

打开是没有代码格式化的,非常乱,我们需要做一下代码格式化再分析

image-20211013095816712

我们用网站的工具进行解码:Javascript在线解压缩_js加密解密混淆 (gjk.cn),将代码格式化

image-20211013095938618

下面这个就是POC所说的Global.login啦,但是发现这里并没有验证,毕竟是前端,只是用一个结构体去存储用户的登录信息,说明验证登录信息的应该在后端,所以这里面应该是没有,但是我们接下来的思路应该是去找谁调用了这个函数(global.login)或者说是这个结构体变量会在后端哪出现,然后看它是如何做验证的

image-20211013104946480

下载下来的固件还有另一个我没有去提取,上面的是关于web的,所以接下来我尝试去binwalk另外一个

image-20211013110047649

image-20211013110004906

提取结果

image-20211013113542185

用grep命令去找global.login,发现有两个二进制文件,aolDaemon和sonia

image-20211013155529302

分析sonia放入ida中分析,在字符串里面搜索global.login,修复过的固件版本NetKeyboard是搜索不到的

image-20211013160059638

找到调用global.login函数的地址

image-20211013160157054

这里发现,clientType直接被赋值为了CGI,没有让用户有输入修改clientType的机会,此固件的确已经修复了clientType

真正的分析开始:从https://files.dahua.support/Firmware/Kamery%20-IP-%20sta%C5%82opozycyjne/EcoSavvy3.0%20%28Pro%29/Stare/?MA上下载了一个旧的固件进行分析QAQ

image-20211014180226040

按照前面的套路,binwalk解包,这次能直接搜到NetKeyboard了,并且也是在sonia中

image-20211014200605920

找到global.login的位置,对sonia逆向分析

image-20211015111013597

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
int __fastcall sub_150330(int a1, int a2, int a3)
{
...

v5 = (unsigned __int8 *)sub_5D88E0(a3, (int)"method");
sub_5D77CA((int)v37, (int)"global.login");
sub_5D8386(v5, (unsigned __int8 *)v37);
sub_5D7EF2(v37, v6);
v7 = sub_5D88E0(a3, (int)"params");
v8 = (unsigned __int8 *)sub_5D88E0(v7, (int)"userName");
v9 = sub_5D7F94(a2, (int)"userName");
sub_5D7918(v37, v9);
sub_5D7876(v36, v37);
sub_5D8386(v8, (unsigned __int8 *)v36);
sub_5D7EF2(v36, v10);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v37);
v11 = sub_5D88E0(a3, (int)"params");
v12 = (unsigned __int8 *)sub_5D88E0(v11, (int)"password");
v13 = sub_5D7F94(a2, (int)"password");
sub_5D7918(v37, v13);
sub_5D7876(v36, v37);
sub_5D8386(v12, (unsigned __int8 *)v36);
sub_5D7EF2(v36, v14);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v37);
if ( sub_5D806C(a2, (int)"clientType") )
{
v15 = sub_5D7F94(a2, (int)"clientType");
if ( sub_5D7C86((int)v15) )
{
v16 = sub_5D88E0(a3, (int)"params");
v17 = (unsigned __int8 *)sub_5D88E0(v16, (int)"clientType");
v18 = sub_5D7F94(a2, (int)"clientType");
sub_5D7918(v37, v18);
sub_5D7876(v36, v37);
sub_5D8386(v17, (unsigned __int8 *)v36);
sub_5D7EF2(v36, v19);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v37);
}
}
if ( sub_5D806C(a2, (int)"authorityType") )
{
v20 = sub_5D7F94(a2, (int)"authorityType");
if ( sub_5D7C86((int)v20) )
{
v21 = sub_5D88E0(a3, (int)"params");
v22 = (unsigned __int8 *)sub_5D88E0(v21, (int)"authorityType");
v23 = sub_5D7F94(a2, (int)"authorityType");
sub_5D7918(v37, v23);
sub_5D7876(v36, v37);
sub_5D8386(v22, (unsigned __int8 *)v36);
sub_5D7EF2(v36, v24);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v37);
}
}
if ( sub_5D806C(a2, (int)"passwordType") )
{
v25 = sub_5D7F94(a2, (int)"passwordType");
if ( sub_5D7C86((int)v25) )
{
v26 = sub_5D88E0(a3, (int)"params");
v27 = (unsigned __int8 *)sub_5D88E0(v26, (int)"passwordType");
v28 = sub_5D7F94(a2, (int)"passwordType");
sub_5D7918(v37, v28);
sub_5D7876(v36, v37);
sub_5D8386(v27, (unsigned __int8 *)v36);
sub_5D7EF2(v36, v29);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v37);
}
}
if ( sub_5D806C(a2, (int)"clientAddress") )
{
v30 = sub_5D7F94(a2, (int)"clientAddress");
if ( sub_5D7C86((int)v30) )
{
v31 = sub_5D88E0(a3, (int)"params");
v32 = (unsigned __int8 *)sub_5D88E0(v31, (int)"ipAddr");
v33 = sub_5D7F94(a2, (int)"clientAddress");
sub_5D7918(v37, v33);
sub_5D7876(v36, v37);
sub_5D8386(v32, (unsigned __int8 *)v36);
sub_5D7EF2(v36, v34);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v37);
}
}
return 1;
}

直接搜索NetKeyboard分析

image-20211015113309952

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
145
146
147
148
149
150
151
int __fastcall sub_14149E(int a1)
{
......
if ( v18 )
{
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v39, v18 + 8);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v47, v19 + 32);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v41, v47);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v47);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v48, v19 + 84);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v43, v48);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v48);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v49, v19 + 108);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v45, v49);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v49);
}
sub_4CB734(
5,
"libDVRIP-404300",
"%s::%s:%d name = %s, password = %s \n",
"Src/Cmds_NetKeyBoard.cpp",
"NetKeyBoardLogin",
918,
v39[0],
v41[0]);
memset(v50, 0, sizeof(v50));
v50[0] = (int)"127.0.0.1";
v50[2] = (int)v39[0];
v50[3] = (int)v41[0];
HIWORD(v50[5]) = 5000;
v50[6] = (int)"NetKeyBoard";
v50[7] = *(_DWORD *)(a1 + 4) + 132596;
v50[11] = v43[0];
v50[8] = v45[0];
if ( !*(_DWORD *)(a1 + 56) )
{
v33 = 0;
v20 = sub_141E80(&Dahua::Component::ClassID::local, &Dahua::Component::ServerInfo::none, &v33);
if ( v20 )
{
v21 = (*(int (__fastcall **)(int, int *))(*(_DWORD *)v20 + 12))(v20, v50);
v22 = v33;
v23 = (void *)sub_4D7DC4(v21);
if ( v23 )
v23 = _dynamic_cast(
v23,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IUnknown,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IClient,
0);
v36 = v23;
v37 = v22;
}
else
{
v36 = 0;
v37 = 0;
}
sub_141DE8(a1 + 56, &v36);
sub_F30C0(&v36);
}
v24 = *(_DWORD *)(a1 + 56);
if ( v24 )
{
v25 = sub_12FCE4(a1 + 56);
if ( (*(int (__fastcall **)(int))(*(_DWORD *)v25 + 24))(v25) )
{
v26 = sub_12FCE4(a1 + 56);
v24 = (*(int (__fastcall **)(int))(*(_DWORD *)v26 + 28))(v26);
}
else
{
v24 = 1;
}
}
sub_4CB734(
5,
"libDVRIP-404300",
"%s::%s:%d loginSuccess = %d \n",
"Src/Cmds_NetKeyBoard.cpp",
"NetKeyBoardLogin",
950,
v24);
if ( v24 )
{
*(_BYTE *)(a1 + 38) = 1;
v27 = *(_BYTE *)(*(_DWORD *)(a1 + 16) + 20);
}
else
{
sub_4CB734(5, "libDVRIP-404300", "CmdsNetKeyBoard::NetKeyBoardLogin>>>>>login user failed\n");
*(_BYTE *)(a1 + 38) = 0;
v27 = 2;
}
*(_BYTE *)(a1 + 40) = v27;
v28 = a1 + 34;
v29 = 0;
do
{
v30 = *(_BYTE *)++v28;
v29 += v30;
}
while ( v28 != a1 + 41 );
*(_BYTE *)(a1 + 42) = v29;
v31 = sub_F3512(a1, **(_DWORD **)(a1 + 8), a1 + 20, 0, 500000);
if ( v31 < 0 )
{
sub_4CB734(5, "libDVRIP-404300", "%s(%d)--", "Src/Cmds_NetKeyBoard.cpp", 979);
sub_4CB734(5, "libDVRIP-404300", "SBM Error(%d).\n", v31);
}
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v45);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v43);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v41);
v15 = (int *)v39;
goto LABEL_34;
}
v7 = sub_F3442(a1, **(_DWORD **)(a1 + 8));
v8 = v7;
if ( v7 )
{
v50[0] = (int)&v50[2];
v50[1] = 0;
LOBYTE(v50[2]) = 0;
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v50, v7 + 8);
sub_F30D4(v8);
sub_5D774C(v49, 0);
v9 = sub_64324(&v34);
(*(void (__fastcall **)(int, int *, _DWORD *))(*(_DWORD *)v9 + 72))(v9, v50, v49);
v10 = sub_5D88E0((int)v49, (int)"Group");
sub_5D7918(v38, v10);
v11 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(v38, "admin");
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v38);
if ( !v11 )
{
v13 = sub_64324(&v34);
(*(void (__fastcall **)(int, int *))(*(_DWORD *)v13 + 60))(v13, v50);
}
if ( *(_DWORD *)(a1 + 56) )
{
v14 = sub_12FCE4(a1 + 56);
(*(void (__fastcall **)(int))(*(_DWORD *)v14 + 32))(v14);
}
sub_5D7EF2(v49, v12);
v15 = v50;
LABEL_34:
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v15);
v8 = 0;
}
LABEL_39:
sub_64310(&v34);
return v8;
}
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
int __fastcall sub_14149E(int a1)
{
const void *v2; // r0
void *v3; // r0
int v4; // r0
int v5; // r7
void *v6; // r0
int v7; // r0
int v8; // r6
int v9; // r0
int v10; // r0
int v11; // r6
int v12; // r1
int v13; // r0
int v14; // r0
int *v15; // r0
int *v16; // r3
int v17; // r1
int v18; // r0
int v19; // r7
int v20; // r0
int v21; // r0
int v22; // r5
void *v23; // r0
int v24; // r5
int v25; // r0
int v26; // r0
char v27; // r3
int v28; // r2
char v29; // r3
char v30; // t1
int v31; // r4
int v33; // [sp+14h] [bp-16Ch] BYREF
void *v34; // [sp+18h] [bp-168h] BYREF
int v35; // [sp+1Ch] [bp-164h]
void *v36; // [sp+20h] [bp-160h] BYREF
int v37; // [sp+24h] [bp-15Ch]
char v38[24]; // [sp+28h] [bp-158h] BYREF
const char *v39[2]; // [sp+40h] [bp-140h] BYREF
char v40; // [sp+48h] [bp-138h] BYREF
const char *v41[2]; // [sp+58h] [bp-128h] BYREF
char v42; // [sp+60h] [bp-120h] BYREF
int v43[2]; // [sp+70h] [bp-110h] BYREF
char v44; // [sp+78h] [bp-108h] BYREF
int v45[2]; // [sp+88h] [bp-F8h] BYREF
char v46; // [sp+90h] [bp-F0h] BYREF
char v47[24]; // [sp+A0h] [bp-E0h] BYREF
char v48[24]; // [sp+B8h] [bp-C8h] BYREF
_DWORD v49[6]; // [sp+D0h] [bp-B0h] BYREF
int v50[32]; // [sp+E8h] [bp-98h] BYREF

v50[0] = 0;
v2 = (const void *)sub_4D68E4(
"UserManager",
&Dahua::Component::ClassID::local,
&Dahua::Component::ServerInfo::none,
v50);
if ( v2
&& (v3 = _dynamic_cast(
v2,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IFactoryUnknown,
(const struct __class_type_info *)&`typeinfo for'Dahua::Manager::IUserManager::IFactory,
0)) != 0 )
{
v4 = (*(int (__fastcall **)(void *))(*(_DWORD *)v3 + 12))(v3);
v5 = v50[0];
v6 = (void *)sub_4D7DF4(v4);
if ( v6 )
v6 = _dynamic_cast(
v6,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IUnknown,
(const struct __class_type_info *)&`typeinfo for'Dahua::Manager::IUserManager,
0);
v34 = v6;
v35 = v5;
}
else
{
v34 = 0;
v35 = 0;
}
if ( !v34 )
{
return_f(
2,
"libDVRIP-404300",
"%s::%s:%d Failed to get user manager component!\n",
"Src/Cmds_NetKeyBoard.cpp",
"NetKeyBoardLogin",
747);
v8 = -1;
goto LABEL_39;
}
if ( *(unsigned __int8 *)(*(_DWORD *)(a1 + 16) + 20) != 255 )
{
memset((void *)(a1 + 20), 0, 0x20u);
*(_BYTE *)(a1 + 23) = 104;
*(_BYTE *)(a1 + 20) = -104;
*(_BYTE *)(a1 + 35) = -112;
*(_BYTE *)(a1 + 36) = -1;
*(_BYTE *)(a1 + 37) = -2;
v39[0] = &v40;
v40 = 0;
v42 = 0;
v44 = 0;
v46 = 0;
v39[1] = 0;
v41[1] = 0;
v43[1] = 0;
v45[1] = 0;
v16 = *(int **)(a1 + 8);
v41[0] = &v42;
v43[0] = (int)&v44;
v17 = *v16;
v45[0] = (int)&v46;
v18 = sub_F3442(a1, v17);
v19 = v18;
if ( v18 )
{
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v39, v18 + 8);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v47, v19 + 32);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v41, v47);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v47);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v48, v19 + 84);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v43, v48);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v48);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v49, v19 + 108);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v45, v49);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v49);
}
return_f(
5,
"libDVRIP-404300",
"%s::%s:%d name = %s, password = %s \n",
"Src/Cmds_NetKeyBoard.cpp",
"NetKeyBoardLogin",
918,
v39[0],
v41[0]);
memset(v50, 0, sizeof(v50));
v50[0] = (int)"127.0.0.1";
v50[2] = (int)v39[0];
v50[3] = (int)v41[0];
HIWORD(v50[5]) = 5000;
v50[6] = (int)"NetKeyBoard";
v50[7] = *(_DWORD *)(a1 + 4) + 132596;
v50[11] = v43[0];
v50[8] = v45[0];
if ( !*(_DWORD *)(a1 + 56) )
{
v33 = 0;
v20 = sub_141E80(&Dahua::Component::ClassID::local, &Dahua::Component::ServerInfo::none, &v33);
if ( v20 )
{
v21 = (*(int (__fastcall **)(int, int *))(*(_DWORD *)v20 + 12))(v20, v50);
v22 = v33;
v23 = (void *)sub_4D7DC4(v21);
if ( v23 )
v23 = _dynamic_cast(
v23,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IUnknown,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IClient,
0);
v36 = v23;
v37 = v22;
}
else
{
v36 = 0;
v37 = 0;
}
sub_141DE8(a1 + 56, &v36);
sub_F30C0(&v36);
}
v24 = *(_DWORD *)(a1 + 56);
if ( v24 )
{
v25 = sub_12FCE4(a1 + 56);
if ( (*(int (__fastcall **)(int))(*(_DWORD *)v25 + 24))(v25) )
{
v26 = sub_12FCE4(a1 + 56);
v24 = (*(int (__fastcall **)(int))(*(_DWORD *)v26 + 28))(v26);
}
else
{
v24 = 1;
}
}
return_f(
5,
"libDVRIP-404300",
"%s::%s:%d loginSuccess = %d \n",
"Src/Cmds_NetKeyBoard.cpp",
"NetKeyBoardLogin",
950,
v24);
if ( v24 )
{
*(_BYTE *)(a1 + 38) = 1;
v27 = *(_BYTE *)(*(_DWORD *)(a1 + 16) + 20);
}
else
{
return_f(5, "libDVRIP-404300", "CmdsNetKeyBoard::NetKeyBoardLogin>>>>>login user failed\n");
*(_BYTE *)(a1 + 38) = 0;
v27 = 2;
}
*(_BYTE *)(a1 + 40) = v27;
v28 = a1 + 34;
v29 = 0;
do
{
v30 = *(_BYTE *)++v28;
v29 += v30;
}
while ( v28 != a1 + 41 );
*(_BYTE *)(a1 + 42) = v29;
v31 = sub_F3512(a1, **(_DWORD **)(a1 + 8), a1 + 20, 0, 500000);
if ( v31 < 0 )
{
return_f(5, "libDVRIP-404300", "%s(%d)--", "Src/Cmds_NetKeyBoard.cpp", 979);
return_f(5, "libDVRIP-404300", "SBM Error(%d).\n", v31);
}
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v45);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v43);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v41);
v15 = (int *)v39;
goto LABEL_34;
}
v7 = sub_F3442(a1, **(_DWORD **)(a1 + 8));
v8 = v7;
if ( v7 )
{
v50[0] = (int)&v50[2];
v50[1] = 0;
LOBYTE(v50[2]) = 0;
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v50, v7 + 8);
sub_F30D4(v8);
sub_5D774C(v49, 0);
v9 = sub_64324(&v34);
(*(void (__fastcall **)(int, int *, _DWORD *))(*(_DWORD *)v9 + 72))(v9, v50, v49);
v10 = sub_5D88E0((int)v49, (int)"Group");
sub_5D7918(v38, v10);
v11 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(v38, "admin");
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v38);
if ( !v11 )
{
v13 = sub_64324(&v34);
(*(void (__fastcall **)(int, int *))(*(_DWORD *)v13 + 60))(v13, v50);
}
if ( *(_DWORD *)(a1 + 56) )
{
v14 = sub_12FCE4(a1 + 56);
(*(void (__fastcall **)(int))(*(_DWORD *)v14 + 32))(v14);
}
sub_5D7EF2(v49, v12);
v15 = v50;
LABEL_34:
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v15);
v8 = 0;
}
LABEL_39:
sub_64310(&v34);
return v8;
}
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
int __fastcall sub_14149E(int a1)
{
const void *v2; // r0
void *v3; // r0
int v4; // r0
int v5; // r7
void *v6; // r0
int v7; // r0
int v8; // r6
int v9; // r0
int v10; // r0
int v11; // r6
int v12; // r1
int v13; // r0
int v14; // r0
int *v15; // r0
int *v16; // r3
int v17; // r1
int v18; // r0
int v19; // r7
int v20; // r0
int v21; // r0
int v22; // r5
void *v23; // r0
int v24; // r5
int v25; // r0
int v26; // r0
char v27; // r3
int v28; // r2
char v29; // r3
char v30; // t1
int v31; // r4
int v33; // [sp+14h] [bp-16Ch] BYREF
void *v34; // [sp+18h] [bp-168h] BYREF
int v35; // [sp+1Ch] [bp-164h]
void *v36; // [sp+20h] [bp-160h] BYREF
int v37; // [sp+24h] [bp-15Ch]
char v38[24]; // [sp+28h] [bp-158h] BYREF
const char *v39[2]; // [sp+40h] [bp-140h] BYREF
char v40; // [sp+48h] [bp-138h] BYREF
const char *v41[2]; // [sp+58h] [bp-128h] BYREF
char v42; // [sp+60h] [bp-120h] BYREF
int v43[2]; // [sp+70h] [bp-110h] BYREF
char v44; // [sp+78h] [bp-108h] BYREF
int v45[2]; // [sp+88h] [bp-F8h] BYREF
char v46; // [sp+90h] [bp-F0h] BYREF
char v47[24]; // [sp+A0h] [bp-E0h] BYREF
char v48[24]; // [sp+B8h] [bp-C8h] BYREF
_DWORD v49[6]; // [sp+D0h] [bp-B0h] BYREF
int v50[32]; // [sp+E8h] [bp-98h] BYREF

v50[0] = 0;
v2 = (const void *)sub_4D68E4(
"UserManager",
&Dahua::Component::ClassID::local,
&Dahua::Component::ServerInfo::none,
v50);
if ( v2
&& (v3 = _dynamic_cast(
v2,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IFactoryUnknown,
(const struct __class_type_info *)&`typeinfo for'Dahua::Manager::IUserManager::IFactory,
0)) != 0 )
{
v4 = (*(int (__fastcall **)(void *))(*(_DWORD *)v3 + 12))(v3);
v5 = v50[0];
v6 = (void *)sub_4D7DF4(v4);
if ( v6 )
v6 = _dynamic_cast(
v6,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IUnknown,
(const struct __class_type_info *)&`typeinfo for'Dahua::Manager::IUserManager,
0);
v34 = v6;
v35 = v5;
}
else
{
v34 = 0;
v35 = 0;
}
if ( !v34 )
{
sub_4CB734(
2,
"libDVRIP-404300",
"%s::%s:%d Failed to get user manager component!\n",
"Src/Cmds_NetKeyBoard.cpp",
"NetKeyBoardLogin",
747);
v8 = -1;
goto LABEL_39;
}
if ( *(unsigned __int8 *)(*(_DWORD *)(a1 + 16) + 20) != 255 )
{
memset((void *)(a1 + 20), 0, 0x20u);
*(_BYTE *)(a1 + 23) = 104;
*(_BYTE *)(a1 + 20) = -104;
*(_BYTE *)(a1 + 35) = -112;
*(_BYTE *)(a1 + 36) = -1;
*(_BYTE *)(a1 + 37) = -2;
v39[0] = &v40;
v40 = 0;
v42 = 0;
v44 = 0;
v46 = 0;
v39[1] = 0;
v41[1] = 0;
v43[1] = 0;
v45[1] = 0;
v16 = *(int **)(a1 + 8);
v41[0] = &v42;
v43[0] = (int)&v44;
v17 = *v16;
v45[0] = (int)&v46;
v18 = sub_F3442(a1, v17);
v19 = v18;
if ( v18 )
{
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v39, v18 + 8);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v47, v19 + 32);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v41, v47);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v47);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v48, v19 + 84);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v43, v48);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v48);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v49, v19 + 108);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v45, v49);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v49);
}
sub_4CB734(
5,
"libDVRIP-404300",
"%s::%s:%d name = %s, password = %s \n",
"Src/Cmds_NetKeyBoard.cpp",
"NetKeyBoardLogin",
918,
v39[0],
v41[0]);
memset(v50, 0, sizeof(v50));
v50[0] = (int)"127.0.0.1";
v50[2] = (int)v39[0];
v50[3] = (int)v41[0];
HIWORD(v50[5]) = 5000;
v50[6] = (int)"NetKeyBoard";
v50[7] = *(_DWORD *)(a1 + 4) + 132596;
v50[11] = v43[0];
v50[8] = v45[0];
if ( !*(_DWORD *)(a1 + 56) )
{
v33 = 0;
v20 = sub_141E80(&Dahua::Component::ClassID::local, &Dahua::Component::ServerInfo::none, &v33);
if ( v20 )
{
v21 = (*(int (__fastcall **)(int, int *))(*(_DWORD *)v20 + 12))(v20, v50);
v22 = v33;
v23 = (void *)sub_4D7DC4(v21);
if ( v23 )
v23 = _dynamic_cast(
v23,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IUnknown,
(const struct __class_type_info *)&`typeinfo for'Dahua::Component::IClient,
0);
v36 = v23;
v37 = v22;
}
else
{
v36 = 0;
v37 = 0;
}
sub_141DE8(a1 + 56, &v36);
sub_F30C0(&v36);
}
v24 = *(_DWORD *)(a1 + 56);
if ( v24 )
{
v25 = sub_12FCE4(a1 + 56);
if ( (*(int (__fastcall **)(int))(*(_DWORD *)v25 + 24))(v25) )
{
v26 = sub_12FCE4(a1 + 56);
v24 = (*(int (__fastcall **)(int))(*(_DWORD *)v26 + 28))(v26);
}
else
{
v24 = 1;
}
}
sub_4CB734(
5,
"libDVRIP-404300",
"%s::%s:%d loginSuccess = %d \n",
"Src/Cmds_NetKeyBoard.cpp",
"NetKeyBoardLogin",
950,
v24);
if ( v24 )
{
*(_BYTE *)(a1 + 38) = 1;
v27 = *(_BYTE *)(*(_DWORD *)(a1 + 16) + 20);
}
else
{
sub_4CB734(5, "libDVRIP-404300", "CmdsNetKeyBoard::NetKeyBoardLogin>>>>>login user failed\n");
*(_BYTE *)(a1 + 38) = 0;
v27 = 2;
}
*(_BYTE *)(a1 + 40) = v27;
v28 = a1 + 34;
v29 = 0;
do
{
v30 = *(_BYTE *)++v28;
v29 += v30;
}
while ( v28 != a1 + 41 );
*(_BYTE *)(a1 + 42) = v29;
v31 = sub_F3512(a1, **(_DWORD **)(a1 + 8), a1 + 20, 0, 500000);
if ( v31 < 0 )
{
sub_4CB734(5, "libDVRIP-404300", "%s(%d)--", "Src/Cmds_NetKeyBoard.cpp", 979);
sub_4CB734(5, "libDVRIP-404300", "SBM Error(%d).\n", v31);
}
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v45);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v43);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v41);
v15 = (int *)v39;
goto LABEL_34;
}
v7 = sub_F3442(a1, **(_DWORD **)(a1 + 8));
v8 = v7;
if ( v7 )
{
v50[0] = (int)&v50[2];
v50[1] = 0;
LOBYTE(v50[2]) = 0;
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_assign(v50, v7 + 8);
sub_F30D4(v8);
sub_5D774C(v49, 0);
v9 = sub_64324(&v34);
(*(void (__fastcall **)(int, int *, _DWORD *))(*(_DWORD *)v9 + 72))(v9, v50, v49);
v10 = sub_5D88E0((int)v49, (int)"Group");
sub_5D7918(v38, v10);
v11 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(v38, "admin");
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v38);
if ( !v11 )
{
v13 = sub_64324(&v34);
(*(void (__fastcall **)(int, int *))(*(_DWORD *)v13 + 60))(v13, v50);
}
if ( *(_DWORD *)(a1 + 56) )
{
v14 = sub_12FCE4(a1 + 56);
(*(void (__fastcall **)(int))(*(_DWORD *)v14 + 32))(v14);
}
sub_5D7EF2(v49, v12);
v15 = v50;
LABEL_34:
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose(v15);
v8 = 0;
}
LABEL_39:
sub_64310(&v34);
return v8;
}

漏洞复现:

下载DahuaConsole

git clone https://github.com/mcw0/Dahua Console.git

image-20211014115215894

安装DahuaConsole

pip3 install -r .\requirements.txt

image-20211014115241252