199 lines
5.2 KiB
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;
|
||
|
}
|
||
|
|