Code:
#define _CRT_SECURE_NO_WARNINGS
#include "RemoteCallback.h"
#include <Windows.h>
#include <Tlhelp32.h>
unsigned char Callback_Bytecode[] = {
0x6A, 0x00, // PUSH 0
0x6A, 0x00, // PUSH 0
0x6A, 0x00, // PUSH 0
0x68, 0x90, 0x90, 0x90, 0x90, // PUSH 0x90909090 -> callback address
0x6A, 0x00, // PUSH 0
0x6A, 0x00, // PUSH 0
0x68, 0x90, 0x90, 0x90, 0x90, // PUSH 0x90909090 -> hproc
0xE8, 0x90, 0x90, 0x90, 0x90, // CALL 0x90909090 -> create remote thread
};
#define bytecode_loc_callback 7
#define bytecode_loc_hproc 16
#define bytecode_loc_CreateThread 21
unsigned char Call_Bytecode[] = {
0xE8, 0x00, 0x00, 0x00, 0x00
};
unsigned char Jump_Bytecode[] = {
0xE9, 0x00, 0x00, 0x00, 0x00
};
#define bytecode_loc_jcall 1
Remote_Callback::Remote_Callback( HANDLE hProc ) : hProc_( hProc ), pid_( 1 ) {}
Remote_Callback::Remote_Callback( DWORD Pid ) : hProc_ ( NULL ), pid_( Pid ) {
hProc_ = OpenProcess( PROCESS_ALL_ACCESS, false, Pid );
if( !hProc_ ) pid_ = NULL;
}
Remote_Callback::Remote_Callback( char* ProcessName ) : hProc_( NULL ), pid_( NULL ) {
if( !ProcessName ) return;
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );
if( !hSnap ) return;
PROCESSENTRY32 pEntry = { 0 };
pEntry.dwSize = sizeof( PROCESSENTRY32 );
if( Process32First( hSnap, &pEntry ) ){
do{
char* str = new char[ MAX_PATH ];
wcstombs( str, pEntry.szExeFile, MAX_PATH );
if( !strcmp( str, ProcessName ) ) {
pid_ = pEntry.th32ProcessID;
hProc_ = OpenProcess( PROCESS_ALL_ACCESS, false, pid_ );
if( !hProc_ ) pid_ = NULL;
delete [] str;
break;
}
delete [] str;
} while ( Process32Next( hSnap, &pEntry ) );
}
CloseHandle( hSnap );
}
Remote_Callback::~Remote_Callback(){
if( r_ptr ) Remote_Free( r_ptr, sizeof( Callback_Bytecode ) + sizeof( Jump_Bytecode ) );
if( First ) delete First;
if( Second ) delete Second;
if( Third ) delete Third;
if( hProc_ ) CloseHandle( hProc_ );
}
bool Remote_Callback::good(){
return (( pid_ ) && ( hProc_ ) ) ? true : false;
}
bool Remote_Callback::Remote_Write( void* Location, void* Data, int Length ){
if( good() ){
if( !WriteProcessMemory( hProc_, Location, Data, Length, NULL ) ) return false;
} else return false;
return true;
}
bool Remote_Callback::Remote_Read( void* Location, void* Data, int Length ){
if( good() ){
if( !ReadProcessMemory( hProc_, Location, Data, Length, NULL ) ) return false;
} else return false;
return true;
}
bool Remote_Callback::Remote_Alloc( void** Ptr, int Length ) {
if( good() ){
*Ptr = VirtualAllocEx( hProc_, NULL, Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( !*Ptr ) return false;
} else return false;
return true;
}
bool Remote_Callback::Remote_Free( void* Ptr, int Length ){
if( good() ){
if( !VirtualFreeEx( hProc_, Ptr, Length, MEM_RELEASE ) ) return false;
} else return false;
return true;
}
bool Remote_Callback::Duplicate_Handle( HANDLE& h_my_proc ){
if( good() ) {
if(
!DuplicateHandle(
GetCurrentProcess(),
GetCurrentProcess(),
hProc_,
&h_my_proc,
PROCESS_ALL_ACCESS,
false,
NULL
)
) return false;
} else return false;
return true;
}
bool Remote_Callback::Set_callback( void* HookAddress, DWORD* CallbackAddress ){
int Lenght = sizeof( Callback_Bytecode );
if( Remote_Alloc( &r_ptr, Lenght + sizeof( Jump_Bytecode ) ) ){
*(DWORD**) &Callback_Bytecode[ bytecode_loc_callback ] = CallbackAddress;
HANDLE *phProc = (HANDLE*) &Callback_Bytecode[ bytecode_loc_hproc ];
Duplicate_Handle( *phProc );
*(FARPROC*) &Callback_Bytecode[ bytecode_loc_CreateThread ] = (FARPROC)( (int) GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "CreateRemoteThread" ) - ( (int)r_ptr + (bytecode_loc_CreateThread-1) + 5) );
if( Remote_Write( r_ptr, (void*) &Callback_Bytecode[0], Lenght ) ){
First = new Hook( this, HookAddress, r_ptr );
Second = new Hook( this, (void*)( (int) r_ptr + Lenght ), First->OrigionalBytes );
Third = new Hook( this, (void*)( (int) First->OrigionalBytes + sizeof( Jump_Bytecode ) ), (void*) ((int) HookAddress + sizeof( Jump_Bytecode )) );
} else return false;
} else return false;
return true;
}
Hook::Hook( Remote_Callback* Callback, void* HookLocation, void* NewLocation ) : HookSize( sizeof( Call_Bytecode ) ) , OrigionalBytes( NULL ), RemoteHookLocation( NULL ), cb( Callback ) {
if( !HookLocation || !NewLocation ) return;
if( cb->Remote_Alloc( &OrigionalBytes, 2*HookSize ) ){
char* TempBuffer = new char[ HookSize ];
if( cb->Remote_Read( HookLocation, (void*)TempBuffer, HookSize ) ){
if( cb->Remote_Write( OrigionalBytes, (void*) TempBuffer, HookSize ) ){
*(void**) &Jump_Bytecode[ bytecode_loc_jcall ] = (void*) ( (int) NewLocation - (int) HookLocation - 5 );
cb->Remote_Write( HookLocation, (void*) &Jump_Bytecode[0], HookSize );
RemoteHookLocation = HookLocation;
} else { delete [] TempBuffer; return; }
} else{ delete [] TempBuffer; return; }
delete [] TempBuffer;
} else return;
return;
}
Hook::~Hook(){
if( OrigionalBytes ) {
if( RemoteHookLocation ){
char* Buffer = new char[ HookSize ];
if( cb->Remote_Read( OrigionalBytes, (void*) Buffer, HookSize ) ){
cb->Remote_Write( RemoteHookLocation, (void*) Buffer, HookSize );
}
delete [] Buffer;
}
cb->Remote_Free( OrigionalBytes, 2*HookSize );
}
}