<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 //返回成成的设备对象指针
);
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