这节课主要学习注册表的相关操作,包括注册表的打开,读取,修改,删除。可以自己通过底层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\n", 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 \n");
}
else if (keyop == REG_OPENED_EXISTING_KEY)
{
DbgPrint("Key has be Opened \n");
}
else {
DbgPrint("Error\n");
}
}
//
//读取注册表
//
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\n", imagepath);
//C:\Windows\System32\drivers
//拷贝驱动文件
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\n", 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的话那代表开机自启,不过这个有条件限制需要注意!