From 4d1f8fe2449bbd97d83b1916eaf346e07ef3fc70 Mon Sep 17 00:00:00 2001 From: INSANEMODE Date: Thu, 19 Nov 2020 10:00:24 -0600 Subject: [PATCH] clean up api related functions, and change version to 1.3 --- ClanTagRank.vcxproj | 14 ++- ClanTagRank.vcxproj.filters | 19 ++-- dllmain.cpp | 11 +-- functions.cpp | 169 ++++++++++++------------------------ functions.h | 24 ++++- utils/hook.cpp | 15 ++++ utils/hook.hpp | 150 ++++++++++++++++++++++++++++++++ utils/memory.cpp | 122 ++++++++++++++++++++++++++ utils/memory.hpp | 76 ++++++++++++++++ 9 files changed, 459 insertions(+), 141 deletions(-) create mode 100644 utils/hook.cpp create mode 100644 utils/hook.hpp create mode 100644 utils/memory.cpp create mode 100644 utils/memory.hpp diff --git a/ClanTagRank.vcxproj b/ClanTagRank.vcxproj index 18e68e1..b4f959b 100644 --- a/ClanTagRank.vcxproj +++ b/ClanTagRank.vcxproj @@ -121,7 +121,7 @@ - Use + NotUsing Level3 true true @@ -165,19 +165,15 @@ - - + + - - Create - Create - Create - Create - + + diff --git a/ClanTagRank.vcxproj.filters b/ClanTagRank.vcxproj.filters index 5291c3b..e95d4f1 100644 --- a/ClanTagRank.vcxproj.filters +++ b/ClanTagRank.vcxproj.filters @@ -18,12 +18,6 @@ - - Header Files - - - Header Files - Header Files @@ -33,15 +27,24 @@ Header Files + + Header Files + + + Header Files + Source Files - + Source Files - + + Source Files + + Source Files diff --git a/dllmain.cpp b/dllmain.cpp index 0ecf7b9..12b39c8 100644 --- a/dllmain.cpp +++ b/dllmain.cpp @@ -1,4 +1,4 @@ -#include "pch.h" + #include #include #include @@ -7,16 +7,17 @@ #include #include #include +HMODULE LogHandle; void init() { - std::cout << "ClanTagRank (1.2) by INSANEMODE\n"; - std::cout << "loaded iw4m-admin url from .\\Plugins\\GetClanTag.ini: " << Game::configfile() << '\n'; - std::thread rank(Game::clanTagThread); - rank.detach(); + std::cout << "ClanTagRank (1.3) by INSANEMODE\n"; + + std::thread addcommands(Game::addCommands); + addcommands.detach(); } BOOL APIENTRY DllMain(HMODULE hModule, diff --git a/functions.cpp b/functions.cpp index 0a8fb87..2ca510d 100644 --- a/functions.cpp +++ b/functions.cpp @@ -1,4 +1,4 @@ -#include "pch.h" + #include #include #include @@ -10,145 +10,84 @@ #include "curl\curl.h" #include "simpleini.h" #include -#define GetCurrentDir _getcwd +#include "utils/hook.hpp" +#include "utils/memory.hpp" +#include +#include "functions.h" + +utils::memory::allocator allocator; + +std::function callback; + +int clientAddr{ 0x02347D10 - 0x57F8 };// check for client GUID instead of name +int clientNameAddr{ 0x02347cd4 - 0x57F8 }; +int clanTagAddr{ 0x30 }; +int clientOffset{ 0x57F8 }; namespace Game { + static Cmd_AddCommand_t Cmd_AddCommand = Cmd_AddCommand_t(0x004DC2A0); + static Cmd_Argv_t Cmd_Argv = (Cmd_Argv_t)0x006B3D40; - std::string configfile() + void clanTagChanger_guid(unsigned int guid, std::string rank) { + - CSimpleIniA ini; - - std::string currentpath = std::filesystem::current_path().generic_string(); - std::string configfile = currentpath + (R"(/t6r/data/plugins/GetClanTag.ini)"); - SI_Error rc = ini.LoadFile(configfile.c_str()); - //SI_Error rc = ini.LoadFile("\\t6r\\data\\plugins\\GetClanTag.ini"); - if (rc < 0) - { - ini.SetValue("Config", "URL", "127.0.0.1:1624"); - ini.SaveFile(configfile.c_str()); - }; - const char* pVal = ini.GetValue("Config", "URL", "http://127.0.0.1:1624"); - return pVal; - } - - - static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) - { - ((std::string*)userp)->append((char*)contents, size * nmemb); - return size * nmemb; - } - std::string testcurl(unsigned int clientguid) - { - std::string guidstring = std::to_string(clientguid); - //std::cout << "guid string: " + guidstring + '\n'; - CURL* curl; - CURLcode res; - std::string readBuffer; - curl = curl_easy_init(); - if (curl) { - curl_easy_setopt(curl, CURLOPT_URL, configfile() + "/api/gsc/clientguid/" + guidstring); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); - /* example.com is redirected, so we tell libcurl to follow redirection */ - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - - /* Perform the request, res will get the return code */ - res = curl_easy_perform(curl); - - /* Check for errors */ - if (res != CURLE_OK) - fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); - - /* always cleanup */ - curl_easy_cleanup(curl); - - } - return readBuffer; - } - std::string ClanTagRequest(unsigned int clientguid) - { - std::string readBuffer; - //const char* constClanTag; - if (clientguid != 0) - { - readBuffer = testcurl(clientguid); - } - readBuffer.erase(std::remove(readBuffer.begin(), readBuffer.end(), '\n'), readBuffer.end()); - readBuffer.erase(std::remove(readBuffer.begin(), readBuffer.end(), '\r'), readBuffer.end()); - - //readBuffer contains the rank that will be put into the clan tag of the client with the requested username - return readBuffer; - - - - - } - void clanTagChanger() - { - - unsigned int clientguid{}; - char emptyname[16]{}; - char currentname[16]{}; - std::string currentname_str; - char currentClanTag[8]{}; const char* changeClanTag{}; - std::string changeClanTag_str; - - - int clientAddr{ 0x02347D10 - 0x57F8 };// check for client GUID instead of name - int clientNameAddr{ 0x02347cd4 - 0x57F8 }; - int clanTagAddr{ 0x30 }; - int clientOffset{ 0x57F8 }; - - //loop through clients to get their name and current clan tag. + //loop through clients to get their guid for (int i = 1; i < 9; i++) { memcpy(&clientguid, (void*)((clientAddr + (clientOffset * i))), 4); - memcpy(¤tname, (void*)((clientNameAddr + (clientOffset * i))), 16); - //currentname_str = std::string(currentname, 16); - memcpy((void*)currentClanTag, (void*)(((clientAddr +(clientOffset * i)) + clanTagAddr)), 8); - //std::cout << "guid uint: " + clientguid << '\n'; - - //if ((strstr(currentClanTag, "Creator") == NULL) && (strstr(currentClanTag, "Admin") == NULL) && (strstr(currentClanTag, "SrAdmin") == NULL) && (strstr(currentClanTag, "Trusted") == NULL) && (strstr(currentClanTag, "Mod") == NULL) && (strstr(currentClanTag, "Owner") == NULL) && (strstr(currentClanTag, "3arc") == NULL) && (clientguid > 0) && (clientguid != NULL)) - if (!*currentClanTag && (clientguid > 0) && (clientguid != NULL)) + if (clientguid == guid) { - changeClanTag_str = ClanTagRequest(clientguid); - - changeClanTag = changeClanTag_str.c_str(); - if ((strstr(currentClanTag, changeClanTag) == NULL) || (strstr(changeClanTag, "Error: Client info is null") == NULL)) - { - - if(!(changeClanTag_str.find("Error:") != std::string::npos)) //&& !(changeClanTag_str.find("User") != std::string::npos)) - { - std::cout << "ClanTag Rank: [" + changeClanTag_str + "]" + currentname + '\n'; - memcpy((void*)(clientAddr + (clientOffset * i) + clanTagAddr), changeClanTag, 8); - } + changeClanTag = rank.c_str(); + memcpy((void*)(clientAddr + (clientOffset * i) + clanTagAddr), changeClanTag, 8); - } } } } - - void clanTagThread() + // + void clanTagChanger_slot(int slot, std::string rank) { - while (true) - { - configfile(); - std::this_thread::sleep_for(std::chrono::milliseconds(10000)); - clanTagChanger(); - } + + const char* changeClanTag{rank.c_str()}; + slot += 1; + //loop through clients to get their guid + memcpy((void*)(clientAddr + (clientOffset * slot) + clanTagAddr), changeClanTag, 8); + } + + void setrank_guid() + { + std::string::size_type sz; // alias of size_t + unsigned int guid = std::stoi(Cmd_Argv(1), &sz); + clanTagChanger_guid(guid, Cmd_Argv(2)); } + void setrank() + { + std::string::size_type sz; // alias of size_t + int client_slot = std::stoi(Cmd_Argv(1), &sz); + clanTagChanger_slot(client_slot, Cmd_Argv(2)); + + } + void addCommands() + { + //std::this_thread::sleep_for(std::chrono::milliseconds(15000)); + const auto cmd_function = allocator.allocate(); + const auto cmd_function_2 = allocator.allocate(); + + Cmd_AddCommand("setrank", setrank, cmd_function); + Cmd_AddCommand("setrank_guid", setrank_guid, cmd_function_2); + //Cmd_AddCommand("commandtest", commandtest); + } + } diff --git a/functions.h b/functions.h index 1a2a0c0..00eab81 100644 --- a/functions.h +++ b/functions.h @@ -1,10 +1,26 @@ +#pragma once #include -HMODULE LogHandle; + namespace Game { - //void Testprint(); - void clanTagThread(); - std::string configfile(); + + void addCommands(); + + struct cmd_function_t + { + cmd_function_t* next; + const char* name; + const char* autoCompleteDir; + const char* autoCompleteExt; + void(__cdecl* function)(); + int flags; + }; + + + typedef void (*Cmd_AddCommand_t)(const char* cmdName, void (*function)(), cmd_function_t* allocedCmd); + extern Cmd_AddCommand_t Cmd_AddCommand; + + typedef char* (*Cmd_Argv_t)(int arg); } diff --git a/utils/hook.cpp b/utils/hook.cpp new file mode 100644 index 0000000..4f4905c --- /dev/null +++ b/utils/hook.cpp @@ -0,0 +1,15 @@ + +//#include "../pch.h" +#include +#include +#include +#include + + +namespace utils::hook +{ + void* allocate_stub_memory(size_t size) + { + return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + } +} diff --git a/utils/hook.hpp b/utils/hook.hpp new file mode 100644 index 0000000..e21caa9 --- /dev/null +++ b/utils/hook.hpp @@ -0,0 +1,150 @@ +#pragma once + +// stolen from plutoscript + +namespace utils::hook +{ + void* allocate_stub_memory(size_t size); + + template + inline ValueType get(AddressType address) + { + return *static_cast(address); + } + + template + inline void set(AddressType address, ValueType value) + { + std::memcpy((void*)address, &value, sizeof(value)); + } + + template + inline void set(AddressType address, const ValueType* data, size_t length) + { + std::memcpy((void*)address, data, sizeof(ValueType) * length); + } + + template + inline void nop(AddressType address, size_t length) + { + std::memset((void*)address, 0x90, length); + } + + template + inline void jump(AddressType address, FuncType func) + { + set(address, 0xE9); + set((uintptr_t)address + 1, (uintptr_t)func - (uintptr_t)address - 5); + } + + template + inline void call(AddressType address, FuncType func) + { + set(address, 0xE8); + set((uintptr_t)address + 1, (intptr_t)func - (intptr_t)address - 5); + } + + template + FuncType detour(AddressType target, FuncType hook, const int len) + { + uintptr_t tampoline = (uintptr_t)allocate_stub_memory(len + 5); + + std::memcpy((void*)tampoline, (void*)target, len); + + set(tampoline + len, 0xE9); + set((uintptr_t)tampoline + len + 1, (intptr_t)target - (intptr_t)tampoline - 5); + + set(target, 0xE9); + set((uintptr_t)target + 1, (intptr_t)hook - (intptr_t)target - 5); + + int pos = len - 5; + if (pos > 0) nop((uintptr_t)target + 5, pos); + + return reinterpret_cast(tampoline); + } + +namespace vp +{ + template + inline void set(AddressType address, ValueType value) + { + DWORD oldProtect; + VirtualProtect((void*)address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtect); + + std::memcpy((void*)address, &value, sizeof(value)); + + VirtualProtect((void*)address, sizeof(value), oldProtect, &oldProtect); + } + + template + inline void set(AddressType address, const ValueType* data, size_t length) + { + DWORD oldProtect; + VirtualProtect((void*)address, sizeof(ValueType) * length, PAGE_EXECUTE_READWRITE, &oldProtect); + + std::memcpy((void*)address, data, sizeof(ValueType) * length); + + VirtualProtect((void*)address, sizeof(ValueType) * length, oldProtect, &oldProtect); + } + + template + inline void nop(AddressType address, size_t length) + { + DWORD oldProtect; + VirtualProtect((void*)address, length, PAGE_EXECUTE_READWRITE, &oldProtect); + + std::memset((void*)address, 0x90, length); + + VirtualProtect((void*)address, length, oldProtect, &oldProtect); + } + + template + inline void jump(AddressType address, FuncType func) + { + DWORD oldProtect; + VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &oldProtect); + + hook::set(address, 0xE9); + hook::set((uintptr_t)address + 1, (intptr_t)func - (intptr_t)address - 5); + + VirtualProtect((void*)address, 5, oldProtect, &oldProtect); + } + + template + inline void call(AddressType address, FuncType func) + { + DWORD oldProtect; + VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &oldProtect); + + hook::set(address, 0xE8); + hook::set((uintptr_t)address + 1, (intptr_t)func - (intptr_t)address - 5); + + VirtualProtect((void*)address, 5, oldProtect, &oldProtect); + } + + template + FuncType detour(AddressType target, FuncType hook, const int len) + { + uintptr_t tampoline = (uintptr_t)allocate_stub_memory(len + 5); + + std::memcpy((void*)tampoline, (void*)target, len); + + hook::set(tampoline + len, 0xE9); + hook::set((uintptr_t)tampoline + len + 1, (intptr_t)target - (intptr_t)tampoline - 5); + + DWORD oldProtect; + VirtualProtect((void*)target, len, PAGE_EXECUTE_READWRITE, &oldProtect); + + hook::set(target, 0xE9); + hook::set((uintptr_t)target + 1, (intptr_t)hook - (intptr_t)target - 5); + + int pos = len - 5; + if (pos > 0) hook::nop((uintptr_t)target + 5, pos); + + VirtualProtect((void*)target, len, oldProtect, &oldProtect); + + return reinterpret_cast(tampoline); + } +} + +} diff --git a/utils/memory.cpp b/utils/memory.cpp new file mode 100644 index 0000000..b0453c2 --- /dev/null +++ b/utils/memory.cpp @@ -0,0 +1,122 @@ +/* + + https://github.com/momo5502/open-iw5 + +*/ +//#include "../pch.h" +#include +#include +#include +#include +#include "memory.hpp" + + + +namespace utils +{ + memory::allocator memory::mem_allocator_; + + memory::allocator::~allocator() + { + this->clear(); + } + + void memory::allocator::clear() + { + std::lock_guard _(this->mutex_); + + for (auto& data : this->pool_) + { + memory::free(data); + } + + this->pool_.clear(); + } + + void memory::allocator::free(void* data) + { + std::lock_guard _(this->mutex_); + + const auto j = std::find(this->pool_.begin(), this->pool_.end(), data); + if (j != this->pool_.end()) + { + memory::free(data); + this->pool_.erase(j); + } + } + + void memory::allocator::free(const void* data) + { + this->free(const_cast(data)); + } + + void* memory::allocator::allocate(const size_t length) + { + std::lock_guard _(this->mutex_); + + const auto data = memory::allocate(length); + this->pool_.push_back(data); + return data; + } + + bool memory::allocator::empty() const + { + return this->pool_.empty(); + } + + /*char* memory::allocator::duplicate_string(const std::string& string) + { + std::lock_guard _(this->mutex_); + + const auto data = memory::duplicate_string(string); + this->pool_.push_back(data); + return data; + }*/ + + void* memory::allocate(const size_t length) + { + const auto data = calloc(length, 1); + assert(data != nullptr); + return data; + } + + /*char* memory::duplicate_string(const std::string& string) + { + const auto new_string = allocate_array(string.size() + 1); + std::memcpy(new_string, string.data(), string.size()); + return new_string; + }*/ + + void memory::free(void* data) + { + if (data) + { + ::free(data); + } + } + + void memory::free(const void* data) + { + free(const_cast(data)); + } + + bool memory::is_set(const void* mem, const char chr, const size_t length) + { + const auto mem_arr = static_cast(mem); + + for (size_t i = 0; i < length; ++i) + { + if (mem_arr[i] != chr) + { + return false; + } + } + + return true; + } + + memory::allocator* memory::get_allocator() + { + return &memory::mem_allocator_; + } +} diff --git a/utils/memory.hpp b/utils/memory.hpp new file mode 100644 index 0000000..74c87ba --- /dev/null +++ b/utils/memory.hpp @@ -0,0 +1,76 @@ +/* + + https://github.com/momo5502/open-iw5 + +*/ + +#pragma once +#include +#include + +namespace utils +{ + class memory final + { + public: + class allocator final + { + public: + ~allocator(); + + void clear(); + + void free(void* data); + + void free(const void* data); + + void* allocate(size_t length); + + template + T* allocate() + { + return this->allocate_array(1); + } + + template + T* allocate_array(const size_t count = 1) + { + return static_cast(this->allocate(count * sizeof(T))); + } + + bool empty() const; + + //char* duplicate_string(const std::string& string); + + private: + std::mutex mutex_; + std::vector pool_; + }; + + static void* allocate(size_t length); + + template + static inline T* allocate() + { + return allocate_array(1); + } + + template + static inline T* allocate_array(const size_t count = 1) + { + return static_cast(allocate(count * sizeof(T))); + } + + //static char* duplicate_string(const std::string& string); + + static void free(void* data); + static void free(const void* data); + + static bool is_set(const void* mem, char chr, size_t length); + + static allocator* get_allocator(); + + private: + static allocator mem_allocator_; + }; +}