应用层和内核层通信

本文介绍了Windows系统中应用层和内核层通信的方法,涉及到LIST_ENTRY双向链表的使用和初始化。在多线程环境下,通过自旋锁确保链表操作的安全性。此外,还探讨了同步事件的实现,如KEVENT数据结构,以及如何在驱动开发中创建设备对象以实现通信。
摘要由CSDN通过智能技术生成

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近在看Windows内核安全与驱动开发,总结了一些东西,主要介绍一些自旋锁,事件,链表相关的东西。</span>

LIST_ENTRY一个双向链表,在Windows中经常使用。在使用时只需在结构体中插入一个LIST_ENTRY结构,位置无所谓(最好在前面)。比如:

typedef	struct	{
	LIST_ENTRY	list_entry;
	UNICODE_STRING	file_name;
}MY_LIST_TEST;

在使用之前需要调用InitializeListHead来初始化:

#define	MEM_TAG  'test'
LIST_ENTRY my_list_head; 		//链表头(注意不是自己定义的链表结构体)
InitializeListHead(&my_list_head);	//初始化
MY_LIST_TEST *my_first_list = ExAllocatePoolWithTag(NonPagedPool, sizeof(CWK_STR_NODE), MEM_TAG);	//申请空间
my_first_list->file_name = .....	//填写数据成员
InsertHeadList(&my_list_head,(PLIST_ENTRY)&my_first_list); 	//添加节点


这样做非常不安全,因为多线程的情况下操作同一个链表会破坏这个链表,这个时候就要引进自旋锁的概念。使用自旋锁首先要初始化一个自旋锁:

KSPIN_LOCK g_cwk_lock;	
KeInitializeSpinLock(&g_cwk_lock);	//初始化一个自旋锁
ExInterlockedInsertHeadList(&my_list_head, (PLIST_ENTRY)&my_first_list, &g_cwk_lock);	//添加节点 并进行加锁
my_first_list = ExInterlockedRemoveHeadList(&my_list_first, &g_cwk_lock);	//移除一个节点 并返回到my_first_list中


下面说一下同步事件,当一个地方需要等待另一个事件完成后才能继续进行时需要设置同步事件,同步事件数据结构是KEVENT

 
KEVENT event;	//定义一个事件
KeInitializeEvent(&event,SynchronizationEvent,TRUE); //事件初始化
......
//这里设置事件等待,如果这个事件没有被设置,那么会一直在这里等待
KeWaitForSingleObject(&_event,Executive,KernelMode,0,0);
......
//这理设置事件,只有这里执行完了以后,上面的等待才能放行,去执行后续流程
KeSetEvent(&_event, 0, TRUE);


要实现用户层和内核层的通信,首先要生成一个设备对象,在驱动开发中设备对象和分发函数构成了整个内核体系的基本框架。生成设备可以使用函数IoCreateDevice函数,

NTSTATUS IoCreateDevice
(
IN PDRIVER_OBJECT DriverObject,		//从DriverEntry的参数获得
IN ULONG DeviceExtensionSize,		//设备扩展大小
IN PUNICODE_STRING DeviceName OPTIONAL,	//设备名
IN DEVICE_TYPE DeviceType,		//设备类型
IN ULONG DeviceCharacteristics,		//设备属性
IN BOOLEAN Exclusive,			//表示是否是一个独占设备
OUT PDEVICE_OBJECT *DeviceObject	//返回成成的设备对象指针
);


