diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d2d70c7..759f5d9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,6 +12,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@master + with: + submodules: 'recursive' - name: Setup JDK 11 uses: actions/setup-java@v1 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2d77378 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "core/src/main/cpp/xz"] + path = core/src/main/cpp/xz + url = https://github.com/tukaani-project/xz-embedded.git diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 85a2af1..30d6303 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -20,7 +20,7 @@ plugins { } dependencies { - implementation("org.lsposed.lsplant:lsplant:5.2-aliucord.1") + implementation("org.lsposed.lsplant:lsplant:6.3-aliucord.1") implementation("io.github.vvb2060.ndk:dobby:1.2") androidTestImplementation("androidx.test.ext:junit:1.1.3") diff --git a/core/src/main/cpp/CMakeLists.txt b/core/src/main/cpp/CMakeLists.txt index c9cb333..9ab7c02 100644 --- a/core/src/main/cpp/CMakeLists.txt +++ b/core/src/main/cpp/CMakeLists.txt @@ -6,8 +6,9 @@ project("aliuhook") set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +include_directories(xz/linux/lib/xz xz/linux/include/linux xz/userspace) -add_library(aliuhook SHARED aliuhook.cpp elf_img.cpp profile_saver.cpp hidden_api.cpp) +add_library(aliuhook SHARED aliuhook.cpp elf_img.cpp profile_saver.cpp hidden_api.cpp xz/linux/lib/xz/xz_crc32.c xz/linux/lib/xz/xz_crc64.c xz/linux/lib/xz/xz_dec_bcj.c xz/linux/lib/xz/xz_dec_lzma2.c xz/linux/lib/xz/xz_dec_stream.c) find_package(lsplant REQUIRED CONFIG) find_package(dobby REQUIRED CONFIG) diff --git a/core/src/main/cpp/elf_img.cpp b/core/src/main/cpp/elf_img.cpp index 47e4396..dd2ba7c 100644 --- a/core/src/main/cpp/elf_img.cpp +++ b/core/src/main/cpp/elf_img.cpp @@ -17,7 +17,7 @@ #include #include "log.h" #include - +#include "xz.h" // Pine changed: namespace using namespace pine; @@ -53,19 +53,30 @@ void ElfImg::Open(const char *path, bool warn_if_symtab_not_found) { header = reinterpret_cast(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0)); close(fd); + parse(header, path, warn_if_symtab_not_found); + if (debugdata_offset != 0 && debugdata_size != 0) { + if (xzdecompress()) { + header_debugdata = reinterpret_cast(elf_debugdata.data()); + parse(header_debugdata, path, warn_if_symtab_not_found); + } + } + //load module base + base = GetModuleBase(path); +} +void ElfImg::parse(Elf_Ehdr *hdr, const char *path, bool warn_if_symtab_not_found) { // Pine changed: Use uintptr_t instead of size_t // section_header = reinterpret_cast(((size_t) header) + header->e_shoff); - section_header = reinterpret_cast(((uintptr_t) header) + header->e_shoff); + section_header = reinterpret_cast(((uintptr_t) hdr) + hdr->e_shoff); // size_t shoff = reinterpret_cast(section_header); auto shoff = reinterpret_cast(section_header); - char *section_str = reinterpret_cast(section_header[header->e_shstrndx].sh_offset + + char *section_str = reinterpret_cast(section_header[hdr->e_shstrndx].sh_offset + // ((size_t) header) - ((uintptr_t) header)); + ((uintptr_t) hdr)); - for (int i = 0; i < header->e_shnum; i++, shoff += header->e_shentsize) { + for (int i = 0; i < hdr->e_shnum; i++, shoff += hdr->e_shentsize) { auto *section_h = (Elf_Shdr *) shoff; char *sname = section_h->sh_name + section_str; Elf_Off entsize = section_h->sh_entsize; @@ -77,8 +88,9 @@ void ElfImg::Open(const char *path, bool warn_if_symtab_not_found) { dynsym_size = section_h->sh_size; dynsym_count = dynsym_size / entsize; // dynsym_start = reinterpret_cast(((size_t) header) + dynsym_offset); - dynsym_start = reinterpret_cast(((uintptr_t) header) + + dynsym_start = reinterpret_cast(((uintptr_t) hdr) + dynsym_offset); + LOGD("dynsym header {:#x} size {}", section_h->sh_offset, section_h->sh_size); } break; case SHT_SYMTAB: @@ -88,8 +100,9 @@ void ElfImg::Open(const char *path, bool warn_if_symtab_not_found) { symtab_size = section_h->sh_size; symtab_count = symtab_size / entsize; // symtab_start = reinterpret_cast(((size_t) header) + symtab_offset); - symtab_start = reinterpret_cast(((uintptr_t) header) + + symtab_start = reinterpret_cast(((uintptr_t) hdr) + symtab_offset); + LOGD("symtab header {:#x} size {} found in {}", section_h->sh_offset, section_h->sh_size, debugdata_offset != 0 ? "gnu_debugdata" : "orgin elf"); } break; case SHT_STRTAB: @@ -97,14 +110,20 @@ void ElfImg::Open(const char *path, bool warn_if_symtab_not_found) { strtab = section_h; symstr_offset = section_h->sh_offset; // strtab_start = reinterpret_cast(((size_t) header) + symstr_offset); - strtab_start = reinterpret_cast(((uintptr_t) header) + + strtab_start = reinterpret_cast(((uintptr_t) hdr) + symstr_offset); + LOGD("strtab header {:#x} size {}", section_h->sh_offset, section_h->sh_size); } if (strcmp(sname, ".strtab") == 0) { symstr_offset_for_symtab = section_h->sh_offset; } break; case SHT_PROGBITS: + if (strcmp(sname, ".gnu_debugdata") == 0) { + debugdata_offset = section_h->sh_offset; + debugdata_size = section_h->sh_size; + LOGD("gnu_debugdata header {:#x} size {}", section_h->sh_offset, section_h->sh_size); + } if (strtab == nullptr || dynsym == nullptr) break; if (bias == -4396) { bias = (off_t) section_h->sh_addr - (off_t) section_h->sh_offset; @@ -117,10 +136,114 @@ void ElfImg::Open(const char *path, bool warn_if_symtab_not_found) { // Pine changed: print log with filename // LOGW("can't find symtab from sections\n"); LOGW("can't find symtab from sections in %s\n", path); + }else + { + LOGW("found symtab %s\n", path); } +} - //load module base - base = GetModuleBase(path); +bool ElfImg::xzdecompress() { + struct xz_buf str_xz_buf; + struct xz_dec *str_xz_dec; + enum xz_ret ret = XZ_OK; + bool bError = true; + +#define BUFSIZE 1024*1024 + + xz_crc32_init(); +#ifdef XZ_USE_CRC64 + xz_crc64_init(); +#endif + str_xz_dec = xz_dec_init(XZ_DYNALLOC, 1 << 26); + if (str_xz_dec == NULL) { + LOGE("xz_dec_init memory allocation failed"); + return false; + } + + uint8_t *sBuffOut = (uint8_t *)malloc(BUFSIZE); + if (sBuffOut == NULL) { + LOGE("allocation for debugdata_header failed"); + return false; + } + + int iSzOut = BUFSIZE; + + str_xz_buf.in = ((uint8_t *)header)+debugdata_offset; + str_xz_buf.in_pos = 0; + str_xz_buf.in_size = debugdata_size; + str_xz_buf.out = sBuffOut; + str_xz_buf.out_pos = 0; + str_xz_buf.out_size = BUFSIZE; + + uint8_t iSkip = 0; + + while (true) { + ret = xz_dec_run(str_xz_dec, &str_xz_buf); + + if (str_xz_buf.out_pos == BUFSIZE) { + str_xz_buf.out_pos = 0; + iSkip++; + } else { + iSzOut -= (BUFSIZE - str_xz_buf.out_pos); + } + + if (ret == XZ_OK) { + iSzOut += BUFSIZE; + sBuffOut = (uint8_t *)realloc(sBuffOut, iSzOut); + str_xz_buf.out = sBuffOut+(iSkip*BUFSIZE); + continue; + } + +#ifdef XZ_DEC_ANY_CHECK + if (ret == XZ_UNSUPPORTED_CHECK) { + LOGW("Unsupported check; not verifying file integrity"); + continue; + } +#endif + break; + } // end while true + + switch (ret) { + case XZ_STREAM_END: + bError = false; + break; + + case XZ_MEM_ERROR: + LOGE("Memory allocation failed"); + break; + + case XZ_MEMLIMIT_ERROR: + LOGE("Memory usage limit reached"); + break; + + case XZ_FORMAT_ERROR: + LOGE("Not a .xz file"); + break; + + case XZ_OPTIONS_ERROR: + LOGE("Unsupported options in the .xz headers"); + break; + + case XZ_DATA_ERROR: + case XZ_BUF_ERROR: + LOGE("File is corrupt"); + break; + + default: + LOGE("xz_dec_run return a wrong value!"); + break; + } + xz_dec_end(str_xz_dec); + if (bError) { + return false; + } + if (sBuffOut[0] != 0x7F && sBuffOut[1] != 0x45 && sBuffOut[2] != 0x4C && sBuffOut[3] != 0x46) { + LOGE("not ELF header in gnu_debugdata"); + return false; + } + elf_debugdata = std::string((char *)sBuffOut, iSzOut); + free(sBuffOut); + return true; } void ElfImg::RelativeOpen(const char *elf, bool warn_if_symtab_not_found) { @@ -186,10 +309,11 @@ Elf_Addr ElfImg::GetSymbolOffset(std::string_view name, bool warn_if_missing, bo //search symtab if (symtab_start != nullptr && symstr_offset_for_symtab != 0) { + auto hdr = header_debugdata != nullptr ? header_debugdata : header; for (int i = 0; i < symtab_count; i++) { unsigned int st_type = ELF_ST_TYPE(symtab_start[i].st_info); // char *st_name = reinterpret_cast(((size_t) header) + symstr_offset_for_symtab + - char *st_name = reinterpret_cast(((uintptr_t) header) + + char *st_name = reinterpret_cast(((uintptr_t) hdr) + symstr_offset_for_symtab + symtab_start[i].st_name); if (st_type == STT_FUNC && symtab_start[i].st_size) { diff --git a/core/src/main/cpp/elf_img.h b/core/src/main/cpp/elf_img.h index d190751..a453061 100644 --- a/core/src/main/cpp/elf_img.h +++ b/core/src/main/cpp/elf_img.h @@ -14,7 +14,7 @@ #include #include #include - +#include #if defined(__LP64__) typedef Elf64_Ehdr Elf_Ehdr; typedef Elf64_Shdr Elf_Shdr; @@ -58,6 +58,10 @@ namespace pine { // Pine changed: GetModuleBase is private void* GetModuleBase(const char* name); + void parse(Elf_Ehdr* header, const char *path, bool warn_if_symtab_not_found); + + bool xzdecompress(); + #ifdef __LP64__ static constexpr const char* kSystemLibDir = "/system/lib64/"; static constexpr const char* kApexRuntimeLibDir = "/apex/com.android.runtime/lib64/"; @@ -75,6 +79,7 @@ namespace pine { off_t size = 0; off_t bias = -4396; Elf_Ehdr* header = nullptr; + Elf_Ehdr* header_debugdata = nullptr; Elf_Shdr* section_header = nullptr; Elf_Shdr* symtab = nullptr; Elf_Shdr* strtab = nullptr; @@ -90,6 +95,9 @@ namespace pine { Elf_Off dynsym_offset = 0; Elf_Off symtab_size = 0; Elf_Off dynsym_size = 0; + Elf_Off debugdata_offset = 0; + Elf_Off debugdata_size = 0; + std::string elf_debugdata; }; } diff --git a/core/src/main/cpp/xz b/core/src/main/cpp/xz new file mode 160000 index 0000000..1b6defd --- /dev/null +++ b/core/src/main/cpp/xz @@ -0,0 +1 @@ +Subproject commit 1b6defd544914bfb4065e343296e5db64ef400e6