您现在的位置是:首页 >技术交流 >tiechui_lesson06_注册表操作网站首页技术交流

tiechui_lesson06_注册表操作

忧郁虫虫 2024-06-14 00:01:02
简介tiechui_lesson06_注册表操作

这节课主要学习注册表的相关操作,包括注册表的打开,读取,修改,删除。可以自己通过底层API手动来获取和设置注册表,也可以用微软提供的运行时函数。我的看法是底层函数用来了解原理,真正在代码中使用的时候还是会优先使用微软封装好的Rtl运行时函数。

而且通过这节课也让我对注册表有了一些认识,注册表就像是一种可视化的数据结构,存放一些程序需要或者系统需要的一些数值,是一些键值对的集合。

一、课程代码

封装了一个函数RegistryCopy,来实验课程代码,不用上来就复制整个文件代码了。

涉及API:

  • ZwCreateKey
  • ZwOpenKey (简化版 ZwCreateKey)
  • ZwQueryValueKey
  • ZwSetValueKey
  • ZwDeleteKey
  • RtlWriteRegistryValue
  • RtlCheckRegistryKey
  • RtlCreateRegistryKey
//注册表操作
VOID RegistryCopy(IN PDRIVER_OBJECT DriverObject,
	IN PUNICODE_STRING RegistryPath)
{
	UNREFERENCED_PARAMETER(DriverObject);
	NTSTATUS status = STATUS_SUCCESS;
	HANDLE keyhandle = NULL;
	OBJECT_ATTRIBUTES obja = { 0 };
	ULONG keyop = 0;
	PVOID keyinfo = NULL;	// 存放注册表
	InitializeObjectAttributes(&obja, RegistryPath,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
		NULL,
		NULL);
	
	DbgPrint("驱动注册表路径:%wZ
", RegistryPath);

	//
	//打开注册表  ZwCreateKey 如果确定注册表存在可以使用ZwOpenKey(只用前三个参数)
	//
	status = ZwCreateKey(
		&keyhandle, 
		KEY_ALL_ACCESS, 
		&obja,
		0, 
		NULL, 
		REG_OPTION_NON_VOLATILE, 
		&keyop);
	if (NT_SUCCESS(status))
	{
		if (keyop == REG_CREATED_NEW_KEY)
		{
			DbgPrint("Key has be Created 
");
		}
		else if (keyop == REG_OPENED_EXISTING_KEY)
		{
			DbgPrint("Key has be Opened 
");
		}
		else {
			DbgPrint("Error
");
		}
	}

	//
	//读取注册表
	//
	keyinfo = ExAllocatePoolWithTag(NonPagedPool, 0x1000, '1213');
	if (!keyinfo)
	{
		return ;
	}
	RtlZeroMemory(keyinfo, 0x1000);

	UNICODE_STRING keyname = RTL_CONSTANT_STRING(L"ImagePath");

	status = ZwQueryValueKey(keyhandle, &keyname,
		KeyValuePartialInformation, keyinfo, 0x1000,&keyop);
	if (!NT_SUCCESS(status))
	{
		ZwClose(keyhandle);
		ExFreePoolWithTag(keyinfo, '1213');
		return;
	}

	PKEY_VALUE_PARTIAL_INFORMATION tempinfo = (PKEY_VALUE_PARTIAL_INFORMATION)keyinfo;

	PWCHAR imagepath = (PWCHAR)(tempinfo->Data);

	DbgPrint("ImagePath is %ws
", imagepath);

	//C:WindowsSystem32drivers

	//拷贝驱动文件
	KernelCopyFile(L"\??\C:\Windows\System32\drivers\asdioss.sys",
		imagepath);

	//
	//修改注册表路径
	//
	PWCHAR rootpath = L"\SystemRoot\system32\dirvers\asdioss.sys";
	status = ZwSetValueKey(keyhandle, &keyname, 0,
		REG_EXPAND_SZ, rootpath, (ULONG)(wcslen(rootpath) * 2 + 2));
	if (!NT_SUCCESS(status))
	{
		DbgPrint("Error code %x
", status);
	}


	//释放缓冲区
	ExFreePoolWithTag(keyinfo, '1213');
	//别忘记关闭句柄
	ZwClose(keyhandle);


	//
	//	使用另外一种方式写入注册表 
	//	微软运行时函数RtlWriteRegistryValue 封装好很多。
	//
	ULONG tempstartlevel = 1;
	RtlWriteRegistryValue(
		RTL_REGISTRY_ABSOLUTE,
		RegistryPath->Buffer,
		L"Start",
		REG_DWORD,
		&tempstartlevel,	//启动 级别
		4);

	//
	//	注册表删除
	//
	//ZwDeleteKey(keyhandle);//只能删除没有子健的注册表

	//
	//运行时函数 RtlCheckRegistryKey 
	//
	status = RtlCheckRegistryKey(RTL_REGISTRY_SERVICES,L"123456");//检测某个注册表是否存在
	if (NT_SUCCESS(status))
	{
		DbgPrint("Be Founed");
	}
	else {
		DbgPrint("Not Founed");
		RtlCreateRegistryKey(RTL_REGISTRY_SERVICES, L"123456");
	}


}

在DriverEntry中:

//入口函数
NTSTATUS DriverEntry(
	IN PDRIVER_OBJECT DriverObject, 
	IN PUNICODE_STRING RegistryPath
)
{
	UNREFERENCED_PARAMETER(RegistryPath);
	
    ······

	//KernelCopyFile(L"\??\C:\888.exe", L"\??\C:\567.exe");
	RegistryCopy(DriverObject, RegistryPath);

	return 0;
}

 二、运行效果

创建的注册表:

小结

感觉打基础是相当枯燥的事情,不想继续敲了!???

不过拓展知识边界的感觉也还不错,就是“这个能有什么用”的小声音再困扰自己,先坚持敲完吧!

这节还是需要注意句柄的打开和关闭,缓冲区的申请和释放。还有驱动服务注册表的Start字段是代表着驱动服务的启动级别(1、2、3、4),正常是3,如果是4的话代表禁止启动,如果是1的话那代表开机自启,不过这个有条件限制需要注意!

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。