diff options
| author | boris <wzn@moneybot.cc> | 2018-12-05 14:25:59 +1300 |
|---|---|---|
| committer | boris <wzn@moneybot.cc> | 2018-12-05 14:25:59 +1300 |
| commit | 793965d3c2816fc1b672c9173b3b831d82cdec33 (patch) | |
| tree | f7e2b8b9f948f5816064d4dc265e91dd755ec7db | |
| parent | bca49754578cd6c002fa258f89fe85bb9966e9c1 (diff) | |
server
| -rw-r--r-- | loader/server/fnv.hpp | 64 | ||||
| -rw-r--r-- | loader/server/manual_map.cpp | 42 | ||||
| -rw-r--r-- | loader/server/manual_map.hpp | 3 |
3 files changed, 105 insertions, 4 deletions
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 <cstdint> +#include <string> + +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<decltype(import_dir)>(m_pe.data()
+ + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+
+ while (import_dir->Characteristics) {
+ orig_first_thunk = reinterpret_cast<decltype(orig_first_thunk)>(m_pe.data() + import_dir->OriginalFirstThunk);
+ first_thunk = reinterpret_cast<decltype(first_thunk)>(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<decltype(import_table)>(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 <iterator>
#include <vector>
+#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;
};
|
