Forum > Coding >

[REL] Out of body function caller

Posts: 224

Threads: 43

Joined: May, 2022

Reputation: -5

Posted

I have previously posted about this though I decided to improve the formatting and make some safety and good practice changes to the code.

 

also came up with a good name for it ( out of body function caller. get it? because of out of body experiences? ok cool )

 

#include <iostream>
#include <Windows.h>
#include <thread>
#include <vector>
#include <tuple>

typedef void( __stdcall* cextf_proto )( const std::uint32_t, const std::uint32_t );

enum calling_conventions : std::uint8_t
{
    stdcall_,
    cdecl_,
    fastcall_
};


template< typename func_ret_t, calling_conventions ccv, typename... function_args >
void __stdcall call_ext_func( std::uint32_t function_address, std::uint32_t tuple_addr )
{
    const auto function_args_tuples = *reinterpret_cast< std::tuple< function_args... > * >( tuple_addr );

    switch ( ccv )
    {
		    case calling_conventions::stdcall_:
		    {
			      typedef func_ret_t( __stdcall* stdcall_proc_func_proto )( function_args... );
			      const auto stdcall_proc_func = reinterpret_cast< stdcall_proc_func_proto >( function_address );
			      std::apply( stdcall_proc_func, function_args_tuples );
			      break;
		    }

		    case calling_conventions::cdecl_:
		    {
			      typedef func_ret_t( __cdecl* cdecl_proc_func_proto )( function_args... );
			      const auto cdecl_proc_func = reinterpret_cast< cdecl_proc_func_proto >( function_address );
			      std::apply( cdecl_proc_func, function_args_tuples );
			      break;
			}
		    case calling_conventions::fastcall_:
		    {
			      typedef func_ret_t( __fastcall* fastcall_proc_func_proto )( function_args... );
			      const auto fastcall_proc_func = reinterpret_cast< fastcall_proc_func_proto >( function_address );
			      std::apply( fastcall_proc_func, function_args_tuples );
			      break;
		    }
    }
}

std::vector< std::uint8_t > ret_function_instrs( void* function_address )
{
	std::vector< std::uint8_t > function_bytes{ };
	auto byte = static_cast< std::uint8_t* >( function_address );
	do 
	{
		function_bytes.push_back( *byte );
		++byte;
	} while ( *reinterpret_cast< std::uint32_t* >( byte ) != 0xCCCCCCCC );
	return function_bytes;
}


void* alloc_func(void* func_address)
{
    const auto function_instructions = ret_function_instrs( func_address );
    const auto allocated_function = VirtualAlloc( nullptr, function_instructions.size( ), MEM_COMMIT, PAGE_EXECUTE_READWRITE );

	if( !allocated_function )
		throw std::runtime_error( "failed to allocate memory for function." );

    std::memcpy( allocated_function, function_instructions.data( ), function_instructions.size( ) );
    return allocated_function;
}


template< typename... tuple_el >
void* alloc_tuple( std::tuple< tuple_el... > tuple )
{   
    const auto allocated_tuple = VirtualAlloc( nullptr, sizeof( tuple ), MEM_COMMIT, PAGE_EXECUTE_READWRITE );
	if( !allocated_tuple )
		throw std::runtime_error( "failed to allocate memory for tuple" );

    std::memcpy( allocated_tuple, &tuple, sizeof( tuple ) );
    return allocated_tuple;
}


void main_thread( HMODULE dll_module )
{
	const auto base = reinterpret_cast< std::uint32_t >( GetModuleHandleA( nullptr ) );
	constexpr auto function_rva = 0x1000;

    constexpr auto arg_tuple = std::make_tuple< const char* >( { "exprssn" } );
	const auto tuple = alloc_tuple( arg_tuple );

    const auto caller_func_address = alloc_func( &call_ext_func< void, calling_conventions::cdecl_, const char* > );
	const auto caller = static_cast< cextf_proto >( caller_func_address );

    caller( base + function_rva, reinterpret_cast< std::uint32_t >( tuple ) );
	FreeLibrary( dll_module );
}

bool __stdcall DllMain( HMODULE dll_module, const std::uint32_t reason_for_call, void*  )
{
    if ( reason_for_call == DLL_PROCESS_ATTACH )
        std::thread{ &main_thread, dll_module }.detach( );
    return true;
}

feel free to ask any questions in the replies!

 

  • 1

https://media.discordapp.net/attachments/1044764388546068510/1051935933836050482/Signature_4.png

pepsi

PePsIDeveloper

vip

Posts: 259

Threads: 4

Joined: Apr, 2021

Reputation: 13

Replied

Man its sad no one vouches for expression its turning him more like depression 😭😭😭😭

 

Also vouch since expression still expression my idk..

  • 0

https://cdn.discordapp.com/attachments/661621789591470090/1013919752294498314/Untitled_1366_768_px_1546_202_px_2.gif

Posts: 224

Threads: 43

Joined: May, 2022

Reputation: -5

Replied

@pepsi

 

it is an unfortunate reality....

  • 0

Added

@_realnickk

 

what do you mean?

where am I not casting to a function type when I should?

  • 0

Added

@_realnickk

 

you mean the typedef void( __stdcall* cextf_proto )( const std::uint32_t, const std::uint32_t ); ?

there's no difference between doing static_cast< void( __stdcall* )( const std::uint32_t, const std::uint32_t ) > and static_cast< cextf_proto >

( also typedef void( __stdcall* cextf_proto )( const std::uint32_t, const std::uint32_t )  does not typedef a class )

it's the same thing except the former is cleaner.

  • 0

https://media.discordapp.net/attachments/1044764388546068510/1051935933836050482/Signature_4.png

Users viewing this thread:

( Members: 0, Guests: 1, Total: 1 )