Hey guys, with this class you can register callbacks in a remote process. For those of you who don't know: a callback is like a number you leave behind if you want someone to call you. If you 'register' a callback this means that when a certain condition is true your function will be called (back).
In this case the condition is execution of a certain piece of code. Just like a hook you can register a callback on a function you'd like to monitor.
For example if you want to register a callback on the Sleep() function in Firefox this is how you'd do it with my class:
Code:
#include "RemoteCallback.h"
#include <iostream>
void Callback(){
std::cout<< "Got here!!!" << std::endl;
return;
}
int main( int argc, char* argv ){
Remote_Callback* r_c = new Remote_Callback( "firefox.exe" ); // open the process and read all internal variables
void* Target = (void*) GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "Sleep" ); // find the address of sleep
r_c->Set_callback( Target, (DWORD*)&Callback ); // register a callback on sleep to call void Callback( void )
Sleep(5000); // wait for 5 seconds
delete r_c; //remove the callback and all hooks in the remote process
system("pause");
return 0;
}
Currently this all works with a call to CreateRemoteThread() in the remote process which start a new thread on our callback function. I'm going to improve this be finding a quicker way to start execution in our own process. Another point I'm going to upgrade are arguments since the whole thing is kinda pointless now since you can't change anything in the target process.
RemoteCallback.h
Code:
#ifndef CALLBACK_R_H
#define CALLHACK_R_H
#include <Windows.h>
class Hook;
class Remote_Callback{
HANDLE hProc_;
DWORD pid_;
void* r_ptr;
bool Remote_Write( void* , void* , int );
bool Remote_Read( void* , void* , int );
bool Remote_Alloc( void** , int );
bool Remote_Free( void*, int );
bool Duplicate_Handle( HANDLE& h_my_proc );
public:
Remote_Callback( HANDLE hProc );
Remote_Callback( DWORD PID );
Remote_Callback( char* ProcessName );
~Remote_Callback();
bool good();
const DWORD pid(){ return pid_; }
const HANDLE& hProc(){ return hProc_; }
bool Set_callback( void* HookAddress , DWORD* CallbackAddress );
private:
friend class Hook;
Hook* First;
Hook* Second;
Hook* Third;
};
class Hook{
friend class Remote_Callback;
void* OrigionalBytes;
void* RemoteHookLocation;
int HookSize;
Remote_Callback* cb;
public:
Hook( Remote_Callback* Callback, void* HookTarget, void* NewLocation );
~Hook();
};
#endif
RemoteCallback.cpp
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 );
}
}