1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-05-12 19:04:32 +02:00

consistency and bug fixes

This commit is contained in:
Brent Cook 2016-03-15 04:59:37 -05:00
parent 31e6ae1a63
commit 423dbaeba2

@ -1,8 +1,6 @@
#include "precomp.h"
#include <shlwapi.h>
DWORD request_registry_create_key(Remote *remote, Packet *packet);
/*!
* @brief Check to see if a registry key exists.
* @param remote Pointer to the \c Remote instance.
@ -12,20 +10,18 @@ DWORD request_registry_create_key(Remote *remote, Packet *packet);
DWORD request_registry_check_key_exists(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
wchar_t *baseKey = NULL;
HKEY rootKey = NULL;
HKEY resultKey = NULL;
BOOL exists = FALSE;
DWORD result;
if (response == NULL) {
goto out;
}
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
HKEY rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
wchar_t *baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
if (rootKey && baseKey)
{
result = RegOpenKeyW(rootKey, baseKey, &resultKey);
if (result == ERROR_SUCCESS)
{
DWORD result = ERROR_INVALID_PARAMETER;
if (rootKey && baseKey) {
BOOL exists = FALSE;
HKEY resultKey = NULL;
if (RegOpenKeyW(rootKey, baseKey, &resultKey) == ERROR_SUCCESS) {
dprintf("[REG] Key found");
RegCloseKey(resultKey);
exists = TRUE;
@ -35,17 +31,11 @@ DWORD request_registry_check_key_exists(Remote *remote, Packet *packet)
packet_add_tlv_bool(response, TLV_TYPE_BOOL, exists);
result = ERROR_SUCCESS;
}
else
{
dprintf("[REG] Invalid parameter");
result = ERROR_INVALID_PARAMETER;
}
free(baseKey);
dprintf("[REG] Returning result: %u %x", result, result);
packet_transmit_response(result, remote, response);
dprintf("[REG] done.");
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
@ -61,64 +51,64 @@ DWORD request_registry_check_key_exists(Remote *remote, Packet *packet)
*/
DWORD request_registry_load_key(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCTSTR baseKey = NULL;
HKEY rootKey = NULL;
LPCSTR hiveFile = NULL;
DWORD result;
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY);
hiveFile = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
if ((!rootKey) || (!baseKey) || (!hiveFile))
result = ERROR_INVALID_PARAMETER;
else
{
result = RegLoadKey(rootKey,baseKey,hiveFile);
Packet *response = packet_create_response(packet);
if (response == NULL) {
goto out;
}
HKEY rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
wchar_t *baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
wchar_t *hiveFile = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH));
DWORD result = ERROR_INVALID_PARAMETER;
if (rootKey && baseKey && hiveFile) {
result = RegLoadKeyW(rootKey, baseKey, hiveFile);
}
free(baseKey);
free(hiveFile);
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
DWORD request_registry_unload_key(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
LPCTSTR baseKey = NULL;
HKEY rootKey = NULL;
DWORD result;
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY);
if ((!rootKey) || (!baseKey))
result = ERROR_INVALID_PARAMETER;
else
{
result = RegUnLoadKey(rootKey,baseKey);
Packet *response = packet_create_response(packet);
if (response == NULL) {
goto out;
}
HKEY rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
wchar_t *baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
DWORD result = ERROR_INVALID_PARAMETER;
if (rootKey && baseKey) {
result = RegUnLoadKeyW(rootKey, baseKey);
}
free(baseKey);
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
static DWORD open_key(Packet *packet, HKEY *rootKey, HKEY *resKey)
{
wchar_t *baseKey = NULL;
DWORD result = ERROR_INVALID_PARAMETER;
DWORD permission;
*rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_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);
*rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
wchar_t *baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
DWORD permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION);
// Validate the parameters and then attempt to create the key
if (rootKey && baseKey)
{
if (!permission)
DWORD result = ERROR_INVALID_PARAMETER;
if (rootKey && baseKey) {
if (!permission) {
permission = KEY_ALL_ACCESS;
}
result = RegOpenKeyExW(*rootKey, baseKey, 0, permission, resKey);
}
free(baseKey);
return result;
@ -137,19 +127,21 @@ static DWORD open_key(Packet *packet, HKEY *rootKey, HKEY *resKey)
DWORD request_registry_open_key(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
DWORD result;
if (response == NULL) {
goto out;
}
HKEY rootKey, resKey;
result = open_key(packet, &rootKey, &resKey);
DWORD result = open_key(packet, &rootKey, &resKey);
// 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_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
@ -165,17 +157,18 @@ DWORD request_registry_open_key(Remote *remote, Packet *packet)
DWORD request_registry_open_remote_key(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
wchar_t *targetHost;
HKEY rootKey = NULL, resKey;
DWORD result;
if (response == NULL) {
goto out;
}
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);
HKEY resKey = NULL;
HKEY rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
wchar_t *targetHost = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_TARGET_HOST));
// Validate the parameters and then attempt to create the key
if ((!rootKey) || (!targetHost)) {
result = ERROR_INVALID_PARAMETER;
} else {
DWORD result = ERROR_INVALID_PARAMETER;
if (rootKey && targetHost) {
result = RegConnectRegistryW(targetHost, rootKey, &resKey);
}
@ -185,9 +178,8 @@ DWORD request_registry_open_remote_key(Remote *remote, Packet *packet)
}
free(targetHost);
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
@ -204,19 +196,18 @@ DWORD request_registry_open_remote_key(Remote *remote, Packet *packet)
DWORD request_registry_create_key(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
wchar_t *baseKey;
HKEY rootKey = NULL, resKey;
DWORD permission;
DWORD result;
if (response == NULL) {
goto out;
}
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_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);
HKEY resKey = NULL;
HKEY rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
wchar_t *baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
DWORD permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION);
// Validate the parameters and then attempt to create the key
if ((!rootKey) || (!baseKey)) {
result = ERROR_INVALID_PARAMETER;
} else {
DWORD result = ERROR_INVALID_PARAMETER;
if (rootKey && baseKey) {
if (!permission) {
permission = KEY_ALL_ACCESS;
}
@ -226,69 +217,124 @@ DWORD request_registry_create_key(Remote *remote, Packet *packet)
}
// 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_transmit_response(result, remote, response);
free(baseKey);
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
static void enum_key(Remote *remote, Packet *packet, HKEY hkey)
{
Packet *response = packet_create_response(packet);
DWORD result;
if (response == NULL) {
return;
}
DWORD result = ERROR_INVALID_PARAMETER;
if (!hkey) {
result = ERROR_INVALID_PARAMETER;
goto err;
}
DWORD nameSize;
result = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &nameSize,
DWORD maxSubKeyLen;
result = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, &maxSubKeyLen,
NULL, NULL, NULL, NULL, NULL, NULL);
if (result != ERROR_SUCCESS) {
goto err;
}
nameSize *= sizeof(wchar_t);
DWORD index = 0;
wchar_t *name = malloc(nameSize);
maxSubKeyLen++;
wchar_t *name = calloc(maxSubKeyLen, sizeof(wchar_t));
if (name == NULL) {
result = ERROR_NOT_ENOUGH_MEMORY;
goto err;
}
// Keep looping until we reach the end
while (1)
{
result = RegEnumKeyW(hkey, index, name, nameSize);
result = RegEnumKeyW(hkey, index, name, maxSubKeyLen);
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;
if (tmp) {
packet_add_tlv_string(response, TLV_TYPE_KEY_NAME, tmp);
free(tmp);
}
} else {
// If we flunked out of school...
if (result == ERROR_NO_MORE_ITEMS) {
result = ERROR_SUCCESS;
}
break;
}
// Next entry
index++;
}
free(name);
err:
// Set the result and transmit the response
packet_transmit_response(result, remote, response);
}
static void enum_value(Remote *remote, Packet *packet, HKEY hkey)
{
Packet *response = packet_create_response(packet);
if (response == NULL) {
return;
}
DWORD result = ERROR_INVALID_PARAMETER;
if (!hkey) {
goto err;
}
DWORD maxValueNameLen;
result = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, &maxValueNameLen, NULL, NULL, NULL);
if (result != ERROR_SUCCESS) {
goto err;
}
DWORD index = 0;
maxValueNameLen++;
wchar_t *name = calloc(maxValueNameLen, sizeof(wchar_t));
if (name == NULL) {
result = ERROR_NOT_ENOUGH_MEMORY;
goto err;
}
while (1)
{
DWORD valueLen = maxValueNameLen;
result = RegEnumValueW(hkey, index, name, &valueLen,
NULL, NULL, NULL, NULL);
if (result == ERROR_SUCCESS) {
char *tmp = wchar_to_utf8(name);
if (tmp) {
packet_add_tlv_string(response, TLV_TYPE_VALUE_NAME, tmp);
free(tmp);
}
} else {
if (result == ERROR_NO_MORE_ITEMS) {
result = ERROR_SUCCESS;
}
break;
}
index++;
}
free(name);
err:
packet_transmit_response(result, remote, response);
}
/*
* Enumerates a supplied registry key and returns a list of all the direct
* sub-keys.
@ -341,18 +387,16 @@ DWORD request_registry_enum_key_direct(Remote *remote, Packet *packet)
DWORD request_registry_delete_key(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
wchar_t *baseKey;
DWORD result = ERROR_SUCCESS;
DWORD flags = 0;
HKEY rootKey = NULL;
if (response == NULL) {
goto out;
}
rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_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);
HKEY rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
wchar_t *baseKey = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY));
DWORD flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
if (!rootKey || !baseKey) {
result = ERROR_INVALID_PARAMETER;
} else {
DWORD result = ERROR_INVALID_PARAMETER;
if (rootKey && baseKey) {
if (flags & DELETE_KEY_FLAG_RECURSIVE) {
result = SHDeleteKeyW(rootKey, baseKey);
} else {
@ -361,10 +405,8 @@ DWORD request_registry_delete_key(Remote *remote, Packet *packet)
}
free(baseKey);
// Set the result and send the response
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
@ -378,25 +420,30 @@ DWORD request_registry_delete_key(Remote *remote, Packet *packet)
DWORD request_registry_close_key(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
DWORD result;
if (response == NULL) {
goto out;
}
HKEY hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY);
// No param? No love.
if (!hkey) {
result = ERROR_INVALID_PARAMETER;
} else {
DWORD result = ERROR_INVALID_PARAMETER;
if (hkey) {
result = RegCloseKey(hkey);
}
// Set the result and send the response
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
static void set_value(Remote *remote, Packet *packet, HKEY hkey)
{
Packet *response = packet_create_response(packet);
if (response == NULL) {
return;
}
wchar_t *valueName;
DWORD valueType = 0;
DWORD result = ERROR_SUCCESS;
@ -477,7 +524,12 @@ DWORD request_registry_set_value_direct(Remote *remote, Packet *packet)
static void query_value(Remote *remote, Packet *packet, HKEY hkey)
{
Packet *response = packet_create_response(packet);
if (response == NULL) {
return;
}
wchar_t *valueName;
char *tmp;
void *valueData = NULL;
DWORD valueDataSize = 0;
DWORD result = ERROR_SUCCESS;
@ -507,22 +559,25 @@ static void query_value(Remote *remote, Packet *packet, HKEY hkey)
// Add the information about the value to the response
packet_add_tlv_uint(response, TLV_TYPE_VALUE_TYPE, valueType);
switch (valueType)
{
case REG_SZ: {
char *tmp = wchar_to_utf8((wchar_t *)valueData);
packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, tmp);
free(tmp);
}
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;
switch (valueType) {
case REG_SZ:
tmp = wchar_to_utf8((wchar_t *)valueData);
if (tmp) {
packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, tmp);
free(tmp);
} else {
packet_add_tlv_raw(response, TLV_TYPE_VALUE_DATA,
valueData, valueDataSize);
}
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:
@ -563,59 +618,15 @@ DWORD request_registry_query_value_direct(Remote *remote, Packet *packet)
open_key(packet, &rootkey, &hkey);
query_value(remote, packet, hkey);
if (hkey)
if (hkey) {
RegCloseKey(hkey);
}
return ERROR_SUCCESS;
}
static void enum_value(Remote *remote, Packet *packet, HKEY hkey)
{
Packet *response = packet_create_response(packet);
DWORD result;
if (!hkey) {
result = ERROR_INVALID_PARAMETER;
goto err;
}
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
packet_transmit_response(result, remote, response);
}
/*
* Enumerates all of the values at the supplied HKEY.
* Enumerates all of the value names at the supplied HKEY.
*
* TLVs:
*
@ -630,7 +641,7 @@ DWORD request_registry_enum_value(Remote *remote, Packet *packet)
}
/*
* Enumerates all of the values at the supplied HKEY.
* Enumerates all of the value names at the supplied HKEY.
*
* TLVs:
*
@ -644,8 +655,9 @@ DWORD request_registry_enum_value_direct(Remote *remote, Packet *packet)
open_key(packet, &rootkey, &hkey);
enum_value(remote, packet, hkey);
if (hkey)
if (hkey) {
RegCloseKey(hkey);
}
return ERROR_SUCCESS;
}
@ -661,25 +673,21 @@ DWORD request_registry_enum_value_direct(Remote *remote, Packet *packet)
DWORD request_registry_delete_value(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
wchar_t *valueName;
DWORD result = ERROR_SUCCESS;
HKEY hkey = NULL;
if (response == NULL) {
goto out;
}
hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY);
valueName = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME));
HKEY hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY);
wchar_t *valueName = utf8_to_wchar(packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME));
// Check for invalid parameters
if (!hkey || !valueName) {
result = ERROR_INVALID_PARAMETER;
} else {
DWORD result = ERROR_INVALID_PARAMETER;
if (hkey && valueName) {
result = RegDeleteValueW(hkey, valueName);
}
free(valueName);
// Set the result and send the response
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}
@ -693,27 +701,55 @@ DWORD request_registry_delete_value(Remote *remote, Packet *packet)
DWORD request_registry_query_class(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
wchar_t *valueData;
DWORD valueDataSize = 0;
DWORD result = ERROR_SUCCESS;
// Acquire the standard TLVs
HKEY hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY);
RegQueryInfoKeyW(hkey, NULL, &valueDataSize,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
valueData = malloc(valueDataSize * sizeof(wchar_t));
// Get the size of the value data
if ((result = RegQueryInfoKeyW(hkey, valueData, &valueDataSize,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS) {
char *tmp = wchar_to_utf8(valueData);
packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, tmp);
free(tmp);
if (response == NULL) {
goto out;
}
free(valueData);
packet_transmit_response(result, remote, response);
HKEY hkey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_HKEY);
DWORD result = ERROR_INVALID_PARAMETER;
if (!hkey) {
goto err;
}
/*
* RegQueryInfoKeyW returns the length in chars minus the NULL terminator
*/
DWORD classNameLen = 0;
result = RegQueryInfoKeyW(hkey, NULL, &classNameLen,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (result != ERROR_SUCCESS) {
goto err;
}
classNameLen++;
wchar_t *className = calloc(classNameLen, sizeof(wchar_t));
if (className == NULL) {
result = ERROR_NOT_ENOUGH_MEMORY;
goto err;
}
if (className) {
result = RegQueryInfoKeyW(hkey, className, &classNameLen,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (result == ERROR_SUCCESS) {
char *tmp = wchar_to_utf8(className);
if (tmp) {
packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, tmp);
free(tmp);
} else {
packet_add_tlv_raw(response,
TLV_TYPE_VALUE_DATA, className,
classNameLen * sizeof(wchar_t));
}
}
} else {
result = ERROR_NOT_ENOUGH_MEMORY;
}
free(className);
err:
packet_transmit_response(result, remote, response);
out:
return ERROR_SUCCESS;
}