实现效果
注册表的查询,,可以查询到驱动的路径,把驱动拷贝到系统目录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()//运行时函数,检测某个注册表是否存在
}