Finish process wrapper
This commit is contained in:
parent
c0be5d7cad
commit
908d480e59
@ -19,8 +19,8 @@ Reverse engineering and analysis of Call of Duty: Black Ops 3. Very experimental
|
|||||||
- [x] Disable Integrity Checks
|
- [x] Disable Integrity Checks
|
||||||
- [x] Demonware Emulation
|
- [x] Demonware Emulation
|
||||||
- [ ] Disable Anti-Debugging Mechanisms (probably never gonna happen cause who needs that if you have printf debugging)
|
- [ ] Disable Anti-Debugging Mechanisms (probably never gonna happen cause who needs that if you have printf debugging)
|
||||||
|
- [x] Process wrapper
|
||||||
- [x] P2P multiplayer
|
- [x] P2P multiplayer
|
||||||
- [ ] Process hollowing loader
|
|
||||||
- [ ] Dedicated Servers
|
- [ ] Dedicated Servers
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
16
premake5.lua
16
premake5.lua
@ -285,10 +285,10 @@ project "common"
|
|||||||
dependencies.imports()
|
dependencies.imports()
|
||||||
|
|
||||||
project "client"
|
project "client"
|
||||||
kind "SharedLib"
|
kind "WindowedApp"
|
||||||
language "C++"
|
language "C++"
|
||||||
|
|
||||||
targetname "d3d11"
|
targetname "boiii"
|
||||||
|
|
||||||
pchheader "std_include.hpp"
|
pchheader "std_include.hpp"
|
||||||
pchsource "src/client/std_include.cpp"
|
pchsource "src/client/std_include.cpp"
|
||||||
@ -311,6 +311,18 @@ project "client"
|
|||||||
|
|
||||||
dependencies.imports()
|
dependencies.imports()
|
||||||
|
|
||||||
|
project "tlsdll"
|
||||||
|
kind "SharedLib"
|
||||||
|
language "C++"
|
||||||
|
|
||||||
|
files {"./src/tlsdll/**.rc", "./src/tlsdll/**.hpp", "./src/tlsdll/**.cpp", "./src/tlsdll/resources/**.*"}
|
||||||
|
|
||||||
|
includedirs {"./src/tlsdll", "%{prj.location}/src"}
|
||||||
|
|
||||||
|
links {"common"}
|
||||||
|
|
||||||
|
resincludedirs {"$(ProjectDir)src"}
|
||||||
|
|
||||||
|
|
||||||
project "runner"
|
project "runner"
|
||||||
kind "WindowedApp"
|
kind "WindowedApp"
|
||||||
|
@ -384,7 +384,7 @@ namespace arxan
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loaded)
|
if (!loaded)
|
||||||
{
|
{
|
||||||
memcpy(buffers[i], func, sizeof(buffer));
|
memcpy(buffers[i], func, sizeof(buffer));
|
||||||
@ -698,14 +698,11 @@ namespace arxan
|
|||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
component()
|
void pre_start() override
|
||||||
{
|
{
|
||||||
auto* dll_characteristics = &utils::nt::library().get_optional_header()->DllCharacteristics;
|
auto* dll_characteristics = &utils::nt::library().get_optional_header()->DllCharacteristics;
|
||||||
utils::hook::set<WORD>(dll_characteristics, *dll_characteristics | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE);
|
utils::hook::set<WORD>(dll_characteristics, *dll_characteristics | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE);
|
||||||
}
|
|
||||||
|
|
||||||
void pre_start() override
|
|
||||||
{
|
|
||||||
disable_tls_callbacks();
|
disable_tls_callbacks();
|
||||||
restore_debug_functions();
|
restore_debug_functions();
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x1420EC8B0};
|
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x1420EC8B0};
|
||||||
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{
|
WEAK symbol<void(const char* cmdName, xcommand_t function, cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{
|
||||||
0x1420ED530_g
|
0x1420ED530
|
||||||
};
|
};
|
||||||
WEAK symbol<void(char* text, int maxSize)> Con_GetTextCopy{0x14133A7D0};
|
WEAK symbol<void(char* text, int maxSize)> Con_GetTextCopy{0x14133A7D0};
|
||||||
|
|
||||||
// DB
|
// DB
|
||||||
WEAK symbol<void(XZoneInfo* zoneInfo, uint32_t zoneCount, bool sync, bool suppressSync)> DB_LoadXAssets{
|
WEAK symbol<void(XZoneInfo* zoneInfo, uint32_t zoneCount, bool sync, bool suppressSync)> DB_LoadXAssets{
|
||||||
0x1414236A0_g
|
0x1414236A0
|
||||||
};
|
};
|
||||||
|
|
||||||
// Live
|
// Live
|
||||||
@ -50,12 +50,12 @@ namespace game
|
|||||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetDebugName{0x1422BDCB0};
|
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetDebugName{0x1422BDCB0};
|
||||||
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetString{0x1422BFFF0};
|
WEAK symbol<const char*(const dvar_t* dvar)> Dvar_GetString{0x1422BFFF0};
|
||||||
WEAK symbol<void(const char* dvarName, const char* string, bool createIfMissing)> Dvar_SetFromStringByName{
|
WEAK symbol<void(const char* dvarName, const char* string, bool createIfMissing)> Dvar_SetFromStringByName{
|
||||||
0x1422C7F60_g
|
0x1422C7F60
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
WEAK symbol<void(const char*, int, void*, float, float, float, float, float, float*, int)> R_AddCmdDrawText{
|
WEAK symbol<void(const char*, int, void*, float, float, float, float, float, float*, int)> R_AddCmdDrawText{
|
||||||
0x141CD98D0_g
|
0x141CD98D0
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
|
@ -138,8 +138,16 @@ std::vector<std::unique_ptr<component_interface>>& component_loader::get_compone
|
|||||||
|
|
||||||
size_t get_base()
|
size_t get_base()
|
||||||
{
|
{
|
||||||
static auto base = size_t(utils::nt::library{}.get_ptr());
|
static auto base = []
|
||||||
assert(base && "Failed to resolve base");
|
{
|
||||||
|
const utils::nt::library host{};
|
||||||
|
if(!host || host == utils::nt::library::get_by_address(get_base))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid host application");
|
||||||
|
}
|
||||||
|
|
||||||
|
return size_t(host.get_ptr());
|
||||||
|
}();
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
118
src/client/loader/loader.cpp
Normal file
118
src/client/loader/loader.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader.hpp"
|
||||||
|
#include "tls.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
|
namespace loader
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void load_imports(const utils::nt::library& target)
|
||||||
|
{
|
||||||
|
const auto* const import_directory = &target.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||||
|
|
||||||
|
auto* descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress);
|
||||||
|
|
||||||
|
while (descriptor->Name)
|
||||||
|
{
|
||||||
|
std::string name = LPSTR(target.get_ptr() + descriptor->Name);
|
||||||
|
|
||||||
|
auto* name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->
|
||||||
|
OriginalFirstThunk);
|
||||||
|
auto* address_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||||
|
|
||||||
|
if (!descriptor->OriginalFirstThunk)
|
||||||
|
{
|
||||||
|
name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*name_table_entry)
|
||||||
|
{
|
||||||
|
FARPROC function = nullptr;
|
||||||
|
std::string function_name;
|
||||||
|
const char* function_procname;
|
||||||
|
|
||||||
|
if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry))
|
||||||
|
{
|
||||||
|
function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry));
|
||||||
|
function_procname = MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto* import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry);
|
||||||
|
function_name = import->Name;
|
||||||
|
function_procname = function_name.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto library = utils::nt::library::load(name);
|
||||||
|
if (library)
|
||||||
|
{
|
||||||
|
function = GetProcAddress(library, function_procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(utils::string::va("Unable to load import '%s' from library '%s'",
|
||||||
|
function_name.data(), name.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::hook::set(address_table_entry, reinterpret_cast<uintptr_t>(function));
|
||||||
|
|
||||||
|
name_table_entry++;
|
||||||
|
address_table_entry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_tls(const utils::nt::library& target)
|
||||||
|
{
|
||||||
|
if (target.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
|
||||||
|
{
|
||||||
|
auto* target_tls = tls::allocate_tls_index();
|
||||||
|
const auto* const source_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(target.get_ptr() + target.
|
||||||
|
get_optional_header()
|
||||||
|
->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||||
|
|
||||||
|
const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData;
|
||||||
|
const auto tls_index = *reinterpret_cast<DWORD*>(target_tls->AddressOfIndex);
|
||||||
|
utils::hook::set<DWORD>(source_tls->AddressOfIndex, tls_index);
|
||||||
|
|
||||||
|
if (target_tls->AddressOfCallBacks)
|
||||||
|
{
|
||||||
|
utils::hook::set<void*>(target_tls->AddressOfCallBacks, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD old_protect;
|
||||||
|
VirtualProtect(PVOID(target_tls->StartAddressOfRawData),
|
||||||
|
source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE,
|
||||||
|
&old_protect);
|
||||||
|
|
||||||
|
auto* const tls_base = *reinterpret_cast<LPVOID*>(__readgsqword(0x58) + 8ull * tls_index);
|
||||||
|
std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||||
|
std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData),
|
||||||
|
tls_size);
|
||||||
|
|
||||||
|
VirtualProtect(target_tls, sizeof(*target_tls), PAGE_READWRITE, &old_protect);
|
||||||
|
*target_tls = *source_tls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::nt::library load_binary(const std::string& filename)
|
||||||
|
{
|
||||||
|
const auto target = utils::nt::library::load(filename);
|
||||||
|
if (!target)
|
||||||
|
{
|
||||||
|
throw std::runtime_error{"Failed to map binary!"};
|
||||||
|
}
|
||||||
|
|
||||||
|
load_imports(target);
|
||||||
|
load_tls(target);
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
7
src/client/loader/loader.hpp
Normal file
7
src/client/loader/loader.hpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <utils/nt.hpp>
|
||||||
|
|
||||||
|
namespace loader
|
||||||
|
{
|
||||||
|
utils::nt::library load_binary(const std::string& filename);
|
||||||
|
}
|
42
src/client/loader/tls.cpp
Normal file
42
src/client/loader/tls.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "tls.hpp"
|
||||||
|
|
||||||
|
#include <utils/nt.hpp>
|
||||||
|
#include <utils/binary_resource.hpp>
|
||||||
|
|
||||||
|
#include "resource.hpp"
|
||||||
|
|
||||||
|
namespace tls
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
utils::binary_resource tls_dll_file(TLS_DLL, "boiii-tlsdll.dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
PIMAGE_TLS_DIRECTORY allocate_tls_index()
|
||||||
|
{
|
||||||
|
static auto already_allocated = false;
|
||||||
|
if (already_allocated)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Currently only a single allocation is supported!");
|
||||||
|
}
|
||||||
|
|
||||||
|
already_allocated = true;
|
||||||
|
|
||||||
|
const auto dll_path = tls_dll_file.get_extracted_file();
|
||||||
|
const auto tls_dll = utils::nt::library::load(dll_path);
|
||||||
|
if (!tls_dll)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to load TLS DLL");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto tls_dir_entry = tls_dll.get_optional_header()
|
||||||
|
->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress;
|
||||||
|
if (!tls_dir_entry)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("TLS DLL is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<PIMAGE_TLS_DIRECTORY>(tls_dll.get_ptr() + tls_dir_entry);
|
||||||
|
}
|
||||||
|
}
|
6
src/client/loader/tls.hpp
Normal file
6
src/client/loader/tls.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace tls
|
||||||
|
{
|
||||||
|
PIMAGE_TLS_DIRECTORY allocate_tls_index();
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
|
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
#include "loader/loader.hpp"
|
||||||
|
|
||||||
#include <utils/finally.hpp>
|
#include <utils/finally.hpp>
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
@ -11,6 +12,7 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
volatile bool g_call_tls_callbacks = false;
|
||||||
std::pair<void**, void*> g_original_import{};
|
std::pair<void**, void*> g_original_import{};
|
||||||
|
|
||||||
DECLSPEC_NORETURN void WINAPI exit_hook(const uint32_t code)
|
DECLSPEC_NORETURN void WINAPI exit_hook(const uint32_t code)
|
||||||
@ -84,8 +86,61 @@ namespace
|
|||||||
utils::io::remove_file(game_path.generic_string());
|
utils::io::remove_file(game_path.generic_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool run()
|
PIMAGE_TLS_CALLBACK* get_tls_callbacks()
|
||||||
{
|
{
|
||||||
|
const utils::nt::library game{};
|
||||||
|
const auto& entry = game.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
|
||||||
|
if (!entry.VirtualAddress || !entry.Size)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* tls_dir = reinterpret_cast<IMAGE_TLS_DIRECTORY*>(game.get_ptr() + entry.VirtualAddress);
|
||||||
|
return reinterpret_cast<PIMAGE_TLS_CALLBACK*>(tls_dir->AddressOfCallBacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_tls_callbacks(const DWORD reason)
|
||||||
|
{
|
||||||
|
if (!g_call_tls_callbacks)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* callback = get_tls_callbacks();
|
||||||
|
while (callback && *callback)
|
||||||
|
{
|
||||||
|
(*callback)(GetModuleHandleA(nullptr), reason, nullptr);
|
||||||
|
++callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] thread_local struct tls_runner
|
||||||
|
{
|
||||||
|
tls_runner()
|
||||||
|
{
|
||||||
|
run_tls_callbacks(DLL_THREAD_ATTACH);
|
||||||
|
}
|
||||||
|
|
||||||
|
~tls_runner()
|
||||||
|
{
|
||||||
|
run_tls_callbacks(DLL_THREAD_DETACH);
|
||||||
|
}
|
||||||
|
} tls_runner;
|
||||||
|
|
||||||
|
FARPROC load_process(const std::string& procname)
|
||||||
|
{
|
||||||
|
const auto proc = loader::load_binary(procname);
|
||||||
|
|
||||||
|
auto* const peb = reinterpret_cast<PPEB>(__readgsqword(0x60));
|
||||||
|
peb->Reserved3[1] = proc.get_ptr();
|
||||||
|
static_assert(offsetof(PEB, Reserved3[1]) == 0x10);
|
||||||
|
|
||||||
|
return FARPROC(proc.get_ptr() + proc.get_relative_entry_point());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
FARPROC entry_point{};
|
||||||
srand(uint32_t(time(nullptr)) ^ ~(GetTickCount() * GetCurrentProcessId()));
|
srand(uint32_t(time(nullptr)) ^ ~(GetTickCount() * GetCurrentProcessId()));
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -100,12 +155,19 @@ namespace
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
patch_imports();
|
|
||||||
remove_crash_file();
|
remove_crash_file();
|
||||||
|
|
||||||
|
entry_point = load_process("BlackOps3.exe");
|
||||||
|
if (!entry_point)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Unable to load binary into memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
patch_imports();
|
||||||
|
|
||||||
if (!component_loader::pre_start())
|
if (!component_loader::pre_start())
|
||||||
{
|
{
|
||||||
return false;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
premature_shutdown = false;
|
premature_shutdown = false;
|
||||||
@ -113,141 +175,17 @@ namespace
|
|||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||||
return false;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
g_call_tls_callbacks = true;
|
||||||
}
|
return static_cast<int>(entry_point());
|
||||||
|
|
||||||
class patch
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
patch() = default;
|
|
||||||
|
|
||||||
patch(void* source, void* target)
|
|
||||||
: source_(source)
|
|
||||||
{
|
|
||||||
memcpy(this->data_, source, sizeof(this->data_));
|
|
||||||
utils::hook::jump(this->source_, target, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
~patch()
|
|
||||||
{
|
|
||||||
if (source_)
|
|
||||||
{
|
|
||||||
utils::hook::copy(this->source_, this->data_, sizeof(this->data_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
patch(patch&& obj) noexcept
|
|
||||||
: patch()
|
|
||||||
{
|
|
||||||
this->operator=(std::move(obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
patch& operator=(patch&& obj) noexcept
|
|
||||||
{
|
|
||||||
if (this != &obj)
|
|
||||||
{
|
|
||||||
this->~patch();
|
|
||||||
|
|
||||||
this->source_ = obj.source_;
|
|
||||||
memcpy(this->data_, obj.data_, sizeof(this->data_));
|
|
||||||
|
|
||||||
obj.source_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* source_{nullptr};
|
|
||||||
uint8_t data_[15]{};
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<patch> initialization_hooks{};
|
|
||||||
|
|
||||||
uint8_t* get_entry_point()
|
|
||||||
{
|
|
||||||
const utils::nt::library game{};
|
|
||||||
return game.get_ptr() + game.get_optional_header()->AddressOfEntryPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t*> get_tls_callbacks()
|
|
||||||
{
|
|
||||||
const utils::nt::library game{};
|
|
||||||
const auto& entry = game.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
|
|
||||||
if (!entry.VirtualAddress || !entry.Size)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto* tls_dir = reinterpret_cast<IMAGE_TLS_DIRECTORY*>(game.get_ptr() + entry.VirtualAddress);
|
|
||||||
auto* callback = reinterpret_cast<uint8_t**>(tls_dir->AddressOfCallBacks);
|
|
||||||
|
|
||||||
std::vector<uint8_t*> addresses{};
|
|
||||||
while (callback && *callback)
|
|
||||||
{
|
|
||||||
addresses.emplace_back(*callback);
|
|
||||||
++callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
return addresses;
|
|
||||||
}
|
|
||||||
|
|
||||||
int patch_main()
|
|
||||||
{
|
|
||||||
if (!run())
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
initialization_hooks.clear();
|
|
||||||
return reinterpret_cast<int(*)()>(get_entry_point())();
|
|
||||||
}
|
|
||||||
|
|
||||||
void nullsub()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void patch_entry_point()
|
|
||||||
{
|
|
||||||
initialization_hooks.emplace_back(get_entry_point(), patch_main);
|
|
||||||
|
|
||||||
for (auto* tls_callback : get_tls_callbacks())
|
|
||||||
{
|
|
||||||
initialization_hooks.emplace_back(tls_callback, nullsub);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE, const DWORD reason, LPVOID)
|
|
||||||
|
int __stdcall WinMain(HINSTANCE, HINSTANCE, PSTR, int)
|
||||||
{
|
{
|
||||||
if (reason == DLL_PROCESS_ATTACH)
|
return main();
|
||||||
{
|
|
||||||
patch_entry_point();
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" __declspec(dllexport)
|
|
||||||
HRESULT D3D11CreateDevice(void* adapter, const uint64_t driver_type,
|
|
||||||
const HMODULE software, const UINT flags,
|
|
||||||
const void* p_feature_levels, const UINT feature_levels,
|
|
||||||
const UINT sdk_version, void** device, void* feature_level,
|
|
||||||
void** immediate_context)
|
|
||||||
{
|
|
||||||
static auto func = []
|
|
||||||
{
|
|
||||||
char dir[MAX_PATH]{0};
|
|
||||||
GetSystemDirectoryA(dir, sizeof(dir));
|
|
||||||
|
|
||||||
const auto d3d11 = utils::nt::library::load(dir + "/d3d11.dll"s);
|
|
||||||
return d3d11.get_proc<decltype(&D3D11CreateDevice)>("D3D11CreateDevice");
|
|
||||||
}();
|
|
||||||
|
|
||||||
return func(adapter, driver_type, software, flags, p_feature_levels, feature_levels, sdk_version, device,
|
|
||||||
feature_level, immediate_context);
|
|
||||||
}
|
}
|
||||||
|
@ -13,3 +13,4 @@
|
|||||||
#define DW_QOSCONFIG 307
|
#define DW_QOSCONFIG 307
|
||||||
|
|
||||||
#define RUNNER 308
|
#define RUNNER 308
|
||||||
|
#define TLS_DLL 309
|
||||||
|
@ -108,6 +108,12 @@ RUNNER RCDATA "../../build/bin/x64/Debug/runner.exe"
|
|||||||
RUNNER RCDATA "../../build/bin/x64/Release/runner.exe"
|
RUNNER RCDATA "../../build/bin/x64/Release/runner.exe"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
TLS_DLL RCDATA "../../build/bin/x64/Debug/tlsdll.dll"
|
||||||
|
#else
|
||||||
|
TLS_DLL RCDATA "../../build/bin/x64/Release/tlsdll.dll"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // English (United States) resources
|
#endif // English (United States) resources
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
7
src/tlsdll/dllmain.cpp
Normal file
7
src/tlsdll/dllmain.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#define TLS_PAYLOAD_SIZE 0x2000
|
||||||
|
thread_local char tls_data[TLS_PAYLOAD_SIZE];
|
||||||
|
|
||||||
|
__declspec(dllexport) void* get_tls_data()
|
||||||
|
{
|
||||||
|
return &tls_data[0];
|
||||||
|
}
|
100
src/tlsdll/resource.rc
Normal file
100
src/tlsdll/resource.rc
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#pragma code_page(65001)
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "windows.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (United States) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""windows.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,0,0
|
||||||
|
PRODUCTVERSION 1,0,0,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE VFT_DLL
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "X Labs"
|
||||||
|
VALUE "FileDescription", "TLS index allocation dll"
|
||||||
|
VALUE "FileVersion", "1.0.0.0"
|
||||||
|
VALUE "InternalName", "TLS DLL"
|
||||||
|
VALUE "LegalCopyright", "All rights reserved."
|
||||||
|
VALUE "OriginalFilename", "tlsdll.dll"
|
||||||
|
VALUE "ProductName", "tlsdll"
|
||||||
|
VALUE "ProductVersion", "1.0.0.0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Binary Data
|
||||||
|
//
|
||||||
|
|
||||||
|
// Nothing here
|
||||||
|
|
||||||
|
#endif // English (United States) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user