#define WIN32_LEAN_AND_MEAN #include struct Delegate { void *obj; void *funct; }; template< typename MethodType > __declspec( naked ) void *__stdcall ConvertMethod( MethodType method ) { __asm { mov eax, dword ptr[ esp + 4 ] ; EAX = method; ret 4 ; return EAX; } } const void *pvVF = VirtualFree; __declspec( naked ) void RestoreESP ( void *pvCode, unsigned long espval, unsigned long retaddr ) { __asm { push 0x00008000 push 0x00000000 push dword ptr[ esp + 8 ] call pvVF ; VirtualFree( pvCode, 0, MEM_RELEASE ); mov eax, dword ptr[ esp + 8 ] ; EAX = retaddr mov esp, dword ptr[ esp + 4 ] ; ESP = espval jmp eax ; jump to retaddr } } const unsigned char codetmpl[] = { 0x68, 0x00, 0x00, 0x00, 0x00, // push imm32( EIP value to return ) 0x68, 0x00, 0x00, 0x00, 0x00, // push imm32( ESP value before calling ) 0x68, 0x00, 0x00, 0x00, 0x00, // push imm32( address of code ) 0xb8, 0x00, 0x00, 0x00, 0x00, // mov EAX, imm32( address of RestoreESP ) 0xff, 0xe0, // jmp EAX ( jump to RestoreESP ) 0xcd, 0x0d // int 0Dh ( guard instruction ) }; void *__stdcall WriteCode( unsigned long espval, unsigned long retaddr ) { unsigned char *pvCode = ( unsigned char* ) VirtualAlloc( NULL, 24, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); memcpy( pvCode, codetmpl, sizeof( codetmpl ) ); memcpy( pvCode + 1, &retaddr, sizeof( retaddr ) ); memcpy( pvCode + 6, &espval, sizeof( espval ) ); memcpy( pvCode + 11, &pvCode, sizeof( pvCode ) ); unsigned long restoringProcAddr = ( unsigned long ) RestoreESP; memcpy( pvCode + 16, &restoringProcAddr, sizeof( restoringProcAddr ) ); return pvCode; } __declspec( naked ) void PascalInvoke( Delegate *pDelegate, ... ) { __asm { lea edx, [ esp + 4 ] ; EDX = [ ESP value before calling ] push dword ptr[ esp ] ; [ EIP value to return ] push edx ; [ ESP value before calling ] call WriteCode ; EAX = pvCode; mov edx, dword ptr[ esp + 4 ] ; EDX = pDelegate add esp, 8 mov ecx, dword ptr[ edx ] ; ECX = pDelegate->obj push eax ; RA = pvCode jmp dword ptr[ edx + 4 ] ; pDelegate->funct() } } __declspec( naked ) void CInvoke( Delegate *pDelegate, ... ) { __asm { lea edx, [ esp + 4 ] ; EDX = [ ESP value before calling ] push dword ptr[ esp ] ; [ EIP value to return ] push edx ; [ ESP value before calling ] call WriteCode ; EAX = pvCode; mov edx, dword ptr[ esp + 4 ] ; EDX = pDelegate add esp, 8 push dword ptr[ edx ] push eax ; RA = pvCode jmp dword ptr[ edx + 4 ] ; pDelegate->funct() } } //////////////////////////////////////////////////////////////////////////////// #include using namespace std; class ClassZ { public: void NoArgFunct( void ) { cout << "ClassZ::NAF" << endl; } void TwoIntArg( int a, int b ) { cout << "ClassZ::TIA( " << a << ", " << b << " )" << endl; } void Sum( int count, ... ) { va_list arg_ptr = NULL; va_start( arg_ptr, count ); int sum = 0; for ( int i = 0; i < count; i++ ) sum += va_arg( arg_ptr, int ); cout << "ClassZ::Sum = " << sum << endl; } }; int main( void ) { ClassZ z; Delegate dlgtNAF = { &z, ConvertMethod( &ClassZ::NoArgFunct ) }; Delegate dlgtTIA = { &z, ConvertMethod( &ClassZ::TwoIntArg ) }; Delegate dlgtSum = { &z, ConvertMethod( &ClassZ::Sum ) }; PascalInvoke( &dlgtNAF ); PascalInvoke( &dlgtTIA, 10, 20 ); CInvoke( &dlgtSum, 10, 0,1,2,3,4,5,6,7,8,9 ); return 0; }