Remote functions

On lunes, 22 de noviembre de 2010 0 comentarios

Remote functions

So you want to remotely control an application, get some information about it?

Maybe your GetRemoteProcAddress implementation sucks alot?

Check this thing out, it's just some code i wrote while working on my manual mapping issues, this isn't *the* code i used but rather its own standalone version, the version i use is a little more sophisticated but basically does the same things.

Remote.h
PHP Code:
#ifndef __REMOTE_HEADER__
#define __REMOTE_HEADER__
namespace Remote {
    
namespace Allocate
    
{
        
void*    Alloc( HANDLE hProcess, size_t Size );
        
void*    Commit( HANDLE hProcess, void* Data, size_t Size );
        
void    Free( HANDLE hProcess, void* Data, size_t Size );
    };

    
HANDLE    GetRemoteProcessHandleA( char *pszProcessName );
    
HMODULE GetRemoteModuleHandleA( HANDLE hProcess, const char *szModule );
    
HMODULE RemoteLoadLibraryA( HANDLE hProcess, char *pszLibraryPath );
    
FARPROC GetRemoteProcAddress( HANDLE hProcess, char *pszModuleName, char *pszProcName );
};

#endif //__REMOTE_HEADER__ 
Remote.cpp
PHP Code:
#include "stdafx.h"
#include "Remote.h"
namespace Remote {
    
namespace Allocate
    
{
        
void* Alloc( HANDLE hProcess, size_t Size )
        {
            return 
VirtualAllocEx( hProcess, NULL, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
        }

        
void* Commit( HANDLE hProcess, void* Data, size_t Size )
        {
            
void* AllocatedPointer = Alloc( hProcess, Size );

            if( 
AllocatedPointer )
            {
                if( 
WriteProcessMemory( hProcess, AllocatedPointer, Data, Size, NULL ) == TRUE )
                {
                    return 
AllocatedPointer;
                }
                
                
Free( hProcess, AllocatedPointer, Size );
            }

            return 
NULL;
        }

        
void Free( HANDLE hProcess, void* Data, size_t Size )
        {
            
VirtualFreeEx( hProcess, Data, Size, MEM_RELEASE );
        }
    };

    
HANDLE GetRemoteProcessHandleA( char *pszProcessName )
    {
        
HANDLE tlh = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );

        
PROCESSENTRY32 proEntry;
        
        
proEntry.dwSize = sizeof( PROCESSENTRY32 );

        
Process32First( tlh, &proEntry );
        do
        {
            if( 
_stricmp( pszProcessName, proEntry.szExeFile ) == 0 )
            {
                
CloseHandle( tlh );

                return 
OpenProcess( PROCESS_ALL_ACCESS, FALSE, proEntry.th32ProcessID );
            }
        }
        while( 
Process32Next( tlh, &proEntry ) );

        
CloseHandle( tlh );

        return 
INVALID_HANDLE_VALUE;
    }

    
HMODULE GetRemoteModuleHandleA( HANDLE hProcess, const char *szModule )
    {
        
HANDLE tlh = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, GetProcessId( hProcess ) );

        
MODULEENTRY32 modEntry;
        
        
modEntry.dwSize = sizeof( MODULEENTRY32 );

        
Module32First( tlh, &modEntry );
        do
        {
            if( 
_stricmp( szModule, modEntry.szModule ) == 0 )
            {
                
CloseHandle( tlh );

                return 
modEntry.hModule;
            }
        }
        while( 
Module32Next( tlh, &modEntry ) );

        
CloseHandle( tlh );

        return 
NULL;
    }

    
