summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorboris <wzn@moneybot.cc>2018-12-05 14:25:59 +1300
committerboris <wzn@moneybot.cc>2018-12-05 14:25:59 +1300
commit793965d3c2816fc1b672c9173b3b831d82cdec33 (patch)
treef7e2b8b9f948f5816064d4dc265e91dd755ec7db
parentbca49754578cd6c002fa258f89fe85bb9966e9c1 (diff)
server
-rw-r--r--loader/server/fnv.hpp64
-rw-r--r--loader/server/manual_map.cpp42
-rw-r--r--loader/server/manual_map.hpp3
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;
};