内核模块字符相关处理

学习自:

B站:写驱动的女装大佬 《–从零开始造核弹—windows驱动程序开发(中级篇-4课)》
感谢大佬制作高水准视频!!

学习笔记

一、初始化字符串 :
RtlInitUnicodeString(&deviceanme, DEVICE_NAME)

#define DEVICE_NAME L"\\Device\\MyfirstDevice" //定义一个驱动的名字

UNICODE_STRING deviceanme = {
    
     0 };//初始一个存储设备名字的内存空间


RtlInitUnicodeString(&deviceanme, DEVICE_NAME);//初始化一个字符串


DbgPrint("--:%wZ--\n",&deviceanme);

二、初始化字符串2:
RTL_CONSTANT_STRING(DEVICE_NAME);
此方法有局限性,如果确定字符100%不能进行修改就可以用这个

#define DEVICE_NAME L"\\Device\\MyfirstDevice" //定义一个驱动的名字
UNICODE_STRING deviceanme = RTL_CONSTANT_STRING(DEVICE_NAME);//初始一个字符串
DbgPrint("--:%wZ--\n",&deviceanme);

三、初始化字符串3:

	PWCHAR testbuffer = ExAllocatePool(NonPagedPool, 0x1000);//创建一个空指针
	RtlZeroMemory(testbuffer, 0x1000);// 缓冲区清零
	RtlCopyMemory(testbuffer, L'FFFFFFFFFF', sizeof(L'FFFFFFFFFF'));//拷贝一个字符串到缓冲区
	RtlInitUnicodeString(&deviceanme, testbuffer);//初始字符串
	DbgPrint("--:%wZ--\n",&deviceanme);

四、窄字符转宽字符:
RtlAnsiStringToUnicodeString(&deviceanme, &str, TRUE);//窄字符转宽字符

UNICODE_STRING deviceanme = {
    
     0 };//初始一个存储宽字符的内存空间
PCHAR tempbuffer = "C:\\123\\321\\567\\123.txt"; //赋值一个字符串
STRING str = {
    
     0 };//定义一个窄字符存储空间
RtlInitString(&str,tempbuffer);//把字符串初始到窄字符空间

//参数1:宽字符存储位置
//参数2:需要转换的字符
//参数3:是否给参数1申请一个内存空间
RtlAnsiStringToUnicodeString(&deviceanme, &str, TRUE);//把窄字符转换到宽字符
DbgPrint("--:%wZ--\n",&deviceanme);
RtlFreeUnicodeString(&deviceanme);//使用完后要释放掉空间

五、字符串之间的复制,及小写字母转大写字母
RtlCopyUnicodeString(&targeunicode,&deviceanme); 字符串拷贝
RtlUpcaseUnicodeString(&deviceanme, &deviceanme, FALSE); 小写字符转大写

	UNICODE_STRING targeunicode = {
    
     0 };//定义一个缓冲区

	targeunicode.Buffer = ExAllocatePool(NonPagedPool, 0x1000);//给缓存区分配一个指针
	
	targeunicode.MaximumLength = 0x1000;//设置缓冲区的长度

	PCHAR tempbuffer = "C:\\123\\321\\567\\123.txt";

	
	STRING str = {
    
     0 };
	
	RtlInitString(&str,tempbuffer);

	RtlAnsiStringToUnicodeString(&deviceanme, &str, TRUE);

	//参数1:目标
	//参数2:源字符串
	RtlCopyUnicodeString(&targeunicode,&deviceanme);
	
	//参数1可以与参数2相同,也可以是另外一个地址空间
	//参数1是被转换后的大写字母存放位置
	//参数2是需要进行转换的小写字母
	//参数3:是否需要为参数一的地址分配一个空间 FALSE 是不要分配空间,TRUE是要分配空间
	RtlUpcaseUnicodeString(&deviceanme, &deviceanme, FALSE);//小写字符串转换为大写
	
	RtlFreeUnicodeString(&deviceanme);//使用完后要释放掉空间
	ExFreePool(targeunicode.Buffer);//释放空间,一般要先清零后再释放,这里没有写清零

