内核操作注册表

实现效果

注册表的查询,,可以查询到驱动的路径,把驱动拷贝到系统目录C:\Windows\System32\drivers,并且把驱动路径改为 C:\Windows\System32\drivers

知识点:

1、驱动文件在注册表中的路径 用 类似 “\SystemRoot\system32\drivers\afd.sys”这样的格式,比用
“??\C:\Windows\System32\drivers\MyDriver2.sys” 这种格式能满足你跟早的启动的需求
2、Start 值 越小启动越早,3是手动启动,4是禁用
在这里插入图片描述

打开注册表函数 ZwCreateKey

//------注册表操作开始-----------------
	
	//打开注册表

	HANDLE keyhandle = NULL;

	OBJECT_ATTRIBUTES obja = {
    
     0 };//存放注册表描述的结构

	ULONG keyop = 0;

	//初始化注册表描述到obja里面去
	//reg_path第二个参数是注册表路径,如果要打开其它注册表路径 就用RtlInitUnicodeString函数初始化一个路径
	InitializeObjectAttributes(&obja,reg_path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

	// 打开注册表KEY 有两个函数 ZwOpenkey 和ZwCreateKey
	
	///ZwCreateKey 可以打开一个注册表,还可以创建一个注册表
	///参数1:&keyhandle 句柄
	///参数2:KEY_ALL_ACCESS 访问权限
	/// 最后一个参数说明:
	/// 如果指定了最后一个参数 &keyop ULONG指针,这个函数内部会根据打开参数的操作为这个指针地址赋值
	/// 根据 &keyop 这个返回值来判断是打开操作,还是创建等操作
	status = ZwCreateKey(&keyhandle,KEY_ALL_ACCESS, &obja,0,NULL,REG_OPTION_NON_VOLATILE, &keyop);

	if (NT_SUCCESS(status))
	{
    
    
		if (keyop == REG_CREATED_NEW_KEY)
		{
    
    
			//等于REG_CREATED_NEW_KEY表示新建注册表
			DbgPrint("Key has be Create\n");
		}
		else if(keyop == REG_OPENED_EXISTING_KEY)
		{
    
    
			//等于REG_OPENED_EXISTING_KEY表示注册表已经存在
			DbgPrint("Key has be Opened\n");
		}
		else
		{
    
    
			DbgPrint("Error\n");
		}

		//
		//
		//

		ZwClose(keyhandle);

读取注册表路径,如下图

在这里插入图片描述

ZwOpenkey函数拿上图的驱动路径

//------------------ZwOpenkey函数的使用开始--------------------
		
		//当我们确定一个注册%100存在的时候就用ZwOpenKey,相对ZwCreateKey参数简单一些
		//拿到句柄
		status = ZwOpenKey(&keyhandle, KEY_ALL_ACCESS, &obja);

		if (NT_SUCCESS(status))
		{
    
    
			//打开成功就可以操作了
			keyinfo = ExAllocatePool(NonPagedPool, 0x10000);//分配一个内存空间

			if (!keyinfo)
			{
    
    
				//如果分配内存失败就返回
				return 0;
			}

			RtlZeroMemory(keyinfo, 0x100000);//申请的内存空间清零

			UNICODE_STRING name = {
    
     0 };

			RtlInitUnicodeString(&name, L"ImagePath");

				//ZwQueryValueKey查询注册表
				//keyhandle 句柄
				//&name注册表键的名字称
				//KeyValuePartialInformation 枚举类型
				//keyinfo查询的缓冲区
				//0x1000查询的长度
			status = ZwQueryValueKey(keyhandle, &name, KeyValuePartialInformation, keyinfo,0x1000,&keyop);
			
			if (!NT_SUCCESS(status))
			{
    
    
				//查询失败
				ZwClose(keyhandle);//关闭句柄
				ExFreePool(keyinfo);//释放缓冲区
				return 0;
			}
			
			// 到这里注册表查询就成功了

			PKEY_VALUE_PARTIAL_INFORMATION tempinfo = (PKEY_VALUE_PARTIAL_INFORMATION)keyinfo;//(PKEY_VALUE_PARTIAL_INFORMATION)强制转换为某类型

			PWCHAR imagepath = (PWCHAR)(tempinfo->Data);//获取注册表路径信息

			DbgPrint("---imagepath-<%ws>--\n",imagepath);
		}

		//*****************ZwOpenkey函数的使用结束*****************

		ZwClose(keyhandle);

获取成功

在这里插入图片描述

一个运行时函数,查询一个注册表是否存在,如果没有回新建一个

在这里插入图片描述
运行结果
在这里插入图片描述
注册表有 123456
注册表有

注意问题

下图位置拷贝驱动文件前需要进行判断 文件是否已经存在,否则第二次启动会蓝屏,因为第二次启动的时候文件已经存在了,要运用前面字符判断的知识,对路径进行判断,看路径是修改过的路径就不拷贝了
在这里插入图片描述

完整代码:

//------注册表操作开始-----------------
	
	//打开注册表

	HANDLE keyhandle = NULL;

	OBJECT_ATTRIBUTES obja = {
    
     0 };//存放注册表描述的结构

	ULONG keyop = 0;

	PVOID keyinfo = NULL; //定义一个缓冲区

	//初始化注册表描述到obja里面去
	//reg_path第二个参数是注册表路径,如果要打开其它注册表路径 就用RtlInitUnicodeString函数初始化一个路径
	InitializeObjectAttributes(&obja,reg_path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

	// 打开注册表KEY 有两个函数 ZwOpenkey 和ZwCreateKey
	
	//------------------ZwCreateKey函数的使用开始--------------------
	
	///ZwCreateKey 可以打开一个注册表,还可以创建一个注册表
	///参数1:&keyhandle 句柄
	///参数2:KEY_ALL_ACCESS 访问权限
	/// 最后一个参数说明:
	/// 如果指定了最后一个参数 &keyop ULONG指针,这个函数内部会根据打开参数的操作为这个指针地址赋值
	/// 根据 &keyop 这个返回值来判断是打开操作,还是创建等操作
	status = ZwCreateKey(&keyhandle,KEY_ALL_ACCESS, &obja,0,NULL,REG_OPTION_NON_VOLATILE, &keyop);

	if (NT_SUCCESS(status))
	{
    
    
		if (keyop == REG_CREATED_NEW_KEY)
		{
    
    
			//等于REG_CREATED_NEW_KEY表示新建注册表
			DbgPrint("Key has be Create\n");
		}
		else if(keyop == REG_OPENED_EXISTING_KEY)
		{
    
    
			//等于REG_OPENED_EXISTING_KEY表示注册表已经存在
			DbgPrint("Key has be Opened\n");
		}
		else
		{
    
    
			DbgPrint("Error\n");
		}

		//************************ZwCreateKey函数的使用结束*********************


		//
		//
		//

		//------------------ZwOpenkey函数的使用开始--------------------
		
		//当我们确定一个注册%100存在的时候就用ZwOpenKey,相对ZwCreateKey参数简单一些
		//拿到句柄
		status = ZwOpenKey(&keyhandle, KEY_ALL_ACCESS, &obja);

		if (NT_SUCCESS(status))
		{
    
    
			//打开成功就可以操作了
			keyinfo = ExAllocatePool(NonPagedPool, 0x10000);//分配一个内存空间

			if (!keyinfo)
			{
    
    
				//如果分配内存失败就返回
				return 0;
			}

			RtlZeroMemory(keyinfo, 0x100000);//申请的内存空间清零

			UNICODE_STRING name = {
    
     0 };

			RtlInitUnicodeString(&name, L"ImagePath");

				//ZwQueryValueKey查询注册表
				//keyhandle 句柄
				//&name注册表键的名字称
				//KeyValuePartialInformation 枚举类型
				//keyinfo查询的缓冲区
				//0x1000查询的长度
			status = ZwQueryValueKey(keyhandle, &name, KeyValuePartialInformation, keyinfo,0x1000,&keyop);
			
			if (!NT_SUCCESS(status))
			{
    
    
				//查询失败
				ZwClose(keyhandle);//关闭句柄
				ExFreePool(keyinfo);//释放缓冲区
				return 0;
			}
			
			// 到这里注册表查询就成功了

			PKEY_VALUE_PARTIAL_INFORMATION tempinfo = (PKEY_VALUE_PARTIAL_INFORMATION)keyinfo;//(PKEY_VALUE_PARTIAL_INFORMATION)强制转换为某类型

			PWCHAR imagepath = (PWCHAR)(tempinfo->Data);//获取驱动程序再注册表路径信息

			DbgPrint("---imagepath-<%ws>--\n",imagepath);

			//拷贝驱动文件到 C:\Windows\System32\drivers目录
			KernelCopyFile(L"\\??\\C:\\Windows\\System32\\drivers\\asdiopss2.sys",imagepath);
			
			
			//------------修改驱动程序再注册表中的路径fix path————————————
			
			PWCHAR rootpath = L"\\SystemRoot\\system32\\drivers\\asdiopss2.sys";
			
			///ZwSetValueKey设置注册表的值
			///keyhandle 句柄
			///imagepath 要修改的名字
			/// REG_EXPAND_SZ 注册表参数类型(打开注册表,抄里面的类型就可以)
			/// 写入的DATA 数据 ,这里是要写入的路径信息 rootpath
			/// wcslen(rootpath) 写入数据的长度
			status = ZwSetValueKey(keyhandle, &name, 0, REG_EXPAND_SZ, rootpath,wcslen(rootpath)*2+2);

			if (!NT_SUCCESS(status)) 
			{
    
    
				//写入注册表信息失败提示
				DbgPrint("Error Code-<%x>-\n", status);
			}
			
		
			
			
			
			
			ExFreePool(keyinfo);//释放缓冲区
		}

		//*****************ZwOpenkey函数的使用结束*****************

		ZwClose(keyhandle);


		//-----使用另外一种方式来写入注册表----------

		ULONG tempstart = 1;

		//RtlWriteRegistryValue是微软封装好的一个修改注册表的函数
		//reg_path->Buffer 驱动路径
		//L"Start" 要修改注册表的键名称
		//tempstart 键的值,这里是设置启动优先级 可以设置 0  1  2 3 4 
		//4  修改数据的大小 ,这里意思是 4个字节大小
		RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, reg_path->Buffer, L"Start",REG_DWORD,&tempstart,4);

		//ZwDeleteKey() //运行时函数, 删除注册表函数,如果有子项目,要先删除子项目
		//RtlCheckRegistryKey()//运行时函数,检测某个注册表是否存在

	}

猜你喜欢

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