首页 > 解决方案 > 检查注册表项是否链接到(或副本)另一个

问题描述

如何检查注册表项是否使用 winapi 链接到另一个注册表项?

例如,我需要找出哪个分支是原始的HKEY_LOCAL_MACHINE\SECURITY\SAMor HKEY_LOCAL_MACHINE\SAM\SAMHKEY_CURRENT_USERor HKEY_USERS\S-1-5-21

我对键和值的类型感到困惑。钥匙有类型吗?我可以REG_LINK为此目的使用类型吗?

标签: c++windowswinapiregistry

解决方案


首先,我们必须打开密钥本身,而不是潜在的符号链接密钥所引用的密钥(这是默认行为)。

为此,我们需要REG_OPTION_OPEN_LINK在 callRegOpenKeyExW或中使用选项ZwOpenKeyEx。替代方式使用OBJ_OPENLINK中的属性OBJECT_ATTRIBUTES。并在通话中使用它ZwOpenKey[Ex]

打开密钥后,我们可以通过查询(从win7开始)未记录的KeyFlagsInformation信息ZwQueryKey。如果标志显示这是符号链接 - 我们可以查询SymbolicLinkValue获取链接目标键的值。请注意,即使使用类型也存在此值REG_LINK- 不能证明这是符号链接。

struct KEY_CONTROL_FLAGS_INFO_W7  // KeyFlagsInformation for Win7
{
    ULONG ControlFlags[3];
};

#define KEY_CTRL_FL_W7_01__IS_VOLATILE                                 0x01
#define KEY_CTRL_FL_W7_01__SYM_LINK                                    0x02

LSTATUS IsSymLink(HKEY hKey, PCWSTR lpSubKey, BOOL& IsLink)
{
    LSTATUS r = RegOpenKeyEx(hKey, lpSubKey, REG_OPTION_OPEN_LINK, KEY_READ|KEY_WOW64_64KEY, &hKey);

    if (r == NOERROR)
    {
        ULONG Type, cb = 0, rcb = 0x80;

        KEY_CONTROL_FLAGS_INFO_W7 kcf;

        NTSTATUS status;

        if (0 <= (status = ZwQueryKey(hKey, KeyFlagsInformation, &kcf, sizeof(kcf), &cb)))
        {
            if (kcf.ControlFlags[1] & KEY_CTRL_FL_W7_01__SYM_LINK)
            {
                IsLink = TRUE;
                DbgPrint("key is link\n");

                PVOID stack = alloca(guz), buf = 0;

                do 
                {
                    if (cb < rcb)
                    {
                        cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
                    }

                    r = RegQueryValueExW(hKey, L"SymbolicLinkValue", 0, &Type, (PBYTE)buf, &(rcb = cb));

                    if (r == NOERROR && Type == REG_LINK && !(rcb & (sizeof(WCHAR) - 1)))
                    {
                        DbgPrint("%.*S\n", rcb / sizeof(WCHAR), buf);
                    }

                } while (r == ERROR_MORE_DATA);
            }
        }
        else
        {
            r = RtlNtStatusToDosError(status);
        }

        RegCloseKey(hKey);
    }

    return r;
}

钥匙有类型吗?

不。类型只有键值

我可以为此目的使用 REG_LINK 类型吗?

我们可以在通常(非链接)键上创建SymbolicLinkValue具有类型的值,REG_LINK但在此之后键没有成为链接。密钥必须最初使用REG_OPTION_CREATE_LINK选项创建。所以通过查询SymbolicLinkValue值我们不能可靠地检查这是否是链接,但如果我们知道这是链接 - 我们可以通过查询获得链接的目标SymbolicLinkValue


推荐阅读