Windows 2000 系统资源管理器的一个漏洞
0x00-前言
这似乎又是一个0 day漏洞(?)
这个漏洞与pif文件有关,是我在研究pif文件的时候发现的,关于pif文件的一些资料我整理到自己的博客里了:
后面会用到里面的一些内容。
实验环境
Microsoft Windows 2000 5.00.2195 Service Pack 4
用到的软件工具
010Editor
ollydbg
IDA pro
0x01-漏洞简述
首先,win 2000系统里存在一个文件_default.pif,它的结构如下:
我在这个文件的基础上添加了一个名为WINDOWS VMM 4.0的块,如下图:
把这个文件放在U盘根目录下,插入win 2000系统后,浏览U盘时,资源管理器崩溃闪退。
0x02-对崩溃的逆向跟踪,找到溢出点
我们可以确定的是,崩溃的出现是由于我们构造的pif文件里新的内容,而且应该出现在对文件内容的处理的过程中。
而根据pif文件的格式:
块名 |
长度 |
应用场景 |
MICROSOFT PIFEX |
0171h |
The basic section, all OS |
WINDOWS 286 3.0 |
0006h |
Windows 3.X in standard mode |
WINDOWS 386 3.0 |
0068h |
Windows 3.X in enhanced mode, 95, 98, NT, 2000 |
WINDOWS NT 3.1 |
008Eh |
Windows NT, 2000 |
WINDOWS NT 4.0 |
068Ch |
Windows NT 4.0, 2000 |
WINDOWS VMM 4.0 |
01ACh |
Windows 95, 98, NT 4.0, 2000 |
CONFIG SYS 4.0 |
Variable |
Windows 95, 98 |
AUTOEXECBAT 4.0 |
Variable |
Windows 95, 98 |
可以看到每个数据块都有一个名字,猜测在对这些数据块处理的代码里可能包含这些名字的字符串常量,也许可以由此定位到数据块处理相关代码。
于是在explorer.exe和其调用的动态链接库中搜索这些字符串,最终发现只有系统shell32.dll中存在这些字符串:
然后在ollydbg里追踪崩溃
由于windows系统只允许存在一个explorer.exe进程实例,我们用ollydbg打开新的explorer.exe进程进行动态调试时,系统会自动关闭该进程,从而阻止了调试的继续进行。所以需要通过File ->Attach菜单项将系统当前的explorer.exe进程附加ollydbg中的方式进行调试。
在调用这些字符串常量的函数里下大量断点,通过函数执行后崩溃是否发生判断溢出点的大致位置:
最后跟踪到这个函数:
也就是函数sub_7909062B
整个跟踪过程如下:
动态分析函数sub_7909062B(上图中蓝色笔的部分),观察堆栈,发现在某次执行lstrcpyA后,堆栈里的返回地址和其它数据被覆盖
执行lstrcpyA前后堆栈里的变化:
0x03-不太成功的漏洞利用
函数的返回地址被覆盖,在Windows 2000系统上的漏洞利用应该是毫无难度的简单劳动,但是这回的不太一样。
在sub_79057E1D函数开始的地方将this指针保存在堆栈里:
在堆栈被覆盖后的代码里又使用到this指针。
造成程序没有执行到函数返回指令的机会,所以按照常规方法通过返回地址得到程序执行权的方法在这里不适用。
但是this指针被覆盖也为我们提供了获得执行的机会,我们在溢出this指针的数据处设置为堆栈地址硬编码,在溢出数据中构造出索引虚函数地址的数据,可以概率性的实现计算器的启动。下面是我构造的pif文件:
程序执行到this指针索引到的虚函数调用时,数据区里包含了我们的shellcode,启动的程序路径,和用来索引虚函数的链表结构。如下图:
其中包含了我写的shellcode:
最终效果如下:
概率性成功的原因是,exploere.exe进程每次启动的其栈地址都是动态变化的,溢出发生时真实的堆栈可能没在我们提前设定的地址处。我这里测试平均每5次会有一次成功启动计算器,最终的频次体验应该和电脑有关。
进一步研究,发现程序运行到调用虚函数地址时的寄存器EAX,EBX,ESI的值是溢出数据的某个位置的地址,所以理想的做法应该是寻找一个与JMP EAX,JMP EBX,JMP ESI类似的指令,假如这个指令的地址为A,设this的值为x,[ ]表示在进程地址空间里寻址后取值;我们可以将被覆盖的this指针设定为满足下面的公式的值:
显然,找到满足上式的x是不容易的,我做了尝试,但失败了。不知道有没有更好的技巧来利用这种漏洞。
0x04-Windows XP及其他版本系统里存在该漏洞吗
进一步的,我对Windows XP的shell32.dll进行了逆向分析,发现同样的位置与windows 2000的代码极为相似,但是它用安全的_StringCopyWorker函数代替了lstrcpy,如下图:
所以有理由相信,在后续的windows系统中微软已经发现了这个漏洞,并修补了它。