Правильно добавить строку в тип REG_BINARY в реестре Windows

Я пытаюсь автоматизировать процесс добавления правил хэширования политики программного обеспечения в 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
);

Это отлично работает и добавляет ключ в реестр:

Мое хеш-правило

Но при сравнении раздела реестра с правилом, добавленным групповой политикой, вы можете увидеть очень важное различие:

Windows добавила правило хеша

Значения ItemData между ними различны. Значение ItemData нижнего изображения является правильным выводом. При отладке программы я ясно вижу, что md5Digest имеет правильное значение, поэтому проблема заключается в преобразовании строки md5Digest в вектор ItemData байтов или неподписанных символов ….

Visual Studio Debugging

В чем проблема с моим кодом, почему данные неправильно вводятся в реестр?

0

Решение

У вас есть строка, которую вы хотите преобразовать в байтовый массив. Вы можете написать вспомогательную функцию для преобразования 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
);
1

Другие решения

У тебя есть '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])     )
);
}
1

По вопросам рекламы [email protected]