但是这个生成的设备具有默认的安全属性,必须用管理员权限的进程才能打开,当用户是普通用户就没办法打开,所以使用IoCreateDeviceSecure函数创建设备
NTSTATUS IoCreateDeviceSecure
(
IN PDRIVER_OBJECT DriverObject,		//从DriverEntry的参数获得
IN ULONG DeviceExtensionSize,		//设备扩展大小
IN PUNICODE_STRING DeviceName OPTIONAL,	//设备名
IN DEVICE_TYPE DeviceType,		//设备类型
IN ULONG DeviceCharacteristics,		//设备属性
IN BOOLEAN Exclusive,			//表示是否是一个独占设备
IN PUCNICODE_STRING DefaultSDDLString,	//设置设备安全
IN LPCGUID DeviceClassGuid,		//微软提供CoCreateGuid生成,第一次生成就一直使用,不要每次启动都生成一个新的
OUT PDEVICE_OBJECT *DeviceObject	//返回成成的设备对象指针
);
可以发现只有两个地方不一样,其中DefaultSDDLString这个参数传入L"D:P(A;;GA;;;WD)"即表示允许任何用户访问该设备的万能安全设置字符串,使用如下:
//全局参数
PDEVICE_OBJECT g_cdo = NULL;
const GUID  CWK_GUID_CLASS_MYCDO = {0x17a0d1e0L, 0x3249, 0x12e1, {0x92,0x16, 0x45, 0x1a, 0x21, 0x30, 0x29, 0x06}};//GUID
//......
NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING reg_path){
	UNICODE_STRING sddl = RTL_CONSTANT_STRING(L"D:P(A;;GA;;;WD)"); 
	UNICODE_STRING cdo_name = RTL_CONSTANT_STRING(L"\\Device\\cwk_3948d33e"); //设备名
	IoCreateDevic
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、imp2源码 整个源码包含三个文件:imp2_k.c, imp2_u.c和imp2.h. 其中imp2_k.c为内核模块的源代码,imp2_u.c为应用程序,即测试代码,imp2.h为两个源文件都需要引用的头文件。其整体的功能是:注册一种新的netlink协议,并注册一个新的NF hook函数。当有ping包发往当前主机或者经过当前主机转发时,内核用户发送ping包的源IP和目的IP。各个文件的简单分析见下文。 1. imp2.h 该文件主要是定义了一种新的Netlink协议类型NL_IMP2(31)。新的协议类型的选值不能和当前内核中已经定义的netlink协议类型重复。定义了基于该协议类型的消息类型,内核根据接收到消息的不同类型,进行不同的处理:IMP2_U_PID和IMP2_CLOSE分别为请求和关闭。IMP2_K_MSG代表内核空间发送的消息。 该头文件的源码如下: 2. imp2_k.c 该程序为内核模块程序。其完成的功能如下: (1)创建一种新的Netlink协议NL_IMP2,并注册该协议的回调函数kernel_receive。但用户空间通过建立且协议类型为NL_IMP2的socket套接字并调用sendto,sendmsg函数发送数据时,传送到内核空间的数据由kernel_receive进行处理。该函数主要是记录用户进程的ID,用于随后发送数据的时候指定目的。 (2)在Netfilter的hook点NF_IP_PRE_ROUTING注册hook函数get_icmp,对经过该hook点的ping包进行处理。get_icmp首先判断是否是ping包,如果不是,直接Accept。如果是,则记录该包的源IP和目的IP,然后调用send_to_user,将记录的信息发送给kernel_recieve函数中记录的用户进程ID。 该文件的源码如下: 3. imp2_u.c 该程序为用户空间的测试程序。该程序包括以下功能: (1)生成NL_IMP2协议的socket.然后通过调用sendto发送IMP2_U_PID类型的请求信息给内核。然后等待接受内核发回的信息。记住:仅当有ping包经过内核的NF时,内核才会向用户进程发送信息。 (2)当用户进程通过Ctrl+C来结束该程序时,调用信号处理函数sig_int,向内核发送IMP2_CLOSE的消息,结束socket。 该文件的源码如下: 二、编译和测试 1. 整个源文件编译的Makefile如下: all: gcc -O2 -DMODULE -D__KERNEL__ -W -Wstrict-prototypes -Wmissing-prototypes -isystem /lib/modules/`uname -r`/build/include -c -o imp2_k.o imp2_k.c gcc imp2_u.c -o imp2_u install: insmod imp2_k.o uninstall: rmmod imp2_k clean: rm -f imp2_k.o imp2_u 2. 加载内核模块,并执行测试程序。 #make install #./imp2_u 当没有ping包时,终端一直处于等待输出状态。通过另一台主机(192.168.1.100)向当前主机(192.168.1.101)发送ping包,则终端已经有输出: #./imp2_u [root@localhost imp2]# ./imp2_u src: 192.168.1.100, dest: 192.168.1.101 src: 192.168.1.100, dest: 192.168.1.101 src: 192.168.1.100, dest: 192.168.1.101 src: 192.168.1.100, dest: 192.168.1.101
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值