diff --git a/armpatch_src/ARMPatch.cpp b/armpatch_src/ARMPatch.cpp index 09a7cc6..1807d49 100644 --- a/armpatch_src/ARMPatch.cpp +++ b/armpatch_src/ARMPatch.cpp @@ -1,69 +1,41 @@ #include "ARMPatch.h" +#include #include #include - -#ifdef __XDL -void* xdl_cached[100] {0}; // Much more enough -int cache_c = 0; - -inline bool xdl_is_cached(void* ptr) -{ - for(int i = 0; i < cache_c; ++i) - if(xdl_cached[i] == ptr) return true; - return false; -} -inline void* xdl_cache(void* ptr) -{ - if(!xdl_is_cached(ptr)) - { - xdl_cached[cache_c] = ptr; - ++cache_c; - } - return ptr; -} -#endif +#include namespace ARMPatch { bool bThumbMode = false; - static const char* __iter_dlName; - static int __iter_callback(struct dl_phdr_info *info, size_t size, void *data) - { - if ((void *)info->dlpi_addr == data) - { - __iter_dlName = info->dlpi_name; - return 1; - } - return 0; - } - + const char* GetPatchVerStr() { #define STRSTRSECPASS(_AA) #_AA #define STRSTRMACRO(_AA) STRSTRSECPASS(_AA) #ifdef __32BIT - return "ARMPatch v." STRSTRMACRO(ARMPATCH_VER) " (32-bit) (compiled " __DATE__ " " __TIME__ ")"; + static constexpr const char* verstr = "ARMPatch v." STRSTRMACRO(ARMPATCH_VER) " (32-bit) (compiled " __DATE__ " " __TIME__ ")"; #elif defined __64BIT - return "ARMPatch v." STRSTRMACRO(ARMPATCH_VER) " (64-bit) (compiled " __DATE__ " " __TIME__ ")"; + static constexpr const char* verstr = "ARMPatch v." STRSTRMACRO(ARMPATCH_VER) " (64-bit) (compiled " __DATE__ " " __TIME__ ")"; #endif + return verstr; } - int GetPatchVerInt() { return ARMPATCH_VER; } + uintptr_t GetLib(const char* soLib) { - FILE *fp = NULL; + FILE *fp = nullptr; uintptr_t address = 0; char buffer[2048]; fp = fopen( "/proc/self/maps", "rt" ); - if (fp != NULL) + if (fp != nullptr) { while (fgets(buffer, sizeof(buffer)-1, fp)) { if ( strstr( buffer, soLib ) && strstr( buffer, "00000000" ) ) // fix android 9.0+ arm64 some sys library { - address = (uintptr_t)strtoul( buffer, NULL, 16 ); + address = (uintptr_t)strtoul( buffer, nullptr, 16 ); break; } } @@ -75,40 +47,53 @@ namespace ARMPatch void* GetLibHandle(const char* soLib) { #ifdef __XDL - return xdl_cache(xdl_open(soLib, XDL_DEFAULT)); + return xdl_open(soLib, XDL_DEFAULT); #else return dlopen(soLib, RTLD_LAZY); #endif } - void* GetLibHandle(uintptr_t addr) + void* GetLibHandle(uintptr_t libAddr) { - __iter_dlName = NULL; #ifdef __XDL - xdl_iterate_phdr(__iter_callback, (void*)addr, XDL_DEFAULT); - return xdl_cache(xdl_open(__iter_dlName, XDL_DEFAULT)); + xdl_info_t info; + void* cache = nullptr; + if (!xdl_addr4(reinterpret_cast(libAddr), &info, &cache, XDL_NON_SYM)) return 0; + void* handle = xdl_open(info.dli_fname, XDL_DEFAULT); + xdl_addr_clean(&cache); + return handle; #else - dl_iterate_phdr(__iter_callback, (void*)addr); - return dlopen(__iter_dlName, RTLD_LAZY); + Dl_info info; + if (!dladdr(reinterpret_cast(libAddr), &info) return 0; + return dlopen(info.dli_fname, RTLD_LAZY); + #endif + } + + void CloseLibHandle(void* handle) + { + #ifdef __XDL + xdl_close(handle); + #else + dlclose(handle); #endif } uintptr_t GetLibLength(const char* soLib) { - FILE *fp = NULL; + FILE *fp = nullptr; uintptr_t address = 0, end_address = 0; char buffer[2048]; fp = fopen( "/proc/self/maps", "rt" ); - if (fp != NULL) + if (fp != nullptr) { while (fgets(buffer, sizeof(buffer)-1, fp)) { if ( strstr( buffer, soLib ) ) { const char* secondPart = strchr(buffer, '-'); - if(!address) end_address = address = (uintptr_t)strtoul( buffer, NULL, 16 ); - if(secondPart != NULL) end_address = (uintptr_t)strtoul( secondPart + 1, NULL, 16 ); + if(!address) end_address = address = (uintptr_t)strtoul( buffer, nullptr, 16 ); + if(secondPart != nullptr) end_address = (uintptr_t)strtoul( secondPart + 1, nullptr, 16 ); } } fclose(fp); @@ -119,90 +104,100 @@ namespace ARMPatch uintptr_t GetSym(void* handle, const char* sym) { #ifdef __XDL - if(xdl_is_cached(handle)) - { - void* ret = xdl_sym(handle, sym, NULL); - if(!ret) ret = xdl_dsym(handle, sym, NULL); - return (uintptr_t)ret; - } + void* addr = xdl_sym(handle, sym, nullptr); + if(!addr) addr = xdl_dsym(handle, sym, nullptr); + return reinterpret_cast(addr); + #else + return reinterpret_cast(dlsym(handle, sym)); #endif - return (uintptr_t)dlsym(handle, sym); } uintptr_t GetSym(uintptr_t libAddr, const char* sym) { - __iter_dlName = NULL; #ifdef __XDL - xdl_iterate_phdr(__iter_callback, (void*)libAddr, XDL_DEFAULT); - void* handle = xdl_cache(xdl_open(__iter_dlName, XDL_DEFAULT)); - return (uintptr_t)xdl_sym(handle, sym, NULL); + xdl_info_t info; + void* cache = nullptr; + if (!xdl_addr4(reinterpret_cast(libAddr), &info, &cache, XDL_NON_SYM)) return 0; + void* handle = xdl_open(info.dli_fname, XDL_DEFAULT); + xdl_addr_clean(&cache); + void* addr = xdl_sym(handle, sym, nullptr); + if(!addr) addr = xdl_dsym(handle, sym, nullptr); + xdl_close(handle); + return reinterpret_cast(addr); #else - dl_iterate_phdr(__iter_callback, (void*)libAddr); - void* handle = dlopen(__iter_dlName, RTLD_LAZY); - return (uintptr_t)dlsym(handle, sym); + Dl_info info; + if (!dladdr(reinterpret_cast(libAddr), &info) return 0; + void* handle = dlopen(info.dli_fname, RTLD_LAZY); + return reinterpret_cast(dlsym(handle, sym)); #endif } int Unprotect(uintptr_t addr, size_t len) { - #ifdef __32BIT - if(mprotect((void*)(addr & 0xFFFFF000), len, PROT_READ | PROT_WRITE | PROT_EXEC) == 0) return 0; - return mprotect((void*)(addr & 0xFFFFF000), len, PROT_READ | PROT_WRITE); - #elif defined __64BIT - if(mprotect((void*)(addr & 0xFFFFFFFFFFFFF000), len, PROT_READ | PROT_WRITE | PROT_EXEC) == 0) return 0; - return mprotect((void*)(addr & 0xFFFFFFFFFFFFF000), len, PROT_READ | PROT_WRITE); + #if defined(__USEGLOSS) + return SetMemoryPermission(addr, len, nullptr) ? 0 : -1; // supports 16kb pages size + #else + #ifdef __32BIT + void* m = reinterpret_cast(addr & 0xFFFFF000); + if (mprotect(m, len, PROT_READ | PROT_WRITE | PROT_EXEC) == 0) return 0; + return mprotect(m, len, PROT_READ | PROT_WRITE); + #elif defined __64BIT + void* m = reinterpret_cast(addr & 0xFFFFFFFFFFFFF000); + if (mprotect(m, len, PROT_READ | PROT_WRITE | PROT_EXEC) == 0) return 0; + return mprotect(m, len, PROT_READ | PROT_WRITE); + #endif #endif } void Write(uintptr_t dest, uintptr_t src, size_t size) { - Unprotect(dest, size); - memcpy((void*)dest, (void*)src, size); + ARMPatch::Unprotect(dest, size); + memcpy(reinterpret_cast(dest), reinterpret_cast(src), size); cacheflush(dest, dest + size, 0); } void Read(uintptr_t src, uintptr_t dest, size_t size) { - Unprotect(src, size); // Do we need it..? - memcpy((void*)src, (void*)dest, size); + ARMPatch::Unprotect(dest, size); + memcpy(reinterpret_cast(src), reinterpret_cast(dest), size); } int WriteNOP(uintptr_t addr, size_t count) { #ifdef __32BIT - if(THUMBMODE(addr)) - { - addr = DETHUMB(addr); - int bytesCount = 2 * count; - uintptr_t endAddr = addr + bytesCount; - Unprotect(addr, bytesCount); - for (uintptr_t p = addr; p != endAddr; p += 2) + if(THUMBMODE(addr)) { - (*(char*)(p + 0)) = 0x00; - (*(char*)(p + 1)) = 0xBF; + addr = DETHUMB(addr); + int bytesCount = 2 * count; + uintptr_t endAddr = addr + bytesCount; + ARMPatch::Unprotect(addr, bytesCount); + for (uintptr_t p = addr; p != endAddr; p += 2) + { + (*(char*)(p + 0)) = 0x00; + (*(char*)(p + 1)) = 0xBF; + } + cacheflush(addr, endAddr, 0); + return bytesCount; } - cacheflush(addr, endAddr, 0); - return bytesCount; - } - else - { - int bytesCount = 4 * count; - uintptr_t endAddr = addr + bytesCount; - Unprotect(addr, bytesCount); - for (uintptr_t p = addr; p != endAddr; p += 4) + else { - (*(char*)(p + 0)) = 0x00; - (*(char*)(p + 1)) = 0xF0; - (*(char*)(p + 2)) = 0x20; - (*(char*)(p + 3)) = 0xE3; + int bytesCount = 4 * count; + uintptr_t endAddr = addr + bytesCount; + ARMPatch::Unprotect(addr, bytesCount); + for (uintptr_t p = addr; p != endAddr; p += 4) + { + (*(char*)(p + 0)) = 0x00; + (*(char*)(p + 1)) = 0xF0; + (*(char*)(p + 2)) = 0x20; + (*(char*)(p + 3)) = 0xE3; + } + cacheflush(addr, endAddr, 0); + return bytesCount; } - cacheflush(addr, endAddr, 0); - return bytesCount; - } #elif defined __64BIT int bytesCount = 4 * count; uintptr_t endAddr = addr + bytesCount; - Unprotect(addr, bytesCount); + ARMPatch::Unprotect(addr, bytesCount); for (uintptr_t p = addr; p != endAddr; p += 4) { (*(char*)(p + 0)) = 0x1F; @@ -220,36 +215,36 @@ namespace ARMPatch int bytesCount = 4 * count; uintptr_t endAddr = addr + bytesCount; #ifdef __32BIT - if(THUMBMODE(addr)) - { - addr = DETHUMB(addr); - endAddr = DETHUMB(endAddr); - Unprotect(addr, bytesCount); - for (uintptr_t p = addr; p != endAddr; p += 4) + if(THUMBMODE(addr)) { - (*(char*)(p + 0)) = 0xAF; - (*(char*)(p + 1)) = 0xF3; - (*(char*)(p + 2)) = 0x00; - (*(char*)(p + 3)) = 0x80; + addr = DETHUMB(addr); + endAddr = DETHUMB(endAddr); + ARMPatch::Unprotect(addr, bytesCount); + for (uintptr_t p = addr; p != endAddr; p += 4) + { + (*(char*)(p + 0)) = 0xAF; + (*(char*)(p + 1)) = 0xF3; + (*(char*)(p + 2)) = 0x00; + (*(char*)(p + 3)) = 0x80; + } + cacheflush(addr, endAddr, 0); + return bytesCount; } - cacheflush(addr, endAddr, 0); - return bytesCount; - } - else - { - Unprotect(addr, count * 4); - for (uintptr_t p = addr; p != endAddr; p += 4) + else { - (*(char*)(p + 0)) = 0x00; - (*(char*)(p + 1)) = 0xF0; - (*(char*)(p + 2)) = 0x20; - (*(char*)(p + 3)) = 0xE3; + ARMPatch::Unprotect(addr, count * 4); + for (uintptr_t p = addr; p != endAddr; p += 4) + { + (*(char*)(p + 0)) = 0x00; + (*(char*)(p + 1)) = 0xF0; + (*(char*)(p + 2)) = 0x20; + (*(char*)(p + 3)) = 0xE3; + } + cacheflush(addr, endAddr, 0); + return bytesCount; } - cacheflush(addr, endAddr, 0); - return bytesCount; - } #elif defined __64BIT - Unprotect(addr, count * 4); + ARMPatch::Unprotect(addr, count * 4); for (uintptr_t p = addr; p != endAddr; p += 4) { (*(char*)(p + 0)) = 0x1F; @@ -262,188 +257,119 @@ namespace ARMPatch #endif } - int WriteB(uintptr_t addr, uintptr_t dest) // B instruction + int WriteRET(uintptr_t addr) { #ifdef __32BIT - if(THUMBMODE(addr)) - { - intptr_t calc = ((intptr_t)dest - (intptr_t)addr) / 2; - if(calc >= -1 && calc < 1) return 0; - else if(calc < -1) - { - goto do_b_w; // Only B.W supports negative offset! - } - else if(calc == 1) + if(THUMBMODE(addr)) { - return WriteNOP(addr, 1); - } - - calc -= 2; // PC - if(calc <= 255) - { - uint16_t newDest = 0xE000 | (calc & 0x7FF); - Write(DETHUMB(addr), newDest); + Write(DETHUMB(addr), (uintptr_t)"\x70\x47", 2); return 2; } else { - do_b_w: - // B.W goes here! - uint32_t imm_val = (dest - addr - 4) & 0x7FFFFF; - uint32_t newDest = ((imm_val & 0xFFF) >> 1 | 0xB800) << 16 | (imm_val >> 12 | 0xF000); - - Write(DETHUMB(addr), newDest); + Write(addr, (uintptr_t)"\x1E\xFF\x2F\xE1", 4); return 4; } - } - else - { - // Probably not working! - uint32_t newDest = 0xEA000000 | ((dest - addr - 4) >> 2) & 0x00FFFFFF; - Write(addr, (uintptr_t)&newDest, sizeof(uint32_t)); - return 4; - } - #elif defined __64BIT - // Probably, the range is [-0xFFFFFF, 0xFFFFFFF] - uint32_t newDest = 0x14000000 | (((dest - addr) >> 2) & 0x03FFFFFF); - Write(addr, (uintptr_t)&newDest, sizeof(uint32_t)); - return 4; - #endif - } - - void WriteBL(uintptr_t addr, uintptr_t dest) // BL instruction (max. is ~0x400000 in both directions) - { - #if defined(__USEGLOSS) - #ifdef __32BIT - if(THUMBMODE(addr)) - { - if(!Gloss::Inst::MakeThumbBL(addr, dest)) Gloss::Inst::MakeThumbBL_W(addr, dest); - } - else - { - Gloss::Inst::MakeArmBL(addr, dest); - } - #elif defined __64BIT - Gloss::Inst::MakeArm64BL(addr, dest); - #endif - #else - #ifdef __32BIT - uint32_t newDest = ((dest - addr - 4) >> 12) & 0x7FF | 0xF000 | - ((((dest - addr - 4) >> 1) & 0x7FF | 0xF800) << 16); - Write(addr, (uintptr_t)&newDest, sizeof(uintptr_t)); - #elif defined __64BIT - uint32_t newDest = 0x94000000 | (((dest - addr) >> 2) & 0x03FFFFFF); - Write(addr, (uintptr_t)&newDest, sizeof(uint32_t)); - #endif - #endif - } - - void WriteBLX(uintptr_t addr, uintptr_t dest) // BLX instruction (max. is ~0x400000 in both directions) - { - #if defined(__USEGLOSS) - #ifdef __32BIT - if(THUMBMODE(addr)) - { - if(!Gloss::Inst::MakeThumbBLX(addr, dest)) Gloss::Inst::MakeThumbBLX_W(addr, dest); - } - else - { - Gloss::Inst::MakeArmBLX(addr, dest); - } - #elif defined __64BIT - __builtin_trap(); // ARMv8 doesnt have that instruction so using it is absurd! - #endif - #else - #ifdef __32BIT - uint32_t newDest = ((dest - addr - 4) >> 12) & 0x7FF | 0xF000 | - ((((dest - addr - 4) >> 1) & 0x7FF | 0xE800) << 16); - Write(addr, (uintptr_t)&newDest, sizeof(uint32_t)); - #elif defined __64BIT - __builtin_trap(); // ARMv8 doesnt have that instruction so using it is absurd! - #endif - #endif - } - - int WriteRET(uintptr_t addr) - { - #ifdef __32BIT - if(THUMBMODE(addr)) - { - Write(DETHUMB(addr), (uintptr_t)"\x70\x47", 2); - return 2; - } - else - { - Write(addr, (uintptr_t)"\x1E\xFF\x2F\xE1", 4); - return 4; - } #elif defined __64BIT Write(addr, (uintptr_t)"\xC0\x03\x5F\xD6", 4); return 4; #endif } - - void WriteMOV(uintptr_t addr, ARMRegister from, ARMRegister to) + + void WriteMOV(uintptr_t addr, ARMRegister from, ARMRegister to, bool is_t16) { #ifdef __32BIT - uint32_t newDest; if(THUMBMODE(addr)) { - newDest = (0x01 << 24) | (to << 16) | (from << 12); + if (is_t16) + { + // TODO thumb 2 + } + else + { + addr = DETHUMB(addr); + uint32_t newDest = (0x01 << 24) | (to << 16) | (from << 12); + Write(addr, (uintptr_t)&newDest, sizeof(uint32_t)); + } } else { - + // TODO arm } - Write(addr, (uintptr_t)&newDest, sizeof(uint32_t)); #elif defined __64BIT + (void)is_t16; if((from >= ARM_REG_X0 && to < ARM_REG_X0) || (to >= ARM_REG_X0 && from < ARM_REG_X0)) return; //__builtin_trap(); else if(from >= ARM_REG_X0) { - Write(addr, ARMv8::MOVRegBits::CreateMOV(from - ARM_REG_X0, to - ARM_REG_X0, true)); + Write(addr, ARMv8::MOVRegBits::Create(from - ARM_REG_X0, to - ARM_REG_X0, true)); } else { - Write(addr, ARMv8::MOVRegBits::CreateMOV(from, to, false)); + Write(addr, ARMv8::MOVRegBits::Create(from, to, false)); } #endif } - int Redirect(uintptr_t addr, uintptr_t to) + int Redirect(uintptr_t addr, uintptr_t to, bool _4byte) { if(!addr || !to) return 0; - #ifdef __32BIT - uint32_t hook[2] = {0xE51FF004, to}; - int ret = 8; - if(THUMBMODE(addr)) - { - addr &= ~0x1; - if (addr & 0x2) - { - WriteNOP(RETHUMB(addr), 1); - addr += 2; - ret = 10; - } - hook[0] = 0xF000F8DF; - } - Write(DETHUMB(addr), (uintptr_t)hook, sizeof(hook)); - return ret; - #elif defined __64BIT - Unprotect(addr, 16); - uint64_t hook[2] = {0xD61F022058000051, to}; - Write(addr, (uintptr_t)hook, sizeof(hook)); - return 16; - #endif + #if defined(__USEGLOSS) + #ifdef __32BIT + i_set mode = I_ARM; + if (THUMBMODE(addr)) mode = I_THUMB; + #else + i_set mode = I_ARM64; + #endif + void* ret = GlossHookRedirect(reinterpret_cast(addr), reinterpret_cast(to), _4byte, mode); + size_t len = 0; + GlossHookGetBackupsInst(ret, &len); + return len; + #else + (void)_4byte; + #ifdef __32BIT + uint32_t hook[2] = {0xE51FF004, to}; + int ret = 8; + if (THUMBMODE(addr)) + { + addr &= ~0x1; + if (addr & 0x2) + { + WriteNOP(RETHUMB(addr), 1); + addr += 2; + ret = 10; + } + hook[0] = 0xF000F8DF; + } + Write(DETHUMB(addr), (uintptr_t)hook, sizeof(hook)); + return ret; + #elif defined __64BIT + ARMPatch::Unprotect(addr, 16); + uint64_t hook[2] = {0xD61F024058000052, to}; + Write(addr, (uintptr_t)hook, sizeof(hook)); + return 16; + #endif + #endif } - bool hookInternal(void* addr, void* func, void** original) + bool hookInternal(void* addr, void* func, void** original, bool _4byte) { - if (addr == NULL || func == NULL || addr == func) return false; + if (addr == nullptr || func == nullptr || addr == func) return false; #if defined(__USEGLOSS) - return GlossHook(addr, func, original) != NULL; + #ifdef __32BIT + i_set mode = I_ARM; + if (THUMBMODE(addr)) mode = I_THUMB; + #else + i_set mode = I_ARM64; + #endif + if (_4byte) + return GlossHookAddr(addr, func, original, _4byte, mode) != nullptr; + else + return GlossHook(addr, func, original) != nullptr; #elif defined(__USEDOBBY) + (void)_4byte; return DobbyHook(addr, (dobby_dummy_func_t)func, (dobby_dummy_func_t*)original) == 0; #else + (void)_4byte; #ifdef __32BIT return MSHookFunction(addr, func, original); #elif defined __64BIT @@ -454,17 +380,20 @@ namespace ARMPatch bool hookPLTInternal(void* addr, void* func, void** original) { - if (addr == NULL || func == NULL || addr == func || - (original != NULL && *original == func)) return false; - if(Unprotect((uintptr_t)addr, sizeof(uintptr_t)) != 0) return false; - if(original != NULL) *((uintptr_t*)original) = *(uintptr_t*)addr; - *(uintptr_t*)addr = (uintptr_t)func; - return true; + if (addr == nullptr || func == nullptr || addr == func || (original != nullptr && *original == func)) return false; + #if defined(__USEGLOSS) + return GlossGotHook(addr, func, original) != nullptr; + #else + if (ARMPatch::Unprotect((uintptr_t)addr, sizeof(uintptr_t)) != 0) return false; + if(original != nullptr) *((uintptr_t*)original) = *(uintptr_t*)addr; + *(uintptr_t*)addr = (uintptr_t)func; + return true; + #endif } static bool CompareData(const uint8_t* data, const bytePattern::byteEntry* pattern, size_t patternlength) { - int index = 0; + uint32_t index = 0; for (size_t i = 0; i < patternlength; i++) { auto byte = *pattern; @@ -479,6 +408,7 @@ namespace ARMPatch uintptr_t GetAddressFromPattern(const char* pattern, const char* soLib) { + if (pattern == nullptr || soLib == nullptr) return 0; bytePattern ret; const char* input = &pattern[0]; while (*input) @@ -488,7 +418,7 @@ namespace ARMPatch if (isxdigit(*input)) { entry.bUnknown = false; - entry.nValue = (uint8_t)std::strtol(input, NULL, 16); + entry.nValue = (uint8_t)std::strtol(input, nullptr, 16); input += 2; } else @@ -501,20 +431,39 @@ namespace ARMPatch auto patternstart = ret.vBytes.data(); auto length = ret.vBytes.size(); - - uintptr_t pMemoryBase = GetLib(soLib); - size_t nMemorySize = GetLibLength(soLib) - length; - - for (size_t i = 0; i < nMemorySize; i++) - { - uintptr_t addr = pMemoryBase + i; - if (CompareData((const uint8_t*)addr, patternstart, length)) return addr; - } - return (uintptr_t)0; + + #if defined(__USEGLOSS) + uintptr_t pMemoryBase = 1; + size_t nMemorySize = 0; + uint32_t nMemoryType = PT_NULL; + for (uint16_t id = 0; pMemoryBase != 0; id++) + { + pMemoryBase = GlossGetLibSegment(soLib, id, &nMemoryType, &nMemorySize); + if (nMemoryType == PT_LOAD && pMemoryBase != 0) + { + nMemorySize -= length; + for (size_t i = 0; i < nMemorySize; i++) + { + uintptr_t addr = pMemoryBase + i; + if (CompareData((const uint8_t*)addr, patternstart, length)) return addr; + } + } + } + #else + uintptr_t pMemoryBase = GetLib(soLib); + size_t nMemorySize = GetLibLength(soLib) - length; + for (size_t i = 0; i < nMemorySize; i++) + { + uintptr_t addr = pMemoryBase + i; + if (CompareData((const uint8_t*)addr, patternstart, length)) return addr; + } + #endif + return 0; } - uintptr_t GetAddressFromPattern(const char* pattern, uintptr_t libStart, uintptr_t scanLen) + uintptr_t GetAddressFromPattern(const char* pattern, uintptr_t libStart, size_t scanLen) { + if (pattern == nullptr || !libStart || !scanLen) return 0; bytePattern ret; const char* input = &pattern[0]; while (*input) @@ -524,7 +473,7 @@ namespace ARMPatch if (isxdigit(*input)) { entry.bUnknown = false; - entry.nValue = (uint8_t)std::strtol(input, NULL, 16); + entry.nValue = (uint8_t)std::strtol(input, nullptr, 16); input += 2; } else @@ -538,112 +487,198 @@ namespace ARMPatch auto patternstart = ret.vBytes.data(); auto length = ret.vBytes.size(); - uintptr_t scanSize = libStart + scanLen; + uintptr_t scanSize = scanLen - length; for (size_t i = 0; i < scanSize; i++) { uintptr_t addr = libStart + i; if (CompareData((const uint8_t*)addr, patternstart, length)) return addr; } - return (uintptr_t)0; + return 0; } - + bool IsThumbAddr(uintptr_t addr) { return THUMBMODE(addr); } // xDL part - bool IsCorrectXDLHandle(void* ptr) - { - #ifdef __XDL - return xdl_is_cached(ptr); - #endif - return false; - } - uintptr_t GetLibXDL(void* ptr) + uintptr_t GetLibXDL(void* handle) { #ifdef __XDL xdl_info_t info; - if (xdl_info(ptr, XDL_DI_DLINFO, &info) == -1) return 0; - return (uintptr_t)info.dli_fbase; + if (xdl_info(handle, XDL_DI_DLINFO, &info) == -1) return 0; + return reinterpret_cast(info.dli_fbase); #endif return 0; } - uintptr_t GetAddrBaseXDL(uintptr_t addr) + + uintptr_t GetSymAddrXDL(uintptr_t libaddr) { #ifdef __XDL xdl_info_t info; - void* cache = NULL; - if(!xdl_addr((void*)addr, &info, &cache)) return 0; + void* cache = nullptr; + if (!xdl_addr(reinterpret_cast(libaddr), &info, &cache)) return 0; + uintptr_t addr = reinterpret_cast(info.dli_saddr); xdl_addr_clean(&cache); - return (uintptr_t)info.dli_saddr; + return addr; #endif return 0; } - size_t GetSymSizeXDL(void* ptr) + + size_t GetSymSizeXDL(uintptr_t libaddr) { #ifdef __XDL xdl_info_t info; - void* cache = NULL; - if(!xdl_addr(ptr, &info, &cache)) return 0; + void* cache = nullptr; + if (!xdl_addr(reinterpret_cast(libaddr), &info, &cache)) return 0; + size_t size = info.dli_ssize; xdl_addr_clean(&cache); - return info.dli_ssize; + return size; #endif return 0; } - const char* GetSymNameXDL(void* ptr) + + const char* GetSymNameXDL(uintptr_t libaddr) { #ifdef __XDL + static char name[255]; + memset(name, 0, sizeof(name)); xdl_info_t info; - void* cache = NULL; - if(!xdl_addr(ptr, &info, &cache)) return NULL; + void* cache = nullptr; + if (!xdl_addr(reinterpret_cast(libaddr), &info, &cache)) return 0; + strlcpy(name, info.dli_sname, sizeof(name) - 1); xdl_addr_clean(&cache); - return info.dli_sname; + return name; #endif - return NULL; + return nullptr; } // GlossHook part + int WriteB(uintptr_t addr, uintptr_t dest, bool is_t16) // B instruction + { + #if defined(__USEGLOSS) + #ifdef __32BIT + if(THUMBMODE(addr)) + { + if (is_t16) + { + Gloss::Inst::MakeThumb16B(addr, dest); + return 2; + } + else + { + Gloss::Inst::MakeThumb32B(addr, dest); + return 4; + } + } + else + { + Gloss::Inst::MakeArmB(addr, dest); + return 4; + } + #elif defined __64BIT + (void)is_t16; + Gloss::Inst::MakeArm64B(addr, dest); + return 4; + #endif + #endif + } - bool hookBranchInternal(void* addr, void* func, void** original) + void WriteBL(uintptr_t addr, uintptr_t dest, bool is_width) // BL instruction { - #ifdef __USEGLOSS - if (addr == NULL || func == NULL || addr == func) return false; + #if defined(__USEGLOSS) #ifdef __32BIT - i_set mode = $ARM; - if (THUMBMODE(addr)) mode = $THUMB; - #else - i_set mode = $ARM64; + if(THUMBMODE(addr)) + { + if (is_width) + { + Gloss::Inst::MakeThumbBL_W(addr, dest); + } + else + { + Gloss::Inst::MakeThumbBL(addr, dest); + } + } + else + { + Gloss::Inst::MakeArmBL(addr, dest); + } + #elif defined __64BIT + (void)is_width; + Gloss::Inst::MakeArm64BL(addr, dest); #endif - return GlossHookBranchB(addr, func, original, mode) != NULL; - #else - return false; #endif } - bool hookBranchLinkInternal(void* addr, void* func, void** original) + void WriteBLX(uintptr_t addr, uintptr_t dest, bool is_width) // BLX instruction + { + #if defined(__USEGLOSS) + #ifdef __32BIT + if(THUMBMODE(addr)) + { + if (is_width) + { + Gloss::Inst::MakeThumbBLX_W(addr, dest); + } + else + { + Gloss::Inst::MakeThumbBLX(addr, dest); + } + } + else + { + Gloss::Inst::MakeArmBLX(addr, dest); + } + #elif defined __64BIT + __builtin_trap(); // ARMv8 doesnt have that instruction so using it is absurd! + #endif + #endif + } + + uintptr_t* GetGot(void* handle, const char* sym, size_t* size) + { + #if defined(__USEGLOSS) + uintptr_t* addr_list = nullptr; + if (GlossGot(handle, sym, &addr_list, size)) return addr_list; + #endif + return nullptr; + } + + uintptr_t GetAddressFromPattern(const char* pattern, const char* soLib, const char* section) + { + #if defined(__USEGLOSS) + if (pattern == nullptr || soLib == nullptr) return 0; + size_t sec_size = 0; + uintptr_t sec_addr = GlossGetLibSection(soLib, section, &sec_size); + if (sec_addr != 0) + return GetAddressFromPattern(pattern, sec_addr, sec_size); + #endif + return 0; + } + + bool hookBranchLinkInternal(void* addr, void* func, void** original) // BL Hook { #ifdef __USEGLOSS - if (addr == NULL || func == NULL || addr == func) return false; + if (addr == nullptr || func == nullptr || addr == func) return false; #ifdef __32BIT - i_set mode = $ARM; - if (THUMBMODE(addr)) mode = $THUMB; + i_set mode = I_ARM; + if (THUMBMODE(addr)) mode = I_THUMB; #else - i_set mode = $ARM64; + i_set mode = I_ARM64; #endif - return GlossHookBranchBL(addr, func, original, mode) != NULL; + return GlossHookBranchBL(addr, func, original, mode) != nullptr; #else return false; #endif } - bool hookBranchLinkXInternal(void* addr, void* func, void** original) + bool hookBranchLinkXInternal(void* addr, void* func, void** original) // BLX Hook { #ifdef __USEGLOSS - if (addr == NULL || func == NULL || addr == func) return false; + if (addr == nullptr || func == nullptr || addr == func) return false; #ifdef __32BIT - if (THUMBMODE(addr)) return GlossHookBranchBLX(addr, func, original, $THUMB) != NULL; - else return GlossHookBranchBLX(addr, func, original, $ARM) != NULL; + if (THUMBMODE(addr)) return GlossHookBranchBLX(addr, func, original, I_THUMB) != nullptr; + else return GlossHookBranchBLX(addr, func, original, I_ARM) != nullptr; #else __builtin_trap(); #endif @@ -659,16 +694,16 @@ namespace ARMPatch if(THUMBMODE(addr)) { addr &= ~0x1; - switch(Gloss::Inst::GetBranch(addr, $THUMB)) + switch(Gloss::Inst::GetBranch(addr, I_THUMB)) { - case Gloss::Inst::branchs::B_COND16: - case Gloss::Inst::branchs::B_16: + case Gloss::Inst::Branchs::B_COND16: + case Gloss::Inst::Branchs::B_16: return (uintptr_t)Gloss::Inst::GetThumb16BranchDestination(addr); - case Gloss::Inst::branchs::B_COND: - case Gloss::Inst::branchs::B: - case Gloss::Inst::branchs::BL: - case Gloss::Inst::branchs::BLX: + case Gloss::Inst::Branchs::B_COND: + case Gloss::Inst::Branchs::B: + case Gloss::Inst::Branchs::BL: + case Gloss::Inst::Branchs::BLX: return (uintptr_t)Gloss::Inst::GetThumb32BranchDestination(addr); default: diff --git a/armpatch_src/ARMPatch.h b/armpatch_src/ARMPatch.h index dd752b9..0023afa 100644 --- a/armpatch_src/ARMPatch.h +++ b/armpatch_src/ARMPatch.h @@ -1,9 +1,9 @@ #include +#include #include #include #include - #ifdef __XDL #include "xdl.h" #endif @@ -18,7 +18,7 @@ #define __32BIT #define DETHUMB(_a) (((uintptr_t)_a) & ~0x1) #define RETHUMB(_a) (((uintptr_t)_a) | 0x1) - #define THUMBMODE(_a) ((((uintptr_t)_a) & 0x1)||(((uintptr_t)_a) & 0x2)||ARMPatch::bThumbMode||(ARMPatch::GetAddrBaseXDL((uintptr_t)_a) & 0x1)) + #define THUMBMODE(_a) ((((uintptr_t)_a) & 0x1)||ARMPatch::bThumbMode||(ARMPatch::GetSymAddrXDL((uintptr_t)_a) & 0x1)) extern "C" bool MSHookFunction(void* symbol, void* replace, void** result); #elif defined __aarch64__ #define __64BIT @@ -49,9 +49,18 @@ /* Just a hook of a function located in PLT section (by address!) */ #define HOOKPLT(_name, _fnAddr) \ ARMPatch::HookPLT((void*)(_fnAddr), (void*)(&HookOf_##_name), (void**)(&_name)); + #define HOOKPLTSYM(_name, _libHndl, _fnSym) \ + do { \ + size_t size = 0; \ + uintptr_t* addr_list = ARMPatch::GetGot(_libHndl, _fnSym, &size); \ + for (size_t i = 0; i < size; i++) \ + ARMPatch::HookPLT((void*)(addr_list[i]), (void*)(&HookOf_##_name), (void**)(&_name)); \ + free(addr_list); \ + addr_list = nullptr; \ + } while (0) #endif -#define ARMPATCH_VER 2 +#define ARMPATCH_VER 3 #ifdef __32BIT enum ARMRegister : char @@ -116,6 +125,7 @@ struct bytePattern namespace ARMPatch { extern bool bThumbMode; + const char* GetPatchVerStr(); int GetPatchVerInt(); /* @@ -130,9 +140,14 @@ namespace ARMPatch void* GetLibHandle(const char* soLib); /* Get library's handle - addr - an address of anything inside a library + libAddr - an address of anything inside a library */ - void* GetLibHandle(uintptr_t addr); + void* GetLibHandle(uintptr_t libAddr); + /* + Close library's handle + handle - HANDLE (NOTICE THIS!!!) of a library (u can obtain it using dlopen) + */ + void CloseLibHandle(void* handle); /* Get library's end address soLib - name of a loaded library @@ -146,7 +161,7 @@ namespace ARMPatch uintptr_t GetSym(void* handle, const char* sym); /* Get library's function address by symbol (__unwind???) - libAddr - ADDRESS (NOTICE THIS!!!) of a library (u can obtain it using getLib) + libAddr - an address of anything inside a library sym - name of a function @XMDS requested this */ @@ -155,6 +170,7 @@ namespace ARMPatch /* Reprotect memory to allow reading/writing/executing addr - address + len - range */ int Unprotect(uintptr_t addr, size_t len = PAGE_SIZE); @@ -173,6 +189,11 @@ namespace ARMPatch { Write(dest, (uintptr_t)data, size); } + inline void Write(uintptr_t dest, uint64_t data) + { + uint64_t dataPtr = data; + Write(dest, (uintptr_t)&dataPtr, 8); + } inline void Write(uintptr_t dest, uint32_t data) { uint32_t dataPtr = data; @@ -213,41 +234,28 @@ namespace ARMPatch int WriteNOP4(uintptr_t addr, size_t count = 1); /* - Place JUMP instruction (reprotects it) - addr - where to put - dest - Jump to what? - */ - int WriteB(uintptr_t addr, uintptr_t dest); - - /* - Place BL instruction (reprotects it) - addr - where to put - dest - Jump to what? - */ - void WriteBL(uintptr_t addr, uintptr_t dest); - - /* - Place BLX instruction (reprotects it) + Place RET instruction (RETURN, function end, reprotects it) addr - where to put - dest - Jump to what? */ - void WriteBLX(uintptr_t addr, uintptr_t dest); + int WriteRET(uintptr_t addr); /* - Place RET instruction (RETURN, function end, reprotects it) + Place MOV instruction (register) addr - where to put + from - src register + to - dest register + is_t16 - thumb16 mov */ - int WriteRET(uintptr_t addr); - - void WriteMOV(uintptr_t addr, ARMRegister from, ARMRegister to); + void WriteMOV(uintptr_t addr, ARMRegister from, ARMRegister to, bool is_t16 = false); /* - Place LDR instruction (moves directly to the function with the same stack!) + Place absolute jump instruction (moves directly to the function with the same stack!) Very fast and very lightweight! addr - where to redirect to - redirect to what? + _4byte - use b instruction jump (GlossHook) */ - int Redirect(uintptr_t addr, uintptr_t to); + int Redirect(uintptr_t addr, uintptr_t to, bool _4byte = false); /* ByteScanner @@ -262,22 +270,23 @@ namespace ARMPatch libStart - library's start address scanLen - how much to scan from libStart */ - uintptr_t GetAddressFromPattern(const char* pattern, uintptr_t libStart, uintptr_t scanLen); + uintptr_t GetAddressFromPattern(const char* pattern, uintptr_t libStart, size_t scanLen); /* - Cydia's Substrate / Rprop's Inline Hook (use hook instead of hookInternal, ofc reprotects it!) + Cydia's Substrate / Rprop's / dobby / Gloss Inline Hook (use hook instead of hookInternal, ofc reprotects it!) addr - what to hook? func - Call that function instead of an original original - Original function! + _4byte - use b instruction jump (GlossHook) */ - bool hookInternal(void* addr, void* func, void** original); + bool hookInternal(void* addr, void* func, void** original, bool _4byte = false); template bool Hook(A addr, B func) { return hookInternal((void*)addr, (void*)func, (void**)NULL); } template bool Hook(A addr, B func, C original) { return hookInternal((void*)addr, (void*)func, (void**)original); } /* - A simple hook of a PLT-section functions (use HookPLT instead of hookPLTInternal, ofc reprotects it!) + A simple hook of a .got .plt section functions (use HookPLT instead of hookPLTInternal, ofc reprotects it!) addr - what to hook? func - Call that function instead of an original original - Original function! @@ -295,26 +304,62 @@ namespace ARMPatch bool IsThumbAddr(uintptr_t addr); // xDL part - bool IsCorrectXDLHandle(void* ptr); - uintptr_t GetLibXDL(void* ptr); - uintptr_t GetAddrBaseXDL(uintptr_t addr); - size_t GetSymSizeXDL(void* ptr); - const char* GetSymNameXDL(void* ptr); + uintptr_t GetLibXDL(void* handle); + uintptr_t GetSymAddrXDL(uintptr_t libaddr); + size_t GetSymSizeXDL(uintptr_t libaddr); + const char* GetSymNameXDL(uintptr_t libaddr); // GlossHook part START + + // Better place branch + + /* + Place B instruction (reprotects it) + addr - where to put + dest - Jump to what? + is_t16 - Thumb16 B + */ + int WriteB(uintptr_t addr, uintptr_t dest, bool is_t16 = false); + + /* + Place BL instruction (reprotects it) + addr - where to put + dest - Jump to what? + is_width - Thumb BL.W + */ + void WriteBL(uintptr_t addr, uintptr_t dest, bool is_width = false); + + /* + Place BLX instruction (reprotects it) + addr - where to put + dest - Jump to what? + is_width - Thumb BLX.W + */ + void WriteBLX(uintptr_t addr, uintptr_t dest, bool is_width = false); + + /* + Get library's .got address by symbol + handle - HANDLE (NOTICE THIS!!!) of a library (only xdl) + sym - name of a function + size - addr array size + return - .got addr array save + */ + uintptr_t* GetGot(void* handle, const char* sym, size_t* size); + + /* + ByteScanner + pattern - pattern. + soLib - library's name + section - section's name (default: ".text") + */ + uintptr_t GetAddressFromPattern(const char* pattern, const char* soLib, const char* section); /* - A branch hook + A branch hook (BL BLX) addr - what to hook? func - Call that function instead of an original original - Original function! */ - bool hookBranchInternal(void* addr, void* func, void** original); - template - bool HookB(A addr, B func) { return hookBranchInternal((void*)addr, (void*)func, (void**)NULL); } - template - bool HookB(A addr, B func, C original) { return hookBranchInternal((void*)addr, (void*)func, (void**)original); } - bool hookBranchLinkInternal(void* addr, void* func, void** original); template bool HookBL(A addr, B func) { return hookBranchLinkInternal((void*)addr, (void*)func, (void**)NULL); } diff --git a/armpatch_src/Android.mk b/armpatch_src/Android.mk index 1c56329..1469a47 100644 --- a/armpatch_src/Android.mk +++ b/armpatch_src/Android.mk @@ -2,13 +2,16 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := substrate -LOCAL_CFLAGS := -O2 -mfloat-abi=softfp +LOCAL_CPPFLAGS += -g0 -O2 -Wall -Wextra -std=c++17 -DNDEBUG \ +-fdata-sections -ffunction-sections -fvisibility=hidden -fstack-protector -fomit-frame-pointer ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) LOCAL_SRC_FILES := substrate/Hooker.cpp substrate/Debug.cpp substrate/PosixMemory.cpp # Cydia Substrate + LOCAL_CPPFLAGS += -mfloat-abi=softfp -mthumb +else ifeq ($(TARGET_ARCH_ABI), arm64-v8a) + LOCAL_SRC_FILES := And64InlineHook/And64InlineHook.cpp # And64InlineHook + LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384 else - ifeq ($(TARGET_ARCH_ABI), arm64-v8a) - LOCAL_SRC_FILES := And64InlineHook/And64InlineHook.cpp # And64InlineHook - endif + $(error Unknown arch, only support armeabi-v7a and arm64-v8a) endif include $(BUILD_STATIC_LIBRARY) @@ -27,8 +30,19 @@ LOCAL_CPP_EXTENSION := .cpp .cc LOCAL_SHARED_LIBRARIES := substrate gloss #dobby LOCAL_MODULE := armpatch LOCAL_SRC_FILES := ARMPatch.cpp -LOCAL_CFLAGS += -O2 -mfloat-abi=softfp -DNDEBUG -LOCAL_LDLIBS += -llog # ARM64 library requires for shared library (because that substrate was made with logs support) +LOCAL_CFLAGS += -g0 -O2 -Wall -Wextra -Werror -std=c17 -DNDEBUG \ +-fstack-protector -fdata-sections -ffunction-sections -fvisibility=hidden -fomit-frame-pointer +LOCAL_CPPFLAGS += -g0 -O2 -Wall -Wextra -Werror -std=c++17 -DNDEBUG \ +-fstack-protector -fdata-sections -ffunction-sections -fvisibility=hidden -fomit-frame-pointer +ifeq ($(TARGET_ARCH_ABI),arm64-v8a) + LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384 +else ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) + LOCAL_CFLAGS += -mfloat-abi=softfp -mthumb + LOCAL_CPPFLAGS += -mfloat-abi=softfp -mthumb +else + $(error Unknown arch, only support armeabi-v7a and arm64-v8a) +endif +LOCAL_LDLIBS += -landroid -llog -ldl ## xDL ## LOCAL_C_INCLUDES += $(LOCAL_PATH)/xDL/xdl/src/main/cpp $(LOCAL_PATH)/xDL/xdl/src/main/cpp/include