MS11-011漏洞分析
早就想分析一下傳說中的長(zhǎng)老漏洞,不過因?yàn)殚_學(xué)的原因,各種事情,一直沒有時(shí)間,這兩天抽時(shí)間把漏洞的分析做完了,本來還計(jì)劃研究一下利用代碼和補(bǔ)丁,但是現(xiàn)在不得不放棄了,現(xiàn)把自己的分析過程貼出來,逆向和語文能力都不怎么樣,有描述不清之處,請(qǐng)見諒,同時(shí)歡迎各位大牛拍磚,但請(qǐng)盡量溫柔!
以下內(nèi)容全部是個(gè)人理解,無法保證其正確性,僅供參考!!!
測(cè)試環(huán)境:Windows 7
測(cè)試工具:VMWare + Windbg + IDA
首先下載漏洞的利用程序,在虛擬機(jī)中測(cè)試一下,發(fā)現(xiàn)程序可以正常運(yùn)行:
代碼:
C:\>whoami
q-test\qever
C:\>poc
C:\>whoami
nt authority\system
下面開始尋找漏洞的成因。
為了減少工作量,應(yīng)該盡可能地確定漏洞產(chǎn)生的準(zhǔn)確位置,在這里采用的方法是在poc的源代碼的shellcode起始位置添加0xcc,對(duì)應(yīng)的是"int 3"指令,這樣shellcode一運(yùn)行,就會(huì)立刻斷下來,然后就可以進(jìn)行分析了。
修改過程就不廢話了,直接運(yùn)行修改后的程序,當(dāng)windbg斷下來之后,查看調(diào)用堆棧,卻發(fā)現(xiàn)調(diào)用堆棧被破壞了
代碼:
kd> k
ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
00000000 00000000 0x3d0000
此時(shí)可以通過對(duì)當(dāng)前棧進(jìn)行分析粗略估計(jì)出錯(cuò)位置。當(dāng)然,還有一種比較好的方法,考慮到程序可以正常執(zhí)行,故shellcode運(yùn)行完畢后必定會(huì)返回調(diào)用位置,那么在shellcode返回位置下斷,運(yùn)行再次斷下來之后查看堆棧可以得到
代碼:
kd> k
ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
92639d14 994bb8d0 0x3d0096
92639d28 83c7f42a win32k!GreEnableEUDC+0x7c
92639d28 772964f4 nt!KiFastCallEntry+0x12a
看到上面的信息,再結(jié)合poc源碼中的漏洞觸發(fā)代碼,就能確定問題就是出現(xiàn)在win32k!GreEnableEUDC函數(shù)里面了,那么就從它開始分析查找漏洞成因吧!
為了減少工作量,這里采用了一種比較笨的方法,多次嘗試來準(zhǔn)確判定出錯(cuò)原因及位置。過程如下:
在win32k!GreEnableEUDC處下斷點(diǎn),運(yùn)行修改后的程序,然后單步跟蹤,直至觸發(fā)shellcode中"int 3"指令,多次嘗試之后可以確定如下調(diào)用信息:
代碼:
win32k!GreEnableEUDC+0x77 : call win32k!BuildAndLoadLinkedFontRoutine+0xeb
win32k!BuildAndLoadLinkedFontRoutine+0x19d : call win32k!bAppendSysDirectory+0x209
win32k!bAppendSysDirectory+0x334 : ret 8 //出錯(cuò)!
即在調(diào)用win32k!bAppendSysDirectory+0x209函數(shù)之后返回時(shí)跳入shellcode,同時(shí)在返回時(shí)查看堆棧可以發(fā)現(xiàn)返回地址被修改了,也就是說在該函數(shù)運(yùn)行過程中棧空間被修改,即棧溢出。
結(jié)合網(wǎng)上的信息,多次嘗試后可以確定整個(gè)漏洞的產(chǎn)生流程:
代碼:
nt!KiFastCallEntry+0x128 : call ebx (win32k!GreEnableEUDC)
win32k!GreEnableEUDC+0x77 : call win32k!BuildAndLoadLinkedFontRoutine+0xeb
win32k!BuildAndLoadLinkedFontRoutine+0x19d : call win32k!bAppendSysDirectory+0x209
win32k!bAppendSysDirectory+0x2de : call dword ptr [win32k!_imp__RtlQueryRegistryValues (9972f104)]
nt!RtlQueryRegistryValues+0x318 : call nt!RtlpCallQueryRegistryRoutine (83e2ab81)
nt!RtlpCallQueryRegistryRoutine+0x290 : call nt!RtlpQueryRegistryDirect (83e33997)
nt!RtlpQueryRegistryDirect+3D : call nt!memcpy (83c797a0) //溢出
win32k!bAppendSysDirectory+0x334 : ret 8 //出錯(cuò)!
那么只要分析上面所列出函數(shù)的行為,就應(yīng)該能確定漏洞的成因了。
接下來我們挨個(gè)來分析以上函數(shù),實(shí)際分析過程中是Windbg動(dòng)態(tài)調(diào)試和IDA靜態(tài)分析同時(shí)進(jìn)行的,在此為了書寫方便,僅對(duì)Windbg代碼進(jìn)行分析。
對(duì)于win32k!GreEnableEUDC,涉及到一些不知道什么意思的變量,不過并不影響分析過程。
代碼:
win32k!GreEnableEUDC+0x37:
9956b88b 33f6 xor esi,esi //esi清零
9956b88d 46 inc esi //esi == 1
……
win32k!GreEnableEUDC+0x75:
9956b8c9 56 push esi //參數(shù)壓棧
9956b8ca 56 push esi //參數(shù)壓棧
9956b8cb e8b8faffff call win32k!BuildAndLoadLinkedFontRoutine+0xeb (9956b388)
在此只簡(jiǎn)單提一下,調(diào)用參數(shù)均為1,畢竟漏洞產(chǎn)生的原因并不在此。
這個(gè)函數(shù)應(yīng)該是對(duì)應(yīng)poc源碼中的EnableEUDC(TRUE);一句,EUDC就不解釋了,因?yàn)闆]找到好的中文資料,附上微軟的介紹:
http://msdn.microsoft.com/zh-cn/library/ms900737.aspx
根據(jù)前面的分析,要關(guān)注win32k!BuildAndLoadLinkedFontRoutine+0xeb函數(shù),所以這里重點(diǎn)列出該函數(shù)的兩個(gè)參數(shù),均為1。
下面來看BuildAndLoadLinkedFontRoutine+0xeb函數(shù),這個(gè)函數(shù)中也沒有什么重點(diǎn)內(nèi)容,依舊是列出參數(shù),和調(diào)用語句。
代碼:
995cb393 be08020000 mov esi,208h
995cb398 56 push esi
995cb399 8d4dfc lea ecx,[ebp-4]
995cb39c e8a6030000 call win32k!MALLOCOBJ::MALLOCOBJ (995cb747) //生成MALLOCOBJ對(duì)象
……
995cb3aa 8b5dfc mov ebx,dword ptr [ebp-4]
……
995cb434 6804010000 push 104h
995cb439 53 push ebx
995cb43a e8a0050000 call win32k!bAppendSysDirectory+0x209 (995cb9df)
win32k!bAppendSysDirectory+0x209 函數(shù)的兩個(gè)參數(shù),依次是MALLOCOBJ對(duì)象指針和0x104。
關(guān)于win32k!MALLOCOBJ,個(gè)人感覺就像一個(gè)字符串的類,而在整個(gè)漏洞分析過程中,該對(duì)象也是扮演了一個(gè)字符串的角色,同時(shí)在內(nèi)存起始位置記錄了字符串信息。
下面這個(gè)win32k!bAppendSysDirectory+0x209函數(shù)就比較關(guān)鍵了,最終出錯(cuò)也是在這個(gè)函數(shù)當(dāng)中,先看代碼:
代碼:
win32k!bAppendSysDirectory+0x209:
9955b9df 8bff mov edi,edi
9955b9e1 55 push ebp
9955b9e2 8bec mov ebp,esp
9955b9e4 83ec20 sub esp,20h
9955b9e7 53 push ebx
9955b9e8 56 push esi
9955b9e9 57 push edi
9955b9ea be08020000 mov esi,208h
9955b9ef 56 push esi
9955b9f0 8d4df4 lea ecx,[ebp-0Ch] //ebp-0Ch為MALLOCOBJ對(duì)象指針
9955b9f3 e84ffdffff call win32k!MALLOCOBJ::MALLOCOBJ (9955b747)
9955b9f8 56 push esi
9955b9f9 8d4dfc lea ecx,[ebp-4] //ebp-4為MALLOCOBJ對(duì)象指針
9955b9fc e846fdffff call win32k!MALLOCOBJ::MALLOCOBJ (9955b747)
9955ba01 8b4df4 mov ecx,dword ptr [ebp-0Ch]
9955ba04 33f6 xor esi,esi //esi == 0
9955ba06 3bce cmp ecx,esi
9955ba08 0f84e6000000 je win32k!bAppendSysDirectory+0x31e (9955baf4)
win32k!bAppendSysDirectory+0x238:
9955ba0e 8b7dfc mov edi,dword ptr [ebp-4]
9955ba11 3bfe cmp edi,esi
9955ba13 0f84db000000 je win32k!bAppendSysDirectory+0x31e (9955baf4)
win32k!bAppendSysDirectory+0x243:
9955ba19 33c0 xor eax,eax
9955ba1b 8975f0 mov dword ptr [ebp-10h],esi
9955ba1e 8975ec mov dword ptr [ebp-14h],esi
9955ba21 668901 mov word ptr [ecx],ax
9955ba24 668907 mov word ptr [edi],ax
9955ba27 668945e0 mov word ptr [ebp-20h],ax
9955ba2b b804010000 mov eax,104h
9955ba30 50 push eax
9955ba31 8bd0 mov edx,eax
9955ba33 57 push edi
9955ba34 8975e8 mov dword ptr [ebp-18h],esi
9955ba37 668955e2 mov word ptr [ebp-1Eh],dx
9955ba3b 894de4 mov dword ptr [ebp-1Ch],ecx
9955ba3e e8d7feffff call win32k!GrePolyPolyline+0xa2 (9955b91a) //返回"\REGISTRY\USER\S-1-5-18\EUDC\936"
9955ba43 3bc6 cmp eax,esi
9955ba45 8945f8 mov dword ptr [ebp-8],eax
9955ba48 7c7c jl win32k!bAppendSysDirectory+0x2f0 (9955bac6)
上面這段代碼,首先生成MALLOCOBJ對(duì)象,通過調(diào)用win32k!GrePolyPolyline+0xa2函數(shù),返回"\REGISTRY\USER\S-1-5-18\EUDC\936",即需要查詢的注冊(cè)表項(xiàng)。
代碼:
win32k!bAppendSysDirectory+0x274:
9955ba4a 8d45e8 lea eax,[ebp-18h]
9955ba4d 50 push eax
9955ba4e 8d45ec lea eax,[ebp-14h]
9955ba51 50 push eax
9955ba52 8d45f0 lea eax,[ebp-10h]
9955ba55 50 push eax
9955ba56 57 push edi
9955ba57 e850010000 call win32k!AutoResource<&ExFreePool>::~AutoResource<&ExFreePool>+0x177 (9955bbac)
9955ba5c 85c0 test eax,eax
9955ba5e 745f je win32k!bAppendSysDirectory+0x2e9 (9955babf)
win32k!bAppendSysDirectory+0x28a:
9955ba60 3975e8 cmp dword ptr [ebp-18h],esi
9955ba63 745a je win32k!bAppendSysDirectory+0x2e9 (9955babf)
這段代碼是打醬油的~~
代碼:
win32k!bAppendSysDirectory+0x28f:
9955ba65 56 push esi
9955ba66 56 push esi
9955ba67 68e0887599 push offset win32k!SharedQueryTable (997588e0)
9955ba6c 57 push edi //"\REGISTRY\USER\S-1-5-18\EUDC\936"
9955ba6d 8d45e0 lea eax,[ebp-20h]
9955ba70 56 push esi
9955ba71 8935e0887599 mov dword ptr [win32k!SharedQueryTable (997588e0)],esi //0
9955ba77 c705e488759924000000 mov dword ptr [win32k!SharedQueryTable+0x4 (997588e4)],24h //24h
9955ba81 c705e888759964a67399 mov dword ptr [win32k!SharedQueryTable+0x8 (997588e8)],offset win32k!`string' (9973a664) //"SystemDefaultEUDCFont"
9955ba8b a3ec887599 mov dword ptr [win32k!SharedQueryTable+0xc (997588ec)],eax //指向函數(shù)棧的指針,最終出錯(cuò)也是因?yàn)檫@個(gè)參數(shù)
9955ba90 8935f0887599 mov dword ptr [win32k!SharedQueryTable+0x10 (997588f0)],esi //0
9955ba96 8935f4887599 mov dword ptr [win32k!SharedQueryTable+0x14 (997588f4)],esi //0
9955ba9c 8935f8887599 mov dword ptr [win32k!SharedQueryTable+0x18 (997588f8)],esi //0
9955baa2 8935fc887599 mov dword ptr [win32k!SharedQueryTable+0x1c (997588fc)],esi //0
9955baa8 893500897599 mov dword ptr [win32k!SharedQueryTable+0x20 (99758900)],esi //0
9955baae 893504897599 mov dword ptr [win32k!SharedQueryTable+0x24 (99758904)],esi //0
9955bab4 ff1504f17299 call dword ptr [win32k!_imp__RtlQueryRegistryValues (9972f104)]
上面是關(guān)鍵的RtlQueryRegistryValues函數(shù)調(diào)用,我們可以查到RtlQueryRegistryValues的定義:
代碼:
NTSTATUS
RtlQueryRegistryValues(
IN ULONG RelativeTo,
IN PCWSTR Path,
IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
IN PVOID Context,
IN PVOID Environment OPTIONAL
);
結(jié)合反匯編的結(jié)果,該函數(shù)的調(diào)用參數(shù):RelativeTo為0,即RTL_REGISTRY_ABSOLUTE,表示絕對(duì)路徑,Path值為"\REGISTRY\USER\S-1-5-18\EUDC\936",由win32k!GrePolyPolyline+0xa2函數(shù)返回。QueryTable參數(shù)的類型為PRTL_QUERY_REGISTRY_TABLE其定義如下:
代碼:
typedef struct _RTL_QUERY_REGISTRY_TABLE {
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine;
ULONG Flags;
PWSTR Name;
PVOID EntryContext;
ULONG DefaultType;
PVOID DefaultData;
ULONG DefaultLength;
} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
可能在Win7下對(duì)此結(jié)構(gòu)有一定的擴(kuò)充,不過并不影響分析。
Name值為"SystemDefaultEUDCFont",即要查詢的內(nèi)容。DefaultType會(huì)存儲(chǔ)查詢結(jié)果,其值為ebp-20h。其余參數(shù)為0。
事實(shí)上,對(duì)于了解RtlQueryRegistryValues函數(shù)的人來說,看到這里就已經(jīng)知道問題所在了,但是作為一次漏洞分析,如果僅僅止步于此的話,并不足以說明問題,按就讓我們接著看下去吧!
下面是RtlQueryRegistryValues函數(shù),這個(gè)函數(shù)內(nèi)容比較多,分段來解釋:
代碼:
kd> uf nt!RtlQueryRegistryValues
nt!RtlQueryRegistryValues:
83e32d85 8bff mov edi,edi
83e32d87 55 push ebp
83e32d88 8bec mov ebp,esp
83e32d8a 83e4f8 and esp,0FFFFFFF8h
83e32d8d 83ec4c sub esp,4Ch
83e32d90 8b4d0c mov ecx,dword ptr [ebp+0Ch] //exc == Path
83e32d93 53 push ebx
83e32d94 56 push esi
83e32d95 8b7508 mov esi,dword ptr [ebp+8] //esi == RelativeTo
83e32d98 57 push edi
83e32d99 8d442420 lea eax,[esp+20h] //eax == ebp - 0x3c esp == 9240fc30
83e32d9d 50 push eax
83e32d9e 33ff xor edi,edi //edi == 0
83e32da0 57 push edi
83e32da1 8bd6 mov edx,esi //edx == RelativeTo
83e32da3 e89f0a0000 call nt!RtlpGetRegistryHandle (83e33847) //打開"\REGISTRY\USER\S-1-5-18\EUDC\936"返回,返回值放入[ebp - 0x3c](KeyHandle)
83e32da8 3bc7 cmp eax,edi //eax ntStatus
83e32daa 8944240c mov dword ptr [esp+0Ch],eax //ebp=9240fc8c esp=9240fc30
83e32dae 0f8cf7030000 jl nt!RtlQueryRegistryValues+0x426 (83e331ab) 0
上面這一段,調(diào)用nt!RtlpGetRegistryHandle,跟進(jìn)之后可以發(fā)現(xiàn),函數(shù)內(nèi)部打開了注冊(cè)表"\REGISTRY\USER\S-1-5-18\EUDC\936"項(xiàng),并將句柄放入[ebp - 0x3c]中,為了表示方便,將其命名為KeyHandle。
代碼:
nt!RtlQueryRegistryValues+0x2f:
83e32db4 8974242c mov dword ptr [esp+2Ch],esi // esp + 2c == ebp - 30
83e32db8 8164242c00000040 and dword ptr [esp+2Ch],40000000h
83e32dc0 8d442438 lea eax,[esp+38h] // esp + 38 == ebp - 24
83e32dc4 7505 jne nt!RtlQueryRegistryValues+0x46 (83e32dcb)
nt!RtlQueryRegistryValues+0x41:
83e32dc6 ff750c push dword ptr [ebp+0Ch]
83e32dc9 eb01 jmp nt!RtlQueryRegistryValues+0x47 (83e32dcc)
//nt!RtlQueryRegistryValues+0x46:
//83e32dcb 57 push edi
nt!RtlQueryRegistryValues+0x47:
83e32dcc 50 push eax //ebp - 24
83e32dcd e81661e4ff call nt!RtlInitUnicodeString (83c78ee8) //ebp - 24 == Unicode_String_Path
83e32dd2 8d44240c lea eax,[esp+0Ch] //eax == ebp-50 status
83e32dd6 50 push eax
83e32dd7 57 push edi
83e32dd8 8d74242c lea esi,[esp+2Ch] //esi == ebp-38
83e32ddc c744242c84000000 mov dword ptr [esp+2Ch],84h
83e32de4 e8d782ffff call nt!RtlpAllocDeallocQueryBuffer (83e2b0c0) //用esi傳參,函數(shù)內(nèi)執(zhí)行ExAllocatePoolWithTag(1,0x84,0x76727152)
83e32de9 8bf0 mov esi,eax //esi指向申請(qǐng)空間首地址
83e32deb 3bf7 cmp esi,edi
83e32ded 7518 jne nt!RtlQueryRegistryValues+0x82 (83e32e07)
以上內(nèi)容調(diào)用了nt!RtlpAllocDeallocQueryBuffer函數(shù),其內(nèi)部執(zhí)行ExAllocatePoolWithTag(1,0x84,0x76727152),即申請(qǐng)大小為0x84的內(nèi)存空間,返回內(nèi)存空間的首地址。
代碼:
nt!RtlQueryRegistryValues+0x82:
83e32e07 8b5d10 mov ebx,dword ptr [ebp+10h] //ebx == QueryTable
83e32e0a 897e08 mov dword ptr [esi+8],edi
83e32e0d 8b442420 mov eax,dword ptr [esp+20h] //eax == KeyHandle
83e32e11 c744242882000000 mov dword ptr [esp+28h],82h //ebp - 34
83e32e19 8944241c mov dword ptr [esp+1Ch],eax //ebp - 40
nt!RtlQueryRegistryValues+0x98:
83e32e1d 8b0b mov ecx,dword ptr [ebx] //ecx == QueryTable->QueryRoutine
83e32e1f 3bcf cmp ecx,edi
83e32e21 750a jne nt!RtlQueryRegistryValues+0xa8 (83e32e2d)
nt!RtlQueryRegistryValues+0x9e:
83e32e23 f6430421 test byte ptr [ebx+4],21h // byte ptr [ebx+4] = 21h
83e32e27 0f8446030000 je nt!RtlQueryRegistryValues+0x3ee (83e33173)
nt!RtlQueryRegistryValues+0xa8:
83e32e2d 8b4304 mov eax,dword ptr [ebx+4]
83e32e30 a820 test al,20h
83e32e32 7419 je nt!RtlQueryRegistryValues+0xc8 (83e32e4d)
nt!RtlQueryRegistryValues+0xaf:
83e32e34 397b08 cmp dword ptr [ebx+8],edi
83e32e37 0f841b030000 je nt!RtlQueryRegistryValues+0x3d3 (83e33158)
nt!RtlQueryRegistryValues+0xb8:
83e32e3d a801 test al,1
83e32e3f 0f8513030000 jne nt!RtlQueryRegistryValues+0x3d3 (83e33158)
nt!RtlQueryRegistryValues+0xc0:
83e32e45 3bcf cmp ecx,edi
83e32e47 0f850b030000 jne nt!RtlQueryRegistryValues+0x3d3 (83e33158)
nt!RtlQueryRegistryValues+0xc8:
83e32e4d a803 test al,3
83e32e4f 7418 je nt!RtlQueryRegistryValues+0xe4 (83e32e69)
nt!RtlQueryRegistryValues+0xe4:
83e32e69 8b4b04 mov ecx,dword ptr [ebx+4] //ecx == QueryTable->Flags
83e32e6c 8b4308 mov eax,dword ptr [ebx+8] //eax == QueryTable->Name
83e32e6f f6c101 test cl,1
83e32e72 0f8438010000 je nt!RtlQueryRegistryValues+0x22b (83e32fb0) 1
nt!RtlQueryRegistryValues+0x22b:
83e32fb0 3bc7 cmp eax,edi
83e32fb2 0f8417010000 je nt!RtlQueryRegistryValues+0x34a (83e330cf)
nt!RtlQueryRegistryValues+0x233:
83e32fb8 50 push eax
83e32fb9 8d442434 lea eax,[esp+34h]
83e32fbd 50 push eax
83e32fbe e8255fe4ff call nt!RtlInitUnicodeString (83c78ee8)
83e32fc3 897c2414 mov dword ptr [esp+14h],edi
nt!RtlQueryRegistryValues+0x242:
83e32fc7 8b442414 mov eax,dword ptr [esp+14h]
83e32fcb ff442414 inc dword ptr [esp+14h]
83e32fcf 83f804 cmp eax,4
83e32fd2 0f8f8a010000 jg nt!RtlQueryRegistryValues+0x3dd (83e33162)
上面這些內(nèi)容并不重要,之所以貼出了是為了用來確定后面寄存器的值。
代碼:
nt!RtlQueryRegistryValues+0x253:
83e32fd8 8d442410 lea eax,[esp+10h] //eax == ebp-4c
83e32fdc 50 push eax //ebp - 4c
83e32fdd ff74242c push dword ptr [esp+2Ch] //0x82
83e32fe1 8d442438 lea eax,[esp+38h] //
83e32fe5 56 push esi //通過nt!RtlpAllocDeallocQueryBuffer申請(qǐng)空間的內(nèi)存空間首地址
83e32fe6 6a01 push 1 //1
83e32fe8 50 push eax //ebp-2c
83e32fe9 ff742430 push dword ptr [esp+30h] //KeyHandle
83e32fed e86a9ee4ff call nt!ZwQueryValueKey (83c7ce5c)
83e32ff2 8944240c mov dword ptr [esp+0Ch],eax
83e32ff6 bf230000c0 mov edi,0C0000023h
83e32ffb 3d05000080 cmp eax,80000005h
83e33000 7504 jne nt!RtlQueryRegistryValues+0x281 (83e33006)
調(diào)用nt!ZwQueryValueKey,通過前面獲得的KeyHandle來讀取鍵值信息,返回的信息放入前面通過nt!RtlpAllocDeallocQueryBuffer函數(shù)申請(qǐng)的內(nèi)存空間中。
根據(jù)nt!ZwQueryValueKey的參數(shù),可以得知返回的信息為KEY_VALUE_FULL_INFORMATION結(jié)構(gòu),其定義如下:
代碼:
typedef struct _KEY_VALUE_FULL_INFORMATION {
ULONG TitleIndex;
ULONG Type;
ULONG DataOffset;
ULONG DataLength;
ULONG NameLength;
WCHAR Name[1]; // Variable size
} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
這個(gè)結(jié)構(gòu)在后面會(huì)用到!
代碼:
nt!RtlQueryRegistryValues+0x281:
83e33006 33c0 xor eax,eax
83e33008 3944240c cmp dword ptr [esp+0Ch],eax
83e3300c 7d69 jge nt!RtlQueryRegistryValues+0x2f2 (83e33077)
nt!RtlQueryRegistryValues+0x2f2:
83e33077 837e0407 cmp dword ptr [esi+4],7
83e3307b 750e jne nt!RtlQueryRegistryValues+0x306 (83e3308b)
nt!RtlQueryRegistryValues+0x306:
83e3308b 8b442428 mov eax,dword ptr [esp+28h]
83e3308f ff7514 push dword ptr [ebp+14h] //Context == 0
83e33092 89442414 mov dword ptr [esp+14h],eax
83e33096 53 push ebx //QueryTable
83e33097 8d4c2418 lea ecx,[esp+18h] //ebp-4c == 0x82
83e3309b 8bc6 mov eax,esi //esi指向申請(qǐng)內(nèi)存空間
83e3309d e8df7affff call nt!RtlpCallQueryRegistryRoutine (83e2ab81)
這就是關(guān)鍵調(diào)用了,nt!RtlpCallQueryRegistryRoutine為問題函數(shù),雖然只有兩個(gè)參數(shù)壓棧,但是還有部分參數(shù)是通過寄存器傳遞的,所以都做了一些標(biāo)示。
其參數(shù)為nt!RtlQueryRegistryValues函數(shù)的參數(shù)Context和QueryTable,以及儲(chǔ)存前面返回的鍵值信息的內(nèi)存空間指針。
接下來看nt!RtlpCallQueryRegistryRoutine函數(shù):
代碼:
nt!RtlpCallQueryRegistryRoutine+0xc8:
83e2ac49 8b7e08 mov edi,dword ptr [esi+8]
83e2ac4c 8b4604 mov eax,dword ptr [esi+4]
83e2ac4f 03fe add edi,esi
83e2ac51 8b760c mov esi,dword ptr [esi+0Ch]
83e2ac54 894508 mov dword ptr [ebp+8],eax
83e2ac57 eb7b jmp nt!RtlpCallQueryRegistryRoutine+0x153 (83e2acd4)
這里修改了ebp+8處的值,即將QueryTable的值修改為[esi+4],對(duì)應(yīng)的是KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中的Type。
代碼:
nt!RtlpCallQueryRegistryRoutine+0x282:
83e2ae03 ff730c push dword ptr [ebx+0Ch] //QueryTable->EntryContext
83e2ae06 f6c120 test cl,20h
83e2ae09 7436 je nt!RtlpCallQueryRegistryRoutine+0x2c0 (83e2ae41)
nt!RtlpCallQueryRegistryRoutine+0x28a:
83e2ae0b 8b5508 mov edx,dword ptr [ebp+8] //edx的值為KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中的Type值
83e2ae0e 57 push edi //edi指向KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中的Name
83e2ae0f 8bc6 mov eax,esi //eax的值為KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中的DataLength值
83e2ae11 e8818b0000 call nt!RtlpQueryRegistryDirect (83e33997)
這個(gè)函數(shù)對(duì)傳進(jìn)來的參數(shù)做了一定的處理,然后傳給nt!RtlpQueryRegistryDirect函數(shù),上面有較詳細(xì)的注釋,這個(gè)應(yīng)該就不用多說了吧。
然后是nt!RtlpQueryRegistryDirect函數(shù):
代碼:
kd> uf nt!RtlpQueryRegistryDirect
nt!RtlpQueryRegistryDirect:
83e33997 8bff mov edi,edi
83e33999 55 push ebp
83e3399a 8bec mov ebp,esp
83e3399c 53 push ebx
83e3399d 8b5d08 mov ebx,dword ptr [ebp+8]
83e339a0 56 push esi
83e339a1 8b750c mov esi,dword ptr [ebp+0Ch] //esi == QueryTable->EntryContext
83e339a4 57 push edi
83e339a5 83fa01 cmp edx,1
83e339a8 7445 je nt!RtlpQueryRegistryDirect+0x56 (83e339ef)
nt!RtlpQueryRegistryDirect+0x13:
83e339aa 83fa02 cmp edx,2
83e339ad 7440 je nt!RtlpQueryRegistryDirect+0x56 (83e339ef)
nt!RtlpQueryRegistryDirect+0x18:
83e339af 83fa07 cmp edx,7
83e339b2 743b je nt!RtlpQueryRegistryDirect+0x56 (83e339ef)
nt!RtlpQueryRegistryDirect+0x1d:
83e339b4 83f804 cmp eax,4
83e339b7 770c ja nt!RtlpQueryRegistryDirect+0x2c (83e339c5)
nt!RtlpQueryRegistryDirect+0x22:
83e339b9 3bf3 cmp esi,ebx
83e339bb 7476 je nt!RtlpQueryRegistryDirect+0x9a (83e33a33)
nt!RtlpQueryRegistryDirect+0x26:
83e339bd 85c0 test eax,eax
83e339bf 7510 jne nt!RtlpQueryRegistryDirect+0x38 (83e339d1)
nt!RtlpQueryRegistryDirect+0x2a:
83e339c1 eb70 jmp nt!RtlpQueryRegistryDirect+0x9a (83e33a33)
nt!RtlpQueryRegistryDirect+0x2c:
83e339c5 8b0e mov ecx,dword ptr [esi]
83e339c7 85c9 test ecx,ecx
83e339c9 7d13 jge nt!RtlpQueryRegistryDirect+0x45 (83e339de)
nt!RtlpQueryRegistryDirect+0x45:
83e339de 8d7808 lea edi,[eax+8]
83e339e1 3bcf cmp ecx,edi
83e339e3 725d jb nt!RtlpQueryRegistryDirect+0xa9 (83e33a42)
以上內(nèi)容意義不大,主要是一些判斷。
代碼:
nt!RtlpQueryRegistryDirect+0x4c:
83e339e5 8906 mov dword ptr [esi],eax //esi指向win32k!bAppendSysDirectory+0x209函數(shù)的棧空間
83e339e7 895604 mov dword ptr [esi+4],edx //溢出!,edx的值為KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中的Type值
83e339ea 83c608 add esi,8
83e339ed ebe2 jmp nt!RtlpQueryRegistryDirect+0x38 (83e339d1)
nt!RtlpQueryRegistryDirect+0x38:
83e339d1 50 push eax //eax的值為KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中DataLength值
83e339d2 53 push ebx //ebx指向KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中的Name
83e339d3 56 push esi //QueryTable->EntryContext + 8
83e339d4 e8c75de4ff call nt!memcpy (83c797a0) //溢出!
從這里就能看到棧的溢出了。函數(shù)起始位置將esi指向QueryTable->EntryContext,這個(gè)變量的值為win32k!bAppendSysDirectory+0x209函數(shù)中ebp-0x20,也就是函數(shù)棧地址。上面的操作會(huì)將棧上的信息覆蓋掉,覆蓋的值一次為KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中的DataLength和Type,然后是通過memcpy將KEY_VALUE_FULL_INFORMATION結(jié)構(gòu)中的Name復(fù)制到棧中。
通過上面的代碼可以看到,棧溢出了!如果要利用的話,需要計(jì)算偏移量,然后修改“\REGISTRY\USER\S-1-5-18\EUDC\936\SystemDefaultEUDCFont”鍵值的信息,將函數(shù)的返回地址覆蓋為shellcode的地址。
關(guān)健詞:MS11-011
新文章:
- CentOS7下圖形配置網(wǎng)絡(luò)的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS單網(wǎng)卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗(yàn)證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網(wǎng)打印機(jī)IP講解
- CentOS7使用hostapd實(shí)現(xiàn)無AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網(wǎng)絡(luò)重啟出錯(cuò)
- 解決Centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統(tǒng)有什么不同呢
- Centos 6.6默認(rèn)iptable規(guī)則詳解