最初看到这个漏洞的exp代码时,以为传说中的内核远程溢出出现了。后来发现这个溢出实际和驱动并没有什么关系,因此把题目换成了“Nvvsvc32溢出”。
关于这个漏洞的一些细节已经在《NVIDIA Driver Helper Service栈溢出简单说明》一文中做了说明。漏洞调试之类的文章,不实际调试一番总是觉得云里雾里。于是动手做了一些分析,现把分析情况笔记如下,也让想了解这个漏洞的tx少走些弯路。
1、 分析环境:
驱动程序提供商 NVIDIA
驱动程序日期 2010-11-12
驱动程序版本 6.14.11.9838
服务名称 NVIDIA Display Driver Service
服务进程 nvsvc32.exe
需要说明的是,在windows xp下产生服务的程序是nvsvc32.exe,windows 7下产生服务的是nvvsvc.exe。
2、 关于管道与DACL
源代码说明中的管道名称有误,NVIDIA Display Driver Service使用的管道名称是\pipe\nvsr。使用pipelist可以查出使用的管道的名称是nvsr。
逆向nvsvc32.exe时,其创建管道的伪代码为:
int __stdcall sub_4051D6(int a1)
{
HANDLE tHandle; // eax@4
DWORD i; // [sp-8h] [bp-40h]@1
struct _SECURITY_ATTRIBUTES *v4; // [sp-4h] [bp-3Ch]@1
HANDLE v5; // [sp-4h] [bp-3Ch]@5
SECURITY_DESCRIPTOR SecurityDescriptor;
struct _SECURITY_ATTRIBUTES SecurityAttributes; // [sp+20h] [bp-18h]@1
SecurityAttributes.nLength = 12;
SecurityAttributes.lpSecurityDescriptor = &SecurityDescriptor;
SecurityAttributes.bInheritHandle = 1;
InitializeSecurityDescriptor(&pSecurityDescriptor, 1u);
SetSecurityDescriptorDacl(&SecurityDescriptor, TRUE, NULL, NULL);
sub_40506E();
v4 = &SecurityAttributes;
for ( i = 0; ; i = 0 )
{
hObject = CreateNamedPipeW(L"\\\\.\\pipe\\nvsr", 3u, 6u, 0xFFu, 0x2010u, 0x2010u, i, v4);
if ( hObject == (HANDLE)-1 )
break;
…… ……
}
以上代码也明确表示了管道名称为 \\\\.\\pipe\\nvsr,另外对SetSecurityDescriptorDacl函数的调用可以知道,由于bDaclPresent参数为true,将会使用pDacl参数和bDaclDefaulted 参数创建DACL,因此创建管道的Dacl是空。如果一个对象没有DACL,那么就是说这个对象是任何人都可以拥有完全的访问权限。
3、 关于ProtocolAction_Receive错误的说明:
从对程序代码的分析可以看出,要成功利用该漏洞一共需要9个步骤。但是,在调试时却发现执行到“Action 3 of 9:”时就已经出错退出。那么是什么原因造成退出的呢?
用IDA逆向该程序时,由于该程序是注册一个windows系统服务,在hexray 的辅助下,程序结构非常清晰。可以知道sub_ 00404E13(StartAddress)就是管道服务端线程的执行体。
该函数读取管道数据后,根据传入数据的第一个双字作为命令字节来决定程序的执行流程。
…… ……
text:00404E79 cmp eax, 44h
.text:00404E7C jz loc_404FA4
.text:00404E82 cmp eax, 47h
.text:00404E85 jz loc_404F32
.text:00404E8B cmp eax, 52h
.text:00404E8E jz loc_404F1A
.text:00404F1A push 20h ; size_t
.text:00404F1C push offset aNotImplemented ; "Not implemented"
.text:00404F21 lea eax, [ebp+7FD8h+var_8044]
.text:00404F24 push eax ; wchar_t *
.text:00404F25 call _wcsncpy
对于0x52操作只是简单地将"Not implemented"字符串拷贝到目的缓冲区中,并且在循环时以0作为写入长度,将"Not implemented"字符串再写到管道中。因此,在第三步执行ReadPipe操作时,由于读取数据的长度为0,因此程序退出了。
这也是《NVIDIA Driver Helper Service栈溢出简单说明》一文中说明的“xp x32版下0x52命令不支持”的原因。
4、 漏洞可利用性说明:
由刚才不支持0x52操作可以说明,在xp 下这个漏洞不存在。(使用0x47号、0x57号操作不清楚,有兴趣的tx可以继续研究)
在在win7 x32版上只能够做到infoleak,原因《简单说明》一文中已经说明:“由于32位版下局部变量的内存布局源地址在目的地址的高位,所以这个洞只能造成infoleak。” 《简单说明》一文末尾给出的两个exe就是对这个结论的实际验证。通过infoleak可以吧stack cookie读取出来,但是最后得到的只是一个内存访问的一异常。
64位环境下,由于局部变量布局情况刚好相反,所以能够利用。老外的exp源代码的说明中已经给出。
5、其他
可笑的36x啊,在还不明了之前就瞎鼓噪,搞得满城风雨啊。
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界