0

我正在开发一个实用程序来挂钩不同应用程序使用的 Windows API 的各个位。目前,该项目的目标是通过使用 easyhook 和 boost(特别是 property_tree 库)将文件系统和注册表调用重定向到自定义位置来使任何应用程序可移植。

我目前正在研究项目的注册表部分,我已经成功创建了 RegCreateKey(ExA/ExW/A/W)、RegOpenKey(ExA/ExW/A/W) 和 RegCloseKey 函数的类似物,它们工作正常(i制作了一个虚拟句柄系统来创建和翻译 hKey 句柄)。它们的工作原理是基本上将所有内容转换为字符串并将它们保存在 boost 属性树中(然后将树写入 .info 文件)。

我开始研究 RegSetValue 和 RegQueryValue 函数,它们实际上处理数据并遇到了一个主要问题。下面是两个函数。请注意,这些是由 easyhook 使用与原始 winapi 调用相同的参数调用的。

LSTATUS WINAPI myRegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData)
{
    boost::property_tree::ptree VirtualRegistry;
    boost::property_tree::read_info("VirtualRegistry.info", VirtualRegistry);
    VirtualRegistry.put(boost::property_tree::ptree::path_type(std::string(GetPathFromHandleA(hKey) + '\\' + lpValueName), '\\'), reinterpret_cast<const char*>(lpData));
    boost::property_tree::write_info("VirtualRegistry.info", VirtualRegistry);

    return ERROR_SUCCESS;
}

这适用于 REG_SZ 调用,但其他类型的数据未正确保存。

LSTATUS WINAPI myRegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
{
    boost::property_tree::ptree VirtualRegistry;
    boost::property_tree::read_info("VirtualRegistry.info", VirtualRegistry);
    try
    {
        *lpData = reinterpret_cast<const BYTE*>VirtualRegistry.get_child(boost::property_tree::ptree::path_type(std::string(GetPathFromHandleA(hKey) + "\\" + lpValueName), '\\')).data();
        return ERROR_SUCCESS;
    }
    catch (const boost::property_tree::ptree_bad_path& e1)
    {
        std::cout << "\n" << "ENTRY NOT FOUND" << "\n";
        return ERROR_FILE_NOT_FOUND;
    }
}

这不起作用。第 6 行的重新解释是无效的,它不会编译。

问题是我的函数处理不同类型数据的方式。注册表调用可以有许多不同的值类型,而我编写 myRegSetValue 的方式似乎只适用于 REG_SZ。在将调用写入文件时,我还必须保存值类型,但这并不能解决问题。

所以我的问题是,有没有办法将调用的原始数据保存为字符串,而不必将其转换为字符串,以便它适用于所有类型的数据,然后从文件中读取一个字符串返回原始数据并将其传递给应用程序?

我想我可以为每种密钥类型编写一个单独的解释器,但我真的不想这样做,因为它会非常hacky并且还会破坏不正确使用注册表API并在注册表中存储无效值的应用程序(例如,例如, Unity 游戏 Sunless Sea)。

谢谢,我希望我解释得足够详细。

4

1 回答 1

1

看来真正的问题已经是myRegSetValueExA. 当您得到 时lpData,您不能假设它指向将保持有效的数据。您必须存储的不是指针,而是指向的数据。

这也是为什么cbData是必要的;您需要知道要存储多少数据。您不能依赖,strlen因为类型可能不是REG_SZ.

请注意,您的假设This works fine for REG_SZ是正确的,只是因为VirtualRegistry.put(std::string key, const char* value)它是一个方便的重载,需要strlen(buf)您。

解决方案是显式创建std::string data(static_cast<const char*>(lpData), cbData)并在put. 要检索它,请使用.get<std::string>(key)而不是get_child(key).data().

于 2020-11-26T14:44:21.797 回答