HMODULE RemoteLoadLibraryA( HANDLE hProcess, char *pszLibraryPath )
    {
        
unsigned long ulReturnValue = NULL;

        if( 
pszLibraryPath )
        {
            
FARPROC fpLoadLibraryARemote = GetRemoteProcAddress( hProcess, "Kernel32.dll", "LoadLibraryA" );

            if( 
fpLoadLibraryARemote )
            {
                
void* AllocatedResult = Allocate::Alloc( hProcess, sizeof( unsigned long ) );
                
void* CommitedLibName = Allocate::Commit( hProcess, pszLibraryPath, strlen( pszLibraryPath ) + 1 );

                if( 
CommitedLibName )
                {
                    
unsigned char LoadLibraryAThreadBuffer[ 22 ] =
                    {
                        
0x68, 0x00, 0x00, 0x00, 0x00,         //push lib name
                        
0xB8, 0x00, 0x00, 0x00, 0x00,        //mov eax, LoadLibraryA
                        
0xFF, 0xD0,                         //call eax
                        
0xA3, 0x00, 0x00, 0x00, 0x00,         //mov result, eax
                        
0x33, 0xC0,                         //xor eax, eax (eax = 0)
                        
0xC2, 0x04, 0x00                     //retn 4
                    
};

                    *( 
unsigned long* )( LoadLibraryAThreadBuffer + 0x01 ) = ( unsigned long ) CommitedLibName;
                    *( 
unsigned long* )( LoadLibraryAThreadBuffer + 0x06 ) = ( unsigned long ) fpLoadLibraryARemote;
                    *( 
unsigned long* )( LoadLibraryAThreadBuffer + 0x0D ) = ( unsigned long ) AllocatedResult;

                    
void* RemoteBufferToWrite = Allocate::Commit( hProcess, LoadLibraryAThreadBuffer, sizeof( LoadLibraryAThreadBuffer ) );

                    if( 
RemoteBufferToWrite )
                    {
                        
HANDLE hSpawnedThread = CreateRemoteThread( hProcess, 0, 0, ( LPTHREAD_START_ROUTINE ) RemoteBufferToWrite, 0, 0, 0 );

                        
WaitForSingleObject( hSpawnedThread, INFINITE ); // Async..

                        
ReadProcessMemory( hProcess, AllocatedResult, &ulReturnValue, sizeof( unsigned long ), NULL );

                        
Allocate::Free( hProcess, RemoteBufferToWrite, sizeof( LoadLibraryAThreadBuffer ) );
                    }

                    
Allocate::Free( hProcess, CommitedLibName, strlen( pszLibraryPath ) + 1 );
                }
            }
        }

        return 
reinterpret_cast< HMODULE >( ulReturnValue );
    }

    
