#pragma once #include #include #include "winapi.hpp" #include "util.hpp" namespace iface { class container { private: struct reg { char m_key; uintptr_t m_ptr; uintptr_t m_module; char m_module_name[ 64 ]; char m_name[ 64 ]; }; std::vector< reg > m_regs; public: void emplace_reg( uintptr_t ptr, uintptr_t module_, const char* name, const char* module_name, char name_key ) { reg new_reg{ }; new_reg.m_ptr = ptr; new_reg.m_module = module_; memcpy( new_reg.m_name, name, 64 ); memcpy( new_reg.m_module_name, module_name, 64 ); new_reg.m_key = name_key; m_regs.emplace_back( new_reg ); } auto& get_regs( ) { return m_regs; } }; struct iface_reg_t { void* m_create_fn; const char* m_name; uintptr_t m_next; inline auto follow( HANDLE process ) { iface_reg_t buf; ReadProcessMemory( process, ( void* )( m_next ), &buf, sizeof( buf ), nullptr ); return buf; } }; class manager { HANDLE& m_process; container m_container; inline auto is_createinterface_export( uintptr_t export_ ) { uint8_t buf[ 12 ]; ReadProcessMemory( m_process, ( void* )( export_ ), buf, sizeof( buf ), nullptr ); return( buf[ 0 ] == 0x55 && buf[ 4 ] == 0xe9 && buf[ 9 ] == 0xcc && buf[ 10 ] == 0xcc ); } inline auto is_createinterface_fn( uintptr_t fn_ ) { uint8_t buf[ 12 ]; ReadProcessMemory( m_process, ( void* )( fn_ ), buf, sizeof( buf ), nullptr ); return( buf[ 0 ] == 0x55 && buf[ 4 ] == 0x8b && buf[ 10 ] == 0x57 ); } inline auto follow_createinterface_export( uintptr_t export_ ) { uintptr_t jmp = export_ + 0x4; uintptr_t rel; ReadProcessMemory( m_process, ( void* )( jmp + 0x1 ), &rel, sizeof( rel ), nullptr ); return jmp + rel + 0x5; } inline auto find_list_ptr( uintptr_t createinterface ) { uintptr_t first = createinterface + 0x6, second, third; ReadProcessMemory( m_process, ( void* )( first ), &second, sizeof( second ), nullptr ); ReadProcessMemory( m_process, ( void* )( second ), &third, sizeof( third ), nullptr ); return third; } inline auto get_list( uintptr_t ptr ) { iface_reg_t reg; ReadProcessMemory( m_process, ( void* )( ptr ), ®, sizeof( reg ), nullptr ); return reg; } public: manager( HANDLE& process ) : m_process( process ) { }; inline void dump_from_module( HMODULE mod, const char* module_name ) { auto read_str = [ this ]( char* buf, size_t size, uintptr_t addr ) { for( size_t i{ }; i < size; ++i ) { char _c; ReadProcessMemory( m_process, ( void* )( addr + i ), &_c, 1, 0 ); buf[ i ] = _c; if( !_c ) break; } buf[ size - 1 ] = 0; }; auto enc_str = [ ]( char* buf, size_t size, char key ) { for( size_t i{ }; i < size; ++i ) { buf[ i ] ^= key; } }; auto create_interface = winapi::get_procaddr_ex( m_process, mod, xors( "CreateInterface" ) ); if( !create_interface || !is_createinterface_export( create_interface ) ) return; auto fn = follow_createinterface_export( create_interface ); if( !is_createinterface_fn( fn ) ) return; auto list_ptr = find_list_ptr( fn ); auto list = get_list( list_ptr ); char name_buf[ 64 ]; char module_buf[ 64 ]; do { read_str( name_buf, 64, ( uintptr_t )( list.m_name ) ); strcpy( module_buf, module_name ); srand( list_ptr ); auto key = rand( ) & 0xff; enc_str( name_buf, 64, key ); enc_str( module_buf, 64, key ); uintptr_t iface_ptr = 0; ReadProcessMemory( m_process, ( void* )( ( uintptr_t )list.m_create_fn + 1 ), &iface_ptr, sizeof( uintptr_t ), nullptr ); m_container.emplace_reg( iface_ptr, uintptr_t( mod ), name_buf, module_name, key ); list_ptr = list.m_next; list = get_list( list_ptr ); } while( list_ptr && name_buf[ 0 ] && list_ptr != list.m_next ); } void dump_all_modules( int pid ) { HANDLE t32_snapshot; MODULEENTRY32 entry; t32_snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pid ); entry.dwSize = sizeof( MODULEENTRY32 ); for( Module32First( t32_snapshot, &entry ); !!Module32Next( t32_snapshot, &entry ); ) { //why valve troll me if( strstr( entry.szModule, xors( "valve_avi" ) ) ) continue; dump_from_module( ( HMODULE )( entry.modBaseAddr ), entry.szModule ); } } auto count( ) { return m_container.get_regs( ).size( ); } auto& get( ) { return m_container; } uintptr_t write_to_process( ) { size_t count_ = count( ); size_t size = count_ * 137 + sizeof( size_t ); auto allocation = VirtualAllocEx( m_process, 0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); WriteProcessMemory( m_process, allocation, &count_, sizeof( count_ ), nullptr ); WriteProcessMemory( m_process, ( void* )( uintptr_t( allocation ) + 0x4 ), get( ).get_regs( ).data( ), size, nullptr ); return ( uintptr_t )( allocation ); } }; }