#pragma once #include #include "util.hpp" namespace winapi { static uintptr_t get_procaddr_ex( HANDLE process, HMODULE mod, const char* proc ) { IMAGE_DOS_HEADER dos_hdr; IMAGE_NT_HEADERS nt_hdrs; IMAGE_EXPORT_DIRECTORY export_dir; uintptr_t export_addr; char export_name[ 64 ]; uintptr_t* names; uintptr_t* funcs; uint16_t* ords; uintptr_t ret{ }; ReadProcessMemory( process, mod, &dos_hdr, sizeof( dos_hdr ), 0 ); ReadProcessMemory( process, ( void* )( uintptr_t( mod ) + dos_hdr.e_lfanew ), &nt_hdrs, sizeof( nt_hdrs ), nullptr ); export_addr = nt_hdrs.OptionalHeader.DataDirectory[ 0 ].VirtualAddress; ReadProcessMemory( process, ( void* )( uintptr_t( mod ) + export_addr ), &export_dir, sizeof( export_dir ), nullptr ); if( !export_dir.NumberOfFunctions ) return uintptr_t{ }; funcs = ( uintptr_t* )( malloc( sizeof( uintptr_t ) * export_dir.AddressOfFunctions ) ); names = ( uintptr_t* )( malloc( sizeof( uintptr_t ) * export_dir.NumberOfNames ) ); ords = ( uint16_t* ) ( malloc( sizeof( uint16_t ) * export_dir.NumberOfNames ) ); ReadProcessMemory( process, ( void* )( uintptr_t( mod ) + export_dir.AddressOfFunctions ), funcs, sizeof( uintptr_t ) * export_dir.NumberOfFunctions, nullptr ); ReadProcessMemory( process, ( void* )( uintptr_t( mod ) + export_dir.AddressOfNames ), names, sizeof( uintptr_t ) * export_dir.NumberOfNames, nullptr ); ReadProcessMemory( process, ( void* )( uintptr_t( mod ) + export_dir.AddressOfNameOrdinals ), ords, sizeof( uint16_t ) * export_dir.NumberOfNames, nullptr ); auto read_str = [ &process ]( char* buf, size_t size, uintptr_t addr ) { for( size_t i{ }; i < size; ++i ) { char _c; ReadProcessMemory( process, ( void* )( addr + i ), &_c, 1, 0 ); buf[ i ] = _c; if( !_c ) break; } buf[ size - 1 ] = 0; }; for( size_t i{ }; i < export_dir.NumberOfNames; ++i ) { read_str( export_name, 64, uintptr_t( mod ) + names[ i ] ); if( !strcmp( export_name, proc ) ) ret = uintptr_t( mod ) + funcs[ ords[ i ] ]; } ::free( funcs ); ::free( names ); ::free( ords ); return ret; } }