From ecb3cea5a5b7b17bcc0bff386a45dc4ecb0d213d Mon Sep 17 00:00:00 2001 From: WhiteChi Date: Wed, 29 Nov 2023 10:11:24 +0800 Subject: [PATCH] `Shamrock`: fix #105 --- .../shamrock/ui/fragment/LabFragment.kt | 4 + .../cpp/anti_detection/anti_detection.cpp | 74 --------------- .../main/cpp/anti_detection/anti_detection.h | 10 +- xposed/src/main/cpp/clover.cpp | 91 ++++++++++++++++++- xposed/src/main/cpp/helper/jnihelper.cpp | 18 ++-- xposed/src/main/cpp/helper/jnihelper.h | 8 +- .../shamrock/xposed/loader/NativeLoader.kt | 7 +- 7 files changed, 113 insertions(+), 99 deletions(-) diff --git a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt index 80bf426..d072baf 100644 --- a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt +++ b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt @@ -192,7 +192,11 @@ fun LabFragment() { descColor = it, isSwitch = AppRuntime.state.supportVoice.value ) { + if(AppRuntime.state.supportVoice.value) { + scope.toast(ctx, "关闭请手动删除文件。") + } else { scope.toast(ctx, "请按照Github提示手动操作。") + } return@Function false } } diff --git a/xposed/src/main/cpp/anti_detection/anti_detection.cpp b/xposed/src/main/cpp/anti_detection/anti_detection.cpp index 21fc76e..0a9bc77 100644 --- a/xposed/src/main/cpp/anti_detection/anti_detection.cpp +++ b/xposed/src/main/cpp/anti_detection/anti_detection.cpp @@ -1,80 +1,6 @@ #include "anti_detection.h" -int (*backup_system_property_get)(const char *name, char *value); -FILE* (*backup_fopen)(const char *filename, const char *mode); -int fake_system_property_get(const char *name, char *value) { - for (auto &prop: qemu_detect_props) { - if (strstr(name, prop.c_str())) { - LOGI("[Shamrock] bypass qemu detection"); - value[0] = 0; - return 0; - } - } - if (strstr(name, "ro.debuggable") - || strstr(name, "ro.kernel.qemu.gles") - || strstr(name, "debug.atrace.tags.enableflags")) { - strcpy(value, "0"); - return 1; - } - if (strstr(name, "ro.product.cpu.abilist")) { - int len = backup_system_property_get(name, value); - if (len > 0) { - if (strstr(value, "x86")) { - strcpy(value, "arm64-v8a,armeabi-v7a,armeabi"); - return 29; - } - } - return len; - } - if (strstr(name, "ro.hardware")) { - int len = backup_system_property_get(name, value); - if (len > 0) { - if (strstr(value, "generic") - || strstr(value, "unknown") - || strstr(value, "emulator") - || strstr(value, "vbox") - || strstr(value, "genymotion") - || strstr(value, "goldfish")) { - strcpy(value, "qcom"); - return 4; - } - } - return len; - } - - //LOGI("[Shamrock] fake_system_property_get(%s)", name); - return backup_system_property_get(name, value); -} - -FILE* fake_fopen(const char *filename, const char *mode) { - if (strstr(filename, "qemu_pipe")) { - LOGI("[Shamrock] bypass qemu detection"); - return nullptr; - } - - if (strstr(filename, "libhoudini.so")) { - LOGI("[Shamrock] bypass emu detection"); - return nullptr; - } - - return backup_fopen(filename, mode); -} - -void on_library_loaded(const char *name, void *handle) { - -} - -extern "C" [[gnu::visibility("default")]] [[gnu::used]] -NativeOnModuleLoaded native_init(const NativeAPIEntries *entries) { - hook_function = entries->hook_func; - LOGI("[Shamrock] LSPosed NativeModule Init: %p", hook_function); - - hook_function((void*) __system_property_get, (void *)fake_system_property_get, (void **) &backup_system_property_get); - hook_function((void*) fopen, (void*) fake_fopen, (void**) &backup_fopen); - - return on_library_loaded; -} diff --git a/xposed/src/main/cpp/anti_detection/anti_detection.h b/xposed/src/main/cpp/anti_detection/anti_detection.h index ccbb9d7..b915af4 100644 --- a/xposed/src/main/cpp/anti_detection/anti_detection.h +++ b/xposed/src/main/cpp/anti_detection/anti_detection.h @@ -7,12 +7,18 @@ #include "lsposed.h" #include "jnihelper.h" -static HookFunType hook_function = nullptr; - static std::vector qemu_detect_props = { "init.svc.qemu-props", "qemu.hw.mainkeys", "qemu.sf.fake_camera", "ro.kernel.android.qemud", "qemu.sf.lcd_density", "init.svc.qemud", "ro.kernel.qemu", "libc.debug.malloc" }; +static int (*backup_system_property_get)(const char *name, char *value); +static FILE* (*backup_fopen)(const char *filename, const char *mode); + +//int fake_system_property_get(const char *name, char *value); +//FILE* fake_fopen(const char *filename, const char *mode); + +//void on_library_loaded(const char *name, void *handle); + #endif //SHAMROCK_ANTI_DETECTION_H diff --git a/xposed/src/main/cpp/clover.cpp b/xposed/src/main/cpp/clover.cpp index b0e0113..e4d0516 100644 --- a/xposed/src/main/cpp/clover.cpp +++ b/xposed/src/main/cpp/clover.cpp @@ -3,17 +3,20 @@ #include "helper/lsposed.h" #include "jnihelper.h" +static JavaVM *global_jvm = nullptr; +static HookFunType hook_function = nullptr; + extern "C" [[gnu::visibility("default")]] [[gnu::used]] jint JNI_OnLoad(JavaVM *jvm, void*) { - JNIHelper::initJavaVM(jvm); + global_jvm = jvm; int attach = 0; - JNIEnv *env = JNIHelper::getJNIEnv(&attach); + JNIEnv *env = JNIHelper::getJNIEnv(jvm, &attach); // do something LOGI("[Shamrock] JNI_OnLoad NativeModule Init: %p", env); if (attach == 1) { - JNIHelper::delJNIEnv(); + JNIHelper::delJNIEnv(jvm); } //hook_function((void *)env->functions->FindClass, (void *)fake_FindClass, (void **)&backup_FindClass); @@ -23,11 +26,89 @@ jint JNI_OnLoad(JavaVM *jvm, void*) { extern "C" JNIEXPORT jboolean JNICALL Java_moe_fuqiuluo_shamrock_xposed_XposedEntry_00024Companion_injected(JNIEnv *env, jobject thiz) { + LOGI("[Shamrock] injected: %p", hook_function); return hook_function != nullptr; } extern "C" JNIEXPORT jboolean JNICALL Java_moe_fuqiuluo_shamrock_xposed_XposedEntry_00024Companion_hasEnv(JNIEnv *env, jobject thiz) { - return JNIHelper::global_jvm != nullptr; -} \ No newline at end of file + LOGI("[Shamrock] hasEnv: %p", global_jvm); + return global_jvm != nullptr; +} + +int fake_system_property_get(const char *name, char *value) { + for (auto &prop: qemu_detect_props) { + if (strstr(name, prop.c_str())) { + LOGI("[Shamrock] bypass qemu detection"); + value[0] = 0; + return 0; + } + } + + if (strstr(name, "ro.debuggable") + || strstr(name, "ro.kernel.qemu.gles") + || strstr(name, "debug.atrace.tags.enableflags")) { + strcpy(value, "0"); + return 1; + } + + if (strstr(name, "ro.product.cpu.abilist")) { + int len = backup_system_property_get(name, value); + if (len > 0) { + if (strstr(value, "x86")) { + strcpy(value, "arm64-v8a,armeabi-v7a,armeabi"); + return 29; + } + } + return len; + } + + if (strstr(name, "ro.hardware")) { + int len = backup_system_property_get(name, value); + if (len > 0) { + if (strstr(value, "generic") + || strstr(value, "unknown") + || strstr(value, "emulator") + || strstr(value, "vbox") + || strstr(value, "genymotion") + || strstr(value, "goldfish")) { + strcpy(value, "qcom"); + return 4; + } + } + return len; + } + + //LOGI("[Shamrock] fake_system_property_get(%s)", name); + return backup_system_property_get(name, value); +} + +FILE* fake_fopen(const char *filename, const char *mode) { + if (strstr(filename, "qemu_pipe")) { + LOGI("[Shamrock] bypass qemu detection"); + return nullptr; + } + + if (strstr(filename, "libhoudini.so")) { + LOGI("[Shamrock] bypass emu detection"); + return nullptr; + } + + return backup_fopen(filename, mode); +} + +void on_library_loaded(const char *name, void *handle) { + +} + +extern "C" [[gnu::visibility("default")]] [[gnu::used]] +NativeOnModuleLoaded native_init(const NativeAPIEntries *entries) { + hook_function = entries->hook_func; + LOGI("[Shamrock] LSPosed NativeModule Init: %p", hook_function); + + hook_function((void*) __system_property_get, (void *)fake_system_property_get, (void **) &backup_system_property_get); + hook_function((void*) fopen, (void*) fake_fopen, (void**) &backup_fopen); + + return on_library_loaded; +} diff --git a/xposed/src/main/cpp/helper/jnihelper.cpp b/xposed/src/main/cpp/helper/jnihelper.cpp index 246132f..0ffe881 100644 --- a/xposed/src/main/cpp/helper/jnihelper.cpp +++ b/xposed/src/main/cpp/helper/jnihelper.cpp @@ -1,19 +1,15 @@ #include "jnihelper.h" -void JNIHelper::initJavaVM(JavaVM *jvm) { - global_jvm = jvm; -} - -JNIEnv *JNIHelper::getJNIEnv(int *attach) { - if (global_jvm == NULL) return NULL; +JNIEnv *JNIHelper::getJNIEnv(JavaVM * jvm, int *attach) { + if (jvm == NULL) return NULL; *attach = 0; JNIEnv *jni_env = NULL; - int status = global_jvm->GetEnv((void **)&jni_env, JNI_VERSION_1_6); + int status = jvm->GetEnv((void **)&jni_env, JNI_VERSION_1_6); if (status == JNI_EDETACHED || jni_env == NULL) { - status = global_jvm->AttachCurrentThread(&jni_env, NULL); + status = jvm->AttachCurrentThread(&jni_env, NULL); if (status < 0) { jni_env = NULL; } else { @@ -23,8 +19,8 @@ JNIEnv *JNIHelper::getJNIEnv(int *attach) { return jni_env; } -jint JNIHelper::delJNIEnv() { - if (global_jvm == nullptr) return 0; - return global_jvm->DetachCurrentThread(); +jint JNIHelper::delJNIEnv(JavaVM * jvm) { + if (jvm == nullptr) return 0; + return jvm->DetachCurrentThread(); } diff --git a/xposed/src/main/cpp/helper/jnihelper.h b/xposed/src/main/cpp/helper/jnihelper.h index 122b825..b92e62b 100644 --- a/xposed/src/main/cpp/helper/jnihelper.h +++ b/xposed/src/main/cpp/helper/jnihelper.h @@ -5,13 +5,9 @@ #include "android/log.h" namespace JNIHelper { - static JavaVM *global_jvm = nullptr; + JNIEnv *getJNIEnv(JavaVM * jvm, int *attach); - void initJavaVM(JavaVM *jvm); - - JNIEnv *getJNIEnv(int *attach); - - jint delJNIEnv(); + jint delJNIEnv(JavaVM * jvm); } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/NativeLoader.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/NativeLoader.kt index babb63f..b4fe925 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/NativeLoader.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/NativeLoader.kt @@ -29,7 +29,12 @@ internal object NativeLoader { val applicationInfo = packageManager.getApplicationInfo("moe.fuqiuluo.shamrock.hided", 0) val file = File(applicationInfo.nativeLibraryDir) LogCenter.log("LoadLibrary(name = $name)") - System.load(file.resolve("lib$name.so").absolutePath) + System.load(file.resolve("lib$name.so").also { + if (!it.exists()) { + LogCenter.log("LoadLibrary(name = $name) failed, file not exists.", level = Level.ERROR) + return + } + }.absolutePath) } else { val sourceFile = externalLibPath.resolve("lib$name.so") val soFile = MobileQQ.getContext().filesDir.parentFile!!.resolve("txlib").resolve("lib$name.so")