mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 01:35:17 +08:00
Modify change third party "me.weishu.reflection" and YukiHookModuleStatus to be automatically generated and fix some problem in automatic generation
This commit is contained in:
@@ -263,6 +263,12 @@ class YukiHookXposedProcessor : SymbolProcessorProvider {
|
||||
packageName = PackageName.YukiHookBridge_Impl,
|
||||
content = data.sources()[ClassName.YukiHookBridge_Impl]
|
||||
)
|
||||
/** 插入 YukiHookModuleStatus_Impl 代码 */
|
||||
createCodeFile(
|
||||
fileName = ClassName.YukiHookModuleStatus_Impl,
|
||||
packageName = PackageName.YukiHookModuleStatus_Impl,
|
||||
content = data.sources()[ClassName.YukiHookModuleStatus_Impl]
|
||||
)
|
||||
/** 插入 xposed_init 代码 */
|
||||
createCodeFile(
|
||||
fileName = data.xInitClassName,
|
||||
@@ -275,6 +281,20 @@ class YukiHookXposedProcessor : SymbolProcessorProvider {
|
||||
packageName = data.entryPackageName,
|
||||
content = data.sources()[ClassName.XposedInit_Impl]
|
||||
)
|
||||
/* 插入 FreeReflection 代码 */
|
||||
createCodeFile(
|
||||
fileName = ClassName.BootstrapClass,
|
||||
packageName = PackageName.BootstrapReflectionClass,
|
||||
content = data.sources()[ClassName.BootstrapClass],
|
||||
extensionName = JAVA_FILE_EXT_NAME
|
||||
)
|
||||
/* 插入 FreeReflection 代码 */
|
||||
createCodeFile(
|
||||
fileName = ClassName.Reflection,
|
||||
packageName = PackageName.BootstrapReflectionClass,
|
||||
content = data.sources()[ClassName.Reflection],
|
||||
extensionName = JAVA_FILE_EXT_NAME
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -37,6 +37,8 @@ import java.util.*
|
||||
object PackageName {
|
||||
const val ModuleApplication_Impl = "com.highcapable.yukihookapi.hook.xposed.application"
|
||||
const val YukiHookBridge_Impl = "com.highcapable.yukihookapi.hook.xposed.bridge"
|
||||
const val YukiHookModuleStatus_Impl = "com.highcapable.yukihookapi.hook.xposed.bridge.status"
|
||||
const val BootstrapReflectionClass = "com.highcapable.yukihookapi.thirdparty.me.weishu.reflection"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,8 +47,21 @@ object PackageName {
|
||||
object ClassName {
|
||||
const val ModuleApplication_Impl = "ModuleApplication_Impl"
|
||||
const val YukiHookBridge_Impl = "YukiHookBridge_Impl"
|
||||
const val YukiHookModuleStatus_Impl = "YukiHookModuleStatus_Impl"
|
||||
const val XposedInit = "xposed_init"
|
||||
const val XposedInit_Impl = "xposed_init_Impl"
|
||||
const val BootstrapClass = "BootstrapClass"
|
||||
const val Reflection = "Reflection"
|
||||
}
|
||||
|
||||
/**
|
||||
* YukiHookModuleStatus 方法名称定义类
|
||||
*/
|
||||
object YukiHookModuleStatusJvmName {
|
||||
const val IS_ACTIVE_METHOD_NAME = "__--"
|
||||
const val HAS_RESOURCES_HOOK_METHOD_NAME = "_--_"
|
||||
const val GET_XPOSED_VERSION_METHOD_NAME = "--__"
|
||||
const val GET_XPOSED_TAG_METHOD_NAME = "_-_-"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +79,7 @@ private fun createCommentContent(entryClassName: String = "", currrentClassTag:
|
||||
(if (entryClassName.isNotBlank()) " * HookEntryClass: [$entryClassName]\n *\n" else "") +
|
||||
" * Generate Date: ${SimpleDateFormat.getDateTimeInstance().format(Date())}\n" +
|
||||
" *\n" +
|
||||
" * Powered by YukiHookAPI (C) HighCapable 2022\n" +
|
||||
" * Powered by YukiHookAPI (C) HighCapable 2019-2022\n" +
|
||||
" *\n" +
|
||||
" * Project Address: [YukiHookAPI](https://github.com/fankes/YukiHookAPI)\n" +
|
||||
" */\n")
|
||||
@@ -97,6 +112,28 @@ fun GenerateData.sources() = mapOf(
|
||||
"\n" +
|
||||
" val compiledTimestamp get() = ${System.currentTimeMillis()}\n" +
|
||||
"}"),
|
||||
ClassName.YukiHookModuleStatus_Impl to ("@file:Suppress(\"ClassName\")\n" +
|
||||
"\n" +
|
||||
"package com.highcapable.yukihookapi.hook.xposed.bridge.status\n" +
|
||||
"\n" +
|
||||
"import androidx.annotation.Keep\n" +
|
||||
"\n" +
|
||||
createCommentContent(currrentClassTag = ClassName.YukiHookModuleStatus_Impl) +
|
||||
"@Keep\n" +
|
||||
"object YukiHookModuleStatus_Impl {\n" +
|
||||
"\n" +
|
||||
" @JvmName(\"${YukiHookModuleStatusJvmName.IS_ACTIVE_METHOD_NAME}\")\n" +
|
||||
" fun isActive() = false\n" +
|
||||
"\n" +
|
||||
" @JvmName(\"${YukiHookModuleStatusJvmName.HAS_RESOURCES_HOOK_METHOD_NAME}\")\n" +
|
||||
" fun hasResourcesHook() = false\n" +
|
||||
"\n" +
|
||||
" @JvmName(\"${YukiHookModuleStatusJvmName.GET_XPOSED_VERSION_METHOD_NAME}\")\n" +
|
||||
" fun getXposedVersion() = -1\n" +
|
||||
"\n" +
|
||||
" @JvmName(\"${YukiHookModuleStatusJvmName.GET_XPOSED_TAG_METHOD_NAME}\")\n" +
|
||||
" fun getXposedBridgeTag() = \"unknown\"\n" +
|
||||
"}"),
|
||||
ClassName.XposedInit to ("@file:Suppress(\"ClassName\")\n" +
|
||||
"\n" +
|
||||
"package $entryPackageName\n" +
|
||||
@@ -192,5 +229,149 @@ fun GenerateData.sources() = mapOf(
|
||||
" fun callHandleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {\n" +
|
||||
" if (resparam != null) callXposedLoaded(resparam = resparam)\n" +
|
||||
" }\n" +
|
||||
"}"),
|
||||
ClassName.BootstrapClass to ("package ${PackageName.BootstrapReflectionClass};\n" +
|
||||
"\n" +
|
||||
"import static android.os.Build.VERSION.SDK_INT;\n" +
|
||||
"\n" +
|
||||
"import android.os.Build;\n" +
|
||||
"import android.util.Log;\n" +
|
||||
"\n" +
|
||||
"import androidx.annotation.Keep;\n" +
|
||||
"\n" +
|
||||
"import java.lang.reflect.Method;\n" +
|
||||
"\n" +
|
||||
createCommentContent(currrentClassTag = ClassName.BootstrapClass) +
|
||||
"@Keep\n" +
|
||||
"public final class BootstrapClass {\n" +
|
||||
"\n" +
|
||||
" private static final String TAG = \"BootstrapClass\";\n" +
|
||||
"\n" +
|
||||
" private static Object sVmRuntime;\n" +
|
||||
" private static Method setHiddenApiExemptions;\n" +
|
||||
"\n" +
|
||||
" static {\n" +
|
||||
" if (SDK_INT >= Build.VERSION_CODES.P) {\n" +
|
||||
" try {\n" +
|
||||
" Method forName = Class.class.getDeclaredMethod(\"forName\", String.class);\n" +
|
||||
" Method getDeclaredMethod = Class.class.getDeclaredMethod(\"getDeclaredMethod\", String.class, Class[].class);\n" +
|
||||
" Class<?> vmRuntimeClass = (Class<?>) forName.invoke(null, \"dalvik.system.VMRuntime\");\n" +
|
||||
" Method getRuntime = (Method) getDeclaredMethod.invoke(vmRuntimeClass, \"getRuntime\", null);\n" +
|
||||
" setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(vmRuntimeClass, \"setHiddenApiExemptions\", new Class[]{String[].class});\n" +
|
||||
" sVmRuntime = getRuntime.invoke(null);\n" +
|
||||
" } catch (Throwable e) {\n" +
|
||||
" Log.w(TAG, \"reflect bootstrap failed:\", e);\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public static boolean exempt(String method) {\n" +
|
||||
" return exempt(new String[]{method});\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public static boolean exempt(String... methods) {\n" +
|
||||
" if (sVmRuntime == null || setHiddenApiExemptions == null) {\n" +
|
||||
" return false;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" try {\n" +
|
||||
" setHiddenApiExemptions.invoke(sVmRuntime, new Object[]{methods});\n" +
|
||||
" return true;\n" +
|
||||
" } catch (Throwable e) {\n" +
|
||||
" return false;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" public static boolean exemptAll() {\n" +
|
||||
" return exempt(new String[]{\"L\"});\n" +
|
||||
" }\n" +
|
||||
"}"),
|
||||
ClassName.Reflection to ("package ${PackageName.BootstrapReflectionClass};\n" +
|
||||
"\n" +
|
||||
"import static android.os.Build.VERSION.SDK_INT;\n" +
|
||||
"import static com.highcapable.yukihookapi.thirdparty.me.weishu.reflection.BootstrapClass.exemptAll;\n" +
|
||||
"\n" +
|
||||
"import android.content.Context;\n" +
|
||||
"import android.text.TextUtils;\n" +
|
||||
"import android.util.Base64;\n" +
|
||||
"\n" +
|
||||
"import androidx.annotation.Keep;\n" +
|
||||
"\n" +
|
||||
"import java.io.File;\n" +
|
||||
"import java.io.FileOutputStream;\n" +
|
||||
"import java.lang.reflect.Method;\n" +
|
||||
"\n" +
|
||||
"import dalvik.system.DexFile;\n" +
|
||||
"\n" +
|
||||
createCommentContent(currrentClassTag = ClassName.Reflection) +
|
||||
"@Keep\n" +
|
||||
"public class Reflection {\n" +
|
||||
" private static final String TAG = \"Reflection\";\n" +
|
||||
"\n" +
|
||||
" private static final String DEX = \"ZGV4CjAzNQCXDT0vQ44GJqsrjm32y0qlQmxUevbk56r0CwAAcAAAAHhWNBIAAAAAAAAAADwLAABDAAAAcAAAABMAAAB8AQAACwAAAMgBAAAMAAAATAIAAA8AAACsAgAAAwAAACQDAABwCAAAhAMAAIQDAACGAwAAiwMAAJUDAACdAwAArQMAALkDAADJAwAA3gMAAPADAAD3AwAA/wMAAAIEAAAGBAAACgQAABAEAAATBAAAGAQAADMEAABZBAAAdQQAAIkEAADYBAAAJgUAAHAFAACDBQAAmQUAAK0FAADBBQAA1QUAAOwFAAAIBgAAFAYAACUGAAAuBgAAMwYAADYGAABEBgAAUgYAAFYGAABZBgAAXQYAAHEGAACGBgAAmwYAAKQGAAC9BgAAwAYAAMgGAADTBgAA3AYAAO0GAAABBwAAFAcAACAHAAAoBwAANQcAAE8HAABXBwAAYAcAAHsHAACEBwAAkAcAAKgHAAC6BwAAwgcAANAHAAALAAAAEQAAABIAAAATAAAAFAAAABUAAAAWAAAAFwAAABgAAAAaAAAAGwAAABwAAAAdAAAAHgAAACMAAAAnAAAAKQAAACoAAAArAAAADAAAAAAAAAD4BwAADQAAAAAAAAAMCAAADgAAAAAAAAAACAAADwAAAAIAAAAAAAAAEAAAAAkAAAAUCAAAEAAAAA0AAADoBwAAIwAAAA4AAAAAAAAAJgAAAA4AAADgBwAAJwAAAA8AAAAAAAAAKAAAAA8AAADgBwAAKAAAAA8AAADwBwAAAgAAAD8AAAADAAAAIQAAAAUACgAEAAAABQAKAAUAAAAFAA8ACQAAAAUACgAKAAAABQAAACQAAAAFAAoAJQAAAAYACgAiAAAABgAJAD0AAAAGAA0APgAAAAcACgAiAAAAAQADADMAAAAEAAIALgAAAAUABgADAAAABgAGAAIAAAAGAAYAAwAAAAYACQAvAAAABgAKAC8AAAAGAAgAMAAAAAcABgADAAAABwABAEAAAAAHAAAAQQAAAAgABQA0AAAACQAGAAMAAAALAAcANwAAAA0ABAA2AAAABQAAABEAAAAJAAAAAAAAAAgAAAAAAAAA7AoAAB8IAAAGAAAAEQAAAAkAAAAAAAAABwAAAAAAAAACCwAAHAgAAAcAAAABAAAACQAAAAAAAAAgAAAAAAAAACULAAArCAAAAAADMS4wAAg8Y2xpbml0PgAGPGluaXQ+AA5BUFBMSUNBVElPTl9JRAAKQlVJTERfVFlQRQAOQm9vdHN0cmFwQ2xhc3MAE0Jvb3RzdHJhcENsYXNzLmphdmEAEEJ1aWxkQ29uZmlnLmphdmEABURFQlVHAAZGTEFWT1IAAUkAAklJAAJJTAAESUxMTAABTAADTExMABlMYW5kcm9pZC9jb250ZW50L0NvbnRleHQ7ACRMYW5kcm9pZC9jb250ZW50L3BtL0FwcGxpY2F0aW9uSW5mbzsAGkxhbmRyb2lkL29zL0J1aWxkJFZFUlNJT047ABJMYW5kcm9pZC91dGlsL0xvZzsATUxjb20vaGlnaGNhcGFibGUveXVraWhvb2thcGkvdGhpcmRwYXJ0eS9tZS93ZWlzaHUvZnJlZXJlZmxlY3Rpb24vQnVpbGRDb25maWc7AExMY29tL2hpZ2hjYXBhYmxlL3l1a2lob29rYXBpL3RoaXJkcGFydHkvbWUvd2Vpc2h1L3JlZmxlY3Rpb24vQm9vdHN0cmFwQ2xhc3M7AEhMY29tL2hpZ2hjYXBhYmxlL3l1a2lob29rYXBpL3RoaXJkcGFydHkvbWUvd2Vpc2h1L3JlZmxlY3Rpb24vUmVmbGVjdGlvbjsAEUxqYXZhL2xhbmcvQ2xhc3M7ABRMamF2YS9sYW5nL0NsYXNzPCo+OwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xhbmcvU3lzdGVtOwAVTGphdmEvbGFuZy9UaHJvd2FibGU7ABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwAKUmVmbGVjdGlvbgAPUmVmbGVjdGlvbi5qYXZhAAdTREtfSU5UAANUQUcAAVYADFZFUlNJT05fQ09ERQAMVkVSU0lPTl9OQU1FAAJWTAABWgACWkwAEltMamF2YS9sYW5nL0NsYXNzOwATW0xqYXZhL2xhbmcvT2JqZWN0OwATW0xqYXZhL2xhbmcvU3RyaW5nOwAHY29udGV4dAAXZGFsdmlrLnN5c3RlbS5WTVJ1bnRpbWUAAWUABmV4ZW1wdAAJZXhlbXB0QWxsAAdmb3JOYW1lAA9mcmVlLXJlZmxlY3Rpb24AEmdldEFwcGxpY2F0aW9uSW5mbwARZ2V0RGVjbGFyZWRNZXRob2QACmdldFJ1bnRpbWUABmludm9rZQALbG9hZExpYnJhcnkAGG1lLndlaXNodS5mcmVlcmVmbGVjdGlvbgAGbWV0aG9kAAdtZXRob2RzABlyZWZsZWN0IGJvb3RzdHJhcCBmYWlsZWQ6AAdyZWxlYXNlAApzVm1SdW50aW1lABZzZXRIaWRkZW5BcGlFeGVtcHRpb25zABB0YXJnZXRTZGtWZXJzaW9uAAZ1bnNlYWwADHVuc2VhbE5hdGl2ZQAOdm1SdW50aW1lQ2xhc3MAAQAAAAoAAAACAAAACgAQAAEAAAASAAAAAQAAAAAAAAADAAAACgAKAAwAAAABAAAAAQAAAAIAAAAJABEAARcGBhc4FzwfFwAEARcBARcfAAAAAAAABgAHDgAWAAcOav8DATIOARUQAwI1DvAEBEMJGgESDwMDNg4BGw+pBQIFAwUEGR4DAC8NAA4ABw4ALAE6Bw4ANgE7ByydGuIBAQMALw0eAEgABw4ADQAHDgATAS0HHXIZa1oAAAEAAQABAAAANAgAAAQAAABwEAwAAAAOAAoAAAADAAEAOQgAAHsAAABgBQEAEwYcADRlbQAcBQgAGgYxABIXI3cQABIIHAkKAE0JBwhuMAsAZQcMARwFCAAaBjQAEicjdxAAEggcCQoATQkHCBIYHAkQAE0JBwhuMAsAZQcMAhIFEhYjZhEAEgcaCC0ATQgGB24wDgBRBgwEHwQIABIlI1URABIGGgc1AE0HBQYSFhIHTQcFBm4wDgBCBQwDHwMNABIlI1URABIGGgc+AE0HBQYSFhIXI3cQABIIHAkSAE0JBwhNBwUGbjAOAEIFDAUfBQ0AaQUKABIFEgYjZhEAbjAOAFMGDAVpBQkADgANABoFBgAaBjsAcTABAGUAKPcAAAYAAABrAAEAAQEMcgEAAQABAAAAaAgAAAQAAABwEAwAAAAOAAMAAQABAAAAbQgAAAsAAAASECMAEgASAU0CAAFxEAYAAAAKAA8AAAAIAAEAAwABAHMIAAAdAAAAEhESAmIDCQA4AwYAYgMKADkDBAABIQ8BYgMKAGIECQASFSNVEQASBk0HBQZuMA4AQwUo8g0AASEo7wAADAAAAA0AAQABAQwaAwAAAAEAAACDCAAADQAAABIQIwASABIBGgIPAE0CAAFxEAYAAAAKAA8AAAABAAEAAQAAAIgIAAAEAAAAcBAMAAAADgAEAAEAAQAAAI0IAAAeAAAAEgBgAQEAEwIcADUhAwAPAHEABwAAAAoBOQH7/xoAMgBxEA0AAABuEAAAAwAMAFIAAABxEAoAAAAKACjqBgABAAIZARkBGQEZARkBGQKBgASYEQMABQAIGgEKAQoDiIAEsBEBgYAExBMBCdwTAYkBhBQBCdwUAQADAAsaCIGABIgVAQmgFQGKAgAAAAAPAAAAAAAAAAEAAAAAAAAAAQAAAEMAAABwAAAAAgAAABMAAAB8AQAAAwAAAAsAAADIAQAABAAAAAwAAABMAgAABQAAAA8AAACsAgAABgAAAAMAAAAkAwAAAiAAAEMAAACEAwAAARAAAAcAAADgBwAABSAAAAMAAAAcCAAAAxAAAAEAAAAwCAAAAyAAAAgAAAA0CAAAASAAAAgAAACYCAAAACAAAAMAAADsCgAAABAAAAEAAAA8CwAA\";\n" +
|
||||
"\n" +
|
||||
" private static native int unsealNative(int targetSdkVersion);\n" +
|
||||
"\n" +
|
||||
" public static int unseal(Context context) {\n" +
|
||||
" if (SDK_INT < 28) {\n" +
|
||||
" // Below Android P, ignore\n" +
|
||||
" return 0;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" // try exempt API first.\n" +
|
||||
" if (exemptAll()) {\n" +
|
||||
" return 0;\n" +
|
||||
" }\n" +
|
||||
" if (unsealByDexFile(context)) {\n" +
|
||||
" return 0;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" return -1;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" @SuppressWarnings({\"deprecation\", \"ResultOfMethodCallIgnored\"})\n" +
|
||||
" private static boolean unsealByDexFile(Context context) {\n" +
|
||||
" byte[] bytes = Base64.decode(DEX, Base64.NO_WRAP);\n" +
|
||||
" File codeCacheDir = getCodeCacheDir(context);\n" +
|
||||
" if (codeCacheDir == null) {\n" +
|
||||
" return false;\n" +
|
||||
" }\n" +
|
||||
" File code = new File(codeCacheDir, \"__temp_\" + System.currentTimeMillis() + \".dex\");\n" +
|
||||
" try {\n" +
|
||||
"\n" +
|
||||
" try (FileOutputStream fos = new FileOutputStream(code)) {\n" +
|
||||
" fos.write(bytes);\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" DexFile dexFile = new DexFile(code);\n" +
|
||||
" // This class is hardcoded in the dex, Don't use BootstrapClass.class to reference it\n" +
|
||||
" // it maybe obfuscated!!\n" +
|
||||
" Class<?> bootstrapClass = dexFile.loadClass(\"com.highcapable.yukihookapi.thirdparty.me.weishu.reflection.BootstrapClass\", null);\n" +
|
||||
" Method exemptAll = bootstrapClass.getDeclaredMethod(\"exemptAll\");\n" +
|
||||
" return (boolean) exemptAll.invoke(null);\n" +
|
||||
" } catch (Throwable e) {\n" +
|
||||
" e.printStackTrace();\n" +
|
||||
" return false;\n" +
|
||||
" } finally {\n" +
|
||||
" if (code.exists()) {\n" +
|
||||
" code.delete();\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" private static File getCodeCacheDir(Context context) {\n" +
|
||||
" if (context != null) {\n" +
|
||||
" return context.getCodeCacheDir();\n" +
|
||||
" }\n" +
|
||||
" String tmpDir = System.getProperty(\"java.io.tmpdir\");\n" +
|
||||
" if (TextUtils.isEmpty(tmpDir)) {\n" +
|
||||
" return null;\n" +
|
||||
" }\n" +
|
||||
" File tmp = new File(tmpDir);\n" +
|
||||
" if (!tmp.exists()) {\n" +
|
||||
" return null;\n" +
|
||||
" }\n" +
|
||||
" return tmp;\n" +
|
||||
" }\n" +
|
||||
"}")
|
||||
)
|
@@ -6,4 +6,10 @@ plugins {
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Used 82 API Version
|
||||
compileOnly 'de.robv.android.xposed:api:82'
|
||||
compileOnly fileTree(include: ['*.jar'], dir: '../yukihookapi/libs')
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
|
||||
* Copyright (C) 2019-2022 HighCapable
|
||||
* https://github.com/fankes/YukiHookAPI
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is Created by fankes on 2023/1/1.
|
||||
*/
|
||||
@file:Suppress("ClassName")
|
||||
|
||||
package com.highcapable.yukihookapi.hook.xposed.bridge.status
|
||||
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
|
||||
/**
|
||||
* YukiHookModuleStatus 注入 Stub
|
||||
*/
|
||||
object YukiHookModuleStatus_Impl {
|
||||
|
||||
/** 定义 Jvm 方法名 */
|
||||
private const val IS_ACTIVE_METHOD_NAME = "__--"
|
||||
|
||||
/** 定义 Jvm 方法名 */
|
||||
private const val HAS_RESOURCES_HOOK_METHOD_NAME = "_--_"
|
||||
|
||||
/** 定义 Jvm 方法名 */
|
||||
private const val GET_XPOSED_VERSION_METHOD_NAME = "--__"
|
||||
|
||||
/** 定义 Jvm 方法名 */
|
||||
private const val GET_XPOSED_TAG_METHOD_NAME = "_-_-"
|
||||
|
||||
/**
|
||||
* 此方法经过 Hook 后返回 true 即模块已激活
|
||||
*
|
||||
* 返回值将在每次编译时自动生成
|
||||
* @return [Boolean]
|
||||
*/
|
||||
@JvmName(IS_ACTIVE_METHOD_NAME)
|
||||
fun isActive(): Boolean = error("Stub!")
|
||||
|
||||
/**
|
||||
* 此方法经过 Hook 后返回 true 即当前 Hook Framework 支持资源钩子(Resources Hook)
|
||||
*
|
||||
* 返回值将在每次编译时自动生成
|
||||
* @return [Boolean]
|
||||
*/
|
||||
@JvmName(HAS_RESOURCES_HOOK_METHOD_NAME)
|
||||
fun hasResourcesHook(): Boolean = error("Stub!")
|
||||
|
||||
/**
|
||||
* 此方法经过 Hook 后返回 [XposedBridge.getXposedVersion]
|
||||
*
|
||||
* 返回值将在每次编译时自动生成
|
||||
* @return [Int]
|
||||
*/
|
||||
@JvmName(GET_XPOSED_VERSION_METHOD_NAME)
|
||||
fun getXposedVersion(): Int = error("Stub!")
|
||||
|
||||
/**
|
||||
* 此方法经过 Hook 后返回 [XposedBridge] 的 TAG
|
||||
*
|
||||
* 返回值将在每次编译时自动生成
|
||||
* @return [String]
|
||||
*/
|
||||
@JvmName(GET_XPOSED_TAG_METHOD_NAME)
|
||||
fun getXposedBridgeTag(): String = error("Stub!")
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
|
||||
* Copyright (C) 2019-2022 HighCapable
|
||||
* https://github.com/fankes/YukiHookAPI
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is Created by weishu on 2018/6/7.
|
||||
* This file is Forked from https://github.com/tiann/FreeReflection and make it to stub
|
||||
*/
|
||||
package com.highcapable.yukihookapi.thirdparty.me.weishu.reflection;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* FreeReflection 注入 Stub
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class Reflection {
|
||||
|
||||
/**
|
||||
* 调用启动方法
|
||||
* <p>
|
||||
* 方法内容将在每次编译时自动生成
|
||||
*
|
||||
* @param context The Base Context
|
||||
* @return int
|
||||
*/
|
||||
public static int unseal(Context context) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
@@ -421,7 +421,7 @@ inline fun Class<*>.allFields(isAccessible: Boolean = true, result: (index: Int,
|
||||
*/
|
||||
@PublishedApi
|
||||
internal fun Class<*>.checkingInternal() {
|
||||
if (name == classOf<YukiHookModuleStatus>().name) return
|
||||
if (name == YukiHookModuleStatus.IMPL_CLASS_NAME) return
|
||||
if (name == classOf<YukiHookAPI>().name || name.startsWith("com.highcapable.yukihookapi.hook")) throw RuntimeException(
|
||||
"!!!DO NOT ALLOWED!!! You cannot hook or reflection to call the internal class of the YukiHookAPI itself, " +
|
||||
"The called class is [$this]"
|
||||
|
@@ -75,7 +75,7 @@ open class ModuleApplication : Application() {
|
||||
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
super.attachBaseContext(base)
|
||||
Reflection.unseal(base)
|
||||
runCatching { Reflection.unseal(base) }
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
|
@@ -27,9 +27,7 @@
|
||||
*/
|
||||
package com.highcapable.yukihookapi.hook.xposed.bridge.status
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerD
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
|
||||
/**
|
||||
@@ -65,6 +63,9 @@ internal object YukiHookModuleStatus {
|
||||
/** 定义 Jvm 方法名 */
|
||||
internal const val GET_XPOSED_TAG_METHOD_NAME = "_-_-"
|
||||
|
||||
/** [YukiHookModuleStatus_Impl] 完整类名 */
|
||||
internal const val IMPL_CLASS_NAME = "com.highcapable.yukihookapi.hook.xposed.bridge.status.YukiHookModuleStatus_Impl"
|
||||
|
||||
/**
|
||||
* 获取当前 Hook 框架的名称
|
||||
*
|
||||
@@ -73,7 +74,10 @@ internal object YukiHookModuleStatus {
|
||||
* 请使用 [YukiHookAPI.Status.executorName] 获取
|
||||
* @return [String] 模块未激活会返回 unknown
|
||||
*/
|
||||
internal val executorName get() = getXposedBridgeTag().replace("Bridge", "").replace("-", "").trim()
|
||||
internal val executorName
|
||||
get() = runCatching {
|
||||
YukiHookModuleStatus_Impl.getXposedBridgeTag().replace("Bridge", "").replace("-", "").trim()
|
||||
}.getOrNull() ?: "unknown"
|
||||
|
||||
/**
|
||||
* 获取当前 Hook 框架的版本
|
||||
@@ -83,7 +87,7 @@ internal object YukiHookModuleStatus {
|
||||
* 请使用 [YukiHookAPI.Status.executorVersion] 获取
|
||||
* @return [Int] 模块未激活会返回 -1
|
||||
*/
|
||||
internal val executorVersion get() = getXposedVersion()
|
||||
internal val executorVersion get() = runCatching { YukiHookModuleStatus_Impl.getXposedVersion() }.getOrNull() ?: -1
|
||||
|
||||
/**
|
||||
* 此方法经过 Hook 后返回 true 即模块已激活
|
||||
@@ -91,12 +95,7 @@ internal object YukiHookModuleStatus {
|
||||
* 请使用 [YukiHookAPI.Status.isModuleActive]、[YukiHookAPI.Status.isXposedModuleActive]、[YukiHookAPI.Status.isTaiChiModuleActive] 判断模块激活状态
|
||||
* @return [Boolean]
|
||||
*/
|
||||
@Keep
|
||||
@JvmName(IS_ACTIVE_METHOD_NAME)
|
||||
internal fun isActive(): Boolean {
|
||||
yLoggerD(msg = IS_ACTIVE_METHOD_NAME, isDisableLog = true)
|
||||
return false
|
||||
}
|
||||
internal fun isActive() = runCatching { YukiHookModuleStatus_Impl.isActive() }.getOrNull() ?: false
|
||||
|
||||
/**
|
||||
* 此方法经过 Hook 后返回 true 即当前 Hook Framework 支持资源钩子(Resources Hook)
|
||||
@@ -104,32 +103,5 @@ internal object YukiHookModuleStatus {
|
||||
* 请使用 [YukiHookAPI.Status.isSupportResourcesHook] 判断支持状态
|
||||
* @return [Boolean]
|
||||
*/
|
||||
@Keep
|
||||
@JvmName(HAS_RESOURCES_HOOK_METHOD_NAME)
|
||||
internal fun hasResourcesHook(): Boolean {
|
||||
yLoggerD(msg = HAS_RESOURCES_HOOK_METHOD_NAME, isDisableLog = true)
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 此方法经过 Hook 后返回 [XposedBridge.getXposedVersion]
|
||||
* @return [Int]
|
||||
*/
|
||||
@Keep
|
||||
@JvmName(GET_XPOSED_VERSION_METHOD_NAME)
|
||||
private fun getXposedVersion(): Int {
|
||||
yLoggerD(msg = GET_XPOSED_VERSION_METHOD_NAME, isDisableLog = true)
|
||||
return -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 此方法经过 Hook 后返回 [XposedBridge] 的 TAG
|
||||
* @return [String]
|
||||
*/
|
||||
@Keep
|
||||
@JvmName(GET_XPOSED_TAG_METHOD_NAME)
|
||||
private fun getXposedBridgeTag(): String {
|
||||
yLoggerD(msg = GET_XPOSED_TAG_METHOD_NAME, isDisableLog = true)
|
||||
return "unknown"
|
||||
}
|
||||
internal fun hasResourcesHook() = runCatching { YukiHookModuleStatus_Impl.hasResourcesHook() }.getOrNull() ?: false
|
||||
}
|
@@ -148,7 +148,7 @@ internal object AppParasitics {
|
||||
if ((param.args?.get(0) as? String?)?.endsWith("preferences.xml") == true) param.args?.set(1, 1)
|
||||
}
|
||||
})
|
||||
if (YukiHookAPI.Configs.isEnableHookModuleStatus) classOf<YukiHookModuleStatus>(loader).apply {
|
||||
if (YukiHookAPI.Configs.isEnableHookModuleStatus) YukiHookModuleStatus.IMPL_CLASS_NAME.toClassOrNull(loader)?.apply {
|
||||
if (type != HookEntryType.RESOURCES) {
|
||||
YukiHookHelper.hook(method { name = YukiHookModuleStatus.IS_ACTIVE_METHOD_NAME }, object : YukiMemberReplacement() {
|
||||
override fun replaceHookedMember(param: Param) = true
|
||||
|
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
|
||||
* Copyright (C) 2019-2022 HighCapable
|
||||
* https://github.com/fankes/YukiHookAPI
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is Created by weishu on 2020/7/13.
|
||||
* This file is Forked from https://github.com/tiann/FreeReflection
|
||||
*/
|
||||
package com.highcapable.yukihookapi.thirdparty.me.weishu.reflection;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* NO ANNOTATION
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Keep
|
||||
public final class BootstrapClass {
|
||||
|
||||
private static final String TAG = "BootstrapClass";
|
||||
|
||||
private static Object sVmRuntime;
|
||||
private static Method setHiddenApiExemptions;
|
||||
|
||||
static {
|
||||
if (SDK_INT >= Build.VERSION_CODES.P) {
|
||||
try {
|
||||
Method forName = Class.class.getDeclaredMethod("forName", String.class);
|
||||
Method getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);
|
||||
|
||||
Class<?> vmRuntimeClass = (Class<?>) forName.invoke(null, "dalvik.system.VMRuntime");
|
||||
Method getRuntime = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "getRuntime", null);
|
||||
setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", new Class[]{String[].class});
|
||||
sVmRuntime = getRuntime.invoke(null);
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "reflect bootstrap failed:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* make the method exempted from hidden API check.
|
||||
*
|
||||
* @param method the method signature prefix.
|
||||
* @return true if success.
|
||||
*/
|
||||
public static boolean exempt(String method) {
|
||||
return exempt(new String[]{method});
|
||||
}
|
||||
|
||||
/**
|
||||
* make specific methods exempted from hidden API check.
|
||||
*
|
||||
* @param methods the method signature prefix, such as "Ldalvik/system", "Landroid" or even "L"
|
||||
* @return true if success
|
||||
*/
|
||||
public static boolean exempt(String... methods) {
|
||||
if (sVmRuntime == null || setHiddenApiExemptions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
setHiddenApiExemptions.invoke(sVmRuntime, new Object[]{methods});
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make all hidden API exempted.
|
||||
*
|
||||
* @return true if success.
|
||||
*/
|
||||
public static boolean exemptAll() {
|
||||
return exempt(new String[]{"L"});
|
||||
}
|
||||
}
|
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
|
||||
* Copyright (C) 2019-2022 HighCapable
|
||||
* https://github.com/fankes/YukiHookAPI
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This file is Created by weishu on 2018/6/7.
|
||||
* This file is Forked from https://github.com/tiann/FreeReflection
|
||||
*/
|
||||
package com.highcapable.yukihookapi.thirdparty.me.weishu.reflection;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static com.highcapable.yukihookapi.thirdparty.me.weishu.reflection.BootstrapClass.exemptAll;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import dalvik.system.DexFile;
|
||||
|
||||
/**
|
||||
* NO ANNOTATION
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Keep
|
||||
public class Reflection {
|
||||
private static final String TAG = "Reflection";
|
||||
|
||||
private static final String DEX = "ZGV4CjAzNQCXDT0vQ44GJqsrjm32y0qlQmxUevbk56r0CwAAcAAAAHhWNBIAAAAAAAAAADwLAABDAAAAcAAAABMAAAB8AQAACwAAAMgBAAAMAAAATAIAAA8AAACsAgAAAwAAACQDAABwCAAAhAMAAIQDAACGAwAAiwMAAJUDAACdAwAArQMAALkDAADJAwAA3gMAAPADAAD3AwAA/wMAAAIEAAAGBAAACgQAABAEAAATBAAAGAQAADMEAABZBAAAdQQAAIkEAADYBAAAJgUAAHAFAACDBQAAmQUAAK0FAADBBQAA1QUAAOwFAAAIBgAAFAYAACUGAAAuBgAAMwYAADYGAABEBgAAUgYAAFYGAABZBgAAXQYAAHEGAACGBgAAmwYAAKQGAAC9BgAAwAYAAMgGAADTBgAA3AYAAO0GAAABBwAAFAcAACAHAAAoBwAANQcAAE8HAABXBwAAYAcAAHsHAACEBwAAkAcAAKgHAAC6BwAAwgcAANAHAAALAAAAEQAAABIAAAATAAAAFAAAABUAAAAWAAAAFwAAABgAAAAaAAAAGwAAABwAAAAdAAAAHgAAACMAAAAnAAAAKQAAACoAAAArAAAADAAAAAAAAAD4BwAADQAAAAAAAAAMCAAADgAAAAAAAAAACAAADwAAAAIAAAAAAAAAEAAAAAkAAAAUCAAAEAAAAA0AAADoBwAAIwAAAA4AAAAAAAAAJgAAAA4AAADgBwAAJwAAAA8AAAAAAAAAKAAAAA8AAADgBwAAKAAAAA8AAADwBwAAAgAAAD8AAAADAAAAIQAAAAUACgAEAAAABQAKAAUAAAAFAA8ACQAAAAUACgAKAAAABQAAACQAAAAFAAoAJQAAAAYACgAiAAAABgAJAD0AAAAGAA0APgAAAAcACgAiAAAAAQADADMAAAAEAAIALgAAAAUABgADAAAABgAGAAIAAAAGAAYAAwAAAAYACQAvAAAABgAKAC8AAAAGAAgAMAAAAAcABgADAAAABwABAEAAAAAHAAAAQQAAAAgABQA0AAAACQAGAAMAAAALAAcANwAAAA0ABAA2AAAABQAAABEAAAAJAAAAAAAAAAgAAAAAAAAA7AoAAB8IAAAGAAAAEQAAAAkAAAAAAAAABwAAAAAAAAACCwAAHAgAAAcAAAABAAAACQAAAAAAAAAgAAAAAAAAACULAAArCAAAAAADMS4wAAg8Y2xpbml0PgAGPGluaXQ+AA5BUFBMSUNBVElPTl9JRAAKQlVJTERfVFlQRQAOQm9vdHN0cmFwQ2xhc3MAE0Jvb3RzdHJhcENsYXNzLmphdmEAEEJ1aWxkQ29uZmlnLmphdmEABURFQlVHAAZGTEFWT1IAAUkAAklJAAJJTAAESUxMTAABTAADTExMABlMYW5kcm9pZC9jb250ZW50L0NvbnRleHQ7ACRMYW5kcm9pZC9jb250ZW50L3BtL0FwcGxpY2F0aW9uSW5mbzsAGkxhbmRyb2lkL29zL0J1aWxkJFZFUlNJT047ABJMYW5kcm9pZC91dGlsL0xvZzsATUxjb20vaGlnaGNhcGFibGUveXVraWhvb2thcGkvdGhpcmRwYXJ0eS9tZS93ZWlzaHUvZnJlZXJlZmxlY3Rpb24vQnVpbGRDb25maWc7AExMY29tL2hpZ2hjYXBhYmxlL3l1a2lob29rYXBpL3RoaXJkcGFydHkvbWUvd2Vpc2h1L3JlZmxlY3Rpb24vQm9vdHN0cmFwQ2xhc3M7AEhMY29tL2hpZ2hjYXBhYmxlL3l1a2lob29rYXBpL3RoaXJkcGFydHkvbWUvd2Vpc2h1L3JlZmxlY3Rpb24vUmVmbGVjdGlvbjsAEUxqYXZhL2xhbmcvQ2xhc3M7ABRMamF2YS9sYW5nL0NsYXNzPCo+OwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xhbmcvU3lzdGVtOwAVTGphdmEvbGFuZy9UaHJvd2FibGU7ABpMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwAKUmVmbGVjdGlvbgAPUmVmbGVjdGlvbi5qYXZhAAdTREtfSU5UAANUQUcAAVYADFZFUlNJT05fQ09ERQAMVkVSU0lPTl9OQU1FAAJWTAABWgACWkwAEltMamF2YS9sYW5nL0NsYXNzOwATW0xqYXZhL2xhbmcvT2JqZWN0OwATW0xqYXZhL2xhbmcvU3RyaW5nOwAHY29udGV4dAAXZGFsdmlrLnN5c3RlbS5WTVJ1bnRpbWUAAWUABmV4ZW1wdAAJZXhlbXB0QWxsAAdmb3JOYW1lAA9mcmVlLXJlZmxlY3Rpb24AEmdldEFwcGxpY2F0aW9uSW5mbwARZ2V0RGVjbGFyZWRNZXRob2QACmdldFJ1bnRpbWUABmludm9rZQALbG9hZExpYnJhcnkAGG1lLndlaXNodS5mcmVlcmVmbGVjdGlvbgAGbWV0aG9kAAdtZXRob2RzABlyZWZsZWN0IGJvb3RzdHJhcCBmYWlsZWQ6AAdyZWxlYXNlAApzVm1SdW50aW1lABZzZXRIaWRkZW5BcGlFeGVtcHRpb25zABB0YXJnZXRTZGtWZXJzaW9uAAZ1bnNlYWwADHVuc2VhbE5hdGl2ZQAOdm1SdW50aW1lQ2xhc3MAAQAAAAoAAAACAAAACgAQAAEAAAASAAAAAQAAAAAAAAADAAAACgAKAAwAAAABAAAAAQAAAAIAAAAJABEAARcGBhc4FzwfFwAEARcBARcfAAAAAAAABgAHDgAWAAcOav8DATIOARUQAwI1DvAEBEMJGgESDwMDNg4BGw+pBQIFAwUEGR4DAC8NAA4ABw4ALAE6Bw4ANgE7ByydGuIBAQMALw0eAEgABw4ADQAHDgATAS0HHXIZa1oAAAEAAQABAAAANAgAAAQAAABwEAwAAAAOAAoAAAADAAEAOQgAAHsAAABgBQEAEwYcADRlbQAcBQgAGgYxABIXI3cQABIIHAkKAE0JBwhuMAsAZQcMARwFCAAaBjQAEicjdxAAEggcCQoATQkHCBIYHAkQAE0JBwhuMAsAZQcMAhIFEhYjZhEAEgcaCC0ATQgGB24wDgBRBgwEHwQIABIlI1URABIGGgc1AE0HBQYSFhIHTQcFBm4wDgBCBQwDHwMNABIlI1URABIGGgc+AE0HBQYSFhIXI3cQABIIHAkSAE0JBwhNBwUGbjAOAEIFDAUfBQ0AaQUKABIFEgYjZhEAbjAOAFMGDAVpBQkADgANABoFBgAaBjsAcTABAGUAKPcAAAYAAABrAAEAAQEMcgEAAQABAAAAaAgAAAQAAABwEAwAAAAOAAMAAQABAAAAbQgAAAsAAAASECMAEgASAU0CAAFxEAYAAAAKAA8AAAAIAAEAAwABAHMIAAAdAAAAEhESAmIDCQA4AwYAYgMKADkDBAABIQ8BYgMKAGIECQASFSNVEQASBk0HBQZuMA4AQwUo8g0AASEo7wAADAAAAA0AAQABAQwaAwAAAAEAAACDCAAADQAAABIQIwASABIBGgIPAE0CAAFxEAYAAAAKAA8AAAABAAEAAQAAAIgIAAAEAAAAcBAMAAAADgAEAAEAAQAAAI0IAAAeAAAAEgBgAQEAEwIcADUhAwAPAHEABwAAAAoBOQH7/xoAMgBxEA0AAABuEAAAAwAMAFIAAABxEAoAAAAKACjqBgABAAIZARkBGQEZARkBGQKBgASYEQMABQAIGgEKAQoDiIAEsBEBgYAExBMBCdwTAYkBhBQBCdwUAQADAAsaCIGABIgVAQmgFQGKAgAAAAAPAAAAAAAAAAEAAAAAAAAAAQAAAEMAAABwAAAAAgAAABMAAAB8AQAAAwAAAAsAAADIAQAABAAAAAwAAABMAgAABQAAAA8AAACsAgAABgAAAAMAAAAkAwAAAiAAAEMAAACEAwAAARAAAAcAAADgBwAABSAAAAMAAAAcCAAAAxAAAAEAAAAwCAAAAyAAAAgAAAA0CAAAASAAAAgAAACYCAAAACAAAAMAAADsCgAAABAAAAEAAAA8CwAA";
|
||||
|
||||
private static native int unsealNative(int targetSdkVersion);
|
||||
|
||||
/**
|
||||
* Begin
|
||||
*
|
||||
* @param context The Base Context
|
||||
* @return int
|
||||
*/
|
||||
public static int unseal(Context context) {
|
||||
if (SDK_INT < 28) {
|
||||
// Below Android P, ignore
|
||||
return 0;
|
||||
}
|
||||
|
||||
// try exempt API first.
|
||||
if (exemptAll()) {
|
||||
return 0;
|
||||
}
|
||||
if (unsealByDexFile(context)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation", "ResultOfMethodCallIgnored"})
|
||||
private static boolean unsealByDexFile(Context context) {
|
||||
byte[] bytes = Base64.decode(DEX, Base64.NO_WRAP);
|
||||
File codeCacheDir = getCodeCacheDir(context);
|
||||
if (codeCacheDir == null) {
|
||||
return false;
|
||||
}
|
||||
File code = new File(codeCacheDir, "__temp_" + System.currentTimeMillis() + ".dex");
|
||||
try {
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(code)) {
|
||||
fos.write(bytes);
|
||||
}
|
||||
|
||||
DexFile dexFile = new DexFile(code);
|
||||
// This class is hardcoded in the dex, Don't use BootstrapClass.class to reference it
|
||||
// it maybe obfuscated!!
|
||||
Class<?> bootstrapClass = dexFile.loadClass("com.highcapable.yukihookapi.thirdparty.me.weishu.reflection.BootstrapClass", null);
|
||||
Method exemptAll = bootstrapClass.getDeclaredMethod("exemptAll");
|
||||
return (boolean) exemptAll.invoke(null);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
} finally {
|
||||
if (code.exists()) {
|
||||
code.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static File getCodeCacheDir(Context context) {
|
||||
if (context != null) {
|
||||
return context.getCodeCacheDir();
|
||||
}
|
||||
String tmpDir = System.getProperty("java.io.tmpdir");
|
||||
if (TextUtils.isEmpty(tmpDir)) {
|
||||
return null;
|
||||
}
|
||||
File tmp = new File(tmpDir);
|
||||
if (!tmp.exists()) {
|
||||
return null;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user