关于windows注册表重定向和虚拟化分析

转载源地址 https://www.cnblogs.com/xenophon/p/4956218.html

在 64 位系统上,32 位程序读写部分注册表路径时会被系统重定向,这有些类似于读写 System32 文件夹的处理方式。比如,写入 HKLM\Software\KeyName,却发现实际写入到 HKLM\Software\Wow6432Node\KeyName,读取亦是如此。现实中发现,很多的程序员在检测一个程序在 HKLM 键下面的注册表信息,通常会针对 HKLM\Software 和 HKLM\Software\Wow6432Node 分别检查,实际上这样检查毫无效果。对于 32 位程序而言,访问 HKLM\Software 时,系统底层会重定向到 HKLM\Software\Wow6432Node,并不能得到真正的 HKLM\Software 下面的信息,即便再访问一次 HKLM\Software\Wow6432Node,经测试也是访问 Wow6432Node 下面的值,和直接访问 HKLM\Software 并没有任何区别。如果你仔细阅读 MSDN 上关于注册表重定向和访问权限等资料,会发现微软提供了两个特殊的注册表权限位:KEY_WOW64_32KEY、KEY_WOW64_64KEY,来控制访问权限。所以,当使用 RegOpenKeyEx 或 RegCreateKeyEx 访问注册表的 HKCR 或 HKLM\Software 下的路径,不需要显式指定 Wow6432Node,而是应当通过其权限位,如 KEY_READ,和上述二者之一进行组合来控制具体的访问位置。如果开发者显示指定 HKLM\Software\Wow6432Node,则程序在任何情况下都是访问这个路径。但是在 32 位系统中,这个路径默认并不存在,如果强行创建,依然没有任何意义。为了保持统一以及遵循 API 的规范,我们应该做到不显式指定 Wow6432Node 子键。如果不通过权限位进行访问视图控制,可能会造成代码逻辑混乱,如访问不同的注册表路径实际上底层逻辑相同,或者同样的代码编译为 32 位或 64 位后逻辑不一致等等。所以,如果要检测 32 位和 64 位注册表 HKLM\SOFTWARE\KeyName 下是否存在 ValueName,规范的代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

BOOL WINAPI RegCheckValueTest(void)

{

    DWORD dwWowFlags[] = { KEY_WOW64_32KEY, KEY_WOW64_64KEY };

    DWORD dwWowCount = ARRAYSIZE(dwWowFlags);

    for (size_t i = 0; i < dwWowCount; i++)

    {

        HKEY hKey = NULL;

        DWORD dwAccess = KEY_READ | dwWowFlags[i];

        DWORD dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\KeyName"), dwAccess, &hKey);

        if (dwError == NO_ERROR)

        {

            dwError = RegQueryValueEx(hkeySub, _T("ValueName"), NULL, NULL, NULL, NULL);

            RegCloseKey(hKey);

            if (dwError == NO_ERROR)

            {

                return TRUE;

            }

        }

    }

    return FALSE;

}

在不同 CPU 位数的系统上,32 位和 64 位程序分别使用不同的权限位组合访问 HKLM\Software 时,系统底层实际访问的注册表位置如下表所示:

系统架构程序架构显式访问路径实际访问路径备注
权限位不含 KEY_WOW64_*权限位包含 KEY_WOW64_32KEY权限位包含 KEY_WOW64_64KEY
32 位系统32 位程序HKLM\SoftwareHKLM\Software原因:在 32 位系统上不存在不同访问视图
影响:参数 KEY_WOW64_* 被系统忽略
64 位系统32 位程序HKLM\SoftwareHKLM\Software\Wow6432NodeHKLM\Software\Wow6432NodeHKLM\Software 
64 位程序HKLM\SoftwareHKLM\Software
32 位程序HKLM\Software\Wow6432NodeHKLM\Software\Wow6432Node原因:在路径中显式指定了 Wow6432Node 节点
影响:参数 KEY_WOW64_* 被系统忽略
64 位程序

备注:注意RegOpenKeyEx第四个形参,KEY_QUERY_VALUE或者KEY_READ、KEY_ALL_ACCESS等,权限是有区别的,不要越权操作,否侧会被返回为空。

KEY_QUERY_VALUE显然权限低于KEY_ALL_ACCESS。

可见,32 位程序访问注册表 HKLM\Software 路径时,默认会被重定向到 HKLM\Software\Wow6432Node,如果权限位指定 KEY_WOW64_64KEY 时则访问 HKLM\Software。64 位程序访问注册表 HKLM\Software 路径时,默认会访问 HKLM\Software,如果权限位指定 KEY_WOW64_32KEY 时则访问 HKLM\Software\Wow6432Node。当然,前提是程序并没有受到注册表虚拟化影响,否则会被写入到以下注册表位置:

1

2

HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\SOFTWARE

HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\SOFTWARE\Wow6432Node

实际观察发现 HKCU\SOFTWARE\Wow6432Node 下面只有极少量的数据,因此 HKCU\SOFTWARE\Wow6432Node 下面(包括其他从此处映射的键)的注册表键通常可以忽略。这可以说明,注册表针对 32 和 64 位的重定向仅针对 HKLM(包括其他从此处映射的键)有效,如果要访问 HKCU 下面的节点,通常无需考虑重定向的问题。而在 32 位系统上,不存在注册表重定向的问题。

关于注册表重定向的更多信息,请访问:
https://msdn.microsoft.com/en-us/library/aa384253.aspx
https://msdn.microsoft.com/en-us/library/aa384129.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值