From 793965d3c2816fc1b672c9173b3b831d82cdec33 Mon Sep 17 00:00:00 2001 From: boris Date: Wed, 5 Dec 2018 14:25:59 +1300 Subject: server --- loader/server/fnv.hpp | 64 ++++++++++++++++++++++++++++++++++++++++++++ loader/server/manual_map.cpp | 42 ++++++++++++++++++++++++++--- loader/server/manual_map.hpp | 3 +++ 3 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 loader/server/fnv.hpp (limited to 'loader/server') diff --git a/loader/server/fnv.hpp b/loader/server/fnv.hpp new file mode 100644 index 0000000..08a478b --- /dev/null +++ b/loader/server/fnv.hpp @@ -0,0 +1,64 @@ +#pragma once + +#pragma warning( disable : 4307 ) // '*': integral constant overflow +#pragma warning( disable : 4244 ) // possible loss of data + +#include +#include + +using hash_t = unsigned int; + +// used for compile-time FNV-1a 32bit hashes. +#define fnv( str ) \ + [&]() { \ + constexpr hash_t out = hash::fnv1a( str ); \ + \ + return out; \ + }() + +// used for compile-time FNV-1a 32bit hashes when above macro cant be used for constexpr variables. +#define fnv_const( str ) Hash::fnv1a_32( str ) + +namespace hash // FNV-1a ( Fowler-Noll-Vo hash ). +{ + // FNV-1a constants. + enum : hash_t { + FNV1A_PRIME = 0x1000193, + FNV1A_BASIS = 0x811C9DC5 + }; + + // compile-time strlen. + __forceinline constexpr size_t ct_strlen( const char *str ) { + size_t out = 1; + + for( ; str[ out ] != '\0'; ++out ); + + return out; + } + + // hash data. + __forceinline constexpr hash_t fnv1a( const uint8_t *data, const size_t len ) { + hash_t out = FNV1A_BASIS; + + for( size_t i = 0; i < len; ++i ) + out = ( out ^ data[ i ] ) * FNV1A_PRIME; + + return out; + } + + // hash c-style string. + __forceinline constexpr hash_t fnv1a( const char *str ) { + hash_t out = FNV1A_BASIS; + size_t len = ct_strlen( str ); + + for( size_t i = 0; i < len; ++i ) + out = ( out ^ str[ i ] ) * FNV1A_PRIME; + + return out; + } + + // hash C++-style string ( runtime only ). + __forceinline hash_t fnv1a( const std::string &str ) { + return fnv1a( ( uint8_t* )str.c_str( ), str.length( ) ); + } +} \ No newline at end of file diff --git a/loader/server/manual_map.cpp b/loader/server/manual_map.cpp index 8198c3e..9e7dad7 100644 --- a/loader/server/manual_map.cpp +++ b/loader/server/manual_map.cpp @@ -42,6 +42,7 @@ namespace remote_code { 0xC3 // retn }; + // reminder client must pass these to the server at some point.. struct shellcode_args_t { uint32_t m_virtual_protect; // 0xDEADBEEF uint32_t m_cheat_entrypoint; // 0xDEADF00D @@ -108,10 +109,6 @@ namespace inject { pe_file.read((char*)m_file.data(), pe_size); pe_file.close(); - - //remote_code::shellcode_args_t args; - //args = { 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555 }; - //remote_code::make_code(&args); } bool c_pe_file::valid() { @@ -175,6 +172,43 @@ namespace inject { IMAGE_IMPORT_DESCRIPTOR* import_dir; IMAGE_IMPORT_BY_NAME* import_table; + import_dir = reinterpret_cast(m_pe.data() + + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + + while (import_dir->Characteristics) { + orig_first_thunk = reinterpret_cast(m_pe.data() + import_dir->OriginalFirstThunk); + first_thunk = reinterpret_cast(m_pe.data() + import_dir->FirstThunk); + + // functions are imported by the fnv hash of func name + while (orig_first_thunk->u1.AddressOfData) { + // ordinals are homo + if (orig_first_thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) { + const uint16_t ordinal = orig_first_thunk->u1.Ordinal & 0xFFFF; + for (auto &it : m_exports) { + if (it.m_ordinal == ordinal) + first_thunk->u1.Function = it.m_address; + } + } + else { + import_table = reinterpret_cast(m_pe.data() + orig_first_thunk->u1.AddressOfData); + + // look up export by hash + const auto hash = hash::fnv1a(import_table->Name); + for (auto &it : m_exports) { + if (it.m_hash == hash) + first_thunk->u1.Function = it.m_address; + } + } + + // advance + orig_first_thunk++; + first_thunk++; + } + + // advance + import_dir++; + } + return true; } diff --git a/loader/server/manual_map.hpp b/loader/server/manual_map.hpp index 7431353..34159da 100644 --- a/loader/server/manual_map.hpp +++ b/loader/server/manual_map.hpp @@ -9,6 +9,8 @@ #include #include +#include "fnv.hpp" + // here's the game plan: // - client runs, waits for game to start and whatnot // - we wait for serverbrowser.dll to load (if source game, we should have an option in the game struct to wait for module) @@ -35,6 +37,7 @@ namespace inject { // used for fixing imports struct process_export_t { uint32_t m_hash; + uint32_t m_ordinal; uint32_t m_address; }; -- cgit v1.2.3