六、字符串安全的复制,追加, 查找前缀,比较两个字符是否相等,查找字符串
需要引用这个头文件 #include <ntstrsafe.h>
RtlStringCbCopyW(tempbuffer2, 0x1000, L"\??\");拷贝函数
RtlStringCbCatW(tempbuffer2, 0x1000, L"C:\123\AAA\bbb\aaa.txt"); 追加字符
RtlPrefixUnicodeString(&temp2, &temp1, FALSE)// 前缀,判断参数1是否是参数2的前缀

FsRtlIsNameInExpression(&temp5, &temp4, TRUE, NULL))//搜索字符串
//这个是关键,这里就是搜索条件,*表示其余字符,可以放在前或后,或者前后都放,一定要大写
RtlInitUnicodeString(&temp5, L"AAA");//设置查找条件
在参数2中查找是否包含参数1
使用FsRtlIsNameInExpression需要引入#include <ntifs.h> 而且要放在 #include <ntddk.h>前面,否则会报错

	PWCHAR tempbuffer2 = ExAllocatePool(NonPagedPool, 0x1000);

	RtlZeroMemory(tempbuffer2, 0x1000);//得到一片被清空的内存

	//拷贝字符串
	//参数1:一个内存空间
	//参数2:一个缓冲区的长度,就是参数1空间的长度
	//参数3:要复制的内容
	RtlStringCbCopyW(tempbuffer2, 0x1000, L"\\??\\");//安全的字符拷贝

	//参数3:要追加的字符串
	RtlStringCbCatW(tempbuffer2, 0x1000, L"C:\\123\\AAA\\bbb\\aaa.txt");//追加字符串

	UNICODE_STRING temp1 = {
    
     0 }, temp2 = {
    
     0 };

	RtlInitUnicodeString(&temp1, tempbuffer2);

	RtlInitUnicodeString(&temp2, L"\\??\\");

	//字符串前缀判断
	//判断一个字符串是否是另外一个字符串的头部,或者说是前缀
	//判断参数1是否是参数2的前缀
	//参数3是大小写是否敏感
	if (RtlPrefixUnicodeString(&temp2, &temp1, FALSE))
	{
    
    
		//如果是前缀就打印这个
		DbgPrint("Be Finde\n");
	}

	UNICODE_STRING temp3 = {
    
     0 }, temp4 = {
    
     0 };

	RtlInitUnicodeString(&temp3, L"D:\\ABc\\AAA\\ddd\\aaa.txt");

	RtlInitUnicodeString(&temp4, L"D:\\ABc\\AAA\\DDD\\aaa.txt");

	//字符串比较
	//参数1与参数2进行比较
	//参数3是大小写是否敏感
	if (RtlEqualUnicodeString(&temp3, &temp4, TRUE))
	{
    
    
		//字符串比较
		DbgPrint("temp3=temp4\n");
	}


	//搜索字符串
	UNICODE_STRING temp5 = {
    
     0 };

	//这个是关键,这里就是搜索条件,*表示其余字符,可以放在前或后,或者前后都放,一定要大写
	RtlInitUnicodeString(&temp5, L"*AAA*");

	//查找字符串
	//参数1就是搜索条件
	//在参数2中查找是否包含参数1
	//如果第三个参数是TRUE ,搜索条件字母必须全部大写,这样就能做到精准搜索
	if (FsRtlIsNameInExpression(&temp5, &temp4, TRUE, NULL))
	{
    
    

		//查找到了就打印下面
		DbgPrint("Searched\n");
	}

	DbgPrint("--%ws--\n", tempbuffer2);//大于出追加的字符串

完整测试代码


#include <ntifs.h>//必须放在前面
#include <ntddk.h>
#include <windef.h>

