From 55ba49c95761706378851d5059dc78028b0b2259 Mon Sep 17 00:00:00 2001 From: Nemirtingas Date: Fri, 8 Nov 2019 15:54:48 +0100 Subject: [PATCH] Clean a bit Linux Overlay --- overlay_experimental/Renderer_Detector.cpp | 127 ++-- overlay_experimental/linux/Linux_Detour.cpp | 636 -------------------- overlay_experimental/linux/Linux_Detour.h | 16 - overlay_experimental/linux/X11_Hook.h | 19 +- 4 files changed, 44 insertions(+), 754 deletions(-) delete mode 100644 overlay_experimental/linux/Linux_Detour.cpp delete mode 100644 overlay_experimental/linux/Linux_Detour.h diff --git a/overlay_experimental/Renderer_Detector.cpp b/overlay_experimental/Renderer_Detector.cpp index 0b686be..bc4f670 100644 --- a/overlay_experimental/Renderer_Detector.cpp +++ b/overlay_experimental/Renderer_Detector.cpp @@ -153,6 +153,16 @@ BOOL WINAPI Renderer_Detector::MywglMakeCurrent(HDC hDC, HGLRC hGLRC) return res; } +void __stdcall Renderer_Detector::MyvkCmdEndRenderPass(void* commandBuffer) +{ + Renderer_Detector& inst = Renderer_Detector::Inst(); + _vkCmdEndRenderPass(commandBuffer); + if (!inst.stop_retry()) + { + Vulkan_Hook::Inst()->start_hook(); + } +} + void Renderer_Detector::HookDXGIPresent(IDXGISwapChain* pSwapChain) { if (!_dxgi_hooked) @@ -628,98 +638,19 @@ Renderer_Detector::Renderer_Detector(): #include "linux/X11_Hook.h" #include -#include extern "C" void *_dl_sym(void *, const char *, void *); static decltype(glXGetProcAddress)* real_glXGetProcAddress = nullptr; static decltype(glXGetProcAddressARB)* real_glXGetProcAddressARB = nullptr; -/* -void Renderer_Detector::MyglXSwapBuffers(Display *dpy, GLXDrawable drawable) -{ - Renderer_Detector& inst = Renderer_Detector::Inst(); - Hook_Manager& hm = Hook_Manager::Inst(); - _glXSwapBuffers(reinterpret_cast<::Display*>(dpy), drawable); - if (!inst.stop_retry()) - { - OpenGLX_Hook::Inst()->start_hook(); - } -} - -void Renderer_Detector::HookglXSwapBuffers(decltype(glXSwapBuffers)* glXSwapBuffers) -{ - _glXSwapBuffers = glXSwapBuffers; - - rendererdetect_hook->BeginHook(); - - rendererdetect_hook->HookFuncs( - std::pair(&(void*&)_glXSwapBuffers, (void*)MyglXSwapBuffers) - ); - - rendererdetect_hook->EndHook(); -} - -void Renderer_Detector::hook_openglx(const char* libname) -{ - if (!_oglx_hooked && !_renderer_found) - { - void* library = dlopen(libname, RTLD_NOW); - decltype(glXSwapBuffers)* glXSwapBuffers = nullptr; - if (library != nullptr) - { - glXSwapBuffers = (decltype(glXSwapBuffers))dlsym(library, "glXSwapBuffers"); - } - if (glXSwapBuffers != nullptr) - { - PRINT_DEBUG("Hooked glXSwapBuffers to detect OpenGLX\n"); - - _oglx_hooked = true; - auto h = OpenGLX_Hook::Inst(); - h->loadFunctions(glXSwapBuffers); - Hook_Manager::Inst().AddHook(h); - HookglXSwapBuffers(glXSwapBuffers); - } - else - { - PRINT_DEBUG("Failed to Hook glXSwapBuffers to detect OpenGLX\n"); - } - } -} - -void Renderer_Detector::create_hook(const char* libname) -{ - if (strcasestr(libname, OpenGLX_Hook::DLL_NAME) != nullptr) - hook_openglx(libname); -} -*/ - -void Renderer_Detector::find_renderer_proc(Renderer_Detector* _this) -{ - /* - _this->rendererdetect_hook = new Base_Hook(); - Hook_Manager& hm = Hook_Manager::Inst(); - hm.AddHook(_this->rendererdetect_hook); - */ -} - -Renderer_Detector::Renderer_Detector(): - _hook_thread(nullptr), - _hook_retries(0), - _renderer_found(false), - _oglx_hooked(false), - rendererdetect_hook(nullptr), - game_renderer(nullptr) -{} - static decltype(dlsym)* real_dlsym = nullptr; -// hook library static loading extern "C" int XEventsQueued(Display *display, int mode) { auto h = X11_Hook::Inst(); - if( h->get_XEventsQueued() == nullptr ) - h->loadXEventsQueued((decltype(XEventsQueued)*)real_dlsym(RTLD_NEXT, "XEventsQueued")); + if( h->_XEventsQueued == nullptr ) + h->_XEventsQueued = reinterpret_cast(real_dlsym(RTLD_NEXT, "XEventsQueued")); return X11_Hook::MyXEventsQueued(display, mode); } @@ -727,26 +658,26 @@ extern "C" int XEventsQueued(Display *display, int mode) //extern "C" int XPeekEvent(Display *display, XEvent *event) //{ // auto h = X11_Hook::Inst(); -// if( h->get_XPeekEvent() == nullptr ) -// h->loadXPeekEvent((decltype(XPeekEvent)*)real_dlsym(RTLD_NEXT, "XPeekEvent")); +// if( h->_XPeekEvent == nullptr ) +// h->_XPeekEvent = reinterpret_cast(real_dlsym(RTLD_NEXT, "XPeekEvent")); // -// return X11_Hook::MyXPeekEvent(display, event); +// return X11_Hook::MyXPeekEvent(display, mode); //} //extern "C" int XNextEvent(Display *display, XEvent *event) //{ // auto h = X11_Hook::Inst(); -// if( h->get_XNextEvent() == nullptr ) -// h->loadXNextEvent((decltype(XNextEvent)*)real_dlsym(RTLD_NEXT, "XNextEvent")); +// if( h->_XNextEvent == nullptr ) +// h->_XNextEvent = reinterpret_cast(real_dlsym(RTLD_NEXT, "XNextEvent")); // -// return X11_Hook::MyXNextEvent(display, event); +// return X11_Hook::MyXNextEvent(display, mode); //} extern "C" int XPending(Display *display) { auto h = X11_Hook::Inst(); - if( h->get_XPending() == nullptr ) - h->loadXPending((decltype(XPending)*)real_dlsym(RTLD_NEXT, "XPending")); + if( h->_XPending == nullptr ) + h->_XPending = reinterpret_cast(real_dlsym(RTLD_NEXT, "XPending")); return X11_Hook::MyXPending(display); } @@ -785,6 +716,24 @@ extern "C" __GLXextFuncPtr glXGetProcAddressARB (const GLubyte* procName) return func; } +void Renderer_Detector::find_renderer_proc(Renderer_Detector* _this) +{ + /* + _this->rendererdetect_hook = new Base_Hook(); + Hook_Manager& hm = Hook_Manager::Inst(); + hm.AddHook(_this->rendererdetect_hook); + */ +} + +Renderer_Detector::Renderer_Detector(): + _hook_thread(nullptr), + _hook_retries(0), + _renderer_found(false), + _oglx_hooked(false), + rendererdetect_hook(nullptr), + game_renderer(nullptr) +{} + extern "C" void* dlsym(void* handle, const char* name) { if (real_dlsym == nullptr) diff --git a/overlay_experimental/linux/Linux_Detour.cpp b/overlay_experimental/linux/Linux_Detour.cpp deleted file mode 100644 index 52d7128..0000000 --- a/overlay_experimental/linux/Linux_Detour.cpp +++ /dev/null @@ -1,636 +0,0 @@ -#include "Linux_Detour.h" - -#include -#include - -#include - -#include -#include -#include -#include - -#include "../../dll/base.h" - -//------------------------------------------------------------------------------// -// Helper funcs -//------------------------------------------------------------------------------// -constexpr static auto relative_addr_jump_size = sizeof(int32_t); -constexpr static auto relative_jump_size = 1 + relative_addr_jump_size; -constexpr static auto absolute_jump_size = 6; - -struct -{ - bool has_r_m; - uint8_t base_size; -} s_opcodes[256] = -{ - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 0 - 7 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 8 - 15 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 16 - 23 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 24 - 31 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 32 - 39 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 40 - 47 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 48 - 55 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 56 - 63 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 64 - 71 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 72 - 79 - // PUSH ... - {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, // 80 - 87 - // POP ... - {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, // 88 - 95 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 96 - 103 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 104 - 111 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 112 - 129 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 120 - 127 - // MOV, ADD, ... R8 <- IMM8 TEST_8 TEST XCHG_8 XCHG - {true , 3}, {true , 6}, {true , 3}, {true , 3}, {true , 2}, {true , 2}, {true , 2}, {true , 2}, // 128 - 135 - // MOV_8 MOV MOV_R8_B MOV_R32_D MOV_32_ES LEA MOV_ES_32 POP - {true , 2}, {true , 2}, {true , 2}, {true , 2}, {true , 2}, {true , 2}, {true , 2}, {false, 2}, // 136 - 143 - // NOP - {false, 1}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 144 - 151 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 152 - 159 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 160 - 167 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 168 - 175 - // MOV_AL MOV_CL MOV_DL MOV_BL MOV_AH MOV_CH MOV_DH MOV_BH - {false, 2}, {false, 2}, {false, 2}, {false, 2}, {false, 2}, {false, 2}, {false, 2}, {false, 2}, // 176 - 183 - // MOV_EAX MOV_ECX MOV_EDX MOV_EBX MOV_ESP MOV_EBP MOV_ESI MOV_EDI, - {false, 5}, {false, 5}, {false, 5}, {false, 5}, {false, 5}, {false, 5}, {false, 5}, {false, 5}, // 184 - 191 - // RETN_IMM16 RETN - {false, 0}, {false, 0}, {false, 3}, {false, 1}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 192 - 199 - // LEAVE RETF_IMM16 RETF INT INT_IMM8 INTO - {false, 0}, {false, 1}, {false, 3}, {false, 1}, {false, 1}, {false, 1}, {false, 1}, {false, 0}, // 200 - 207 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 208 - 215 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 216 - 223 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 224 - 231 - // CALL JMP LJMP SHORT_JMP - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 232 - 239 - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, // 240 - 247 - // EXTENDED - {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 0}, {false, 6}, // 248 - 255 -}; - -static constexpr auto mod_mask = 0xC0; -static constexpr auto register_addressing_mode = 0xC0; -static constexpr auto four_bytes_signed_displacement = 0x80; -static constexpr auto one_byte_signed_displacement = 0x40; - -static constexpr auto rm_mask = 0x05; -static constexpr auto displacement_only_addressing = 0x05; -static constexpr auto sib_with_no_displacement = 0x04; -static constexpr auto register_indirect_addressing_mode = 0x00; - -enum opcodes_e // Commonly used opcode in the beginning of functions -{ - PUSH_EAX = 0x50, PUSH_ECX, PUSH_EDX, PUSH_EBX, PUSH_ESP, PUSH_EBP, PUSH_ESI, PUSH_EDI, - POP_EAX , POP_ECX , POP_EDX , POP_EBX , POP_ESP , POP_EBP , POP_ESI , POP_EDI , - - R8_IMM8 = 0x80, R32_IMM32, R8_IMM8_2, R32_IMM8, - TEST_8, TEST, - XCHG_8, XCHG, - MOV_8 , MOV, - MOV_8_B, MOV_32_D, MOV_32_ES, - LEA, - MOV_ES_32, POP, - NOP, - MOV_AL = 0xB0, MOV_CL, MOV_DL, MOV_BL, MOV_AH, MOV_CH, MOV_DH, MOV_BH, - MOV_EAX, MOV_ECX, MOV_EDX, MOV_EBX, MOV_ESP, MOV_EBP, MOV_ESI, MOV_EDI, - RETN_IMM16 = 0xC2, RETN, - LEAVE = 0xC9, RETF_IMM16, RETF, INT, INT_IMM8, INTO, - CALL = 0xE8, // 5 bytes don't process - JMP, // 5 bytes don't process - LJMP, // 7 bytes, don't process - SHORT_JMP, // 2 bytes don't process - EXTENDED = 0xFF, -}; - -const char* opcode_name(uint8_t opcode) -{ -#define NAME(opcode_name) case opcode_name: return #opcode_name - switch( opcode ) - { - NAME(PUSH_EAX); NAME(PUSH_ECX); NAME(PUSH_EDX); NAME(PUSH_EBX); - NAME(PUSH_ESP); NAME(PUSH_EBP); NAME(PUSH_ESI); NAME(PUSH_EDI); - NAME(POP_EAX); NAME(POP_ECX); NAME(POP_EDX); NAME(POP_EBX); - NAME(POP_ESP); NAME(POP_EBP); NAME(POP_ESI); NAME(POP_EDI); - NAME(R8_IMM8); NAME(R32_IMM32); NAME(R8_IMM8_2); NAME(R32_IMM8); - NAME(TEST_8); NAME(TEST); NAME(XCHG_8); NAME(XCHG); NAME(MOV_8); NAME(MOV); - NAME(MOV_8_B); NAME(MOV_32_D); NAME(MOV_32_ES); - NAME(LEA); - NAME(MOV_ES_32); NAME(POP); - NAME(NOP); - NAME(MOV_AL) ; NAME(MOV_CL) ; NAME(MOV_DL) ; NAME(MOV_BL) ; NAME(MOV_AH) ; NAME(MOV_CH) ; NAME(MOV_DH) ; NAME(MOV_BH) ; - NAME(MOV_EAX); NAME(MOV_ECX); NAME(MOV_EDX); NAME(MOV_EBX); NAME(MOV_ESP); NAME(MOV_EBP); NAME(MOV_ESI); NAME(MOV_EDI); - NAME(RETN_IMM16); NAME(RETN); NAME(LEAVE); NAME(RETF_IMM16); NAME(RETF); - NAME(INT); NAME(INT_IMM8); NAME(INTO); NAME(CALL); NAME(JMP); NAME(LJMP); NAME(SHORT_JMP); - NAME(EXTENDED); - } -#undef NAME - return "no registered"; -} - -#pragma pack(push, 1) - -struct trampoline_x86_t -{ - uint8_t trampolineBytes[16+relative_jump_size]; // trampoline + original function opcodes - uint8_t hookJump[relative_jump_size]; // jump to hook addr, needed because of relative jump overflow - uint8_t nOriginalBytes; // number of original function bytes bkp -}; - -typedef trampoline_x86_t trampoline_t; - -struct trampoline_region_t -{ - uint8_t numTrampolines; // current trampolines allocated - trampoline_t *trampolines_start; // start pointer of current region trampolines - trampoline_t *next_free_trampoline; // next free trampoline in region -}; - -#pragma pack(pop) - -struct transaction_t -{ - bool detach; - void** ppOriginalFunc; - trampoline_t *trampoline; -}; - -static std::list trampoline_regions; - -static bool transaction_started = false; -static std::list cur_transaction; - -inline size_t page_size() -{ - static size_t _page_size = sysconf(_SC_PAGESIZE); - return _page_size; -} - -inline size_t region_size() -{ - return page_size(); -} - -static uint8_t max_trampolines_in_region = region_size() / sizeof(trampoline_t); - -inline void* library_address_by_handle(void *library) -{ - return (library == nullptr ? nullptr : *reinterpret_cast(library)); -} - -inline size_t page_align(size_t size, size_t page_size) -{ - return (size+(page_size-1)) & (((size_t)-1)^(page_size-1)); -} - -inline void* page_addr(void* addr, size_t page_size) -{ - return reinterpret_cast(reinterpret_cast(addr) & (((size_t)-1)^(page_size-1))); -} - -//////////////////////////////////////////////////// -/// Tiny disasm - -bool is_opcode_terminating_function(uint8_t* pCode) -{ - switch( *pCode ) - { - case LEAVE: - case RETN: case RETN_IMM16: - case RETF: case RETF_IMM16: - case INT: case INT_IMM8: case INTO: - return true; - } - return false; -} - -int find_space_for_trampoline(uint8_t* func, int bytes_needed) -{ - if( func == nullptr ) - return -1; - - int code_len = 0; - bool search = true; - uint8_t *startCode = reinterpret_cast(func); - uint8_t *pCode = startCode; - while( search ) // Find opcodes size and try to find at least 5 bytes for our JMP - { - if( is_opcode_terminating_function(pCode) ) - break; - - if( s_opcodes[*pCode].has_r_m ) - { // MOD-REG-R/M Byte - // 7 6 5 4 3 2 1 0 - bits - //[ MOD ][ REG ][ R/M ] - switch( pCode[1] & mod_mask ) // Check MOD to know how many bytes we have after this opcode - { - case register_addressing_mode : pCode += s_opcodes[*pCode].base_size ; break;// register addressing mode [opcode] [R/M] [XX] - case four_bytes_signed_displacement: pCode += s_opcodes[*pCode].base_size+5; break;// address mode byte + 4 bytes displacement - case one_byte_signed_displacement : pCode += s_opcodes[*pCode].base_size+2; break;// address mode byte + 1 byte displacement - case 0x00: - switch( pCode[1] & rm_mask ) - { - case sib_with_no_displacement : pCode += s_opcodes[*pCode].base_size+1; break;// SIB with no displacement - case displacement_only_addressing : pCode += s_opcodes[*pCode].base_size+4; break;// 4 bytes Displacement only addressing mode - case register_indirect_addressing_mode: pCode += s_opcodes[*pCode].base_size; // Register indirect addressing mode - } - } - } - else if( s_opcodes[*pCode].base_size ) - { - pCode += s_opcodes[*pCode].base_size; - } - else - { - switch( *pCode ) - { - case CALL: case JMP: case LJMP: case SHORT_JMP: - PRINT_DEBUG("JMP or CALL is forbidden for trampolines.\n"); - search = false; - break; - - case EXTENDED: - //std::cerr << "IMPORT_JUMP is not handled" << std::endl; - if (pCode[1] == 0x25) // This is an imported function - { // Get the true function call - //pCode = (uint8_t*)*(pCode+2); - //startCode = pCode; - // For now disable this case - search = false; - } - else - { - search = false; - } - break; - - default: - PRINT_DEBUG("Unknown opcode %02X\n", (int)*pCode); - search = false; - } - } - - if( (pCode - startCode) >= bytes_needed && search ) - { - search = false; - code_len = pCode-startCode; - } - } - return code_len; -} - -/////////////////////////////////////////// -// Tiny asm - -inline uint8_t* gen_immediate_addr(uint8_t* opcode_addr, uint8_t* dest) -{ - *reinterpret_cast(opcode_addr) = (dest - (opcode_addr + relative_addr_jump_size)); - return opcode_addr + relative_addr_jump_size; -} - -inline uint8_t* gen_immediate_jump(uint8_t* opcode_addr, uint8_t* dest) -{ - *opcode_addr++ = JMP; - return gen_immediate_addr(opcode_addr, dest); -} - -inline uint8_t* gen_immediate_call(uint8_t* opcode_addr, uint8_t* dest) -{ - *opcode_addr++ = CALL; - return gen_immediate_addr(opcode_addr, dest); -} - -uint8_t* relative_addr_to_absolute(int32_t rel_addr, uint8_t *code_addr) -{ - return code_addr + rel_addr + relative_jump_size; -} - -void alloc_new_trampoline_region() -{ - trampoline_region_t region; - - region.numTrampolines = 0; - // allocate new trampoline right in the middle of memory so relative jump can access any function - region.trampolines_start = reinterpret_cast(mmap((void*)std::numeric_limits::max(), // allocate the page near the half of memory addressing - region_size(), // size - PROT_EXEC|PROT_WRITE|PROT_READ, // protection - MAP_PRIVATE|MAP_32BIT|MAP_ANONYMOUS, // don't map a file but memory - -1, // fd = -1 - 0) // offset - ); - // Fill the region with 0 - std::fill(reinterpret_cast(region.trampolines_start), reinterpret_cast(region.trampolines_start)+region_size(), 0); - region.next_free_trampoline = region.trampolines_start; - // Protect trampoline region memory - mprotect((void*)region.trampolines_start, region_size(), PROT_READ|PROT_EXEC); - - trampoline_regions.push_back(region); -} - -trampoline_t* get_free_trampoline() -{ - if (!transaction_started) - return nullptr; - - trampoline_t *res = nullptr; - auto it = std::find_if(trampoline_regions.begin(), trampoline_regions.end(), [&res](trampoline_region_t ®ion){ - if( region.numTrampolines == max_trampolines_in_region ) - return false; - return true; - }); - - if( it == trampoline_regions.end() ) - { - alloc_new_trampoline_region(); - it = --trampoline_regions.end(); - } - res = it->next_free_trampoline; - - trampoline_t *next_new_trampoline = res+1; - if( it->numTrampolines != max_trampolines_in_region ) - { - while( next_new_trampoline->nOriginalBytes != 0 ) - { - ++next_new_trampoline; - } - } - else - { - next_new_trampoline = nullptr; - } - it->next_free_trampoline = next_new_trampoline; - - ++it->numTrampolines; - - return res; -} - -void clear_trampoline(trampoline_region_t& region, trampoline_t *trampoline) -{ - --region.numTrampolines; - - std::fill(reinterpret_cast(trampoline), reinterpret_cast(trampoline+1), 0); - if( region.next_free_trampoline == nullptr || region.next_free_trampoline > trampoline ) - region.next_free_trampoline = trampoline; -} - -inline bool is_page_inside_region(void *page, trampoline_region_t& region) -{ - if( page >= region.trampolines_start && page <= (region.trampolines_start+region_size()) ) - return true; - return false; -} - -//------------------------------------------------------------------------------// - -/* -#include -#include - -static pid_t tid = 0; - -struct dism_pthread_t -{ - uint32_t d0; - uint32_t d4; - uint32_t d8; - uint32_t dc; - uint32_t d10; - uint32_t d14; - uint32_t d18; - uint32_t d1c; - uint32_t d20; - uint32_t d24; - uint32_t d28; - uint32_t d2c; - uint32_t d30; - uint32_t d34; - uint32_t d38; - uint32_t d3c; - uint32_t d40; - uint32_t d44; - uint32_t d48; - uint32_t d4c; - uint32_t d50; - uint32_t d54; - uint32_t d58; - uint32_t d5c; - uint32_t d60; - uint32_t d64; - pid_t task_id; -}; -*/ - -int Linux_Detour::update_thread(pthread_t thread_id) -{ - //dism_pthread_t *dt = (dism_pthread_t*)thread_id; - - // dt->task_id == syscall(SYS_gettid); - - - return 0; -} - -int Linux_Detour::transaction_begin() -{ - if( transaction_started ) - return -1; - - transaction_started = true; - - return 0; -} - -int Linux_Detour::transaction_abort() -{ - if(!transaction_started) - return -1; - - for( auto &i : cur_transaction ) - { - trampoline_t *trampoline = i.trampoline; - void *page_start = page_addr(reinterpret_cast(trampoline), page_size()); - auto it = std::find_if(trampoline_regions.begin(), trampoline_regions.end(), [page_start](trampoline_region_t ®ion){ - if( is_page_inside_region(page_start, region) ) - return true; - return false; - }); - if( it != trampoline_regions.end() ) - { - clear_trampoline(*it, trampoline); - } - } - cur_transaction.clear(); - transaction_started = false; - - return 0; -} - -int Linux_Detour::transaction_commit() -{ - if (!transaction_started ) - return -1; - - for( auto &i : cur_transaction) - { - trampoline_t *trampoline = i.trampoline; - void **ppOriginalFunc = i.ppOriginalFunc; - - int res; - - if( i.detach ) - { - void* trampoline_page = page_addr(reinterpret_cast(trampoline), page_size()); - - *ppOriginalFunc = (void*)(relative_addr_to_absolute(*reinterpret_cast(trampoline->trampolineBytes+trampoline->nOriginalBytes+1), - trampoline->trampolineBytes)); - - void* originalFunctionPage = page_addr(*ppOriginalFunc, page_size()); - - // Allow write on the original func - res = mprotect(originalFunctionPage, page_size()*2, PROT_READ|PROT_WRITE|PROT_EXEC); - - // Write the original opcodes - std::copy(trampoline->trampolineBytes, trampoline->trampolineBytes+trampoline->nOriginalBytes, - reinterpret_cast(*ppOriginalFunc)); - - // Remove write permission - res = mprotect(originalFunctionPage, page_size()*2, PROT_READ|PROT_EXEC); - - // Allow write on trampoline page - res = mprotect(trampoline_page, page_size()*2, PROT_READ|PROT_WRITE|PROT_EXEC); - - clear_trampoline(*reinterpret_cast(trampoline_page), trampoline); - - // Remove write permission - res = mprotect(trampoline_page, page_size()*2, PROT_READ|PROT_EXEC); - } - else - { - void* originalFunctionPage = page_addr(*ppOriginalFunc, page_size()); - - // Allow write on the original func - res = mprotect(originalFunctionPage, page_size()*2, PROT_READ|PROT_WRITE|PROT_EXEC); - - // Write the jump to trampoline - gen_immediate_jump(reinterpret_cast(*ppOriginalFunc), trampoline->hookJump); - - // Remove write permission - res = mprotect(originalFunctionPage, page_size()*2, PROT_READ|PROT_EXEC); - - *ppOriginalFunc = (void*)(trampoline->trampolineBytes); - } - } - cur_transaction.clear(); - transaction_started = false; - - return 0; -} - -int Linux_Detour::unhook_func(void** ppOriginalFunc, void* _hook) -{ - if( !transaction_started ) - return -EPERM; - - if( ppOriginalFunc == nullptr || _hook == nullptr || *ppOriginalFunc == nullptr ) - return -EINVAL; - - trampoline_t *trampoline = reinterpret_cast(*ppOriginalFunc); - void *page_start = page_addr(reinterpret_cast(trampoline), page_size()); - auto it = std::find_if(trampoline_regions.begin(), trampoline_regions.end(), [page_start](trampoline_region_t ®ion){ - if( is_page_inside_region(page_start, region) ) - return true; - return false; - }); - if( it != trampoline_regions.end() ) - { - cur_transaction.push_back({true, ppOriginalFunc, trampoline}); - } - - return -EINVAL; -} - -int Linux_Detour::hook_func(void** ppOriginalFunc, void* _hook) -{ - if( !transaction_started ) - return -EPERM; - - if( ppOriginalFunc == nullptr || _hook == nullptr || *ppOriginalFunc == nullptr ) - return -EINVAL; - - uint8_t* hook = reinterpret_cast(_hook); - uint8_t* pOriginalFunc = reinterpret_cast(*ppOriginalFunc); - int code_len = find_space_for_trampoline(pOriginalFunc, relative_jump_size); - - if( code_len < relative_jump_size ) - return -ENOSPC; - - // Allocate the trampoline, try to put it right in the middle of the mem, so a relative jump can access any function in the app (+/-2GB) - // - // Our hook is a 5 bytes JMP (1 bytes for opcode, 4 for RELATIVE jump) - // /!\ TODO: Add checks on JMP overflow - - trampoline_t *trampoline = get_free_trampoline(); - uint8_t *pTrampolineCode = trampoline->trampolineBytes; - - void* trampoline_page = page_addr(reinterpret_cast(trampoline), page_size()); - - // Enable write to the trampoline region - mprotect(trampoline_page, page_size()*2, PROT_READ|PROT_WRITE|PROT_EXEC); - // Create relative jmp to hook - gen_immediate_jump(trampoline->hookJump, hook); - // Copy original opcodes - trampoline->nOriginalBytes = code_len; - std::copy((uint8_t*)pOriginalFunc, ((uint8_t*)pOriginalFunc)+code_len, pTrampolineCode); - pTrampolineCode += code_len; - // Create the relative jmp to original (function + backed up opcodes) - pTrampolineCode = gen_immediate_jump(pTrampolineCode, pOriginalFunc+code_len); - pTrampolineCode += relative_addr_jump_size; - - // Disable trampoline region write - mprotect(trampoline_page, page_size()*2, PROT_READ|PROT_EXEC); - - cur_transaction.push_back({false, ppOriginalFunc, trampoline}); - - return 0; -} - -/* ------ DOCUMENTATION ------ -http://www.c-jump.com/CIS77/CPU/x86/lecture.html <- some help to understand [MOD][REG][R/M] (see paragraph #6) -http://shell-storm.org/online/Online-Assembler-and-Disassembler <- online assembler -http://ref.x86asm.net/coder32.html <- opcodes reference - -X86 - -push ebx : 0x53 -sub esp ?? : 0x83 0xEC 0x?? -call ????????: 0xE8 0x?? 0x?? 0x?? 0x?? - - -// relative jmp: ???????? = dst_addr - curr_addr - 5 -jmp ???????? : 0xe9 0x?? 0x?? 0x?? 0x?? -destination = 0x8dba8 -jmp location: 0x91995 - opcodes: e9 0e c2 ff ff -0e c2 ff ff = 0x8dba8 - 0x91995 - 5 - -// short jmp: ?? = dst_addr - curr_addr - 2 -jmp short ??: 0xeb 0x?? -destination = 0x91964 -jmp location: 0x9198f - opcodes: 0xeb 0xd3 -d3 = 0x91964 - 0x9198f - 2 - -X64 - -TODO: - Hint: make relative jump to near (+/-2Gb) code : 5 bytes - load absolute addr into R11 and call a jmp on register R11 : 13 bytes - Or - Reuse x86 relative jmp method - -Example: -mov r11, 0x0123456789abcdef -> 0x49 0xbb 0xef 0xcd 0xab 0x89 0x67 0x45 0x23 0x01 -jmp r11 -> 0x41 0xff 0xe3 - - -*/ diff --git a/overlay_experimental/linux/Linux_Detour.h b/overlay_experimental/linux/Linux_Detour.h deleted file mode 100644 index bbc1760..0000000 --- a/overlay_experimental/linux/Linux_Detour.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef LINUX_DETOUR_H -#define LINUX_DETOUR_H - -#include - -namespace Linux_Detour -{ - int update_thread(pthread_t thread_id); - int transaction_begin(); - int transaction_abort(); - int transaction_commit(); - int hook_func(void** ppOriginalFunc, void* _hook); - int unhook_func(void** ppOriginalFunc, void* _hook); -}; - -#endif // LINUX_DETOUR_H diff --git a/overlay_experimental/linux/X11_Hook.h b/overlay_experimental/linux/X11_Hook.h index 5282466..08a0aba 100644 --- a/overlay_experimental/linux/X11_Hook.h +++ b/overlay_experimental/linux/X11_Hook.h @@ -9,9 +9,14 @@ #include // XEvent types #include // XEvent structure +extern "C" int XEventsQueued(Display *display, int mode); +extern "C" int XPending(Display *display); + class X11_Hook : public Base_Hook { public: + friend int XEventsQueued(Display *display, int mode); + friend int XPending(Display *display); static constexpr const char* DLL_NAME = "libX11.so"; private: @@ -27,8 +32,6 @@ private: int check_for_overlay(Display *d, int num_events); // Hook to X11 window messages - - decltype(XEventsQueued)* _XEventsQueued; decltype(XPeekEvent)* _XPeekEvent; decltype(XNextEvent)* _XNextEvent; @@ -37,12 +40,12 @@ private: //decltype(XLookupKeysym)* _XLookupKeysym; //decltype(XGetGeometry)* _XGetGeometry; -public: static int MyXEventsQueued(Display * display, int mode); static int MyXNextEvent(Display* display, XEvent *event); static int MyXPeekEvent(Display* display, XEvent *event); static int MyXPending(Display* display); +public: virtual ~X11_Hook(); void resetRenderState(); @@ -53,16 +56,6 @@ public: bool start_hook(); static X11_Hook* Inst(); virtual const char* get_lib_name() const; - - inline decltype(XEventsQueued)* get_XEventsQueued() const { return _XEventsQueued; } - inline decltype(XPeekEvent)* get_XPeekEvent() const { return _XPeekEvent; } - inline decltype(XNextEvent)* get_XNextEvent() const { return _XNextEvent; } - inline decltype(XPending)* get_XPending() const { return _XPending; } - - inline void loadXEventsQueued(decltype(XEventsQueued)* pfnXEventsQueued) { _XEventsQueued = pfnXEventsQueued; } - inline void loadXPeekEvent(decltype(XPeekEvent)* pfnXPeekEvent) { _XPeekEvent = pfnXPeekEvent; } - inline void loadXNextEvent(decltype(XNextEvent)* pfnXNextEvent) { _XNextEvent = pfnXNextEvent; } - inline void loadXPending(decltype(XPending)* pfnXPending) { _XPending = pfnXPending; } }; #endif//NO_OVERLAY