mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-04-29 01:22:07 +08:00
This commit is contained in:
parent
44a0ccc850
commit
9a27afefe1
@ -1,5 +1,6 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.android.library) apply false
|
||||
}
|
||||
|
||||
@ -11,8 +12,8 @@ tasks.register("copyZygiskFiles") {
|
||||
val zygiskBuildDir = zygiskModule.layout.buildDirectory.get().asFile
|
||||
|
||||
val classesJar = zygiskBuildDir
|
||||
.resolve("intermediates/aar_main_jar/release/syncReleaseLibJars/classes.jar")
|
||||
classesJar.copyTo(moduleFolder.resolve("classes.jar"), overwrite = true)
|
||||
.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
|
||||
classesJar.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)
|
||||
|
||||
val zygiskSoDir = zygiskBuildDir
|
||||
.resolve("intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib")
|
||||
|
@ -1,9 +0,0 @@
|
||||
Telegram channel:
|
||||
https://t.me/playintegrityfix
|
||||
|
||||
Donations:
|
||||
https://www.paypal.com/paypalme/chiteroman0
|
||||
|
||||
# v18.9
|
||||
|
||||
- Update fingerprint.
|
@ -9,3 +9,4 @@ hiddenapibypass = { group = "org.lsposed.hiddenapibypass", name = "hiddenapibypa
|
||||
|
||||
[plugins]
|
||||
android-library = { id = "com.android.library", version.ref = "agp" }
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
@ -15,7 +15,7 @@ static nlohmann::json json;
|
||||
static bool spoofProps = true, spoofProvider = true, spoofSignature = false;
|
||||
|
||||
static bool DEBUG = false;
|
||||
static std::string DEVICE_INITIAL_SDK_INT, SECURITY_PATCH, BUILD_ID;
|
||||
static std::string DEVICE_INITIAL_SDK_INT = "21", SECURITY_PATCH, BUILD_ID;
|
||||
|
||||
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
||||
|
||||
@ -215,11 +215,10 @@ static void injectDex() {
|
||||
auto dexClClass = env->FindClass("dalvik/system/PathClassLoader");
|
||||
auto dexClInit = env->GetMethodID(
|
||||
dexClClass, "<init>",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
|
||||
auto str1 = env->NewStringUTF((dir + "/classes.dex").c_str());
|
||||
auto str2 = env->NewStringUTF(dir.c_str());
|
||||
"(Ljava/lang/String;Ljava/lang/ClassLoader;)V");
|
||||
auto classesJar = env->NewStringUTF((dir + "/classes.dex").c_str());
|
||||
auto dexCl =
|
||||
env->NewObject(dexClClass, dexClInit, str1, str2, systemClassLoader);
|
||||
env->NewObject(dexClClass, dexClInit, classesJar, systemClassLoader);
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
@ -257,8 +256,7 @@ static void injectDex() {
|
||||
env->DeleteLocalRef(entryClassObj);
|
||||
env->DeleteLocalRef(jsonStr);
|
||||
env->DeleteLocalRef(dexCl);
|
||||
env->DeleteLocalRef(str1);
|
||||
env->DeleteLocalRef(str2);
|
||||
env->DeleteLocalRef(classesJar);
|
||||
env->DeleteLocalRef(dexClClass);
|
||||
env->DeleteLocalRef(clClass);
|
||||
|
||||
@ -266,8 +264,7 @@ static void injectDex() {
|
||||
}
|
||||
|
||||
extern "C" [[gnu::visibility("default"), maybe_unused]] bool
|
||||
init(JavaVM *vm, const std::string &gmsDir) {
|
||||
bool close = true;
|
||||
init(JavaVM *vm, const std::string &gmsDir, bool trickyStore, bool testSignedRom) {
|
||||
|
||||
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
LOGE("[INJECT] JNI_ERR!");
|
||||
@ -283,20 +280,28 @@ init(JavaVM *vm, const std::string &gmsDir) {
|
||||
|
||||
parseJSON();
|
||||
|
||||
if (trickyStore) {
|
||||
spoofProvider = false;
|
||||
spoofSignature = false;
|
||||
spoofProps = false;
|
||||
}
|
||||
|
||||
if (testSignedRom) {
|
||||
spoofProvider = true;
|
||||
spoofSignature = true;
|
||||
}
|
||||
|
||||
UpdateBuildFields();
|
||||
|
||||
if (spoofProvider || spoofSignature) {
|
||||
injectDex();
|
||||
} else {
|
||||
LOGD("[INJECT] Dex file won't be injected due spoofProvider and "
|
||||
"spoofSignature are false");
|
||||
LOGD("[INJECT] Dex file won't be injected due spoofProvider and spoofSignature are false");
|
||||
}
|
||||
|
||||
if (spoofProps) {
|
||||
close = !doHook();
|
||||
return !doHook();
|
||||
}
|
||||
|
||||
LOGD("[INJECT] Done!");
|
||||
|
||||
return close;
|
||||
return true;
|
||||
}
|
Binary file not shown.
@ -1,7 +1,6 @@
|
||||
id=playintegrityfix
|
||||
name=Play Integrity Fix
|
||||
version=v18.9
|
||||
versionCode=18900
|
||||
name=Play Integrity Fix [INJECT]
|
||||
version=v3-inject
|
||||
versionCode=3
|
||||
author=chiteroman
|
||||
description=Universal modular fix for Play Integrity (and SafetyNet) on devices running Android 8-15
|
||||
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
||||
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"version": "v18.9",
|
||||
"versionCode": 18900,
|
||||
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v18.9/PlayIntegrityFix_v18.9.zip",
|
||||
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
alias(libs.plugins.android.application)
|
||||
}
|
||||
|
||||
android {
|
||||
@ -53,9 +53,7 @@ android {
|
||||
release {
|
||||
isMinifyEnabled = true
|
||||
multiDexEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
||||
)
|
||||
proguardFiles += file("proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,3 @@ find_package(cxx REQUIRED CONFIG)
|
||||
link_libraries(cxx::cxx)
|
||||
|
||||
add_library(zygisk SHARED zygisk.cpp)
|
||||
|
||||
add_subdirectory(xdl)
|
||||
|
||||
target_link_libraries(zygisk PRIVATE xdl)
|
||||
|
@ -1,21 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.22.1)
|
||||
project(xdl)
|
||||
|
||||
file(GLOB XDL_SRC *.c)
|
||||
add_library(xdl STATIC ${XDL_SRC})
|
||||
target_compile_features(xdl PRIVATE c_std_17)
|
||||
target_compile_options(xdl PRIVATE -std=c17)
|
||||
target_include_directories(xdl PUBLIC include .)
|
||||
#target_link_libraries(xdl log)
|
||||
|
||||
if (USEASAN)
|
||||
target_compile_options(xdl PRIVATE -fsanitize=address -fno-omit-frame-pointer)
|
||||
target_link_options(xdl PRIVATE -fsanitize=address)
|
||||
else ()
|
||||
target_compile_options(xdl PRIVATE -Oz -ffunction-sections -fdata-sections)
|
||||
target_link_options(xdl PRIVATE -Oz -Wl,--exclude-libs,ALL -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/xdl.map.txt)
|
||||
endif ()
|
||||
|
||||
if ((${ANDROID_ABI} STREQUAL "arm64-v8a") OR (${ANDROID_ABI} STREQUAL "x86_64"))
|
||||
target_link_options(xdl PRIVATE "-Wl,-z,max-page-size=16384")
|
||||
endif ()
|
@ -1,95 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2020-10-04.
|
||||
|
||||
//
|
||||
// xDL version: 2.2.0
|
||||
//
|
||||
// xDL is an enhanced implementation of the Android DL series functions.
|
||||
// For more information, documentation, and the latest version please check:
|
||||
// https://github.com/hexhacking/xDL
|
||||
//
|
||||
|
||||
#ifndef IO_GITHUB_HEXHACKING_XDL
|
||||
#define IO_GITHUB_HEXHACKING_XDL
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// same as Dl_info:
|
||||
const char *dli_fname; // Pathname of shared object that contains address.
|
||||
void *dli_fbase; // Address at which shared object is loaded.
|
||||
const char *dli_sname; // Name of nearest symbol with address lower than addr.
|
||||
void *dli_saddr; // Exact address of symbol named in dli_sname.
|
||||
// added by xDL:
|
||||
size_t dli_ssize; // Symbol size of nearest symbol with address lower than addr.
|
||||
const ElfW(Phdr) *dlpi_phdr; // Pointer to array of ELF program headers for this object.
|
||||
size_t dlpi_phnum; // Number of items in dlpi_phdr.
|
||||
} xdl_info_t;
|
||||
|
||||
//
|
||||
// Default value for flags in xdl_open(), xdl_addr4(), and xdl_iterate_phdr().
|
||||
//
|
||||
#define XDL_DEFAULT 0x00
|
||||
|
||||
//
|
||||
// Enhanced dlopen() / dlclose() / dlsym().
|
||||
//
|
||||
#define XDL_TRY_FORCE_LOAD 0x01
|
||||
#define XDL_ALWAYS_FORCE_LOAD 0x02
|
||||
void *xdl_open(const char *filename, int flags);
|
||||
void *xdl_open2(struct dl_phdr_info *info);
|
||||
void *xdl_close(void *handle);
|
||||
void *xdl_sym(void *handle, const char *symbol, size_t *symbol_size);
|
||||
void *xdl_dsym(void *handle, const char *symbol, size_t *symbol_size);
|
||||
|
||||
//
|
||||
// Enhanced dladdr().
|
||||
//
|
||||
#define XDL_NON_SYM 0x01
|
||||
int xdl_addr(void *addr, xdl_info_t *info, void **cache);
|
||||
int xdl_addr4(void *addr, xdl_info_t *info, void **cache, int flags);
|
||||
void xdl_addr_clean(void **cache);
|
||||
|
||||
//
|
||||
// Enhanced dl_iterate_phdr().
|
||||
//
|
||||
#define XDL_FULL_PATHNAME 0x01
|
||||
int xdl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data, int flags);
|
||||
|
||||
//
|
||||
// Custom dlinfo().
|
||||
//
|
||||
#define XDL_DI_DLINFO 1 // type of info: xdl_info_t
|
||||
int xdl_info(void *handle, int request, void *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
{
|
||||
global:
|
||||
xdl_open;
|
||||
xdl_open2;
|
||||
xdl_close;
|
||||
xdl_sym;
|
||||
xdl_dsym;
|
||||
xdl_addr;
|
||||
xdl_addr4;
|
||||
xdl_addr_clean;
|
||||
xdl_iterate_phdr;
|
||||
xdl_info;
|
||||
|
||||
local:
|
||||
*;
|
||||
};
|
@ -1,297 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2020-10-04.
|
||||
|
||||
#include "xdl_iterate.h"
|
||||
|
||||
#include <android/api-level.h>
|
||||
#include <ctype.h>
|
||||
#include <dlfcn.h>
|
||||
#include <elf.h>
|
||||
#include <inttypes.h>
|
||||
#include <link.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/auxv.h>
|
||||
|
||||
#include "xdl.h"
|
||||
#include "xdl_linker.h"
|
||||
#include "xdl_util.h"
|
||||
|
||||
/*
|
||||
* =========================================================================================================
|
||||
* API-LEVEL ANDROID-VERSION SOLUTION
|
||||
* =========================================================================================================
|
||||
* 16 4.1 /proc/self/maps
|
||||
* 17 4.2 /proc/self/maps
|
||||
* 18 4.3 /proc/self/maps
|
||||
* 19 4.4 /proc/self/maps
|
||||
* 20 4.4W /proc/self/maps
|
||||
* ---------------------------------------------------------------------------------------------------------
|
||||
* 21 5.0 dl_iterate_phdr() + __dl__ZL10g_dl_mutex + linker/linker64 from getauxval(3)
|
||||
* 22 5.1 dl_iterate_phdr() + __dl__ZL10g_dl_mutex + linker/linker64 from getauxval(3)
|
||||
* ---------------------------------------------------------------------------------------------------------
|
||||
* 23 >= 6.0 dl_iterate_phdr() + linker/linker64 from getauxval(3)
|
||||
* =========================================================================================================
|
||||
*/
|
||||
|
||||
extern __attribute((weak)) int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), void *);
|
||||
extern __attribute((weak)) unsigned long int getauxval(unsigned long int);
|
||||
|
||||
static uintptr_t xdl_iterate_get_min_vaddr(struct dl_phdr_info *info) {
|
||||
uintptr_t min_vaddr = UINTPTR_MAX;
|
||||
for (size_t i = 0; i < info->dlpi_phnum; i++) {
|
||||
const ElfW(Phdr) *phdr = &(info->dlpi_phdr[i]);
|
||||
if (PT_LOAD == phdr->p_type) {
|
||||
if (min_vaddr > phdr->p_vaddr) min_vaddr = phdr->p_vaddr;
|
||||
}
|
||||
}
|
||||
return min_vaddr;
|
||||
}
|
||||
|
||||
static int xdl_iterate_open_or_rewind_maps(FILE **maps) {
|
||||
if (NULL == *maps) {
|
||||
*maps = fopen("/proc/self/maps", "r");
|
||||
if (NULL == *maps) return -1;
|
||||
} else
|
||||
rewind(*maps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xdl_iterate_get_pathname_from_maps(uintptr_t base, char *buf, size_t buf_len, FILE **maps) {
|
||||
// open or rewind maps-file
|
||||
if (0 != xdl_iterate_open_or_rewind_maps(maps)) return -1; // failed
|
||||
|
||||
char line[1024];
|
||||
while (fgets(line, sizeof(line), *maps)) {
|
||||
// check base address
|
||||
uintptr_t start, end;
|
||||
if (2 != sscanf(line, "%" SCNxPTR "-%" SCNxPTR " r", &start, &end)) continue;
|
||||
if (base < start) break; // failed
|
||||
if (base >= end) continue;
|
||||
|
||||
// get pathname
|
||||
char *pathname = strchr(line, '/');
|
||||
if (NULL == pathname) break; // failed
|
||||
xdl_util_trim_ending(pathname);
|
||||
|
||||
// found it
|
||||
strlcpy(buf, pathname, buf_len);
|
||||
return 0; // OK
|
||||
}
|
||||
|
||||
return -1; // failed
|
||||
}
|
||||
|
||||
static int xdl_iterate_by_linker_cb(struct dl_phdr_info *info, size_t size, void *arg) {
|
||||
uintptr_t *pkg = (uintptr_t *)arg;
|
||||
xdl_iterate_phdr_cb_t cb = (xdl_iterate_phdr_cb_t)*pkg++;
|
||||
void *cb_arg = (void *)*pkg++;
|
||||
FILE **maps = (FILE **)*pkg++;
|
||||
uintptr_t linker_load_bias = *pkg++;
|
||||
int flags = (int)*pkg;
|
||||
|
||||
// ignore invalid ELF
|
||||
if (0 == info->dlpi_addr || NULL == info->dlpi_name || '\0' == info->dlpi_name[0]) return 0;
|
||||
|
||||
// ignore linker if we have returned it already
|
||||
if (linker_load_bias == info->dlpi_addr) return 0;
|
||||
|
||||
struct dl_phdr_info info_fixed;
|
||||
info_fixed.dlpi_addr = info->dlpi_addr;
|
||||
info_fixed.dlpi_name = info->dlpi_name;
|
||||
info_fixed.dlpi_phdr = info->dlpi_phdr;
|
||||
info_fixed.dlpi_phnum = info->dlpi_phnum;
|
||||
info = &info_fixed;
|
||||
|
||||
// fix dlpi_phdr & dlpi_phnum (from memory)
|
||||
if (NULL == info->dlpi_phdr || 0 == info->dlpi_phnum) {
|
||||
ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)info->dlpi_addr;
|
||||
info->dlpi_phdr = (ElfW(Phdr) *)(info->dlpi_addr + ehdr->e_phoff);
|
||||
info->dlpi_phnum = ehdr->e_phnum;
|
||||
}
|
||||
|
||||
// fix dlpi_name (from /proc/self/maps)
|
||||
if ('/' != info->dlpi_name[0] && '[' != info->dlpi_name[0] && (0 != (flags & XDL_FULL_PATHNAME))) {
|
||||
// get base address
|
||||
uintptr_t min_vaddr = xdl_iterate_get_min_vaddr(info);
|
||||
if (UINTPTR_MAX == min_vaddr) return 0; // ignore this ELF
|
||||
uintptr_t base = (uintptr_t)(info->dlpi_addr + min_vaddr);
|
||||
|
||||
char buf[1024];
|
||||
if (0 != xdl_iterate_get_pathname_from_maps(base, buf, sizeof(buf), maps)) return 0; // ignore this ELF
|
||||
|
||||
info->dlpi_name = (const char *)buf;
|
||||
}
|
||||
|
||||
// callback
|
||||
return cb(info, size, cb_arg);
|
||||
}
|
||||
|
||||
static uintptr_t xdl_iterate_get_linker_base(void) {
|
||||
if (NULL == getauxval) return 0;
|
||||
|
||||
uintptr_t base = (uintptr_t)getauxval(AT_BASE);
|
||||
if (0 == base) return 0;
|
||||
if (0 != memcmp((void *)base, ELFMAG, SELFMAG)) return 0;
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
static int xdl_iterate_do_callback(xdl_iterate_phdr_cb_t cb, void *cb_arg, uintptr_t base,
|
||||
const char *pathname, uintptr_t *load_bias) {
|
||||
ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)base;
|
||||
|
||||
struct dl_phdr_info info;
|
||||
info.dlpi_name = pathname;
|
||||
info.dlpi_phdr = (const ElfW(Phdr) *)(base + ehdr->e_phoff);
|
||||
info.dlpi_phnum = ehdr->e_phnum;
|
||||
|
||||
// get load bias
|
||||
uintptr_t min_vaddr = xdl_iterate_get_min_vaddr(&info);
|
||||
if (UINTPTR_MAX == min_vaddr) return 0; // ignore invalid ELF
|
||||
info.dlpi_addr = (ElfW(Addr))(base - min_vaddr);
|
||||
if (NULL != load_bias) *load_bias = info.dlpi_addr;
|
||||
|
||||
return cb(&info, sizeof(struct dl_phdr_info), cb_arg);
|
||||
}
|
||||
|
||||
static int xdl_iterate_by_linker(xdl_iterate_phdr_cb_t cb, void *cb_arg, int flags) {
|
||||
if (NULL == dl_iterate_phdr) return 0;
|
||||
|
||||
int api_level = xdl_util_get_api_level();
|
||||
FILE *maps = NULL;
|
||||
int r;
|
||||
|
||||
// dl_iterate_phdr(3) does NOT contain linker/linker64 when Android version < 8.1 (API level 27).
|
||||
// Here we always try to get linker base address from auxv.
|
||||
uintptr_t linker_load_bias = 0;
|
||||
uintptr_t linker_base = xdl_iterate_get_linker_base();
|
||||
if (0 != linker_base) {
|
||||
if (0 !=
|
||||
(r = xdl_iterate_do_callback(cb, cb_arg, linker_base, XDL_UTIL_LINKER_PATHNAME, &linker_load_bias)))
|
||||
return r;
|
||||
}
|
||||
|
||||
// for other ELF
|
||||
uintptr_t pkg[5] = {(uintptr_t)cb, (uintptr_t)cb_arg, (uintptr_t)&maps, linker_load_bias, (uintptr_t)flags};
|
||||
if (__ANDROID_API_L__ == api_level || __ANDROID_API_L_MR1__ == api_level) xdl_linker_lock();
|
||||
r = dl_iterate_phdr(xdl_iterate_by_linker_cb, pkg);
|
||||
if (__ANDROID_API_L__ == api_level || __ANDROID_API_L_MR1__ == api_level) xdl_linker_unlock();
|
||||
|
||||
if (NULL != maps) fclose(maps);
|
||||
return r;
|
||||
}
|
||||
|
||||
#if (defined(__arm__) || defined(__i386__)) && __ANDROID_API__ < __ANDROID_API_L__
|
||||
static int xdl_iterate_by_maps(xdl_iterate_phdr_cb_t cb, void *cb_arg) {
|
||||
FILE *maps = fopen("/proc/self/maps", "r");
|
||||
if (NULL == maps) return 0;
|
||||
|
||||
int r = 0;
|
||||
char buf1[1024], buf2[1024];
|
||||
char *line = buf1;
|
||||
uintptr_t prev_base = 0;
|
||||
bool try_next_line = false;
|
||||
|
||||
while (fgets(line, sizeof(buf1), maps)) {
|
||||
// Try to find an ELF which loaded by linker.
|
||||
uintptr_t base, offset;
|
||||
char exec;
|
||||
if (3 != sscanf(line, "%" SCNxPTR "-%*" SCNxPTR " r%*c%cp %" SCNxPTR " ", &base, &exec, &offset))
|
||||
goto clean;
|
||||
|
||||
if ('-' == exec && 0 == offset) {
|
||||
// r--p
|
||||
prev_base = base;
|
||||
line = (line == buf1 ? buf2 : buf1);
|
||||
try_next_line = true;
|
||||
continue;
|
||||
} else if (exec == 'x') {
|
||||
// r-xp
|
||||
char *pathname = NULL;
|
||||
if (try_next_line && 0 != offset) {
|
||||
char *prev = (line == buf1 ? buf2 : buf1);
|
||||
char *prev_pathname = strchr(prev, '/');
|
||||
if (NULL == prev_pathname) goto clean;
|
||||
|
||||
pathname = strchr(line, '/');
|
||||
if (NULL == pathname) goto clean;
|
||||
|
||||
xdl_util_trim_ending(prev_pathname);
|
||||
xdl_util_trim_ending(pathname);
|
||||
if (0 != strcmp(prev_pathname, pathname)) goto clean;
|
||||
|
||||
// we found the line with r-xp in the next line
|
||||
base = prev_base;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if (0 != offset) goto clean;
|
||||
|
||||
// get pathname
|
||||
if (NULL == pathname) {
|
||||
pathname = strchr(line, '/');
|
||||
if (NULL == pathname) goto clean;
|
||||
xdl_util_trim_ending(pathname);
|
||||
}
|
||||
|
||||
if (0 != memcmp((void *)base, ELFMAG, SELFMAG)) goto clean;
|
||||
ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)base;
|
||||
struct dl_phdr_info info;
|
||||
info.dlpi_name = pathname;
|
||||
info.dlpi_phdr = (const ElfW(Phdr) *)(base + ehdr->e_phoff);
|
||||
info.dlpi_phnum = ehdr->e_phnum;
|
||||
|
||||
// callback
|
||||
if (0 != (r = xdl_iterate_do_callback(cb, cb_arg, base, pathname, NULL))) break;
|
||||
}
|
||||
|
||||
clean:
|
||||
try_next_line = false;
|
||||
}
|
||||
|
||||
fclose(maps);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
int xdl_iterate_phdr_impl(xdl_iterate_phdr_cb_t cb, void *cb_arg, int flags) {
|
||||
// iterate by /proc/self/maps in Android 4.x (Android 4.x only supports arm32 and x86)
|
||||
#if (defined(__arm__) || defined(__i386__)) && __ANDROID_API__ < __ANDROID_API_L__
|
||||
if (xdl_util_get_api_level() < __ANDROID_API_L__) return xdl_iterate_by_maps(cb, cb_arg);
|
||||
#endif
|
||||
|
||||
// iterate by dl_iterate_phdr()
|
||||
return xdl_iterate_by_linker(cb, cb_arg, flags);
|
||||
}
|
||||
|
||||
int xdl_iterate_get_full_pathname(uintptr_t base, char *buf, size_t buf_len) {
|
||||
FILE *maps = NULL;
|
||||
int r = xdl_iterate_get_pathname_from_maps(base, buf, buf_len, &maps);
|
||||
if (NULL != maps) fclose(maps);
|
||||
return r;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2020-10-04.
|
||||
|
||||
#ifndef IO_GITHUB_HEXHACKING_XDL_ITERATE
|
||||
#define IO_GITHUB_HEXHACKING_XDL_ITERATE
|
||||
|
||||
#include <link.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int (*xdl_iterate_phdr_cb_t)(struct dl_phdr_info *info, size_t size, void *arg);
|
||||
int xdl_iterate_phdr_impl(xdl_iterate_phdr_cb_t cb, void *cb_arg, int flags);
|
||||
|
||||
int xdl_iterate_get_full_pathname(uintptr_t base, char *buf, size_t buf_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,231 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2021-02-21.
|
||||
|
||||
#include "xdl_linker.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xdl.h"
|
||||
#include "xdl_iterate.h"
|
||||
#include "xdl_util.h"
|
||||
|
||||
#define XDL_LINKER_SYM_MUTEX "__dl__ZL10g_dl_mutex"
|
||||
#define XDL_LINKER_SYM_DLOPEN_EXT_N "__dl__ZL10dlopen_extPKciPK17android_dlextinfoPv"
|
||||
#define XDL_LINKER_SYM_DO_DLOPEN_N "__dl__Z9do_dlopenPKciPK17android_dlextinfoPv"
|
||||
#define XDL_LINKER_SYM_DLOPEN_O "__dl__Z8__dlopenPKciPKv"
|
||||
#define XDL_LINKER_SYM_LOADER_DLOPEN_P "__loader_dlopen"
|
||||
|
||||
#ifndef __LP64__
|
||||
#define LIB "lib"
|
||||
#else
|
||||
#define LIB "lib64"
|
||||
#endif
|
||||
|
||||
typedef void *(*xdl_linker_dlopen_n_t)(const char *, int, const void *, void *);
|
||||
typedef void *(*xdl_linker_dlopen_o_t)(const char *, int, const void *);
|
||||
|
||||
static pthread_mutex_t *xdl_linker_mutex = NULL;
|
||||
static void *xdl_linker_dlopen = NULL;
|
||||
|
||||
typedef enum { MATCH_PREFIX, MATCH_SUFFIX } xdl_linker_match_type_t;
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wpadded"
|
||||
typedef struct {
|
||||
xdl_linker_match_type_t type;
|
||||
const char *value;
|
||||
} xdl_linker_match_t;
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
typedef struct {
|
||||
void *addr;
|
||||
xdl_linker_match_t *matches;
|
||||
size_t matches_cursor;
|
||||
} xdl_linker_caller_t;
|
||||
|
||||
// https://source.android.com/docs/core/architecture/vndk/linker-namespace
|
||||
// The following rules are loose and incomplete, you can add more according to your needs.
|
||||
static xdl_linker_match_t xdl_linker_match_default[] = {{MATCH_SUFFIX, "/libc.so"}};
|
||||
static xdl_linker_match_t xdl_linker_match_art[] = {{MATCH_SUFFIX, "/libart.so"}};
|
||||
static xdl_linker_match_t xdl_linker_match_sphal[] = {{MATCH_PREFIX, "/vendor/" LIB "/egl/"},
|
||||
{MATCH_PREFIX, "/vendor/" LIB "/hw/"},
|
||||
{MATCH_PREFIX, "/vendor/" LIB "/"},
|
||||
{MATCH_PREFIX, "/odm/" LIB "/"}};
|
||||
static xdl_linker_match_t xdl_linker_match_vndk[] = {{MATCH_PREFIX, "/apex/com.android.vndk.v"},
|
||||
{MATCH_PREFIX, "/vendor/" LIB "/vndk-sp/"},
|
||||
{MATCH_PREFIX, "/odm/" LIB "/vndk-sp/"}};
|
||||
static xdl_linker_caller_t xdl_linker_callers[] = {
|
||||
{NULL, xdl_linker_match_default, sizeof(xdl_linker_match_default) / sizeof(xdl_linker_match_t)},
|
||||
{NULL, xdl_linker_match_art, sizeof(xdl_linker_match_art) / sizeof(xdl_linker_match_t)},
|
||||
{NULL, xdl_linker_match_sphal, sizeof(xdl_linker_match_sphal) / sizeof(xdl_linker_match_t)},
|
||||
{NULL, xdl_linker_match_vndk, sizeof(xdl_linker_match_vndk) / sizeof(xdl_linker_match_t)}};
|
||||
|
||||
static void xdl_linker_init_symbols_impl(void) {
|
||||
// find linker from: /proc/self/maps (API level < 18) or getauxval (API level >= 18)
|
||||
void *handle = xdl_open(XDL_UTIL_LINKER_BASENAME, XDL_DEFAULT);
|
||||
if (NULL == handle) return;
|
||||
|
||||
int api_level = xdl_util_get_api_level();
|
||||
if (__ANDROID_API_L__ == api_level || __ANDROID_API_L_MR1__ == api_level) {
|
||||
// == Android 5.x
|
||||
xdl_linker_mutex = (pthread_mutex_t *)xdl_dsym(handle, XDL_LINKER_SYM_MUTEX, NULL);
|
||||
} else if (__ANDROID_API_N__ == api_level || __ANDROID_API_N_MR1__ == api_level) {
|
||||
// == Android 7.x
|
||||
xdl_linker_dlopen = xdl_dsym(handle, XDL_LINKER_SYM_DLOPEN_EXT_N, NULL);
|
||||
if (NULL == xdl_linker_dlopen) {
|
||||
xdl_linker_dlopen = xdl_dsym(handle, XDL_LINKER_SYM_DO_DLOPEN_N, NULL);
|
||||
xdl_linker_mutex = (pthread_mutex_t *)xdl_dsym(handle, XDL_LINKER_SYM_MUTEX, NULL);
|
||||
}
|
||||
} else if (__ANDROID_API_O__ == api_level || __ANDROID_API_O_MR1__ == api_level) {
|
||||
// == Android 8.x
|
||||
xdl_linker_dlopen = xdl_dsym(handle, XDL_LINKER_SYM_DLOPEN_O, NULL);
|
||||
} else if (api_level >= __ANDROID_API_P__) {
|
||||
// >= Android 9.0
|
||||
xdl_linker_dlopen = xdl_sym(handle, XDL_LINKER_SYM_LOADER_DLOPEN_P, NULL);
|
||||
}
|
||||
|
||||
xdl_close(handle);
|
||||
}
|
||||
|
||||
static void xdl_linker_init_symbols(void) {
|
||||
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool inited = false;
|
||||
if (!inited) {
|
||||
pthread_mutex_lock(&lock);
|
||||
if (!inited) {
|
||||
xdl_linker_init_symbols_impl();
|
||||
inited = true;
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
void xdl_linker_lock(void) {
|
||||
xdl_linker_init_symbols();
|
||||
|
||||
if (NULL != xdl_linker_mutex) pthread_mutex_lock(xdl_linker_mutex);
|
||||
}
|
||||
|
||||
void xdl_linker_unlock(void) {
|
||||
if (NULL != xdl_linker_mutex) pthread_mutex_unlock(xdl_linker_mutex);
|
||||
}
|
||||
|
||||
static void *xdl_linker_get_caller_addr(struct dl_phdr_info *info) {
|
||||
for (size_t i = 0; i < info->dlpi_phnum; i++) {
|
||||
const ElfW(Phdr) *phdr = &(info->dlpi_phdr[i]);
|
||||
if (PT_LOAD == phdr->p_type) {
|
||||
return (void *)(info->dlpi_addr + phdr->p_vaddr);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void xdl_linker_save_caller_addr(struct dl_phdr_info *info, xdl_linker_caller_t *caller,
|
||||
size_t cursor) {
|
||||
void *addr = xdl_linker_get_caller_addr(info);
|
||||
if (NULL != addr) {
|
||||
caller->addr = addr;
|
||||
caller->matches_cursor = cursor;
|
||||
}
|
||||
}
|
||||
|
||||
static int xdl_linker_get_caller_addr_cb(struct dl_phdr_info *info, size_t size, void *arg) {
|
||||
(void)size, (void)arg;
|
||||
if (0 == info->dlpi_addr || NULL == info->dlpi_name) return 0; // continue
|
||||
|
||||
int ret = 1; // OK
|
||||
for (size_t i = 0; i < sizeof(xdl_linker_callers) / sizeof(xdl_linker_callers[0]); i++) {
|
||||
xdl_linker_caller_t *caller = &xdl_linker_callers[i];
|
||||
for (size_t j = 0; j < caller->matches_cursor; j++) {
|
||||
xdl_linker_match_t *match = &caller->matches[j];
|
||||
if (MATCH_PREFIX == match->type) {
|
||||
if (xdl_util_starts_with(info->dlpi_name, match->value)) {
|
||||
xdl_linker_save_caller_addr(info, caller, j);
|
||||
}
|
||||
} else if (MATCH_SUFFIX == match->type) {
|
||||
if (xdl_util_ends_with(info->dlpi_name, match->value)) {
|
||||
xdl_linker_save_caller_addr(info, caller, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NULL == caller->addr || 0 != caller->matches_cursor) ret = 0; // continue
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void xdl_linker_init_caller_addr_impl(void) {
|
||||
xdl_iterate_phdr_impl(xdl_linker_get_caller_addr_cb, NULL, XDL_DEFAULT);
|
||||
}
|
||||
|
||||
static void xdl_linker_init_caller_addr(void) {
|
||||
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool inited = false;
|
||||
if (!inited) {
|
||||
pthread_mutex_lock(&lock);
|
||||
if (!inited) {
|
||||
xdl_linker_init_caller_addr_impl();
|
||||
inited = true;
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
void *xdl_linker_force_dlopen(const char *filename) {
|
||||
int api_level = xdl_util_get_api_level();
|
||||
|
||||
if (api_level <= __ANDROID_API_M__) {
|
||||
// <= Android 6.0
|
||||
return dlopen(filename, RTLD_NOW);
|
||||
} else {
|
||||
xdl_linker_init_symbols();
|
||||
if (NULL == xdl_linker_dlopen) return NULL;
|
||||
xdl_linker_init_caller_addr();
|
||||
|
||||
void *handle = NULL;
|
||||
if (__ANDROID_API_N__ == api_level || __ANDROID_API_N_MR1__ == api_level) {
|
||||
// == Android 7.x
|
||||
xdl_linker_lock();
|
||||
for (size_t i = 0; i < sizeof(xdl_linker_callers) / sizeof(xdl_linker_callers[0]); i++) {
|
||||
xdl_linker_caller_t *caller = &xdl_linker_callers[i];
|
||||
if (NULL != caller->addr) {
|
||||
handle = ((xdl_linker_dlopen_n_t)xdl_linker_dlopen)(filename, RTLD_NOW, NULL, caller->addr);
|
||||
if (NULL != handle) break;
|
||||
}
|
||||
}
|
||||
xdl_linker_unlock();
|
||||
} else {
|
||||
// >= Android 8.0
|
||||
for (size_t i = 0; i < sizeof(xdl_linker_callers) / sizeof(xdl_linker_callers[0]); i++) {
|
||||
xdl_linker_caller_t *caller = &xdl_linker_callers[i];
|
||||
if (NULL != caller->addr) {
|
||||
handle = ((xdl_linker_dlopen_o_t)xdl_linker_dlopen)(filename, RTLD_NOW, caller->addr);
|
||||
if (NULL != handle) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2021-02-21.
|
||||
|
||||
#ifndef IO_GITHUB_HEXHACKING_XDL_LINKER
|
||||
#define IO_GITHUB_HEXHACKING_XDL_LINKER
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void xdl_linker_lock(void);
|
||||
void xdl_linker_unlock(void);
|
||||
|
||||
void *xdl_linker_force_dlopen(const char *filename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,187 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2020-11-08.
|
||||
|
||||
#include "xdl_lzma.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xdl.h"
|
||||
#include "xdl_util.h"
|
||||
|
||||
// LZMA library pathname & symbol names
|
||||
#ifndef __LP64__
|
||||
#define XDL_LZMA_PATHNAME "/system/lib/liblzma.so"
|
||||
#else
|
||||
#define XDL_LZMA_PATHNAME "/system/lib64/liblzma.so"
|
||||
#endif
|
||||
#define XDL_LZMA_SYM_CRCGEN "CrcGenerateTable"
|
||||
#define XDL_LZMA_SYM_CRC64GEN "Crc64GenerateTable"
|
||||
#define XDL_LZMA_SYM_CONSTRUCT "XzUnpacker_Construct"
|
||||
#define XDL_LZMA_SYM_ISFINISHED "XzUnpacker_IsStreamWasFinished"
|
||||
#define XDL_LZMA_SYM_FREE "XzUnpacker_Free"
|
||||
#define XDL_LZMA_SYM_CODE "XzUnpacker_Code"
|
||||
|
||||
// LZMA data type definition
|
||||
#define SZ_OK 0
|
||||
typedef struct ISzAlloc ISzAlloc;
|
||||
typedef const ISzAlloc *ISzAllocPtr;
|
||||
struct ISzAlloc {
|
||||
void *(*Alloc)(ISzAllocPtr p, size_t size);
|
||||
void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
|
||||
};
|
||||
typedef enum {
|
||||
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||
CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||
CODER_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||
CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */
|
||||
} ECoderStatus;
|
||||
typedef enum {
|
||||
CODER_FINISH_ANY, /* finish at any point */
|
||||
CODER_FINISH_END /* block must be finished at the end */
|
||||
} ECoderFinishMode;
|
||||
|
||||
// LZMA function type definition
|
||||
typedef void (*xdl_lzma_crcgen_t)(void);
|
||||
typedef void (*xdl_lzma_crc64gen_t)(void);
|
||||
typedef void (*xdl_lzma_construct_t)(void *, ISzAllocPtr);
|
||||
typedef int (*xdl_lzma_isfinished_t)(const void *);
|
||||
typedef void (*xdl_lzma_free_t)(void *);
|
||||
typedef int (*xdl_lzma_code_t)(void *, uint8_t *, size_t *, const uint8_t *, size_t *, ECoderFinishMode,
|
||||
ECoderStatus *);
|
||||
typedef int (*xdl_lzma_code_q_t)(void *, uint8_t *, size_t *, const uint8_t *, size_t *, int,
|
||||
ECoderFinishMode, ECoderStatus *);
|
||||
|
||||
// LZMA function pointor
|
||||
static xdl_lzma_construct_t xdl_lzma_construct = NULL;
|
||||
static xdl_lzma_isfinished_t xdl_lzma_isfinished = NULL;
|
||||
static xdl_lzma_free_t xdl_lzma_free = NULL;
|
||||
static void *xdl_lzma_code = NULL;
|
||||
|
||||
// LZMA init
|
||||
static void xdl_lzma_init(void) {
|
||||
void *lzma = xdl_open(XDL_LZMA_PATHNAME, XDL_TRY_FORCE_LOAD);
|
||||
if (NULL == lzma) return;
|
||||
|
||||
xdl_lzma_crcgen_t crcgen = NULL;
|
||||
xdl_lzma_crc64gen_t crc64gen = NULL;
|
||||
if (NULL == (crcgen = (xdl_lzma_crcgen_t)xdl_sym(lzma, XDL_LZMA_SYM_CRCGEN, NULL))) goto end;
|
||||
if (NULL == (crc64gen = (xdl_lzma_crc64gen_t)xdl_sym(lzma, XDL_LZMA_SYM_CRC64GEN, NULL))) goto end;
|
||||
if (NULL == (xdl_lzma_construct = (xdl_lzma_construct_t)xdl_sym(lzma, XDL_LZMA_SYM_CONSTRUCT, NULL)))
|
||||
goto end;
|
||||
if (NULL == (xdl_lzma_isfinished = (xdl_lzma_isfinished_t)xdl_sym(lzma, XDL_LZMA_SYM_ISFINISHED, NULL)))
|
||||
goto end;
|
||||
if (NULL == (xdl_lzma_free = (xdl_lzma_free_t)xdl_sym(lzma, XDL_LZMA_SYM_FREE, NULL))) goto end;
|
||||
if (NULL == (xdl_lzma_code = xdl_sym(lzma, XDL_LZMA_SYM_CODE, NULL))) goto end;
|
||||
crcgen();
|
||||
crc64gen();
|
||||
|
||||
end:
|
||||
xdl_close(lzma);
|
||||
}
|
||||
|
||||
// LZMA internal alloc / free
|
||||
static void *xdl_lzma_internal_alloc(ISzAllocPtr p, size_t size) {
|
||||
(void)p;
|
||||
return malloc(size);
|
||||
}
|
||||
static void xdl_lzma_internal_free(ISzAllocPtr p, void *address) {
|
||||
(void)p;
|
||||
free(address);
|
||||
}
|
||||
|
||||
int xdl_lzma_decompress(uint8_t *src, size_t src_size, uint8_t **dst, size_t *dst_size) {
|
||||
size_t src_offset = 0;
|
||||
size_t dst_offset = 0;
|
||||
size_t src_remaining;
|
||||
size_t dst_remaining;
|
||||
ISzAlloc alloc = {.Alloc = xdl_lzma_internal_alloc, .Free = xdl_lzma_internal_free};
|
||||
long long state[4096 / sizeof(long long)]; // must be enough, 8-bit aligned
|
||||
ECoderStatus status;
|
||||
int api_level = xdl_util_get_api_level();
|
||||
|
||||
// init and check
|
||||
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool inited = false;
|
||||
if (!inited) {
|
||||
pthread_mutex_lock(&lock);
|
||||
if (!inited) {
|
||||
xdl_lzma_init();
|
||||
inited = true;
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
if (NULL == xdl_lzma_code) return -1;
|
||||
|
||||
xdl_lzma_construct(&state, &alloc);
|
||||
|
||||
*dst_size = 2 * src_size;
|
||||
*dst = NULL;
|
||||
do {
|
||||
*dst_size *= 2;
|
||||
if (NULL == (*dst = realloc(*dst, *dst_size))) {
|
||||
xdl_lzma_free(&state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
src_remaining = src_size - src_offset;
|
||||
dst_remaining = *dst_size - dst_offset;
|
||||
|
||||
int result;
|
||||
if (api_level >= __ANDROID_API_Q__) {
|
||||
xdl_lzma_code_q_t lzma_code_q = (xdl_lzma_code_q_t)xdl_lzma_code;
|
||||
result = lzma_code_q(&state, *dst + dst_offset, &dst_remaining, src + src_offset, &src_remaining, 1,
|
||||
CODER_FINISH_ANY, &status);
|
||||
} else {
|
||||
xdl_lzma_code_t lzma_code = (xdl_lzma_code_t)xdl_lzma_code;
|
||||
result = lzma_code(&state, *dst + dst_offset, &dst_remaining, src + src_offset, &src_remaining,
|
||||
CODER_FINISH_ANY, &status);
|
||||
}
|
||||
if (SZ_OK != result) {
|
||||
free(*dst);
|
||||
xdl_lzma_free(&state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
src_offset += src_remaining;
|
||||
dst_offset += dst_remaining;
|
||||
} while (status == CODER_STATUS_NOT_FINISHED);
|
||||
|
||||
xdl_lzma_free(&state);
|
||||
|
||||
if (!xdl_lzma_isfinished(&state)) {
|
||||
free(*dst);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*dst_size = dst_offset;
|
||||
*dst = realloc(*dst, *dst_size);
|
||||
return 0;
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2020-11-08.
|
||||
|
||||
#ifndef IO_GITHUB_HEXHACKING_XDL_LZMA
|
||||
#define IO_GITHUB_HEXHACKING_XDL_LZMA
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int xdl_lzma_decompress(uint8_t *src, size_t src_size, uint8_t **dst, size_t *dst_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,95 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2020-10-04.
|
||||
|
||||
#include "xdl_util.h"
|
||||
|
||||
#include <android/api-level.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
bool xdl_util_starts_with(const char *str, const char *start) {
|
||||
while (*str && *str == *start) {
|
||||
str++;
|
||||
start++;
|
||||
}
|
||||
|
||||
return '\0' == *start;
|
||||
}
|
||||
|
||||
bool xdl_util_ends_with(const char *str, const char *ending) {
|
||||
size_t str_len = strlen(str);
|
||||
size_t ending_len = strlen(ending);
|
||||
|
||||
if (ending_len > str_len) return false;
|
||||
|
||||
return 0 == strcmp(str + (str_len - ending_len), ending);
|
||||
}
|
||||
|
||||
size_t xdl_util_trim_ending(char *start) {
|
||||
char *end = start + strlen(start);
|
||||
while (start < end && isspace((int)(*(end - 1)))) {
|
||||
end--;
|
||||
*end = '\0';
|
||||
}
|
||||
return (size_t)(end - start);
|
||||
}
|
||||
|
||||
static int xdl_util_get_api_level_from_build_prop(void) {
|
||||
char buf[128];
|
||||
int api_level = -1;
|
||||
|
||||
FILE *fp = fopen("/system/build.prop", "r");
|
||||
if (NULL == fp) goto end;
|
||||
|
||||
while (fgets(buf, sizeof(buf), fp)) {
|
||||
if (xdl_util_starts_with(buf, "ro.build.version.sdk=")) {
|
||||
api_level = atoi(buf + 21);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
end:
|
||||
return (api_level > 0) ? api_level : -1;
|
||||
}
|
||||
|
||||
int xdl_util_get_api_level(void) {
|
||||
static int xdl_util_api_level = -1;
|
||||
|
||||
if (xdl_util_api_level < 0) {
|
||||
int api_level = android_get_device_api_level();
|
||||
if (api_level < 0)
|
||||
api_level = xdl_util_get_api_level_from_build_prop(); // compatible with unusual models
|
||||
if (api_level < __ANDROID_API_J__) api_level = __ANDROID_API_J__;
|
||||
|
||||
__atomic_store_n(&xdl_util_api_level, api_level, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
return xdl_util_api_level;
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
// Copyright (c) 2020-2024 HexHacking Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
// Created by caikelun on 2020-10-04.
|
||||
|
||||
#ifndef IO_GITHUB_HEXHACKING_XDL_UTIL
|
||||
#define IO_GITHUB_HEXHACKING_XDL_UTIL
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef __LP64__
|
||||
#define XDL_UTIL_LINKER_BASENAME "linker"
|
||||
#define XDL_UTIL_LINKER_PATHNAME "/system/bin/linker"
|
||||
#define XDL_UTIL_APP_PROCESS_BASENAME "app_process32"
|
||||
#define XDL_UTIL_APP_PROCESS_PATHNAME "/system/bin/app_process32"
|
||||
#define XDL_UTIL_APP_PROCESS_BASENAME_K "app_process"
|
||||
#define XDL_UTIL_APP_PROCESS_PATHNAME_K "/system/bin/app_process"
|
||||
#else
|
||||
#define XDL_UTIL_LINKER_BASENAME "linker64"
|
||||
#define XDL_UTIL_LINKER_PATHNAME "/system/bin/linker64"
|
||||
#define XDL_UTIL_APP_PROCESS_BASENAME "app_process64"
|
||||
#define XDL_UTIL_APP_PROCESS_PATHNAME "/system/bin/app_process64"
|
||||
#endif
|
||||
#define XDL_UTIL_VDSO_BASENAME "[vdso]"
|
||||
|
||||
#define XDL_UTIL_TEMP_FAILURE_RETRY(exp) \
|
||||
({ \
|
||||
__typeof__(exp) _rc; \
|
||||
do { \
|
||||
errno = 0; \
|
||||
_rc = (exp); \
|
||||
} while (_rc == -1 && errno == EINTR); \
|
||||
_rc; \
|
||||
})
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool xdl_util_starts_with(const char *str, const char *start);
|
||||
bool xdl_util_ends_with(const char *str, const char *ending);
|
||||
|
||||
size_t xdl_util_trim_ending(char *start);
|
||||
|
||||
int xdl_util_get_api_level(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -6,12 +6,12 @@
|
||||
#include <cerrno>
|
||||
#include <filesystem>
|
||||
#include <sys/stat.h>
|
||||
#include "xdl.h"
|
||||
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF", __VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "PIF", __VA_ARGS__)
|
||||
|
||||
#define DEX_PATH "/data/adb/modules/playintegrityfix/classes.jar"
|
||||
#define TS_PATH "/data/adb/modules/tricky_store"
|
||||
|
||||
#define DEX_PATH "/data/adb/modules/playintegrityfix/classes.dex"
|
||||
|
||||
#define LIB_64 "/data/adb/modules/playintegrityfix/inject/arm64-v8a.so"
|
||||
#define LIB_32 "/data/adb/modules/playintegrityfix/inject/armeabi-v7a.so"
|
||||
@ -61,17 +61,37 @@ static bool copyFile(const std::string &from, const std::string &to, mode_t perm
|
||||
);
|
||||
}
|
||||
|
||||
static bool checkOtaZip() {
|
||||
std::array<char, 256> buffer{};
|
||||
std::string result;
|
||||
bool found = false;
|
||||
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(
|
||||
popen("unzip -l /system/etc/security/otacerts.zip", "r"), pclose);
|
||||
if (!pipe) return false;
|
||||
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
if (result.find("testkey") != std::string::npos) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static void companion(int fd) {
|
||||
bool ok = true;
|
||||
|
||||
int length = 0;
|
||||
xread(fd, &length, sizeof(int));
|
||||
int size = 0;
|
||||
xread(fd, &size, sizeof(int));
|
||||
|
||||
std::string dir;
|
||||
dir.resize(length + 1);
|
||||
auto bytes = xread(fd, dir.data(), length);
|
||||
dir.resize(size);
|
||||
auto bytes = xread(fd, dir.data(), size);
|
||||
dir.resize(bytes);
|
||||
dir[bytes - 1] = '\0';
|
||||
dir.shrink_to_fit();
|
||||
|
||||
LOGD("[COMPANION] GMS dir: %s", dir.c_str());
|
||||
|
||||
@ -84,7 +104,7 @@ static void companion(int fd) {
|
||||
|
||||
LOGD("[COMPANION] copied inject lib");
|
||||
|
||||
auto dexFile = dir + "/classes.jar";
|
||||
auto dexFile = dir + "/classes.dex";
|
||||
ok &= copyFile(DEX_PATH, dexFile, 0644);
|
||||
|
||||
LOGD("[COMPANION] copied dex");
|
||||
@ -100,6 +120,15 @@ static void companion(int fd) {
|
||||
|
||||
LOGD("[COMPANION] copied json");
|
||||
|
||||
std::string ts(TS_PATH);
|
||||
bool trickyStore = std::filesystem::exists(ts) &&
|
||||
!std::filesystem::exists(ts + "/disable") &&
|
||||
!std::filesystem::exists(ts + "/remove");
|
||||
xwrite(fd, &trickyStore, sizeof(bool));
|
||||
|
||||
bool testSignedRom = checkOtaZip();
|
||||
xwrite(fd, &testSignedRom, sizeof(bool));
|
||||
|
||||
xwrite(fd, &ok, sizeof(bool));
|
||||
}
|
||||
|
||||
@ -146,11 +175,15 @@ public:
|
||||
|
||||
auto fd = api->connectCompanion();
|
||||
|
||||
int size = static_cast<int>(dir.length());
|
||||
int size = static_cast<int>(dir.size());
|
||||
xwrite(fd, &size, sizeof(int));
|
||||
|
||||
xwrite(fd, dir.data(), size);
|
||||
|
||||
xread(fd, &trickyStore, sizeof(bool));
|
||||
|
||||
xread(fd, &testSignedRom, sizeof(bool));
|
||||
|
||||
bool ok = false;
|
||||
xread(fd, &ok, sizeof(bool));
|
||||
|
||||
@ -164,17 +197,22 @@ public:
|
||||
if (gmsDir.empty())
|
||||
return;
|
||||
|
||||
typedef bool (*InitFuncPtr)(JavaVM *, const std::string &);
|
||||
typedef bool (*InitFuncPtr)(JavaVM *, const std::string &, bool, bool);
|
||||
|
||||
auto handle = xdl_open((gmsDir + "/libinject.so").c_str(), XDL_DEFAULT);
|
||||
auto init_func = reinterpret_cast<InitFuncPtr>(xdl_sym(handle, "init", nullptr));
|
||||
void *handle = dlopen((gmsDir + "/libinject.so").c_str(), RTLD_NOW);
|
||||
|
||||
if (!handle)
|
||||
return;
|
||||
|
||||
auto init_func = reinterpret_cast<InitFuncPtr>(dlsym(handle, "init"));
|
||||
|
||||
JavaVM *vm = nullptr;
|
||||
env->GetJavaVM(&vm);
|
||||
|
||||
init_func(vm, gmsDir);
|
||||
|
||||
xdl_close(handle);
|
||||
if (init_func(vm, gmsDir, trickyStore, testSignedRom)) {
|
||||
LOGD("dlclose injected lib");
|
||||
dlclose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
void preServerSpecialize(ServerSpecializeArgs *args) override {
|
||||
@ -185,6 +223,8 @@ private:
|
||||
Api *api = nullptr;
|
||||
JNIEnv *env = nullptr;
|
||||
std::string gmsDir;
|
||||
bool trickyStore = false;
|
||||
bool testSignedRom = false;
|
||||
};
|
||||
|
||||
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
||||
|
Loading…
Reference in New Issue
Block a user