#include <ntstrsafe.h>//提供以下比较安全的函数



	NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    
    
	NTSTATUS status = STATUS_SUCCESS; //定义一个返回值



	UNICODE_STRING deviceanme = {
    
     0 };//初始一个存储设备名字的内存空间

	//UNICODE_STRING deviceanme = RTL_CONSTANT_STRING(DEVICE_NAME);//初始一个存储设备名字的内存空间 (方式二)

	PDEVICE_OBJECT pdevice = NULL; //设备创建后的输出参数,如果不为NULL就表示设备创建成功了

	driver->DriverUnload = DrvUnload;



	//------字符串的操作测试开始--------
	UNICODE_STRING targeunicode = {
    
     0 };//定义一个缓冲区

	targeunicode.Buffer = ExAllocatePool(NonPagedPool, 0x1000);//给缓存区分配一个指针

	targeunicode.MaximumLength = 0x1000;//设置缓冲区的长度

	PCHAR tempbuffer = "C:\\123\\AAA\\bbb\\aaa.txt";


	STRING str = {
    
     0 }; //定义一个窄字符串

	RtlInitString(&str, tempbuffer);//初始化一个字符串

	RtlAnsiStringToUnicodeString(&deviceanme, &str, TRUE);//窄字符转换为宽字符

	RtlCopyUnicodeString(&targeunicode, &deviceanme);//复制字串



	RtlUpcaseUnicodeString(&deviceanme, &deviceanme, FALSE);//小写字符串转换为大写
	DbgPrint("--%wZ--\n", &deviceanme);
	ExFreePool(targeunicode.Buffer);//释放空间,一般要先清零后再释放,这里没有写清零
	RtlFreeUnicodeString(&deviceanme);//使用完后要释放掉空间

	//------字符串的操作测试结尾--------------

	//------字符串安全操作测试开始-----------
	PWCHAR tempbuffer2 = ExAllocatePool(NonPagedPool, 0x1000);

	RtlZeroMemory(tempbuffer2, 0x1000);//得到一片被清空的内存

	//拷贝字符串
	//参数1:一个内存空间
	//参数2:一个缓冲区的长度,就是参数1空间的长度
	//参数3:要复制的内容
	RtlStringCbCopyW(tempbuffer2, 0x1000, L"\\??\\");//安全的字符拷贝

	//参数3:要追加的字符串
	RtlStringCbCatW(tempbuffer2, 0x1000, L"C:\\123\\AAA\\bbb\\aaa.txt");//追加字符串

	UNICODE_STRING temp1 = {
    
     0 }, temp2 = {
    
     0 };

	RtlInitUnicodeString(&temp1, tempbuffer2);

	RtlInitUnicodeString(&temp2, L"\\??\\");

	//字符串前缀判断
	//判断一个字符串是否是另外一个字符串的头部,或者说是前缀
	//判断参数1是否是参数2的前缀
	//参数3是大小写是否敏感
	if (RtlPrefixUnicodeString(&temp2, &temp1, FALSE))
	{
    
    
		//如果是前缀就打印这个
		DbgPrint("Be Finde\n");
	}

	UNICODE_STRING temp3 = {
    
     0 }, temp4 = {
    
     0 };

	RtlInitUnicodeString(&temp3, L"D:\\ABc\\AAA\\ddd\\aaa.txt");

	RtlInitUnicodeString(&temp4, L"D:\\ABc\\AAA\\DDD\\aaa.txt");

	//字符串比较
	//参数1与参数2进行比较
	//参数3是大小写是否敏感
	if (RtlEqualUnicodeString(&temp3, &temp4, TRUE))
	{
    
    
		//字符串比较
		DbgPrint("temp3=temp4\n");
	}


	//搜索字符串
	UNICODE_STRING temp5 = {
    
     0 };

	//这个是关键,这里就是搜索条件,*表示其余字符,可以放在前或后,或者前后都放,一定要大写
	RtlInitUnicodeString(&temp5, L"*AAA*");

	//查找字符串
	//参数1就是搜索条件
	//在参数2中查找是否包含参数1
	//如果第三个参数是TRUE ,搜索条件字母必须全部大写,这样就能做到精准搜索
	if (FsRtlIsNameInExpression(&temp5, &temp4, TRUE, NULL))
	{
    
    

		//查找到了就打印下面
		DbgPrint("Searched\n");
	}

	DbgPrint("--%ws--\n", tempbuffer2);//大于出追加的字符串
	

	
	//------字符串安全操作结尾-----------

	
	RtlInitUnicodeString(&deviceanme, DEVICE_NAME);//初始化一个字符串,这个是符合连接用的
												   
/*
	* IoCreateDevice创建设备 
	    参数1:driver 设备对象;
		参数2:0 设备扩展的大小;
		参数3:&deviceanme 设备名字;
		参数4:FILE_DEVICE_UNKNOWN(未知设备) 设备类型
		参数5:0  默认参数
		参数6:TRUE  默认参数
		参数7:&pdevice 输出参数,设备创建成功后,会把设备对象传出来
	*/
	status = IoCreateDevice(driver,200, &deviceanme, FILE_DEVICE_UNKNOWN,0,TRUE,&pdevice);

	if (!NT_SUCCESS(status))
	{
    
    
		//如果设备创建设备就打印下面的信息
		DbgPrint("Create Device Failed:%x\n",status);
		//返回错误信息
		return status;
	}

	//设备的读写方式(必须设置,否则蓝屏)
	pdevice->Flags |= DO_BUFFERED_IO;

	
	//到这里 设备就创建成功了
	
	
	UNICODE_STRING symname = {
    
     0 };//定义一个符号连接名称
	RtlInitUnicodeString(&symname, SYM_NAME);//初始化一个字符串
	/*IoCreateSymbolicLink创建符号连接
	
	  参数1:&symname 符号连接名字
	  参数2:&deviceanme 设备名字
	
	*/
	status = IoCreateSymbolicLink(&symname, &deviceanme);
	if (!NT_SUCCESS(status))
	{
    
    
		//如果创建符号连接失败就打印下面的信息
		DbgPrint("Create SymbolicLink Failed:%x\n", status);
		//既然创建符号连接失败,就要删除这个设备
		IoDeleteDevice(pdevice);
		//返回错误信息
		return status;
	}

	//到这里 符号连接就创建成功了

	//驱动的功能都写在下面,派遣函数

	//打开设备
	driver->MajorFunction[IRP_MJ_CREATE] = MyCreate;
	
	//关闭设备
	driver->MajorFunction[IRP_MJ_CLOSE] = MyClose;
	
	//清理设备
	driver->MajorFunction[IRP_MJ_CLEANUP] = MyCleanUp;
	
	//读取,应用层把内核数据读取出去
	driver->MajorFunction[IRP_MJ_READ] = MyRead;
	
	//写入取,应用层把数据写入内核
	driver->MajorFunction[IRP_MJ_WRITE] = MyWrite;

	//自定义控制
	driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyControl;

	return 0;
}

猜你喜欢

转载自blog.csdn.net/lygl35/article/details/112764847