将字符串正确添加到 Windows 注册表中的 REG_BINARY 类型
Correctly add string to a REG_BINARY type in Windows Registry
我正在尝试自动执行将软件策略哈希规则添加到 Windows 的过程,但目前在向注册表添加有效哈希时遇到问题。此代码创建一个密钥并将散列添加到注册表:
HKEY* m_hKey;
string md5Digest;
string valueName = "ItemData";
vector<BYTE> itemData;
/*
use Crypto++ to get file hash
*/
//convert string to format that can be loaded into registry
for (int i = 1; i < md5Digest.length(); i += 2)
itemData.push_back('0x' + md5Digest[i - 1] + md5Digest[i]);
// Total data size, in bytes
const DWORD dataSize = static_cast<DWORD>(itemData.size());
::RegSetValueEx(
m_hKey,
valueName.c_str(),
0, // reserved
REG_BINARY,
&itemData[0],
dataSize
);
这工作正常,并将密钥添加到注册表:
但是当将注册表项与组策略添加的规则进行比较时,您会发现一个非常重要的区别:
它们之间的 'ItemData' 值不同。底部图片的 ItemData 值是正确的输出。在调试程序时,我可以清楚地看到 md5Digest 具有正确的值,所以问题在于将 md5Digest 字符串转换为 BYTE 或 unsigned chars 的 ItemData 向量....
我的代码有什么问题,为什么向注册表输入的数据不正确?
您有 '0x'
个由 md5Digest[i - 1] + md5Digest[i]
总结的两个字母的字符文字,然后传送到 BYTE
。这看起来像是您试图从中构建“0xFF”字节值。您应该直接存储 md5 字符串:
const DWORD dataSize = static_cast<DWORD>(md5Digest.size());
::RegSetValueEx(
m_hKey,
valueName.c_str(),
0, // reserved
REG_BINARY,
reinterpret_cast< BYTE const *>(md5Digest.data()),
dataSize
);
如果您确实需要存储来自 md5 的十六进制数的二进制表示,那么您需要像这样将它们转换为字节:
BYTE char_to_halfbyte(char const c)
{
if(('0' <= c) && (c <= '9'))
{
return(static_cast<BYTE>(c - `0`));
}
else
{
assert(('A' <= c) && (c <= 'F'));
return(static_cast<BYTE>(10 + c - `A`));
}
}
for(std::size_t i = 0; i < md5Digest.length(); i += 2)
{
assert((i + 1) < md5Digest.length());
itemData.push_back
(
(char_to_halfbyte(md5Digest[i ]) << 4)
|
(char_to_halfbyte(md5Digest[i + 1]) )
);
}
您有一个要转换为字节数组的字符串。您可以编写一个辅助函数将 2 个字符转换为 BYTE:
using BYTE = unsigned char;
BYTE convert(char a, char b)
{
// Convert hex char to byte
// Needs fixin for lower case
if (a >= '0' && a <= '9') a -= '0';
else a -= 55; // 55 = 'A' - 10
if (b >= '0' && b <= '9') b -= '0';
else b -= 55;
return (a << 4) | b;
}
....
vector<BYTE> v;
string s = "3D65B8EBDD0E";
for (int i = 0; i < s.length(); i+=2) {
v.push_back(convert(s[i], s[i+1]));
}
v 现在包含 {0x3D, 0x65, 0xB8, 0xEB, 0xDD, 0x0E}
或者,如@RbMm 所述,您可以使用 CryptStringToBinary
Windows 函数:
#include <wincrypt.h>
...
std::string s = "3D65B8EBDD0E";
DWORD hex_len = s.length() / 2;
BYTE *buffer = new BYTE[hex_len];
CryptStringToBinary(s.c_str(),
s.length(),
CRYPT_STRING_HEX,
buffer,
&hex_len,
NULL,
NULL
);
我正在尝试自动执行将软件策略哈希规则添加到 Windows 的过程,但目前在向注册表添加有效哈希时遇到问题。此代码创建一个密钥并将散列添加到注册表:
HKEY* m_hKey;
string md5Digest;
string valueName = "ItemData";
vector<BYTE> itemData;
/*
use Crypto++ to get file hash
*/
//convert string to format that can be loaded into registry
for (int i = 1; i < md5Digest.length(); i += 2)
itemData.push_back('0x' + md5Digest[i - 1] + md5Digest[i]);
// Total data size, in bytes
const DWORD dataSize = static_cast<DWORD>(itemData.size());
::RegSetValueEx(
m_hKey,
valueName.c_str(),
0, // reserved
REG_BINARY,
&itemData[0],
dataSize
);
这工作正常,并将密钥添加到注册表:
但是当将注册表项与组策略添加的规则进行比较时,您会发现一个非常重要的区别:
它们之间的 'ItemData' 值不同。底部图片的 ItemData 值是正确的输出。在调试程序时,我可以清楚地看到 md5Digest 具有正确的值,所以问题在于将 md5Digest 字符串转换为 BYTE 或 unsigned chars 的 ItemData 向量....
我的代码有什么问题,为什么向注册表输入的数据不正确?
您有 '0x'
个由 md5Digest[i - 1] + md5Digest[i]
总结的两个字母的字符文字,然后传送到 BYTE
。这看起来像是您试图从中构建“0xFF”字节值。您应该直接存储 md5 字符串:
const DWORD dataSize = static_cast<DWORD>(md5Digest.size());
::RegSetValueEx(
m_hKey,
valueName.c_str(),
0, // reserved
REG_BINARY,
reinterpret_cast< BYTE const *>(md5Digest.data()),
dataSize
);
如果您确实需要存储来自 md5 的十六进制数的二进制表示,那么您需要像这样将它们转换为字节:
BYTE char_to_halfbyte(char const c)
{
if(('0' <= c) && (c <= '9'))
{
return(static_cast<BYTE>(c - `0`));
}
else
{
assert(('A' <= c) && (c <= 'F'));
return(static_cast<BYTE>(10 + c - `A`));
}
}
for(std::size_t i = 0; i < md5Digest.length(); i += 2)
{
assert((i + 1) < md5Digest.length());
itemData.push_back
(
(char_to_halfbyte(md5Digest[i ]) << 4)
|
(char_to_halfbyte(md5Digest[i + 1]) )
);
}
您有一个要转换为字节数组的字符串。您可以编写一个辅助函数将 2 个字符转换为 BYTE:
using BYTE = unsigned char;
BYTE convert(char a, char b)
{
// Convert hex char to byte
// Needs fixin for lower case
if (a >= '0' && a <= '9') a -= '0';
else a -= 55; // 55 = 'A' - 10
if (b >= '0' && b <= '9') b -= '0';
else b -= 55;
return (a << 4) | b;
}
....
vector<BYTE> v;
string s = "3D65B8EBDD0E";
for (int i = 0; i < s.length(); i+=2) {
v.push_back(convert(s[i], s[i+1]));
}
v 现在包含 {0x3D, 0x65, 0xB8, 0xEB, 0xDD, 0x0E}
或者,如@RbMm 所述,您可以使用 CryptStringToBinary
Windows 函数:
#include <wincrypt.h>
...
std::string s = "3D65B8EBDD0E";
DWORD hex_len = s.length() / 2;
BYTE *buffer = new BYTE[hex_len];
CryptStringToBinary(s.c_str(),
s.length(),
CRYPT_STRING_HEX,
buffer,
&hex_len,
NULL,
NULL
);