From 11571a5f10d9c8bc3ff3f732559ad41431958a77 Mon Sep 17 00:00:00 2001 From: xerox Date: Mon, 10 Aug 2020 22:18:26 -0700 Subject: [PATCH] working with new ligma-utils code --- anticheat/libtersafe.idb | Bin 42958862 -> 42958862 bytes ligma-cheat/ligma-cheat/bypass/bypass.cpp | 11 +- ligma-cheat/ligma-cheat/bypass/bypass.h | 2 +- ligma-cheat/ligma-cheat/hooks/dlsym_hook.cpp | 49 ++++++ ligma-cheat/ligma-cheat/hooks/dlsym_hook.h | 45 +++++ ligma-cheat/ligma-cheat/hooks/shithook.cpp | 62 +++++++ ligma-cheat/ligma-cheat/hooks/shithook.h | 158 ++++-------------- ligma-cheat/ligma-cheat/ligma-cheat.vcxproj | 3 + .../ligma-cheat/ligma-cheat.vcxproj.filters | 12 ++ ligma-cheat/ligma-cheat/ligma.h | 1 + ligma-cheat/ligma-cheat/main.cpp | 9 +- ligma-cheat/ligma-cheat/utils/utils.cpp | 76 ++++----- ligma-cheat/ligma-cheat/utils/utils.h | 15 +- 13 files changed, 257 insertions(+), 186 deletions(-) create mode 100644 ligma-cheat/ligma-cheat/hooks/dlsym_hook.cpp create mode 100644 ligma-cheat/ligma-cheat/hooks/dlsym_hook.h create mode 100644 ligma-cheat/ligma-cheat/hooks/shithook.cpp diff --git a/anticheat/libtersafe.idb b/anticheat/libtersafe.idb index f42df06af9299150e4bd7d435365569958acb3a2..c41993f0a688175b28fb1f37ec196923c8650ade 100644 GIT binary patch delta 71755 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 diff --git a/ligma-cheat/ligma-cheat/bypass/bypass.cpp b/ligma-cheat/ligma-cheat/bypass/bypass.cpp index dc375a23e..ad840252e 100644 --- a/ligma-cheat/ligma-cheat/bypass/bypass.cpp +++ b/ligma-cheat/ligma-cheat/bypass/bypass.cpp @@ -8,10 +8,10 @@ namespace ligma // do not call anything that will call dlopen inside of callback.... // __attribute__((noinline)) - void init(const std::function& callback) + void init(const std::function& callback) { ligma::utils::on_image_load("libil2cpp.so", callback); - ligma::utils::on_image_load("libxlua.so", [&](const std::uintptr_t module_base) + ligma::utils::on_image_load("libxlua.so", [&](std::uintptr_t module_base, void* module_handle) -> bool { LOGI("libxlua.so base = %p", module_base); ligma::hook::make_hook( @@ -19,17 +19,18 @@ namespace ligma reinterpret_cast(&load_bufferx_hook) ); LOGI("installed libxlua.so hooks!"); + return false; }); - ligma::utils::on_image_load("libtersafe.so", [&](const std::uintptr_t module_base) + // TODO: add more hooks on libtersafe.so with dlsym_hook... + ligma::utils::on_image_load("libtersafe.so", [&](std::uintptr_t module_base, void* module_handle) -> bool { LOGI("libtersafe.so = %p", module_base); - LOGI("libtersafe.so handle = %p", dlopen("libtersafe.so", RTLD_NOLOAD)); + return false; }); fopen_ptr = dlsym(dlopen("libc.so", RTLD_NOLOAD), "fopen"); system_prop_get = dlsym(dlopen("libc.so", RTLD_NOLOAD), "__system_property_get"); - ligma::hook::make_hook(fopen_ptr, reinterpret_cast(&fopen_hook)); ligma::hook::make_hook(system_prop_get, reinterpret_cast(&system_property_hook)); } diff --git a/ligma-cheat/ligma-cheat/bypass/bypass.h b/ligma-cheat/ligma-cheat/bypass/bypass.h index 7f9524935..1c0421eb3 100644 --- a/ligma-cheat/ligma-cheat/bypass/bypass.h +++ b/ligma-cheat/ligma-cheat/bypass/bypass.h @@ -18,7 +18,7 @@ namespace ligma inline std::mutex fopen_mutex; inline std::mutex system_prop_mutex; - void init(const std::function& callback); + void init(const std::function& callback); FILE* fopen_hook(const char* path, const char* mode); int system_property_hook(const char* name, char* value); int load_bufferx_hook(void* L, const char* buff, size_t sz, const char* name, const char* mode); diff --git a/ligma-cheat/ligma-cheat/hooks/dlsym_hook.cpp b/ligma-cheat/ligma-cheat/hooks/dlsym_hook.cpp new file mode 100644 index 000000000..d93be2622 --- /dev/null +++ b/ligma-cheat/ligma-cheat/hooks/dlsym_hook.cpp @@ -0,0 +1,49 @@ +#include "dlsym_hook.h" +#include "../ligma.h" + +namespace ligma +{ + namespace hook + { + auto get_dlsym_hooks() -> std::map, void*>* + { + static std::map, void*> hooks{}; + return &hooks; + } + + __attribute__((noinline)) + void* dlsym_bypass(void* handle, const char* symbol) + { + dlsym_mutex.lock(); + ligma::hook::disable(dlsym_ptr); + const auto result = + reinterpret_cast(dlsym_ptr)(handle, symbol); + ligma::hook::enable(dlsym_ptr); + dlsym_mutex.unlock(); + return result; + } + + __attribute__((noinline)) + void* dlsym_handler(void* handle, const char* symbol) + { + LOGI("dlsym hook called! handle = %p, symbol = %s", handle, symbol); + try + { + return get_dlsym_hooks()->at({ handle, symbol }); + } + catch (std::out_of_range& e) + {} + return dlsym_bypass(handle, symbol); + } + + void dlsym_unhook(const std::pair& symbol_data) + { + try + { + get_dlsym_hooks()->erase(symbol_data); + } + catch (std::out_of_range& e) + {} + } + } +} \ No newline at end of file diff --git a/ligma-cheat/ligma-cheat/hooks/dlsym_hook.h b/ligma-cheat/ligma-cheat/hooks/dlsym_hook.h new file mode 100644 index 000000000..3498bb138 --- /dev/null +++ b/ligma-cheat/ligma-cheat/hooks/dlsym_hook.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +#include +#include "shithook.h" + +#define LOGI(...) ((void)__android_log_print(4, "ligma", __VA_ARGS__)) +#define LOGW(...) ((void)__android_log_print(5, "ligma", __VA_ARGS__)) + +namespace ligma +{ + namespace hook + { + inline void* dlsym_ptr = nullptr; + inline std::mutex dlsym_mutex; + + void* dlsym_bypass(void* handle, const char* symbol); + void* dlsym_handler(void* handle, const char* symbol); + auto get_dlsym_hooks() -> std::map, void*>*; + void dlsym_unhook(const std::pair& symbol_data); + + template + inline void dlsym_hook(std::pair symbol_data, T* function_ptr) + { + static std::once_flag once; + std::call_once(once, [&]() + { + make_hook((dlsym_ptr = dlsym(dlopen("libdl.so", RTLD_NOLOAD), "dlsym")), &dlsym_handler); + make_hook(&dlsym, &dlsym_bypass); + }); + + get_dlsym_hooks()->insert + ( + { + { + symbol_data.first, + std::string_view{ symbol_data.second } + }, + reinterpret_cast(function_ptr) + } + ); + } + } +} \ No newline at end of file diff --git a/ligma-cheat/ligma-cheat/hooks/shithook.cpp b/ligma-cheat/ligma-cheat/hooks/shithook.cpp new file mode 100644 index 000000000..633eb5540 --- /dev/null +++ b/ligma-cheat/ligma-cheat/hooks/shithook.cpp @@ -0,0 +1,62 @@ +#include "shithook.h" + +namespace ligma +{ + namespace hook + { + detour::detour(void* addr_to_hook, void* jmp_to, bool enable) + : + hook_addr(addr_to_hook), + detour_addr(jmp_to), + hook_installed(false) + { + reinterpret_cast(jmp_code)[0] = ARM_JMP_CODE; // LDR PC, [PC, #-4] + reinterpret_cast(jmp_code)[1] = jmp_to; + memcpy(org_bytes, hook_addr, sizeof(org_bytes)); + if (enable) install(); + } + + detour::~detour() + { + uninstall(); + } + + bool detour::installed() { return hook_installed; } + void* detour::hook_address() { return hook_addr; } + void* detour::detour_address() { return detour_addr; } + + void detour::install() + { + if (hook_installed.load()) + return; + + if (!mprotect(PAGE_START(hook_addr), getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC)) + { + memcpy((void*)((long)hook_addr), jmp_code, sizeof(jmp_code)); + mprotect(PAGE_START(hook_addr), getpagesize(), PROT_READ | PROT_EXEC); + cacheflush(reinterpret_cast(hook_addr), reinterpret_cast(hook_addr) + getpagesize(), NULL); + hook_installed.exchange(true); + } + } + + void detour::uninstall() + { + if (!hook_installed.load()) + return; + + if (!mprotect(PAGE_START(hook_addr), getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC)) + { + memcpy(hook_addr, org_bytes, sizeof(jmp_code)); + mprotect(PAGE_START(hook_addr), getpagesize(), PROT_READ | PROT_EXEC); + cacheflush(reinterpret_cast(hook_addr), reinterpret_cast(hook_addr) + getpagesize(), NULL); + hook_installed.exchange(false); + } + } + + std::map>* get_hooks() + { + static std::map> hooks{}; + return &hooks; + } + } +} \ No newline at end of file diff --git a/ligma-cheat/ligma-cheat/hooks/shithook.h b/ligma-cheat/ligma-cheat/hooks/shithook.h index 57759f4ea..2b72049c3 100644 --- a/ligma-cheat/ligma-cheat/hooks/shithook.h +++ b/ligma-cheat/ligma-cheat/hooks/shithook.h @@ -28,8 +28,6 @@ #include #include #include -#include -#include #define PAGE_START(ptr) reinterpret_cast(reinterpret_cast(ptr) >> 12 << 12) #define ARM_JMP_CODE 0xE51FF004 @@ -41,156 +39,62 @@ namespace ligma class detour { public: - detour(void* addr_to_hook, void* jmp_to, bool enable = true) - : - hook_addr(addr_to_hook), - detour_addr(jmp_to), - hook_installed(false) - { - reinterpret_cast(jmp_code)[0] = ARM_JMP_CODE; // LDR PC, [PC, #-4] - reinterpret_cast(jmp_code)[1] = jmp_to; - memcpy(org_bytes, hook_addr, sizeof(org_bytes)); - if (enable) install(); - } - - void install() - { - if (hook_installed.load()) - return; - - if (!mprotect(PAGE_START(hook_addr), getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC)) - { - memcpy((void*)((long)hook_addr), jmp_code, sizeof(jmp_code)); - mprotect(PAGE_START(hook_addr), getpagesize(), PROT_READ | PROT_EXEC); - cacheflush(reinterpret_cast(hook_addr), reinterpret_cast(hook_addr) + getpagesize(), NULL); - hook_installed.exchange(true); - } - } - - void uninstall() - { - if (!hook_installed.load()) - return; - - if (!mprotect(PAGE_START(hook_addr), getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC)) - { - memcpy(hook_addr, org_bytes, sizeof(jmp_code)); - mprotect(PAGE_START(hook_addr), getpagesize(), PROT_READ | PROT_EXEC); - cacheflush(reinterpret_cast(hook_addr), reinterpret_cast(hook_addr) + getpagesize(), NULL); - hook_installed.exchange(false); - } - } - - ~detour() { uninstall(); } - bool installed() { return hook_installed; } - void* hook_address() { return hook_addr; } - void* detour_address() { return detour_addr; } + detour(void* addr_to_hook, void* jmp_to, bool enable = true); + void install(); + void uninstall(); + ~detour(); + bool installed(); + void* hook_address(); + void* detour_address(); private: std::atomic hook_installed; void* hook_addr, * detour_addr; - unsigned char jmp_code[8]{}; std::uint8_t org_bytes[sizeof(jmp_code)]; }; - inline std::map>* get_hooks() - { - static std::map> hooks; - return &hooks; - } - - inline std::map, void*>* get_dlsym_hook() - { - static std::map, void*> hooks{}; - return &hooks; - } + std::map>* get_hooks(); - inline void make_hook(void* addr_to_hook, void* jmp_to_addr, bool enable = true) + template + void make_hook(T* addr_to_hook, U* jmp_to_addr, bool enable = true) { - if (!addr_to_hook) + if (!addr_to_hook || !jmp_to_addr) return; get_hooks()->insert({ - addr_to_hook, + (void*)addr_to_hook, std::make_unique( - addr_to_hook, - jmp_to_addr, + (void*) addr_to_hook, + (void*) jmp_to_addr, enable )} ); } - inline void enable(void* addr) - { - if (!addr) - return; - get_hooks()->at(addr)->install(); - } - - inline void disable(void* addr) + template + inline void enable(T* addr) { - if (!addr) - return; - get_hooks()->at(addr)->uninstall(); + if (!addr) return; + get_hooks()->at((void*)addr)->install(); } - inline void remove(void* addr) - { - if (!addr) - return; - get_hooks()->erase(addr); - } - - inline std::mutex dlsym_mutex; - inline void* dlsym_ptr = nullptr; - - __attribute__((noinline)) - void* dlsym_bypass(void* handle, const char* symbol) + template + inline void disable(T* addr) { - dlsym_mutex.lock(); - ligma::hook::disable(dlsym_ptr); - const auto result = - reinterpret_cast(dlsym_ptr)(handle, symbol); - ligma::hook::enable(dlsym_ptr); - dlsym_mutex.unlock(); - return result; - } - - __attribute__((noinline)) - void* dlsym_handler(void* handle, const char* symbol) - { - for (const auto& [so_data, hook_ptr] : *get_dlsym_hook()) - if (strcmp(so_data.second.c_str(), symbol)) - if (dlopen(so_data.first.c_str(), RTLD_NOLOAD) == handle) - return hook_ptr; - - dlsym_mutex.lock(); - ligma::hook::disable(dlsym_ptr); - const auto result = dlsym(handle, symbol); - ligma::hook::enable(dlsym_ptr); - dlsym_mutex.unlock(); - return result; + if (!addr) return; + try + { + get_hooks()->at((void*)addr)->uninstall(); + } + catch (std::out_of_range& e) + {} } - void dlsym_hook(std::pair symbol_data, void* function_ptr) + template + inline void remove(T* addr) { - static std::once_flag once; - std::call_once(once, [&]() - { - make_hook( - dlsym(dlopen("libdl.so", RTLD_NOLOAD), "dlsym"), - reinterpret_cast(&dlsym_handler) - ); - - // - // this allows us to use "dlsym" anywhere in the code :) - // - make_hook( - reinterpret_cast(&dlsym), - reinterpret_cast(&dlsym_bypass) - ); - }); - get_dlsym_hook()->insert({ symbol_data, function_ptr }); + if (!addr) return; + get_hooks()->erase((void*)addr); } } } diff --git a/ligma-cheat/ligma-cheat/ligma-cheat.vcxproj b/ligma-cheat/ligma-cheat/ligma-cheat.vcxproj index 73e989052..555faceb1 100644 --- a/ligma-cheat/ligma-cheat/ligma-cheat.vcxproj +++ b/ligma-cheat/ligma-cheat/ligma-cheat.vcxproj @@ -36,11 +36,14 @@ + + + diff --git a/ligma-cheat/ligma-cheat/ligma-cheat.vcxproj.filters b/ligma-cheat/ligma-cheat/ligma-cheat.vcxproj.filters index 6d53f559f..a5df519b9 100644 --- a/ligma-cheat/ligma-cheat/ligma-cheat.vcxproj.filters +++ b/ligma-cheat/ligma-cheat/ligma-cheat.vcxproj.filters @@ -22,6 +22,9 @@ {83d12913-a2bb-4372-a9a4-387cd3b158ad} + + {f084f5b1-c94a-4e1b-ac6d-6fdeecb34ba4} + @@ -33,6 +36,12 @@ source\utils + + source\hooks + + + source\hooks + @@ -47,5 +56,8 @@ headers + + headers\hooks + \ No newline at end of file diff --git a/ligma-cheat/ligma-cheat/ligma.h b/ligma-cheat/ligma-cheat/ligma.h index 1d7fef398..0f7329ec7 100644 --- a/ligma-cheat/ligma-cheat/ligma.h +++ b/ligma-cheat/ligma-cheat/ligma.h @@ -2,6 +2,7 @@ #include #include "utils/utils.h" #include "hooks/shithook.h" +#include "hooks/dlsym_hook.h" #define LOGI(...) ((void)__android_log_print(4, "ligma", __VA_ARGS__)) #define LOGW(...) ((void)__android_log_print(5, "ligma", __VA_ARGS__)) \ No newline at end of file diff --git a/ligma-cheat/ligma-cheat/main.cpp b/ligma-cheat/ligma-cheat/main.cpp index 66de01915..50e8a3aa3 100644 --- a/ligma-cheat/ligma-cheat/main.cpp +++ b/ligma-cheat/ligma-cheat/main.cpp @@ -1,14 +1,11 @@ -#include -#include -#include -#include #include "bypass/bypass.h" __attribute__((constructor)) void init() { - ligma::bypass::init([&](const std::uintptr_t il2cpp_base) + ligma::bypass::init([&](std::uintptr_t il2cpp_base, void* module_handle) -> bool { - LOGI("il2cpp base address = %p", il2cpp_base); + LOGI("il2cpp base address = %p, module_handle = %p", il2cpp_base, module_handle); + return false; }); } \ No newline at end of file diff --git a/ligma-cheat/ligma-cheat/utils/utils.cpp b/ligma-cheat/ligma-cheat/utils/utils.cpp index 56ab70507..c465c3869 100644 --- a/ligma-cheat/ligma-cheat/utils/utils.cpp +++ b/ligma-cheat/ligma-cheat/utils/utils.cpp @@ -1,69 +1,63 @@ #include "utils.h" +#include "../ligma.h" namespace ligma { namespace utils { - void on_image_load(const std::string& module_name, const std::function& callback) + std::uintptr_t get_module_base(const char* module_name) { - static std::once_flag once; - std::call_once(once, [&]() { - ligma::hook::make_hook( - dlsym(dlopen("libdl.so", RTLD_NOLOAD), "dlopen"), - reinterpret_cast(&dlopen_handler) - ); - }); - get_callbacks()->insert({ module_name, callback }); + std::unique_ptr maps_handle(fopen("/proc/self/maps", "r"), &fclose); + char line[512], mod_name[64]; + std::uintptr_t base; + while (fgets(line, sizeof(line), maps_handle.get())) + if (std::sscanf(line, "%" PRIXPTR "-%*" PRIXPTR " %*s %*s %*s %*s %s", &base, mod_name)) + if (std::strstr(mod_name, module_name)) + return base; + return NULL; } - auto get_callbacks() -> std::map>* + auto get_callbacks() -> std::map>* { - static std::map> callback_map{}; + static std::map> callback_map{}; return &callback_map; } - std::uintptr_t get_module_base(const char* module_name) - { - const auto maps_handle = fopen("/proc/self/maps", "r"); - char line[512]; - while (fgets(line, sizeof line, maps_handle)) - { - std::uintptr_t base; - char tmp[64]; - sscanf(line, "%" PRIXPTR "-%*" PRIXPTR " %*s %*s %*s %*s %s", &base, tmp); - if (strstr(tmp, module_name)) - { - fclose(maps_handle); - return base; - } - } - fclose(maps_handle); - return NULL; - } - __attribute__((noinline)) void* dlopen_handler(const char* filename, int flags) { - dlopen_hook.second.lock(); - ligma::hook::disable(dlopen_hook.first); - const auto result = dlopen(filename, reinterpret_cast(RTLD_NEXT)); - if (ligma::utils::get_callbacks()->size()) - ligma::hook::enable(dlopen_hook.first); - dlopen_hook.second.unlock(); + dlopen_mutex.lock(); + ligma::hook::disable(dlopen_ptr); + const auto result = dlopen(filename, flags); + ligma::hook::enable(dlopen_ptr); + dlopen_mutex.unlock(); - // - // if there is a callback for this module, call it and then remove it. - // for (const auto& [file_key, callback] : *ligma::utils::get_callbacks()) { - if (strstr(filename, file_key.c_str())) + if (std::strstr(filename, file_key.c_str())) { + // remove the callback before calling it, this prevents loops... ligma::utils::get_callbacks()->erase(file_key); - callback(ligma::utils::get_module_base(file_key.c_str())); + if (callback(ligma::utils::get_module_base(file_key.c_str()), result)) + on_image_load(file_key, callback); // add it back if we still want the callback... break; } } return result; } + + void on_image_load(const std::string& module_name, const std::function& callback) + { + static std::once_flag once; + std::call_once(once, [&]() + { + ligma::hook::make_hook + ( + (dlopen_ptr = dlsym(dlopen("libdl.so", RTLD_NOLOAD), "dlopen")), + &dlopen_handler + ); + }); + get_callbacks()->insert({ module_name, callback }); + } } } \ No newline at end of file diff --git a/ligma-cheat/ligma-cheat/utils/utils.h b/ligma-cheat/ligma-cheat/utils/utils.h index a2af3b307..6e0a0e06f 100644 --- a/ligma-cheat/ligma-cheat/utils/utils.h +++ b/ligma-cheat/ligma-cheat/utils/utils.h @@ -1,20 +1,23 @@ #pragma once -#include -#include #include +#include #include #include +#include +#include +#include #include "../hooks/shithook.h" namespace ligma { namespace utils { - inline std::pair dlopen_hook; + inline void* dlopen_ptr = nullptr; + inline std::mutex dlopen_mutex; + std::uintptr_t get_module_base(const char* module_name); - auto get_callbacks() -> std::map>*; - void on_image_load(const std::string& module_name, const std::function& callback); - void dlsym_hook(const std::string& symbol_name, void* function_ptr); + auto get_callbacks() -> std::map>*; void* dlopen_handler(const char* filename, int flags); + void on_image_load(const std::string& module_name, const std::function& callback); } } \ No newline at end of file