clean up api related functions, and change version to 1.3

This commit is contained in:
INSANEMODE 2020-11-19 10:00:24 -06:00
parent 8834f75f63
commit 4d1f8fe244
9 changed files with 459 additions and 141 deletions

View File

@ -121,7 +121,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
@ -165,19 +165,15 @@
<ItemGroup>
<ClInclude Include="..\bo2plugin_test - Copy\framework.h" />
<ClInclude Include="functions.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="SimpleIni.h" />
<ClInclude Include="utils\hook.hpp" />
<ClInclude Include="utils\memory.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="functions.cpp" />
<ClCompile Include="utils\hook.cpp" />
<ClCompile Include="utils\memory.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@ -18,12 +18,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\bo2plugin_test - Copy\framework.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -33,15 +27,24 @@
<ClInclude Include="SimpleIni.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utils\hook.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utils\memory.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<ClCompile Include="functions.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="functions.cpp">
<ClCompile Include="utils\hook.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utils\memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@ -1,4 +1,4 @@
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include <string>
@ -7,16 +7,17 @@
#include <cstdlib>
#include <chrono>
#include <thread>
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,

View File

@ -1,4 +1,4 @@
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include <string>
@ -10,145 +10,84 @@
#include "curl\curl.h"
#include "simpleini.h"
#include <filesystem>
#define GetCurrentDir _getcwd
#include "utils/hook.hpp"
#include "utils/memory.hpp"
#include <functional>
#include "functions.h"
utils::memory::allocator allocator;
std::function<void(const std::string& code)> 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(&currentname, (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<cmd_function_t>();
const auto cmd_function_2 = allocator.allocate<cmd_function_t>();
Cmd_AddCommand("setrank", setrank, cmd_function);
Cmd_AddCommand("setrank_guid", setrank_guid, cmd_function_2);
//Cmd_AddCommand("commandtest", commandtest);
}
}

View File

@ -1,10 +1,26 @@
#pragma once
#include <Windows.h>
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);
}

15
utils/hook.cpp Normal file
View File

@ -0,0 +1,15 @@
//#include "../pch.h"
#include <windows.h>
#include <vector>
#include <cassert>
#include <mutex>
namespace utils::hook
{
void* allocate_stub_memory(size_t size)
{
return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
}

150
utils/hook.hpp Normal file
View File

@ -0,0 +1,150 @@
#pragma once
// stolen from plutoscript
namespace utils::hook
{
void* allocate_stub_memory(size_t size);
template<typename ValueType, typename AddressType>
inline ValueType get(AddressType address)
{
return *static_cast<ValueType*>(address);
}
template<typename ValueType, typename AddressType>
inline void set(AddressType address, ValueType value)
{
std::memcpy((void*)address, &value, sizeof(value));
}
template<typename ValueType, typename AddressType>
inline void set(AddressType address, const ValueType* data, size_t length)
{
std::memcpy((void*)address, data, sizeof(ValueType) * length);
}
template<typename AddressType>
inline void nop(AddressType address, size_t length)
{
std::memset((void*)address, 0x90, length);
}
template<typename FuncType, typename AddressType>
inline void jump(AddressType address, FuncType func)
{
set<uint8_t>(address, 0xE9);
set<uintptr_t>((uintptr_t)address + 1, (uintptr_t)func - (uintptr_t)address - 5);
}
template<typename FuncType, typename AddressType>
inline void call(AddressType address, FuncType func)
{
set<uint8_t>(address, 0xE8);
set<int>((uintptr_t)address + 1, (intptr_t)func - (intptr_t)address - 5);
}
template<typename FuncType, typename AddressType>
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<uint8_t>(tampoline + len, 0xE9);
set<int>((uintptr_t)tampoline + len + 1, (intptr_t)target - (intptr_t)tampoline - 5);
set<uint8_t>(target, 0xE9);
set<int>((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<FuncType>(tampoline);
}
namespace vp
{
template<typename ValueType, typename AddressType>
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<typename ValueType, typename AddressType>
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<typename AddressType>
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<typename FuncType, typename AddressType>
inline void jump(AddressType address, FuncType func)
{
DWORD oldProtect;
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
hook::set<uint8_t>(address, 0xE9);
hook::set<int>((uintptr_t)address + 1, (intptr_t)func - (intptr_t)address - 5);
VirtualProtect((void*)address, 5, oldProtect, &oldProtect);
}
template<typename FuncType, typename AddressType>
inline void call(AddressType address, FuncType func)
{
DWORD oldProtect;
VirtualProtect((void*)address, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
hook::set<uint8_t>(address, 0xE8);
hook::set<int>((uintptr_t)address + 1, (intptr_t)func - (intptr_t)address - 5);
VirtualProtect((void*)address, 5, oldProtect, &oldProtect);
}
template<typename FuncType, typename AddressType>
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<uint8_t>(tampoline + len, 0xE9);
hook::set<int>((uintptr_t)tampoline + len + 1, (intptr_t)target - (intptr_t)tampoline - 5);
DWORD oldProtect;
VirtualProtect((void*)target, len, PAGE_EXECUTE_READWRITE, &oldProtect);
hook::set<uint8_t>(target, 0xE9);
hook::set<int>((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<FuncType>(tampoline);
}
}
}

122
utils/memory.cpp Normal file
View File

@ -0,0 +1,122 @@
/*
https://github.com/momo5502/open-iw5
*/
//#include "../pch.h"
#include <windows.h>
#include <vector>
#include <cassert>
#include <mutex>
#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<void*>(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<char>(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<void*>(data));
}
bool memory::is_set(const void* mem, const char chr, const size_t length)
{
const auto mem_arr = static_cast<const char*>(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_;
}
}

76
utils/memory.hpp Normal file
View File

@ -0,0 +1,76 @@
/*
https://github.com/momo5502/open-iw5
*/
#pragma once
#include <mutex>
#include <vector>
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 <typename T>
T* allocate()
{
return this->allocate_array<T>(1);
}
template <typename T>
T* allocate_array(const size_t count = 1)
{
return static_cast<T*>(this->allocate(count * sizeof(T)));
}
bool empty() const;
//char* duplicate_string(const std::string& string);
private:
std::mutex mutex_;
std::vector<void*> pool_;
};
static void* allocate(size_t length);
template <typename T>
static inline T* allocate()
{
return allocate_array<T>(1);
}
template <typename T>
static inline T* allocate_array(const size_t count = 1)
{
return static_cast<T*>(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_;
};
}