首页
社区
课程
招聘
[翻译]创建注册表符号链接
2020-9-19 15:05 9424

[翻译]创建注册表符号链接

2020-9-19 15:05
9424

标准的Windows 注册表包含一些键,他们并不是真实的键,而是一种符号链接。比如说,在大多数情况下HKEY_LOCAL_MACHINE\System\CurrentControlSet就是一个链接到HKEY_LOCAL_MACHINE\System\ControlSet001的符号。当我们用注册表编辑器RegEdit.exe查看注册表时,符号链接看起来和正常的键没什么区别,他和链接目标完全一样。下面这张图展示了上面提到的键。他们看上去确实没什么不同。

 

 

在注册表中还存在着其他符号链接。另外一个例子就是HIVE HKEY_CURRENT_CONFIG就是一个链接到HKLM\SYSTEM\CurrentControlSet\Hardware Profiles\Current的符号。(HKLM 是 HKEY_LOCAL_MACHINE的缩写)

 

但是我们如何创建自己的链接呢?微软官方文档给出了如何做到这点的部分细节,但是文档里并未透露两个重要细节来使我们的符号链接生效。

 

让我们来看看我们能否创建一个符号链接。为了示范,我们在 HKEY_CURRENT_USER里创建一个链接到HKEY_CURRENT_USER\Control Panel\Destop\Colors的符号。

 

第一步是创建一个键并指定为一个链接而不是一个正常的键。(以下代码错误处理被省略了)

1
2
3
HKEY hKey;
RegCreateKeyEx(HKEY_CURRENT_USER,L"DesktopColors",0,nullptr,
    REG_OPTION_CREATE_LINK,KEY_WRITE,nullptr,&hKey,nullptr);

最重要部分是 REG_OPTION_CREATE_LINK 标志,他表明了期望创建的是一个链接,而不是标准的键。KEY_WRITE访问掩码也是必须的,因为我们要指定链接的目标。

 

接下来到了第一处棘手的部分。文档里指出链接的目标应该写在“SymbolicLinkValue”这个值里面,而且应该指定为一个完整的绝对路径。听上去很简单,对嘛?不,你错了。问题在于这个绝对路径,你可能想他应该是长这样:“HKEY_CURRENT_USER\Control Panel\Desktop\Colors”,和我们期望的一样。也许可以进一步把“HKEY_CURRENT_USER”精简为“HKCU”,毕竟他只是一个字符串而已。

 

事实证明这两种想法都是错误的。这里要求的绝对路径是一个原始的注册表路径。原始的注册表的样子在RegEdit.exe是看不到的,但是在我自己的注册表编辑工具RegEditX中可以看到,可以从链接里下载到。下面是一个运行截图。

 

 

上面的视图才是被Windows 内核实际看到的注册表。可以发现并没有HKEY_CURRENT_USER,只有一个USER键和基于用户会话id在这台机器上创建的用户账户的子键。在 HKEY_USERS Hive下的标准注册表项绝大部分都可见了。

 

前面提到的绝对路径就是应该是下面这样的。下面的代码写入了基于我当前账户的会话ID的正确路径。

1
2
3
WCHAR path[] = L"\\REGISTRY\\USER\\S-1-5-21-2575492975-396570422-1775383339-1001\\Control Panel\\Desktop\\Colors";
RegSetValueEx(hKey, L"SymbolicLinkValue", 0, REG_LINK, (const BYTE*)path,
    wcslen(path) * sizeof(WCHAR));

上面的代码展示了第二个未文档化的关键信息,符号链接的路径长度是按字节计算的,而且不包含NULL结束符。运气好,我猜对了

 

就是这样。现在我们可以安全的收尾了,关闭HKEY,完成了创建。

 

如果你想尝试使用RegEdit.exe来删除刚才你创建的键话,链接的目标将会被删除,而不是你创建的符号本身。所以你该怎么删除你创建的符号链接呢?我的RegEditX目前还不支持这样的操作。

 

标准的RegDeleteKeyRegDeleteKeyExAPIs也不能删除这个符号链接。即使你给他以REG_OPTION_OPEN_LINK打开的句柄,他也会忽略这个然后找到链接目标。唯一奏效的API还是来自NtDll.Dll的NtDeleteKey函数。

 

首先,我们添加一个函数声明,然后导入NtDll。

1
2
extern "C" int NTAPI NtDeleteKey(HKEY);
#pragame comment(lib,"ntdll")

现在我们可以像这样删除一个符号链接。

1
2
3
HKEY hKey;
RegOpenKeyEx(HKEY_CURRENT_USER,L"DesktopColors",REG_OPTION_DELETE,&hKey);
NtDeleteKey(hKey);

最后我想说的是,RegCreateKeyEx不能打开一个存在的符号链接键,他只能进行创建操作。这与可以用RegCreateEx创建或打开标准键完全不同。这意味着如果你想改变存在符号链接的链接目标,你首先必须调用RegOpenKeyEx (REG_OPTION_OPEN_LINK),然后做更改操作(删除键或者重新创建它)

 

注册表真有趣!不是嘛?


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回