《0day安全》——探索Ring0

内核基础知识

内核态 Ring0

用户态 Ring3

那么内核漏洞是Ring0程序中能被利用的bug或缺陷

除了操作系统内核程序,驱动程序也是运行在Ring0,一些安全软件,游戏软件,工具软件等第三方驱动程序都是在Ring0级别上运行的

驱动编写之Hello World

编写代码

#include <ntddk.h>

#define DEVICE_NAME L"\\Device\\HelloWorld"
#define DEVICE_LINK L"\\DosDevices\\HelloWorld"
// 创建的设备对象指针
PDEVICE_OBJECT g_DeviceObject;

// 驱动卸载函数
VOID DriverUnload(IN PDRIVER_OBJECT driverObject){
	// 什么都不用做,打印一句话,helloword就这套路
	KdPrint(("DriverUnload: 88!\n"));
}
// 驱动派遣例程函数
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT driverObject, IN PIRP pIrp){
	KdPrint(("Enter DrvDispatch\n"));
	// 设置IRP的完成状态
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	// 设置IRP的操作字节数
	pIrp->IoStatus.Information = 0;
	// 完成IRP处理
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}
// 驱动入口函数(相当于main函数)
NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath){
	NTSTATUS ntStatus;
	UNICODE_STRING devname;
	UNICODE_STRING symLinkName;
	int i;
	// 打印一句调试信息
	KdPrint(("DriverEntry: Hello world driver demo!"));
	// 设置该驱动对象的卸载函数
	//driverObject->DriverUnload = DriverUnload;
	// 创建设备
	RtlInitUnicodeString(&devname, DEVICE_NAME);
	ntStatus = IoCreateDevice(driverObject, 
		0, 
		&devname, 
		FILE_DEVICE_UNKNOWN, 
		0, TRUE, 
		&g_DeviceObject);
	if (!NT_SUCCESS(ntStatus))	{
		return ntStatus;
	}
	// 创建符号链接
	RtlInitUnicodeString(&symLinkName, DEVICE_LINK);
	ntStatus = IoCreateSymbolicLink(&symLinkName, &devname);
	if (!NT_SUCCESS(ntStatus)){
		IoDeleteDevice(g_DeviceObject);
		return ntStatus;
	}
	// 设置该驱动对象的派遣例程函数
	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++){
		driverObject->MajorFunction[i] = DrvDispatch;
	}
	// 返回成功结果
	return STATUS_SUCCESS;
}

之后安装WDK

blob.png

继续

blob.png

跟着抄的程序,这应该影响不大

blob.png

作者给的源码编译的结果,perfect

blob.png

看到驱动文件了

blob.png

这不能像exe那样运行,需要作为内核模块来加载和运行

我们可以在用户态使用服务管理器创建服务,将xxx.sys和服务关联在一起,通过启动服务向内核加载xxx.sys

初学还是用工具

不知为啥不能卸载驱动

blob.png

看看代码原来是注释了

blob.png

就是用比对软件看看自己敲的跟作者的差别时加了注释

blob.png

注释删掉就可以啦

blob.png

派遣例程与IRP结构


IRP(I/O Request Package):输入输出请求包

Ring3通过DeviceControl等函数向驱动发出I/O请求后,在内核中由操作系统将其转化为IRP的数据结构,并“派遣”到对应驱动的派遣函数中

一个驱动还有多个派遣函数,具体要派遣到哪个派遣函数

由RIP结构中的MajorFunction属性决定

但现在文档只有下面的属性

blob.png

不知道是不是这里显示不全,作者说是0x1b,即27个

那个helloworld全都设置成同一个函数了

为了更灵活查询内和数据结构,还要其他工具,比如下载符号文件的

以前分析漏洞下断点时,符号文件在ida,windbg调试的时候也是很有用的

blob.png

那个看pdb文件的在xp打开不了

blob.png

win7就可以打开软件,但是!!打开失败,就不截图了,打得开别的也看不到符号

之后发现是在xp下载的符号文件有问题

blob.png

终于可以了,很清晰了这样就

blob.png

后面两小节就看看书就好了

继续前行

内核调试入门

内核调试3中方法,这里使用虚拟机还是比较方便的

首先设置虚拟机添加硬件,串行端口

blob.png

继续

blob.png

继续

blob.png

我的还要这个

blob.png

要打钩哦

blob.png

之后修改虚拟机的boot.ini文件

首先去除保护属性

blob.png

增加一个系统启动项blob.png恢复保护属性

blob.png

重启选择调试系统

blob.png

好像卡住了似的,不用怕,它是等待调试器

windbg搞个快捷方式

在目标后加上

-b -k com:port=\\.\pipe\com_1,baud=115200,pipe

之后发现打开那个快捷方式竟然连不上,搜了一下,原来打印机占用了串口1,我们建的变2了

blob.png

果断删掉,之后串口再建,就行了

blob.png

下面是蓝屏分析,应该是没有设置转存文件,以后知道怎么做再补上

内核漏洞概述

内核漏洞分类:

按照严重程度分类:

  1. 远程拒绝服务

  2. 本地拒绝服务

  3. 远程任意代码执行

  4. 本地权限提升

按照漏洞利用类型分类:

  1. 拒绝服务

  2. 缓冲区溢出

  3. 内存篡改

    1. 任意地址写任意数据

    2. 固定地址写任意数据

    3. 任意地址写固定数据

  4. 设计缺陷

内核漏洞研究过程

  1. 漏洞重现:环境搭建,POC编译

  2. 漏洞分析:源码对比,反汇编分析,POC分析,补丁对比,内核调试跟踪,蓝屏分析

  3. 漏洞利用:特权提升,远程溢出,本地溢出,远程DOS,本地DOS

  4. 漏洞总结:根本原因,修补方法

内核漏洞挖掘:手工和工具咯,加上你的经验和知识

好,继续学吧,敲敲文字也挺好的

编写安全的驱动程序

  1. 输入输出检查

  2. 验证驱动调用者:可以检查调用者进程文件的md5,等,还可以用户态程序和驱动程序通信加密,解密失败和非法通信数据直接不处理

  3. 白名单机制的挑战:就是安全软件为了避免第三方驱动运行出现问题,大多开设了白名单机制,假如白名单中的驱动存在漏洞,那么木马不用加载自己的驱动也能提权什么的,所以加入白名单需要经过安全评估才能加入

打赏作者
喜欢本博客,打赏让博客永久运行,多少你说了算

您的支持将鼓励我们继续创作!

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注