1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-02-16 00:24:29 +01:00

Convert registry access to use UTF-8

This commit is contained in:
Brent Cook 2015-11-10 14:44:27 -06:00
parent 3a7dc24a10
commit bc8dfb17b5

View File

@ -12,18 +12,20 @@ DWORD request_registry_create_key(Remote *remote, Packet *packet);
DWORD request_registry_check_key_exists(Remote *remote, Packet *packet) DWORD request_registry_check_key_exists(Remote *remote, Packet *packet)
{ {
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
LPCTSTR baseKey = NULL; char *tmp;
wchar_t *baseKey = NULL;
HKEY rootKey = NULL; HKEY rootKey = NULL;
HKEY resultKey = NULL; HKEY resultKey = NULL;
BOOL exists = FALSE; BOOL exists = FALSE;
DWORD result; DWORD result;
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY); rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY); tmp = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY);
baseKey = utf8_to_wchar(tmp);
if (rootKey && baseKey) if (rootKey && baseKey)
{ {
result = RegOpenKeyA(rootKey, baseKey, &resultKey); result = RegOpenKeyW(rootKey, baseKey, &resultKey);
if (result == ERROR_SUCCESS) if (result == ERROR_SUCCESS)
{ {
dprintf("[REG] Key found"); dprintf("[REG] Key found");
@ -41,6 +43,7 @@ DWORD request_registry_check_key_exists(Remote *remote, Packet *packet)
result = ERROR_INVALID_PARAMETER; result = ERROR_INVALID_PARAMETER;
} }
free(baseKey);
dprintf("[REG] Returning result: %u %x", result, result); dprintf("[REG] Returning result: %u %x", result, result);
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
@ -102,12 +105,12 @@ DWORD request_registry_unload_key(Remote *remote, Packet *packet)
static DWORD open_key(Packet *packet, HKEY *rootKey, HKEY *resKey) static DWORD open_key(Packet *packet, HKEY *rootKey, HKEY *resKey)
{ {
LPCTSTR baseKey = NULL; wchar_t *baseKey = NULL;
DWORD result = ERROR_INVALID_PARAMETER; DWORD result = ERROR_INVALID_PARAMETER;
DWORD permission; DWORD permission;
*rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY); *rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY); baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION); permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION);
// Validate the parameters and then attempt to create the key // Validate the parameters and then attempt to create the key
@ -116,8 +119,9 @@ static DWORD open_key(Packet *packet, HKEY *rootKey, HKEY *resKey)
if (!permission) if (!permission)
permission = KEY_ALL_ACCESS; permission = KEY_ALL_ACCESS;
result = RegOpenKeyEx(*rootKey, baseKey, 0, permission, resKey); result = RegOpenKeyExW(*rootKey, baseKey, 0, permission, resKey);
} }
free(baseKey);
return result; return result;
} }
@ -163,27 +167,27 @@ DWORD request_registry_open_key(Remote *remote, Packet *packet)
DWORD request_registry_open_remote_key(Remote *remote, Packet *packet) DWORD request_registry_open_remote_key(Remote *remote, Packet *packet)
{ {
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
LPCTSTR targetHost = NULL; wchar_t *targetHost;
HKEY rootKey = NULL, resKey; HKEY rootKey = NULL, resKey;
DWORD result; DWORD result;
targetHost = packet_get_tlv_value_string(packet, TLV_TYPE_TARGET_HOST); targetHost = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_TARGET_HOST));
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY); rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
// Validate the parameters and then attempt to create the key // Validate the parameters and then attempt to create the key
if ((!rootKey) || (!targetHost)) if ((!rootKey) || (!targetHost)) {
result = ERROR_INVALID_PARAMETER; result = ERROR_INVALID_PARAMETER;
else } else {
{ result = RegConnectRegistryW(targetHost, rootKey, &resKey);
result = RegConnectRegistry(targetHost, rootKey, &resKey);
} }
// Add the HKEY if we succeeded, but always return a result // Add the HKEY if we succeeded, but always return a result
if (result == ERROR_SUCCESS) if (result == ERROR_SUCCESS) {
{
packet_add_tlv_qword(response, TLV_TYPE_HKEY, (QWORD)resKey); packet_add_tlv_qword(response, TLV_TYPE_HKEY, (QWORD)resKey);
} }
free(targetHost);
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
return ERROR_SUCCESS; return ERROR_SUCCESS;
@ -202,24 +206,24 @@ DWORD request_registry_open_remote_key(Remote *remote, Packet *packet)
DWORD request_registry_create_key(Remote *remote, Packet *packet) DWORD request_registry_create_key(Remote *remote, Packet *packet)
{ {
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
LPCTSTR baseKey = NULL; wchar_t *baseKey;
HKEY rootKey = NULL, resKey; HKEY rootKey = NULL, resKey;
DWORD permission; DWORD permission;
DWORD result; DWORD result;
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY); rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY); baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION); permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION);
// Validate the parameters and then attempt to create the key // Validate the parameters and then attempt to create the key
if ((!rootKey) || (!baseKey)) if ((!rootKey) || (!baseKey)) {
result = ERROR_INVALID_PARAMETER; result = ERROR_INVALID_PARAMETER;
else } else {
{ if (!permission) {
if (!permission)
permission = KEY_ALL_ACCESS; permission = KEY_ALL_ACCESS;
}
result = RegCreateKeyEx(rootKey, baseKey, 0, NULL, 0, result = RegCreateKeyExW(rootKey, baseKey, 0, NULL, 0,
permission, NULL, &resKey, NULL); permission, NULL, &resKey, NULL);
} }
@ -231,6 +235,8 @@ DWORD request_registry_create_key(Remote *remote, Packet *packet)
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
free(baseKey);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -239,61 +245,47 @@ static void enum_key(Remote *remote, Packet *packet, HKEY hkey)
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
DWORD result; DWORD result;
if (!hkey) if (!hkey) {
result = ERROR_INVALID_PARAMETER; result = ERROR_INVALID_PARAMETER;
else goto err;
{
DWORD nameSize = 4096;
DWORD index = 0;
DWORD tries = 0;
LPSTR name = NULL;
// Keep looping until we reach the end
while (1)
{
// If the name storage is NULL, allocate it
if (!name)
name = (LPSTR)malloc(nameSize);
result = RegEnumKey(hkey, index, name, nameSize);
// If we need more room...
if (result == ERROR_MORE_DATA)
{
if (tries > 3)
break;
free(name);
nameSize *= 2;
name = NULL;
tries++;
continue;
}
// If we've reached the end of our road...
else if (result == ERROR_NO_MORE_ITEMS)
{
result = ERROR_SUCCESS;
break;
}
// If we flunked out of school...
else if (result != ERROR_SUCCESS)
break;
// Reset tries
tries = 0;
// Add the registry key name
packet_add_tlv_string(response, TLV_TYPE_KEY_NAME,
name);
// Next entry
index++;
}
} }
DWORD nameSize;
result = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &nameSize,
NULL, NULL, NULL, NULL, NULL, NULL);
if (result != ERROR_SUCCESS) {
goto err;
}
DWORD index = 0;
wchar_t *name = malloc(nameSize);
// Keep looping until we reach the end
while (1)
{
result = RegEnumKeyW(hkey, index, name, nameSize);
if (result == ERROR_SUCCESS) {
// Add the registry key name
char *tmp = wchar_to_utf8(name);
packet_add_tlv_string(response, TLV_TYPE_KEY_NAME, tmp);
free(tmp);
}
// If we've reached the end of our road...
else if (result == ERROR_NO_MORE_ITEMS) {
result = ERROR_SUCCESS;
break;
} else {
// If we flunked out of school...
break;
}
// Next entry
index++;
}
free(name);
err:
// Set the result and transmit the response // Set the result and transmit the response
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
} }
@ -330,8 +322,9 @@ DWORD request_registry_enum_key_direct(Remote *remote, Packet *packet)
open_key(packet, &rootkey, &hkey); open_key(packet, &rootkey, &hkey);
enum_key(remote, packet, hkey); enum_key(remote, packet, hkey);
if (hkey) if (hkey) {
RegCloseKey(hkey); RegCloseKey(hkey);
}
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -349,26 +342,27 @@ DWORD request_registry_enum_key_direct(Remote *remote, Packet *packet)
DWORD request_registry_delete_key(Remote *remote, Packet *packet) DWORD request_registry_delete_key(Remote *remote, Packet *packet)
{ {
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
LPCSTR baseKey = NULL; wchar_t *baseKey;
DWORD result = ERROR_SUCCESS; DWORD result = ERROR_SUCCESS;
DWORD flags = 0; DWORD flags = 0;
HKEY rootKey = NULL; HKEY rootKey = NULL;
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY); rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY); baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS); flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
if ((!rootKey) || if (!rootKey || !baseKey) {
(!baseKey))
result = ERROR_INVALID_PARAMETER; result = ERROR_INVALID_PARAMETER;
else } else {
{ if (flags & DELETE_KEY_FLAG_RECURSIVE) {
if (flags & DELETE_KEY_FLAG_RECURSIVE) result = SHDeleteKeyW(rootKey, baseKey);
result = SHDeleteKey(rootKey, baseKey); } else {
else result = RegDeleteKeyW(rootKey, baseKey);
result = RegDeleteKey(rootKey, baseKey); }
} }
free(baseKey);
// Set the result and send the response // Set the result and send the response
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
@ -389,10 +383,11 @@ DWORD request_registry_close_key(Remote *remote, Packet *packet)
HKEY hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY); HKEY hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY);
// No param? No love. // No param? No love.
if (!hkey) if (!hkey) {
result = ERROR_INVALID_PARAMETER; result = ERROR_INVALID_PARAMETER;
else } else {
result = RegCloseKey(hkey); result = RegCloseKey(hkey);
}
// Set the result and send the response // Set the result and send the response
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
@ -403,30 +398,35 @@ DWORD request_registry_close_key(Remote *remote, Packet *packet)
static void set_value(Remote *remote, Packet *packet, HKEY hkey) static void set_value(Remote *remote, Packet *packet, HKEY hkey)
{ {
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
LPCSTR valueName = NULL; wchar_t *valueName;
DWORD valueType = 0; DWORD valueType = 0;
DWORD result = ERROR_SUCCESS; DWORD result = ERROR_SUCCESS;
Tlv valueData; Tlv valueData;
// Acquire the standard TLVs // Acquire the standard TLVs
valueName = packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME); valueName = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME));
valueType = packet_get_tlv_value_uint(packet, TLV_TYPE_VALUE_TYPE); valueType = packet_get_tlv_value_uint(packet, TLV_TYPE_VALUE_TYPE);
do // Get the value data TLV
{ if (packet_get_tlv(packet, TLV_TYPE_VALUE_DATA, &valueData) != ERROR_SUCCESS) {
// Get the value data TLV result = ERROR_INVALID_PARAMETER;
if (packet_get_tlv(packet, TLV_TYPE_VALUE_DATA, } else {
&valueData) != ERROR_SUCCESS)
{
result = ERROR_INVALID_PARAMETER;
break;
}
// Now let's rock this shit! // Now let's rock this shit!
result = RegSetValueEx(hkey, valueName, 0, valueType, void *buf;
valueData.buffer, valueData.header.length); size_t len = valueData.header.length;
if (valueType == REG_SZ) {
buf = utf8_to_wchar(valueData.buffer);
len = (wcslen(buf) + 1) * sizeof(wchar_t);
} else {
buf = valueData.buffer;
}
result = RegSetValueExW(hkey, valueName, 0, valueType, buf, (DWORD)len);
if (buf != valueData.buffer) {
free(buf);
}
}
} while (0); free(valueName);
// Populate the result code // Populate the result code
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
@ -468,8 +468,9 @@ DWORD request_registry_set_value_direct(Remote *remote, Packet *packet)
open_key(packet, &rootkey, &hkey); open_key(packet, &rootkey, &hkey);
set_value(remote, packet, hkey); set_value(remote, packet, hkey);
if (hkey) if (hkey) {
RegCloseKey(hkey); RegCloseKey(hkey);
}
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -477,55 +478,62 @@ DWORD request_registry_set_value_direct(Remote *remote, Packet *packet)
static void query_value(Remote *remote, Packet *packet, HKEY hkey) static void query_value(Remote *remote, Packet *packet, HKEY hkey)
{ {
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
LPCSTR valueName; wchar_t *valueName;
LPBYTE valueData = NULL; void *valueData = NULL;
DWORD valueDataSize = 4096; DWORD valueDataSize = 0;
DWORD result = ERROR_SUCCESS; DWORD result = ERROR_SUCCESS;
DWORD valueType = 0; DWORD valueType = 0;
valueName = packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME); valueName = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME));
do { // Get the size of the value data
// Get the size of the value data if ((result = RegQueryValueExW(hkey, valueName, 0, NULL, NULL,
if ((result = RegQueryValueEx(hkey, valueName, 0, NULL, NULL, &valueDataSize)) != ERROR_SUCCESS) {
&valueDataSize)) != ERROR_SUCCESS) goto err;
break; }
// Allocate storage for the value data valueDataSize++;
if (!(valueData = (LPBYTE)malloc(valueDataSize)))
continue;
// Query the value's information // Allocate storage for the value data
if ((result = RegQueryValueEx(hkey, valueName, 0, &valueType, valueData, if (!(valueData = calloc(1, valueDataSize))) {
&valueDataSize)) != ERROR_SUCCESS) goto err;
break; }
// Add the information about the value to the response // Query the value's information
packet_add_tlv_uint(response, TLV_TYPE_VALUE_TYPE, valueType); if ((result = RegQueryValueExW(hkey, valueName, 0, &valueType, valueData,
&valueDataSize)) != ERROR_SUCCESS) {
goto err;
}
switch (valueType) // Add the information about the value to the response
{ packet_add_tlv_uint(response, TLV_TYPE_VALUE_TYPE, valueType);
case REG_SZ:
packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, switch (valueType)
(LPCSTR)valueData); {
break; case REG_SZ: {
case REG_DWORD: char *tmp = wchar_to_utf8((wchar_t *)valueData);
packet_add_tlv_uint(response, TLV_TYPE_VALUE_DATA, packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, tmp);
*(LPDWORD)valueData); free(tmp);
break;
default:
packet_add_tlv_raw(response, TLV_TYPE_VALUE_DATA,
valueData, valueDataSize);
break;
} }
} while (0); break;
case REG_DWORD:
packet_add_tlv_uint(response, TLV_TYPE_VALUE_DATA,
*(LPDWORD)valueData);
break;
default:
packet_add_tlv_raw(response, TLV_TYPE_VALUE_DATA,
valueData, valueDataSize);
break;
}
err:
free(valueName);
// Populate the result code // Populate the result code
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
} }
/* /*
* Queries a registry value's type and data for a given HKEY. * Queries a registry value's type and data for a given HKEY.RegEnumValueW
* *
* TLVs: * TLVs:
* *
@ -567,65 +575,41 @@ static void enum_value(Remote *remote, Packet *packet, HKEY hkey)
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
DWORD result; DWORD result;
if (!hkey) if (!hkey) {
result = ERROR_INVALID_PARAMETER; result = ERROR_INVALID_PARAMETER;
else goto err;
{
DWORD nameSize = 4096, realSize = 4096;
DWORD index = 0;
DWORD tries = 0;
LPSTR name = NULL;
// Keep looping until we reach the end
while (1)
{
// If the name storage is NULL, allocate it
if (!name)
name = (LPSTR)malloc(nameSize);
result = RegEnumValue(hkey, index, name, &nameSize,
NULL, NULL, NULL, NULL);
// Reset the real size
nameSize = realSize;
// If we need more room...
if (result == ERROR_MORE_DATA)
{
if (tries > 3)
break;
free(name);
realSize = nameSize *= 3;
name = NULL;
tries++;
continue;
}
// If we've reached the end of our road...
else if (result == ERROR_NO_MORE_ITEMS)
{
result = ERROR_SUCCESS;
break;
}
// If we flunked out of school...
else if (result != ERROR_SUCCESS)
break;
// Reset tries
tries = 0;
// Add the registry value name
packet_add_tlv_string(response, TLV_TYPE_VALUE_NAME,
name);
// Next entry
index++;
}
} }
DWORD index = 0;
wchar_t name[16383];
// Keep looping until we reach the end
while (1)
{
DWORD nameSize = sizeof(name);
result = RegEnumValueW(hkey, index, name, &nameSize,
NULL, NULL, NULL, NULL);
if (result == ERROR_SUCCESS) {
// Add the registry value name
char *tmp = wchar_to_utf8(name);
packet_add_tlv_string(response, TLV_TYPE_VALUE_NAME, tmp);
free(tmp);
} else
// If we've reached the end of our road...
if (result == ERROR_NO_MORE_ITEMS) {
result = ERROR_SUCCESS;
break;
} else {
// If we flunked out of school...
break;
}
// Next entry
index++;
}
err:
// Set the result and transmit the response // Set the result and transmit the response
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
} }
@ -678,19 +662,21 @@ DWORD request_registry_enum_value_direct(Remote *remote, Packet *packet)
DWORD request_registry_delete_value(Remote *remote, Packet *packet) DWORD request_registry_delete_value(Remote *remote, Packet *packet)
{ {
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
LPCSTR valueName = NULL; wchar_t *valueName;
DWORD result = ERROR_SUCCESS; DWORD result = ERROR_SUCCESS;
HKEY hkey = NULL; HKEY hkey = NULL;
hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY); hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY);
valueName = (LPCSTR)packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME); valueName = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME));
// Check for invalid parameters // Check for invalid parameters
if ((!hkey) || if (!hkey || !valueName) {
(!valueName))
result = ERROR_INVALID_PARAMETER; result = ERROR_INVALID_PARAMETER;
else } else {
result = RegDeleteValue(hkey, valueName); result = RegDeleteValueW(hkey, valueName);
}
free(valueName);
// Set the result and send the response // Set the result and send the response
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);
@ -708,25 +694,20 @@ DWORD request_registry_delete_value(Remote *remote, Packet *packet)
DWORD request_registry_query_class(Remote *remote, Packet *packet) DWORD request_registry_query_class(Remote *remote, Packet *packet)
{ {
Packet *response = packet_create_response(packet); Packet *response = packet_create_response(packet);
LPCSTR valueName = NULL; wchar_t valueData[4096];
BYTE valueData[4096]; DWORD valueDataSize = sizeof(valueData);
DWORD valueDataSize = 4096;
DWORD result = ERROR_SUCCESS; DWORD result = ERROR_SUCCESS;
DWORD valueType = 0;
HKEY hkey = NULL;
// Acquire the standard TLVs // Acquire the standard TLVs
hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY); HKEY hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY);
do // Get the size of the value data
{ if ((result = RegQueryInfoKeyW(hkey, valueData, &valueDataSize,
// Get the size of the value data NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) {
if ((result = RegQueryInfoKey(hkey, valueData, &valueDataSize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) != ERROR_SUCCESS) char *tmp = wchar_to_utf8(valueData);
break; packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, tmp);
free(tmp);
packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, (LPCSTR)valueData); }
} while (0);
packet_transmit_response(result, remote, response); packet_transmit_response(result, remote, response);