Author:**k0Sh1**
### 漏洞复现
Network Scanner是一款扫描工具,其中有一个针对域名扫描的功能,但是这个功能对加载的字符串没有进行严格的控制,比如Textbox长度控制,或者长度校验导致如果不输入域名,而是改输入一个超长字符串,则会导致执行任意代码,下面对此漏洞进行详细分析。
首先生成一个畸形字符串,按照exploit-db上的方法在域名位置加载这个字符串,程序崩溃,直接执行会由于SEH到达eip可控位置。
```
0:002> g
(af4.de8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0012f564 ebx=00eeb690 ecx=006e6304 edx=41414141 esi=0012f590 edi=00f11c20
eip=00406e58 esp=0012f370 ebp=0012f568 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210206
*** WARNING: Unable to verify checksum for C:\Documents and Settings\Administrator\桌面\8a419b10772d811ce5eea44cb88ae55b-
NetScan\NetScanner.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Documents and Settings\Administrator\桌面
\8a419b10772d811ce5eea44cb88ae55b-NetScan\NetScanner.exe
NetScanner+0x6e58:
00406e58 8b4af8 mov ecx,dword ptr [edx-8] ds:0023:41414139=????????
0:000> g
(af4.de8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=41414141 edx=7c9232bc esi=00000000 edi=00000000
eip=41414141 esp=0012efa0 ebp=0012efc0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210246
41414141 ?? ???
```
通过kb回溯堆栈调用
```
0:000> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f568 41414141 41414141 41414141 00004141 NetScanner+0x6e4c
0012f598 0044f2a6 014b9050 004ee572 0012f774 0x41414141
0012f70c 004d8865 0012f958 00e846d0 00000000 NetScanner+0x4f2a6
0012f758 0047fb85 00e846d0 0012f958 00e846d0 NetScanner+0xd8865
0012f784 004d89b8 000f0304 0012f9d0 00e5ea60 NetScanner+0x7fb85
0012f8d4 004d8865 0104096f 00e5ea60 00469847 NetScanner+0xd89b8
0012f920 004d7f03 0012f934 004d7f1b 0012f950 NetScanner+0xd8865
0012f950 0044f952 00000111 00000304 000f0304 NetScanner+0xd7f03
```
这个堆栈回溯作用并不是很大,因为只有一个exe,这个exe中很多GUI的MFC的内容以及功能函数都封装在程序里,而回溯中很多函数调用会涉及到在GUI加载调用功能函数,所以会不易命中想要到达的位置。
### 漏洞分析
在分析的过程中,我找到了关于GUI界面中处理域名的关键部分。
```
if ( (unsigned __int8)sub_4B79E8(&v23, L"Example: www.atlas.cz, www.google.com") )
{
sub_5FE3CC(v3, &v22);
if ( v22 )
{
if ( (unsigned __int8)sub_4B79E8(&v22, &off_6CD7BC) )
{
sub_5FDF0C(&v20, 0);
sub_407F04(v4, v20);
v21 = sub_5FE01C(v14, v15, v16, v17);
BYTE3(v21) = 0;
sub_5FE118(v5, &v19);
v6 = *(_DWORD *)(v2 + 1648);
sub_4D26E0(v7, v19);
v21 = sub_5FE01C(v14, v15, v16, v17);
BYTE3(v21) = -2;
sub_5FE118(v8, &v18);
v9 = *(_DWORD *)(v2 + 1652);
sub_4D26E0(v10, v18);
}
}
```
处理部分关键的字符串已经打印出来了,会调用到函数sub_4B79E8,这个函数就是处理GUI窗口中负责传入畸形字符串的部分,接下来如果接收到了域名字符串后,会调用sub_5fdf0c函数。
```
0:002> g
Breakpoint 1 hit
eax=0171b6dc ebx=00eeb690 ecx=00f40c48 edx=0012f590 esi=004ee99c edi=00f11c20
eip=006cd614 esp=0012f570 ebp=0012f598 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
NetScanner+0x2cd614:
006cd614 e8b30df3ff call NetScanner+0x1fe3cc (005fe3cc)
```
跟进这个函数,这个函数中处理的是和域名字符串,在这里是畸形字符串的连接。调用了WSA的函数开始处理。
```
int __usercall sub_5FE3CC@<eax>(int a1@<eax>, int *a2@<edx>)
{
v18 = 0;
v19 = 0;
v20 = 0;
v2 = a2;
v23 = a1;
sub_407E98();
v16 = &savedregs;
v15 = &loc_5FE508;
v14 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v14);
sub_407EB0(v3, 0);
sub_4169E0(v4, &v20);
if ( v20 )
{
WSAStartup(0x101u, &WSAData);
sub_408104(0, v23);
sub_418BF4();
v5 = gethostbyname(&name);
if ( v5 )
{
v6 = v5->h_addr_list;
for ( i = 0; v6[i]; ++i )
{
v8 = *v2;
v9 = inet_ntoa(*(struct in_addr *)v6[i]);
sub_40803C(v10, v9);
sub_408478(v11, 3, &dword_5FE524, v18, v8);
}
v17 = *v2;
v12 = v17;
if ( v17 )
v12 = *(_DWORD *)(v17 - 4);
sub_408770(1, v12);
WSACleanup();
}
}
__writefsdword(0, v14);
sub_407EA0(&loc_5FE50F);
sub_406E4C(&v19);
sub_407EA0(v16);
}
```
跟进这个函数,可以看到WSAStartup之后,会调用给一个名为sub_418BF4的函数,在这个函数中,会调用拷贝畸形字符串,而在这个过程没有对畸形字符串进行控制,导致溢出,来看一下这个函数的内容。
```
int __fastcall sub_418BF4(int a1, int a2)
{
v10 = a2;
sub_40759C();
v9 = &savedregs;
v8 = &loc_418C6A;
v7 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v7);
v2 = v10;
if ( v10 && *(_WORD *)(v10 - 10) != 1 )
v2 = sub_407068(0, v10);
v3 = v2;
if ( v2 )
v3 = *(_DWORD *)(v2 - 4);
v4 = sub_4075AC();
v5 = sub_418B84(v3, v4);
```
在函数中会调用到sub_418b84函数,这个函数中会处理畸形字符串,并执行拷贝,来看一下这个函数的内容。
```
_BYTE *__usercall sub_418B84@<eax>(_BYTE *result@<eax>, _BYTE *a2@<edx>, int a3@<ecx>)
{
_BYTE *v3; // edi@1
int v4; // ebx@1
bool v5; // zf@1
unsigned int v6; // ebx@6
char *v7; // edi@6
int v8; // ecx@6
v3 = a2;
v4 = a3;
v5 = a3 == 0;
if ( a3 )
{
do
{
if ( !a3 )
break;
v5 = *v3++ == 0;
--a3;
}
while ( !v5 );
if ( v5 )
++a3;
}
v6 = v4 - a3;
qmemcpy(result, a2, 4 * (v6 >> 2));
v7 = &result[4 * (v6 >> 2)];
v8 = v6 & 3;
qmemcpy(v7, &a2[4 * (v6 >> 2)], v8);
v7[v8] = 0;
return result;
}
```
这个函数中执行了qmemcpy,这个拷贝会造成栈溢出覆盖到关键指针,来跟踪一下覆盖的时候。
```
0:000> g
Breakpoint 1 hit
eax=0012f500 ebx=00000048 ecx=00000001 edx=0012f524 esi=01a0efa0 edi=0012f568
eip=00418ba5 esp=0012f33c ebp=0012f364 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00210206
NetScanner+0x18ba5:
00418ba5 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] es:0023:0012f568=0012f598 ds:0023:01a0efa0=41414141
0:000> dd 0012f564
0012f564 41414141 0012f598 006cd619 0012f928
```
这里执行了拷贝,可以看到0012f564位置的关键指针被覆盖,随后返回后,回到最外层函数调用,紧接着调用了gethostbyname,这个函数明显是由于域名不能获取信息,导致后面的if语句判断不通过。
```
0:000> p
eax=0012f524 ebx=00eeb690 ecx=00000000 edx=01a0ef5c esi=0012f590 edi=00f11c20
eip=005fe461 esp=0012f368 ebp=0012f568 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
NetScanner+0x1fe461:
005fe461 e80e42f1ff call NetScanner+0x112674 (00512674)
0:000> p
eax=00000000 ebx=00eeb690 ecx=0000b5f7 edx=00290001 esi=0012f590 edi=00f11c20
eip=005fe466 esp=0012f36c ebp=0012f568 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200246
NetScanner+0x1fe466:
005fe466 85c0 test eax,eax
0:000> p
eax=00000000 ebx=00eeb690 ecx=0000b5f7 edx=00290001 esi=0012f590 edi=00f11c20
eip=005fe468 esp=0012f36c ebp=0012f568 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200246
NetScanner+0x1fe468:
005fe468 7467 je NetScanner+0x1fe4d1 (005fe4d1) [br=1]
0:000> p
eax=00000000 ebx=00eeb690 ecx=0000b5f7 edx=00290001 esi=0012f590 edi=00f11c20
eip=005fe4d1 esp=0012f36c ebp=0012f568 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200246
NetScanner+0x1fe4d1:
005fe4d1 33c0 xor eax,eax
```
这里je是if跳转不通过,进入到后面的WSACleanup处理,退出,随后会调用到另一个函数。
```
0:000> p
eax=0012f390 ebx=00eeb690 ecx=006e62e4 edx=01716c70 esi=0012f590 edi=00f11c20
eip=005fe4ff esp=0012f374 ebp=0012f568 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200246
NetScanner+0x1fe4ff:
005fe4ff 8d45fc lea eax,[ebp-4]
0:000> p
eax=0012f564 ebx=00eeb690 ecx=006e62e4 edx=01716c70 esi=0012f590 edi=00f11c20
eip=005fe502 esp=0012f374 ebp=0012f568 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200246
NetScanner+0x1fe502:
005fe502 e89999e0ff call NetScanner+0x7ea0 (00407ea0)
0:000> dc eax
0012f564 41414141 41414141 006cd600 0012f928 AAAAAAAA..l.(...
```
此时eax作为一个指针已经被覆盖了,随后会由于指针引用,导致异常触发,SEH异常处理,通过覆盖SEH指针,达到代码执行。
```
0:000> p
eax=0012f564 ebx=00eeb690 ecx=006e6304 edx=41414141 esi=0012f590 edi=00f11c20
eip=00406e4e esp=0012f370 ebp=0012f568 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200246
NetScanner+0x6e4e:
00406e4e 85d2 test edx,edx
0:000> p
eax=0012f564 ebx=00eeb690 ecx=006e6304 edx=41414141 esi=0012f590 edi=00f11c20
eip=00406e50 esp=0012f370 ebp=0012f568 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206
NetScanner+0x6e50:
00406e50 741c je NetScanner+0x6e6e (00406e6e) [br=0]
0:000> p
eax=0012f564 ebx=00eeb690 ecx=006e6304 edx=41414141 esi=0012f590 edi=00f11c20
eip=00406e52 esp=0012f370 ebp=0012f568 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206
NetScanner+0x6e52:
00406e52 c70000000000 mov dword ptr [eax],0 ds:0023:0012f564=41414141
0:000> p
eax=0012f564 ebx=00eeb690 ecx=006e6304 edx=41414141 esi=0012f590 edi=00f11c20
eip=00406e58 esp=0012f370 ebp=0012f568 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206
NetScanner+0x6e58:
00406e58 8b4af8 mov ecx,dword ptr [edx-8] ds:0023:41414139=????????
```
暂无评论