FARPROC GetRemoteProcAddress( HANDLE hProcess, char *pszModuleName, char *pszProcName )
    {
        
FARPROC fpReturnValue = NULL;
        
        
HMODULE hLocalKernel = GetModuleHandleA( "Kernel32.dll" );

        if( 
hLocalKernel )
        {
            
HMODULE hRemoteKernel = GetRemoteModuleHandleA( hProcess, "Kernel32.dll" );

            if( 
hRemoteKernel )
            {
                
unsigned long RemoteGetProcAddress = 
                    ( 
unsigned long ) hRemoteKernel + ( unsigned long )( ( unsigned long ) GetProcAddress - ( unsigned long ) hLocalKernel );

                
void* ResultOfGetProcAddress = Allocate::Alloc( hProcess, sizeof( unsigned long ) );

                
void* CommitedProcName = Allocate::Commit( hProcess, pszProcName, strlen( pszProcName ) + 1 );

                if( 
ResultOfGetProcAddress && CommitedProcName )
                {
                    
unsigned char GetProcAddressThreadBuffer[ 27 ] =
                    {
                        
0x68, 0x00, 0x00, 0x00, 0x00,         //push proc name
                        
0x68, 0x00, 0x00, 0x00, 0x00,         //push module address
                        
0xB8, 0x00, 0x00, 0x00, 0x00,        //mov eax, GetProcAddress
                        
0xFF, 0xD0,                         //call eax
                        
0xA3, 0x00, 0x00, 0x00, 0x00,         //mov result, eax
                        
0x33, 0xC0,                         //xor eax, eax (eax = 0)
                        
0xC2, 0x04, 0x00                     //retn 4
                    
};

                    *( 
unsigned long* )( GetProcAddressThreadBuffer + 0x01 ) = ( unsigned long ) CommitedProcName;
                    *( 
unsigned long* )( GetProcAddressThreadBuffer + 0x06 ) = ( unsigned long ) hRemoteKernel;
                    *( 
unsigned long* )( GetProcAddressThreadBuffer + 0x0B ) = ( unsigned long ) RemoteGetProcAddress;
                    *( 
unsigned long* )( GetProcAddressThreadBuffer + 0x12 ) = ( unsigned long ) ResultOfGetProcAddress;

                    
void* RemoteBufferToWrite = Allocate::Commit( hProcess, GetProcAddressThreadBuffer, sizeof( GetProcAddressThreadBuffer ) );

                    if( 
RemoteBufferToWrite )
                    {
                        
HANDLE hSpawnedThread = CreateRemoteThread( hProcess, 0, 0, ( LPTHREAD_START_ROUTINE ) RemoteBufferToWrite, 0, 0, 0 );

                        
WaitForSingleObject( hSpawnedThread, INFINITE ); // Async..

                        
ReadProcessMemory( hProcess, ResultOfGetProcAddress, &fpReturnValue, sizeof( unsigned long ), NULL );

                        
Allocate::Free( hProcess, RemoteBufferToWrite, sizeof( GetProcAddressThreadBuffer ) );
                    }
                }

                if( 
ResultOfGetProcAddress )
                {
                    
Allocate::Free( hProcess, ResultOfGetProcAddress, sizeof( unsigned long ) );
                }

                if( 
CommitedProcName )
                {
                    
Allocate::Free( hProcess, CommitedProcName, strlen( pszProcName ) + 1 );
                }

            }
        }

        return 
fpReturnValue;
    }
}; 
Usage
PHP Code:
#include "stdafx.h"
#include "Remote.h"
DWORD WINAPI lpThreadForSpaceBar( LPVOID lpParam )
{
    while( ( 
GetAsyncKeyState( VK_SPACE ) & 1 ) == 0 )
    {
        
Sleep( 100 );
    }

    return 
0;
}
int _tmain(int argc, _TCHAR* argv[])
{
    
HANDLE hCalculator = Remote::GetRemoteProcessHandleA( "calc.exe" );

    if( 
hCalculator != INVALID_HANDLE_VALUE )
    {
        
FARPROC RemoteLoadLibraryA = Remote::GetRemoteProcAddress( hCalculator, "Kernel32.dll", "LoadLibraryA" );

        if( 
RemoteLoadLibraryA )
        {
            
printf( "LoadLibraryA Address is [0x%X]\n", RemoteLoadLibraryA );
        }
        else
        {
            
printf( "LoadLibraryA Address was not found..\n" );
        }

        
HMODULE hRemoteUser32 = Remote::RemoteLoadLibraryA( hCalculator, "User32.dll" );

        if( 
hRemoteUser32 )
        {
            
printf( "USER32.DLL Address is [0x%X][0x%X]\n", hRemoteUser32, GetModuleHandleA( "User32.dll" ) );
        }
        else
        {
            
printf( "USER32.DLL was not found..\n" );
        }

        
CloseHandle( hCalculator ); // Remember to close the handle from OpenProcess
    
}
    else
    {
        
printf( "Error opening process: INVALID_HANDLE_VALUE\n" );
    }

    
printf( "Press the space bar to continue...\n" );

    
WaitForSingleObject( CreateThread( 0, 0, lpThreadForSpaceBar, 0, 0, 0 ), INFINITE );

    return 
0;
} 
Benefits using this implementation for a loader for example, would be that you don't need to actually load modules into your loader to get the foreign address of them (Except Kernel32.dll, but, COME ON, lol) and that modules impossible to load from your loader (like CSS's tier0.dll or vstdlib.dll) will not be a problem anymore.

0 comentarios:

Publicar un comentario