diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..3448c611 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "edxp-core/src/main/cpp/external/Dobby"] + path = edxp-core/src/main/cpp/external/Dobby + url = https://github.com/jmpews/Dobby.git diff --git a/README.md b/README.md index f744c057..e256db98 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,5 @@ Notice: These community group don't accept any bug report, please use [Get help] - [Riru](https://github.com/RikkaApps/Riru): provides a way to inject codes into zygote process - [XposedBridge](https://github.com/rovo89/XposedBridge): the OG xposed framework APIs - [dexmaker](https://github.com/linkedin/dexmaker) and [dalvikdx](https://github.com/JakeWharton/dalvik-dx): to dynamiclly generate YAHFA hooker classes -- [Whale](https://github.com/asLody/whale): used for inline hooking - [SandHook](https://github.com/ganyao114/SandHook/): ART hooking framework for SandHook variant - +- [Dobby](https://github.com/jmpews/Dobby): used for inline hooking diff --git a/README_CN.md b/README_CN.md index dd449fc2..0fd87e5d 100644 --- a/README_CN.md +++ b/README_CN.md @@ -91,6 +91,6 @@ Edxposed 拥有三个不同的版本 - [Riru](https://github.com/RikkaApps/Riru): 提供一种将代码注入 zygote 进程的方法 - [XposedBridge](https://github.com/rovo89/XposedBridge): 原版 xposed 框架的 API - [dexmaker](https://github.com/linkedin/dexmaker) 和 [dalvikdx](https://github.com/JakeWharton/dalvik-dx): 动态生成 YAHFA hook 类 -- [Whale](https://github.com/asLody/whale): 用于 hook 内联方法 - [SandHook](https://github.com/ganyao114/SandHook/): SandHook 分支的 ART hooking 框架 +- [Dobby](https://github.com/jmpews/Dobby): 用于 hook 内联方法 diff --git a/appveyor.yml b/appveyor.yml index 1bfe270a..a6a254ee 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,11 @@ -version: '0.4.6.4 ({build})' +version: '0.5.0.6_{build}-{branch}' environment: ANDROID_HOME: C:\android-sdk-windows install: + - cd %APPVEYOR_BUILD_FOLDER% + - git submodule update --init --recursive - appveyor DownloadFile https://dl.google.com/android/repository/sdk-tools-windows-4333796.zip - 7z x sdk-tools-windows-4333796.zip -oC:\android-sdk-windows > nul - yes | C:\android-sdk-windows\tools\bin\sdkmanager.bat --licenses > nul @@ -12,7 +14,7 @@ install: - C:\android-sdk-windows\tools\bin\sdkmanager.bat "build-tools;28.0.3" > nul - C:\android-sdk-windows\tools\bin\sdkmanager.bat "cmake;3.6.4111459" > nul - C:\android-sdk-windows\tools\bin\sdkmanager.bat "patcher;v4" > nul - - C:\android-sdk-windows\tools\bin\sdkmanager.bat "ndk-bundle" > nul + - C:\android-sdk-windows\tools\bin\sdkmanager.bat "ndk;22.0.6917172" --channel=1 > nul - set PATH=%PATH%;C:\android-sdk-windows\ndk-bundle;C:\android-sdk-windows\build-tools\28.0.3 build_script: @@ -34,7 +36,6 @@ only_commits: - edxp-common/ - edxp-core/ - edxp-sandhook/ - - edxp-whale/ - edxp-yahfa/ - hiddenapi-stubs/ - xposed-bridge/ diff --git a/build.gradle b/build.gradle index 5db8a85b..ddd888e9 100644 --- a/build.gradle +++ b/build.gradle @@ -7,8 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' - + classpath 'com.android.tools.build:gradle:4.1.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -24,7 +23,7 @@ allprojects { templateLibPath = templateRootPath + "/system/lib/" templateLib64Path = templateRootPath + "/system/lib64/" templateEtcPath = templateRootPath + "/system/etc/" - hiddenApiStubJarFilePath = project(":hiddenapi-stubs").projectDir.absolutePath + "/libs/framework-stub.jar" + hiddenApiStubJarFilePath = project(":hiddenapi-stubs").buildDir.absolutePath + "/libs/framework-stub.jar" } repositories { google() diff --git a/dalvikdx/.gitignore b/dalvikdx/.gitignore index 796b96d1..8b8c3dc1 100644 --- a/dalvikdx/.gitignore +++ b/dalvikdx/.gitignore @@ -1 +1,2 @@ /build +dex diff --git a/dalvikdx/build.gradle b/dalvikdx/build.gradle index c31ce47a..a1d358bc 100644 --- a/dalvikdx/build.gradle +++ b/dalvikdx/build.gradle @@ -1,47 +1,33 @@ -import org.gradle.internal.os.OperatingSystem -apply plugin: 'java-library' +apply plugin: 'com.android.application' -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) +repositories { + jcenter() } -sourceCompatibility = "7" -targetCompatibility = "7" +android { + compileSdkVersion androidCompileSdkVersion.toInteger() + ndkVersion androidCompileNdkVersion +} -task findDx { - if (OperatingSystem.current().isWindows()){ - return true - } - doLast { - new ByteArrayOutputStream().withStream { os -> - exec { - commandLine "which", "dx" - standardOutput os +afterEvaluate { + android.applicationVariants.all { variant -> + def variantNameCapped = variant.name.capitalize() + def variantNameLowered = variant.name.toLowerCase() + + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}" + from (dexOutPath){ + rename("classes.dex", "eddalvikdx.dex") } - rootProject.ext.dxPath = os.toString() + destinationDir file(templateRootPath + "system/framework/") + outputs.upToDateWhen { false } + } + task("makeJar${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + dependsOn "assemble${variantNameCapped}" + from "${buildDir}/intermediates/javac/${variantNameLowered}/classes" + baseName "dalvikdx" + outputs.file(archivePath) } } } - -task dexInJar(type: Jar) { - dependsOn jar - dependsOn findDx - doFirst { - exec { - workingDir jar.destinationDir - if (OperatingSystem.current().isWindows()){ - executable "dx.bat" - args "--dex", "--output", "classes.dex", "${jar.archiveName}" - } else { - executable "bash" - args rootProject.ext.dxPath.trim(), "--dex", "--output", "classes.dex", "${jar.archiveName}" - } - } - } - from "${jar.destinationDir}/classes.dex" - destinationDir jar.destinationDir - baseName "eddalvikdx" - onlyIf { - !jar.state.upToDate || !file(archiveName).exists() - } -} \ No newline at end of file diff --git a/dalvikdx/src/main/AndroidManifest.xml b/dalvikdx/src/main/AndroidManifest.xml new file mode 100644 index 00000000..7474421e --- /dev/null +++ b/dalvikdx/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/dexmaker/.gitignore b/dexmaker/.gitignore index 42afabfd..8b8c3dc1 100644 --- a/dexmaker/.gitignore +++ b/dexmaker/.gitignore @@ -1 +1,2 @@ -/build \ No newline at end of file +/build +dex diff --git a/dexmaker/build.gradle b/dexmaker/build.gradle index 9d4bc920..a3a6cc1b 100644 --- a/dexmaker/build.gradle +++ b/dexmaker/build.gradle @@ -1,37 +1,39 @@ -import org.gradle.internal.os.OperatingSystem -apply plugin: 'java' +apply plugin: 'com.android.application' description = "A utility for doing compile or runtime code generation targeting Android's Dalvik VM" -targetCompatibility = '1.7' -sourceCompatibility = '1.7' - repositories { jcenter() } -dependencies { - compileOnly project(':dalvikdx') +android { + compileSdkVersion androidCompileSdkVersion.toInteger() + ndkVersion androidCompileNdkVersion } -task dexInJar(type: Jar) { - dependsOn jar - doFirst { - exec { - workingDir jar.destinationDir - if (OperatingSystem.current().isWindows()){ - executable "dx.bat" - args "--dex", "--output", "classes.dex", "${jar.archiveName}" - } else { - executable "bash" - args rootProject.ext.dxPath.trim(), "--dex", "--output", "classes.dex", "${jar.archiveName}" +dependencies { + compileOnly files(project(":dalvikdx").tasks.getByName("makeJarRelease").outputs) +} + +afterEvaluate { + android.applicationVariants.all { variant -> + def variantNameCapped = variant.name.capitalize() + def variantNameLowered = variant.name.toLowerCase() + + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}" + from (dexOutPath){ + rename("classes.dex", "eddexmaker.dex") } + destinationDir file(templateRootPath + "system/framework/") + outputs.upToDateWhen { false } + } + task("makeJar${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + dependsOn "assemble${variantNameCapped}" + from "${buildDir}/intermediates/javac/${variantNameLowered}/classes" + baseName "dexmaker" + outputs.file(archivePath) } } - from "${jar.destinationDir}/classes.dex" - destinationDir jar.destinationDir - baseName "eddexmaker" - onlyIf { - !jar.state.upToDate || !file(archiveName).exists() - } -} +} \ No newline at end of file diff --git a/dexmaker/src/main/AndroidManifest.xml b/dexmaker/src/main/AndroidManifest.xml new file mode 100644 index 00000000..419831dd --- /dev/null +++ b/dexmaker/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/edxp-common/build.gradle b/edxp-common/build.gradle index f07a4dda..3d07b300 100644 --- a/edxp-common/build.gradle +++ b/edxp-common/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 28 + compileSdkVersion androidCompileSdkVersion.toInteger() defaultConfig { minSdkVersion 26 @@ -17,13 +17,14 @@ android { } } + ndkVersion androidCompileNdkVersion } dependencies { compileOnly project(':hiddenapi-stubs') - implementation project(':xposed-bridge') + api project(':xposed-bridge') compileOnly project(':dexmaker') - api "androidx.annotation:annotation:1.1.0-rc01" + compileOnly 'com.android.support:support-annotations:28.0.0' } diff --git a/edxp-common/proguard-rules.pro b/edxp-common/proguard-rules.pro index 721fdf5c..427bf7d0 100644 --- a/edxp-common/proguard-rules.pro +++ b/edxp-common/proguard-rules.pro @@ -21,6 +21,7 @@ #-renamesourcefileattribute SourceFile -dontobfuscate +-dontoptimize -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java deleted file mode 100644 index cccc23e2..00000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.elderdrivers.riru.edxp._hooker.impl; - -import com.elderdrivers.riru.edxp.core.Main; -import com.elderdrivers.riru.edxp.util.Hookers; - -import dalvik.system.BaseDexClassLoader; -import de.robv.android.xposed.XC_MethodHook; -import de.robv.android.xposed.XposedBridge; - -/** - * On OnePlus stock roms (Android Pie), {@link BaseDexClassLoader#findClass(String)} - * will open /dev/binder to communicate with PackageManagerService to check whether - * current package name inCompatConfigList, which is an OnePlus OEM feature enabled only when - * system prop "persist.sys.oem.region" set to "CN".(detail of related source code: - * https://gist.github.com/solohsu/ecc07141759958fc096ba0781fac0a5f) - * If we invoke intZygoteCallbacks in - * {@link Main#forkAndSpecializePre}, where in zygote process, - * we would get a chance to invoke findclass, leaving fd of /dev/binder open in zygote process, - * which is not allowed because /dev/binder is not in predefined whitelist here: - * http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/jni/fd_utils.cpp#35 - * So we just hook BaseDexClassLoader#inCompatConfigList to return false to prevent - * open of /dev/binder and we haven't found side effects yet. - * Other roms might share the same problems but not reported too. - */ -public class OneplusWorkaround extends XC_MethodHook { - - @Override - protected void beforeHookedMethod(MethodHookParam param) throws Throwable { - if (XposedBridge.disableHooks || Main.getEdxpImpl().getRouter().isForkCompleted()) { - return; - } - Hookers.logD("BaseDexClassLoader#inCompatConfigList() starts"); - param.setResult(false); - } - -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/HandleBindAppHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/HandleBindAppHooker.java index c203f31b..2174fff8 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/HandleBindAppHooker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/HandleBindAppHooker.java @@ -4,7 +4,10 @@ import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp._hooker.impl.HandleBindApp; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) public class HandleBindAppHooker implements KeepMembers { public static String className = "android.app.ActivityThread"; diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/LoadedApkConstructorHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/LoadedApkConstructorHooker.java index d499f2bf..14845299 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/LoadedApkConstructorHooker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/LoadedApkConstructorHooker.java @@ -8,7 +8,10 @@ import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp._hooker.impl.LoadedApkCstr; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) public class LoadedApkConstructorHooker implements KeepMembers { public static String className = "android.app.LoadedApk"; public static String methodName = ""; diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java deleted file mode 100644 index 2fb6b3d0..00000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.elderdrivers.riru.edxp._hooker.yahfa; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; -import com.elderdrivers.riru.edxp.core.yahfa.HookMain; - -import de.robv.android.xposed.XC_MethodHook; - -public class OnePlusWorkAroundHooker implements KeepMembers { - - static { - HookMain.addHookItemWhiteList(OnePlusWorkAroundHooker.class.getName()); - } - - public static String className = "dalvik.system.BaseDexClassLoader"; - public static String methodName = "inCompatConfigList"; - public static String methodSig = "(ILjava/lang/String;)Z"; - - public static boolean hook(int type, String packageName) throws Throwable { - final XC_MethodHook methodHook = new OneplusWorkaround(); - final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); - param.thisObject = null; - param.args = new Object[]{type, packageName}; - methodHook.callBeforeHookedMethod(param); - if (!param.returnEarly) { - param.setResult(backup(type, packageName)); - } - methodHook.callAfterHookedMethod(param); - return (boolean) param.getResult(); - } - - public static boolean backup(int type, String packageName) { - return false; - } -} \ No newline at end of file diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/StartBootstrapServicesHooker11.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/StartBootstrapServicesHooker11.java new file mode 100644 index 00000000..e47facfb --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/StartBootstrapServicesHooker11.java @@ -0,0 +1,31 @@ +package com.elderdrivers.riru.edxp._hooker.yahfa; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.StartBootstrapServices; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; + +@ApiSensitive(Level.LOW) +public class StartBootstrapServicesHooker11 implements KeepMembers { + public static String className = "com.android.server.SystemServer"; + public static String methodName = "startBootstrapServices"; + public static String methodSig = "(Lcom/android/server/utils/TimingsTraceAndSlog;)V"; + + public static void hook(Object systemServer, Object traceAndSlog) throws Throwable { + final XC_MethodHook methodHook = new StartBootstrapServices(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = systemServer; + param.args = new Object[]{traceAndSlog}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + backup(systemServer, traceAndSlog); + } + methodHook.callAfterHookedMethod(param); + } + + public static void backup(Object systemServer, Object traceAndSlog) { + + } +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/SystemMainHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/SystemMainHooker.java index 544fe5ea..be3a46a8 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/SystemMainHooker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/SystemMainHooker.java @@ -6,7 +6,10 @@ import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp._hooker.impl.SystemMain; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) public class SystemMainHooker implements KeepMembers { public static String className = "android.app.ActivityThread"; diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/ClassLinker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/ClassLinker.java index 16e169f0..b51097f3 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/ClassLinker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/ClassLinker.java @@ -1,10 +1,8 @@ package com.elderdrivers.riru.edxp.art; import com.elderdrivers.riru.common.KeepAll; -import com.elderdrivers.riru.edxp.core.Yahfa; import java.lang.reflect.Member; -import java.util.function.Consumer; import de.robv.android.xposed.PendingHooks; diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/Heap.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/Heap.java index 8cff4275..68e9ce05 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/Heap.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/Heap.java @@ -1,7 +1,5 @@ package com.elderdrivers.riru.edxp.art; -import java.lang.reflect.Member; - public class Heap { public static native int waitForGcToComplete(long thread); diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java index 12474f64..345635fd 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java @@ -27,10 +27,6 @@ public class BaseEdxpConfig implements EdxpConfig { public String getLibSandHookName() { return ConfigManager.getLibSandHookName(); } - @Override - public String getLibWhaleName() { - return ConfigManager.getLibWhaleName(); - } @Override public boolean isDynamicModulesMode() { @@ -51,4 +47,7 @@ public class BaseEdxpConfig implements EdxpConfig { public boolean isBlackWhiteListMode() { return ConfigManager.isBlackWhiteListEnabled(); } + + @Override + public String getModulesList() { return ConfigManager.getModulesList(); } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java index e237c276..6c2dd834 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java @@ -43,11 +43,9 @@ public class ConfigManager { public static native String getLibSandHookName(); - public static native String getLibWhaleName(); - public static native String getInstallerConfigPath(String suffix); public static native String getDataPathPrefix(); - public static native boolean isAppNeedHook(String appDataDir); + public static native String getModulesList(); } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java index 8b7593c2..8d2101d0 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java @@ -1,14 +1,12 @@ package com.elderdrivers.riru.edxp.core; -import androidx.annotation.NonNull; +import android.support.annotation.NonNull; -import com.elderdrivers.riru.edxp.proxy.BlackWhiteListProxy; import com.elderdrivers.riru.edxp.proxy.NormalProxy; import com.elderdrivers.riru.edxp.proxy.Router; public abstract class BaseEdxpImpl implements EdxpImpl { - protected Proxy mBlackWhiteListProxy; protected Proxy mNormalProxy; protected Router mRouter; @@ -23,15 +21,6 @@ public abstract class BaseEdxpImpl implements EdxpImpl { return mInitialized; } - @NonNull - @Override - public Proxy getBlackWhiteListProxy() { - if (mBlackWhiteListProxy == null) { - mBlackWhiteListProxy = createBlackWhiteListProxy(); - } - return mBlackWhiteListProxy; - } - @NonNull @Override public Proxy getNormalProxy() { @@ -50,10 +39,6 @@ public abstract class BaseEdxpImpl implements EdxpImpl { return mRouter; } - protected Proxy createBlackWhiteListProxy() { - return new BlackWhiteListProxy(getRouter()); - } - protected Proxy createNormalProxy() { return new NormalProxy(getRouter()); } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java index 33260594..236a46cb 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java @@ -1,7 +1,7 @@ package com.elderdrivers.riru.edxp.core; -import androidx.annotation.IntDef; -import androidx.annotation.NonNull; +import android.support.annotation.IntDef; +import android.support.annotation.NonNull; import com.elderdrivers.riru.common.KeepAll; import com.elderdrivers.riru.edxp.proxy.Router; @@ -15,14 +15,10 @@ public interface EdxpImpl extends KeepAll { int NONE = 0; int YAHFA = 1; int SANDHOOK = 2; - int WHALE = 3; @NonNull Proxy getNormalProxy(); - @NonNull - Proxy getBlackWhiteListProxy(); - @NonNull Router getRouter(); @@ -34,7 +30,7 @@ public interface EdxpImpl extends KeepAll { boolean isInitialized(); @Retention(SOURCE) - @IntDef({NONE, YAHFA, SANDHOOK, WHALE}) + @IntDef({NONE, YAHFA, SANDHOOK}) @interface Variant { } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java index 634dde34..c4ac4727 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java @@ -1,30 +1,20 @@ package com.elderdrivers.riru.edxp.core; import android.annotation.SuppressLint; -import android.os.Process; import com.elderdrivers.riru.common.KeepAll; -import com.elderdrivers.riru.edxp.common.BuildConfig; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.framework.ProcessHelper; import com.elderdrivers.riru.edxp.util.Utils; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Arrays; import java.util.Iterator; import java.util.ServiceLoader; import java.util.concurrent.atomic.AtomicReference; -import static com.elderdrivers.riru.edxp.proxy.BaseProxy.onBlackListed; +import static com.elderdrivers.riru.edxp.core.EdxpImpl.NONE; @SuppressLint("DefaultLocale") public class Main implements KeepAll { - - private static final boolean logEnabled = BuildConfig.DEBUG; - private static String forkAndSpecializePramsStr = ""; - private static String forkSystemServerPramsStr = ""; - private static final AtomicReference edxpImplRef = new AtomicReference<>(null); static { @@ -40,74 +30,23 @@ public class Main implements KeepAll { String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { - if (isBlackListedProcess(uid)) { - return; - } - final EdxpImpl edxp = getEdxpImpl(); - if (edxp == null || !edxp.isInitialized()) { - return; - } - if (logEnabled) { - forkAndSpecializePramsStr = String.format( - "Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)", - uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), - mountExternal, seInfo, niceName, Arrays.toString(fdsToClose), - Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir); - } - - if (ConfigManager.isBlackWhiteListEnabled()) { - edxp.getBlackWhiteListProxy().forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, - mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, - instructionSet, appDataDir); - } else { - edxp.getNormalProxy().forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal, - seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, - appDataDir); - } + // won't be loaded } public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - if (isBlackListedProcess(Process.myUid())) { - onBlackListed(); - return; - } final EdxpImpl edxp = getEdxpImpl(); if (edxp == null || !edxp.isInitialized()) { + Utils.logE("Not started up"); return; } if (pid == 0) { - if (logEnabled) { - Utils.logI(forkAndSpecializePramsStr + " = " + Process.myPid()); - } - if (ConfigManager.isBlackWhiteListEnabled()) { - edxp.getBlackWhiteListProxy().forkAndSpecializePost(pid, appDataDir, niceName); - } else { - edxp.getNormalProxy().forkAndSpecializePost(pid, appDataDir, niceName); - } - } else { - // in zygote process, res is child zygote pid - // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66 + edxp.getNormalProxy().forkAndSpecializePost(pid, appDataDir, niceName); } } public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { - final EdxpImpl edxp = getEdxpImpl(); - if (edxp == null || !edxp.isInitialized()) { - return; - } - if (logEnabled) { - forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)", - uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), - permittedCapabilities, effectiveCapabilities); - } - if (ConfigManager.isBlackWhiteListEnabled()) { - edxp.getBlackWhiteListProxy().forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, - permittedCapabilities, effectiveCapabilities); - } else { - edxp.getNormalProxy().forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, - permittedCapabilities, effectiveCapabilities); - } + // Won't load } public static void forkSystemServerPost(int pid) { @@ -116,17 +55,7 @@ public class Main implements KeepAll { return; } if (pid == 0) { - if (logEnabled) { - Utils.logI(forkSystemServerPramsStr + " = " + Process.myPid()); - } - if (ConfigManager.isBlackWhiteListEnabled()) { - edxp.getBlackWhiteListProxy().forkSystemServerPost(pid); - } else { - edxp.getNormalProxy().forkSystemServerPost(pid); - } - } else { - // in zygote process, res is child zygote pid - // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66 + edxp.getNormalProxy().forkSystemServerPost(pid); } } @@ -144,25 +73,16 @@ public class Main implements KeepAll { } private static void loadEdxpImpls() { - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - Iterator iterator = ServiceLoader.load( - EdxpImpl.class, Main.class.getClassLoader()).iterator(); - try { - while (iterator.hasNext()) { - iterator.next(); - } - } catch (Throwable t) { - Utils.logE("error when loadEdxpImpls", t); - } - return null; - } - }); - } - - private static boolean isBlackListedProcess(int uid) { - return ProcessHelper.isIsolated(uid) - || ProcessHelper.isRELROUpdater(uid) - || ProcessHelper.isWebViewZygote(uid); + // We don't have Manifest now, so we have to load manually. + try { + Class.forName("com.elderdrivers.riru.edxp.sandhook.core.SandHookEdxpImpl"); + }catch(Throwable ignored) { + Utils.logD("not using sandhook"); + } + try { + Class.forName("com.elderdrivers.riru.edxp.yahfa.core.YahfaEdxpImpl"); + }catch(Throwable ignored) { + Utils.logD("not using yahfa"); + } } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMain.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMain.java index 4a400a10..bd840818 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMain.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMain.java @@ -122,7 +122,9 @@ public class HookMain { checkCompatibleMethods(target, backup, "Original", "Backup"); } if (backup != null) { - HookMethodResolver.resolveMethod(hook, backup); + HookMethodResolver.resolveMethod(hook, backup, target); + } else { + Utils.logD("wanna resolve backup method, but it's null, target: " + target); } // make sure GC completed before hook Thread currentThread = Thread.currentThread(); diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMethodResolver.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMethodResolver.java index d9545051..e1c81acb 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMethodResolver.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMethodResolver.java @@ -91,22 +91,23 @@ public class HookMethodResolver { } } - public static void resolveMethod(Method hook, Method backup) { + public static void resolveMethod(Method hook, Method backup, Object target) { if (canResolvedInJava && artMethodField != null) { // in java try { - resolveInJava(hook, backup); + resolveInJava(hook, backup, target); } catch (Exception e) { // in native - resolveInNative(hook, backup); + resolveInNative(hook, backup, target); } } else { // in native - resolveInNative(hook, backup); + resolveInNative(hook, backup, target); } } - private static void resolveInJava(Method hook, Method backup) throws Exception { + private static void resolveInJava(Method hook, Method backup, Object target) throws Exception { + Utils.logD("start to resolve in java. target: " + target); Object dexCache = dexCacheField.get(hook.getDeclaringClass()); if (isArtMethod) { Object artMethod = artMethodField.get(backup); @@ -121,7 +122,8 @@ public class HookMethodResolver { } } - private static void resolveInNative(Method hook, Method backup) { + private static void resolveInNative(Method hook, Method backup, Object target) { + Utils.logD("start to resolve in native. target: " + target); Yahfa.ensureMethodCached(hook, backup); } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/InlinedMethodCallers.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/InlinedMethodCallers.java index daf891b5..093942f6 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/InlinedMethodCallers.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/deopt/InlinedMethodCallers.java @@ -2,6 +2,9 @@ package com.elderdrivers.riru.edxp.deopt; import java.util.HashMap; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; + /** * Providing a whitelist of methods which are the callers of the target methods we want to hook. * Because the target methods are inlined into the callers, we deoptimize the callers to @@ -10,6 +13,7 @@ import java.util.HashMap; * Only for methods which are included in pre-compiled framework codes. * TODO recompile system apps and priv-apps since their original dex files are available */ +@ApiSensitive(Level.MIDDLE) public class InlinedMethodCallers { public static final String KEY_BOOT_IMAGE = "boot_image"; @@ -28,8 +32,10 @@ public class InlinedMethodCallers { private static final String[][] BOOT_IMAGE = { // callers of Application#attach(Context) {"android.app.Instrumentation", "newApplication", "(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Context;)Landroid/app/Application;"}, + {"android.app.Instrumentation", "newApplication", "(Ljava/lang/ClassLoader;Landroid/content/Context;)Landroid/app/Application;"}, }; + // TODO deprecate this private static final String[][] BOOT_IMAGE_FOR_MIUI_RES = { // for MIUI resources hooking {"android.content.res.MiuiResources", "init", "(Ljava/lang/String;)V"}, diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/Hook.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/Hook.java deleted file mode 100644 index 06d65505..00000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/Hook.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.elderdrivers.riru.edxp.entry; - -public interface Hook { -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/HookImpl.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/HookImpl.java deleted file mode 100644 index 6dae3896..00000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/HookImpl.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.elderdrivers.riru.edxp.entry; - -public class HookImpl implements Hook { - -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java index c76b47af..8fb6d759 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java @@ -3,12 +3,10 @@ package com.elderdrivers.riru.edxp.entry.yahfa; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; public class AppBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { HandleBindAppHooker.class.getName(), LoadedApkConstructorHooker.class.getName(), - OnePlusWorkAroundHooker.class.getName() }; } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java index 68656961..fb50926c 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java @@ -3,7 +3,6 @@ package com.elderdrivers.riru.edxp.entry.yahfa; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.SystemMainHooker; public class SysBootstrapHookInfo implements KeepMembers { @@ -11,6 +10,5 @@ public class SysBootstrapHookInfo implements KeepMembers { HandleBindAppHooker.class.getName(), SystemMainHooker.class.getName(), LoadedApkConstructorHooker.class.getName(), - OnePlusWorkAroundHooker.class.getName() }; } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysInnerHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysInnerHookInfo.java index 19400753..28b1f194 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysInnerHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysInnerHookInfo.java @@ -2,9 +2,18 @@ package com.elderdrivers.riru.edxp.entry.yahfa; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp._hooker.yahfa.StartBootstrapServicesHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.StartBootstrapServicesHooker11; +import com.elderdrivers.riru.edxp.util.Versions; public class SysInnerHookInfo implements KeepMembers { + + public static Class getSysInnerHookerClass() { + return Versions.hasR() ? + StartBootstrapServicesHooker11.class : + StartBootstrapServicesHooker.class; + } + public static String[] hookItemNames = { - StartBootstrapServicesHooker.class.getName() + getSysInnerHookerClass().getName() }; } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java deleted file mode 100644 index ecf36e5e..00000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.elderdrivers.riru.edxp.entry.yahfa; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; - -public class WorkAroundHookInfo implements KeepMembers { - public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName() - }; -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/ProcessHelper.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/ProcessHelper.java deleted file mode 100644 index 6018a1ea..00000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/ProcessHelper.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.elderdrivers.riru.edxp.framework; - -import de.robv.android.xposed.XposedHelpers; - -public class ProcessHelper { - - static { - // WEBVIEW_ZYGOTE_UID differ among versions - WEBVIEW_ZYGOTE_UID = XposedHelpers.getStaticIntField(android.os.Process.class, "WEBVIEW_ZYGOTE_UID"); - } - - /** - * Defines the UID/GID for the shared RELRO file updater process. - */ - public static final int SHARED_RELRO_UID = 1037; - - /** - * Defines the UID/GID for the WebView zygote process. - */ - public static final int WEBVIEW_ZYGOTE_UID; - - /** - * First uid used for fully isolated sandboxed processes (with no permissions of their own) - */ - public static final int FIRST_ISOLATED_UID = 99000; - /** - * Last uid used for fully isolated sandboxed processes (with no permissions of their own) - */ - public static final int LAST_ISOLATED_UID = 99999; - - /** - * Range of uids allocated for a user. - */ - public static final int PER_USER_RANGE = 100000; - - public static int getAppId(int uid) { - return uid % PER_USER_RANGE; - } - - public static boolean isRELROUpdater(int uid) { - return getAppId(uid) == SHARED_RELRO_UID; - } - - public static boolean isWebViewZygote(int uid) { - return getAppId(uid) == WEBVIEW_ZYGOTE_UID; - } - - public static boolean isIsolated(int uid) { - uid = getAppId(uid); - return uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID; - } -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java index 9ca7606c..f59cc562 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java @@ -3,15 +3,11 @@ package com.elderdrivers.riru.edxp.framework; import com.elderdrivers.riru.edxp.util.Utils; import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) public class Zygote { - - // prevent from fatal error caused by holding not whitelisted file descriptors when forking zygote - // https://github.com/rovo89/Xposed/commit/b3ba245ad04cd485699fb1d2ebde7117e58214ff - public static native void closeFilesBeforeFork(); - - public static native void reopenFilesAfterFork(); - public static void allowFileAcrossFork(String path) { try { Class zygote = XposedHelpers.findClass("com.android.internal.os.Zygote", null); diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/hooker/SliceProviderFix.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/hooker/SliceProviderFix.java index eadb33c5..d2d4e469 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/hooker/SliceProviderFix.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/hooker/SliceProviderFix.java @@ -4,7 +4,10 @@ import android.os.StrictMode; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) public class SliceProviderFix { public static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui"; diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/hooker/XposedInstallerHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/hooker/XposedInstallerHooker.java index 719b757c..07953b16 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/hooker/XposedInstallerHooker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/hooker/XposedInstallerHooker.java @@ -21,8 +21,13 @@ public class XposedInstallerHooker { final String xposedAppClass = LEGACY_INSTALLER_PACKAGE_NAME + ".XposedApp"; final Class InstallZipUtil = XposedHelpers.findClass(LEGACY_INSTALLER_PACKAGE_NAME + ".util.InstallZipUtil", classLoader); - XposedHelpers.findAndHookMethod(xposedAppClass, classLoader, "getActiveXposedVersion", - XC_MethodReplacement.returnConstant(XposedBridge.getXposedVersion())); + XposedHelpers.findAndHookMethod(xposedAppClass, classLoader, "getActiveXposedVersion", new XC_MethodHook() { + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + Utils.logD("after getActiveXposedVersion..."); + param.setResult(XposedBridge.getXposedVersion()); + } + }); XposedHelpers.findAndHookMethod(xposedAppClass, classLoader, "reloadXposedProp", new XC_MethodHook() { @Override diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java index e4758e99..4c8ef585 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java @@ -7,37 +7,34 @@ import android.text.TextUtils; import com.elderdrivers.riru.edxp._hooker.impl.HandleBindApp; import com.elderdrivers.riru.edxp._hooker.impl.LoadedApkCstr; -import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; import com.elderdrivers.riru.edxp._hooker.impl.StartBootstrapServices; import com.elderdrivers.riru.edxp._hooker.impl.SystemMain; import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.StartBootstrapServicesHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.SystemMainHooker; import com.elderdrivers.riru.edxp.core.yahfa.HookMain; import com.elderdrivers.riru.edxp.entry.yahfa.AppBootstrapHookInfo; import com.elderdrivers.riru.edxp.entry.yahfa.SysBootstrapHookInfo; import com.elderdrivers.riru.edxp.entry.yahfa.SysInnerHookInfo; -import com.elderdrivers.riru.edxp.entry.yahfa.WorkAroundHookInfo; import com.elderdrivers.riru.edxp.util.Utils; +import com.elderdrivers.riru.edxp.util.Versions; import java.util.concurrent.atomic.AtomicBoolean; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedInit; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; public abstract class BaseRouter implements Router { - protected volatile boolean forkCompleted = false; - protected volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); protected static boolean useXposedApi = false; public void initResourcesHook() { - startWorkAroundHook(); // for OnePlus devices XposedBridge.initXResources(); } @@ -46,18 +43,6 @@ public abstract class BaseRouter implements Router { XposedInit.startsSystemServer = isSystem; } - public void onForkStart() { - forkCompleted = false; - } - - public void onForkFinish() { - forkCompleted = true; - } - - public boolean isForkCompleted() { - return forkCompleted; - } - public void installBootstrapHooks(boolean isSystem) { // Initialize the Xposed framework try { @@ -72,10 +57,9 @@ public abstract class BaseRouter implements Router { } } - public void loadModulesSafely(boolean isInZygote, boolean callInitZygote) { + public void loadModulesSafely(boolean callInitZygote) { try { - // FIXME some coredomain app can't reading modules.list - XposedInit.loadModules(isInZygote, callInitZygote); + XposedInit.loadModules(callInitZygote); } catch (Exception exception) { Utils.logE("error loading module list", exception); } @@ -93,6 +77,7 @@ public abstract class BaseRouter implements Router { } + @ApiSensitive(Level.LOW) public void startBootstrapHook(boolean isSystem) { Utils.logD("startBootstrapHook starts: isSystem = " + isSystem); ClassLoader classLoader = BaseRouter.class.getClassLoader(); @@ -127,9 +112,13 @@ public abstract class BaseRouter implements Router { public void startSystemServerHook() { ClassLoader classLoader = BaseRouter.class.getClassLoader(); if (useXposedApi) { + StartBootstrapServices sbsHooker = new StartBootstrapServices(); + Object[] paramTypesAndCallback = Versions.hasR() ? + new Object[]{"com.android.server.utils.TimingsTraceAndSlog", sbsHooker} : + new Object[]{sbsHooker}; XposedHelpers.findAndHookMethod(StartBootstrapServicesHooker.className, SystemMain.systemServerCL, - StartBootstrapServicesHooker.methodName, new StartBootstrapServices()); + StartBootstrapServicesHooker.methodName, paramTypesAndCallback); } else { HookMain.doHookDefault( classLoader, @@ -137,21 +126,4 @@ public abstract class BaseRouter implements Router { SysInnerHookInfo.class.getName()); } } - - public void startWorkAroundHook() { - ClassLoader classLoader = BaseRouter.class.getClassLoader(); - if (useXposedApi) { - try { - XposedHelpers.findAndHookMethod(OnePlusWorkAroundHooker.className, - classLoader, OnePlusWorkAroundHooker.methodName, - int.class, String.class, new OneplusWorkaround()); - } catch (Throwable ignored) { - } - } else { - HookMain.doHookDefault( - BaseRouter.class.getClassLoader(), - classLoader, - WorkAroundHookInfo.class.getName()); - } - } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java deleted file mode 100644 index 0ff1f134..00000000 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.elderdrivers.riru.edxp.proxy; - -import android.text.TextUtils; - -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.util.ProcessUtils; -import com.elderdrivers.riru.edxp.util.Utils; - -import de.robv.android.xposed.XposedBridge; - -import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; - -/** - * 1. Non dynamic mode - * - system_server is whitelisted - * * for all child processes of main zygote - * What've been done in main zygote pre-forking system_server - * 1) non dynamic flag set (no need to reset) - * 2) boot image methods deopted (no need to redo) - * 3) startSystemServer flag set to true (need to reset) - * 4) workaround hooks installed (need to redo) - * 5) module list loaded and initZygote called (no need to redo) - * 6) close all fds (no need to redo because of 5)) - * * for all child processes of secondary zygote - * 1) do the same things pre-forking first child process - * - system_server is blacklisted: - * * for all child processes of both main zygote and secondary zygote - * 1) do the same things pre-forking first child process - * 2. Dynamic mode: - * to be continued - */ -public class BlackWhiteListProxy extends BaseProxy { - - public BlackWhiteListProxy(Router router) { - super(router); - } - - public void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - String appDataDir) { - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (isDynamicModulesMode) { - onForkPreForDynamicMode(false); - } else { - onForkPreForNonDynamicMode(false); - } - } - - public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - onForkPostCommon(false, appDataDir, niceName); - } - - public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, long permittedCapabilities, - long effectiveCapabilities) { - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (isDynamicModulesMode) { - onForkPreForDynamicMode(true); - } else { - onForkPreForNonDynamicMode(true); - } - } - - public void forkSystemServerPost(int pid) { - onForkPostCommon(true, getDataPathPrefix() + "android", "system_server"); - } - - private void onForkPreForDynamicMode(boolean isSystemServer) { - mRouter.onForkStart(); - mRouter.initResourcesHook(); - mRouter.prepare(isSystemServer); - mRouter.loadModulesSafely(true, false); - } - - /** - * Some details are different between main zygote and secondary zygote. - */ - private void onForkPreForNonDynamicMode(boolean isSystemServer) { - mRouter.onForkStart(); - mRouter.initResourcesHook(); - // set startsSystemServer flag used when loadModules - mRouter.prepare(isSystemServer); - // deoptBootMethods once for all child processes of zygote - PrebuiltMethodsDeopter.deoptBootMethods(); - // we never install bootstrap hooks here in black/white list mode except workaround hooks - // because installed hooks would be propagated to all child processes of zygote - mRouter.startWorkAroundHook(); - // loadModules once for all child processes of zygote - mRouter.loadModulesSafely(true, false); - } - - private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { - ConfigManager.appDataDir = appDataDir; - ConfigManager.niceName = niceName; - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - mRouter.onEnterChildProcess(); - if (!checkNeedHook(appDataDir, niceName)) { - // if is blacklisted, just stop here - mRouter.onForkFinish(); - return; - } - if (isDynamicModulesMode) { - mRouter.initResourcesHook(); - } - mRouter.prepare(isSystemServer); - PrebuiltMethodsDeopter.deoptBootMethods(); - mRouter.installBootstrapHooks(isSystemServer); - - // under dynamic modules mode, don't call initZygote when loadModule - // cuz loaded module won't has that chance to do it - if (isDynamicModulesMode) { - mRouter.loadModulesSafely(false, false); - } - // call all initZygote callbacks - XposedBridge.callInitZygotes(); - - mRouter.onForkFinish(); - } - - private boolean checkNeedHook(String appDataDir, String niceName) { - boolean needHook; - if (TextUtils.isEmpty(appDataDir)) { - Utils.logE("niceName:" + niceName + ", procName:" - + ProcessUtils.getCurrentProcessName(ConfigManager.appProcessName) + ", appDataDir is null, blacklisted!"); - needHook = false; - } else { - // FIXME some process cannot read app_data_file because of MLS, e.g. bluetooth - needHook = ConfigManager.isAppNeedHook(appDataDir); - } - if (!needHook) { - // clean up the scene - onBlackListed(); - } - return needHook; - } -} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java index 54b0d052..92d26252 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java @@ -18,8 +18,9 @@ public class NormalProxy extends BaseProxy { String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { - // mainly for secondary zygote - mRouter.onForkStart(); + } + + public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { SELinuxHelper.initOnce(); mRouter.initResourcesHook(); // call this to ensure the flag is set to false ASAP @@ -27,18 +28,15 @@ public class NormalProxy extends BaseProxy { PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote // install bootstrap hooks for secondary zygote mRouter.installBootstrapHooks(false); - // only load modules for secondary zygote - mRouter.loadModulesSafely(true, true); - } - - public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { // TODO consider processes without forkAndSpecializePost being called forkPostCommon(pid, false, appDataDir, niceName); } public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { - mRouter.onForkStart(); + } + + public void forkSystemServerPost(int pid) { SELinuxHelper.initOnce(); mRouter.initResourcesHook(); // set startsSystemServer flag used when loadModules @@ -48,13 +46,6 @@ public class NormalProxy extends BaseProxy { // in case we miss some processes not forked via forkAndSpecialize // for instance com.android.phone mRouter.installBootstrapHooks(true); - // loadModules have to be executed in zygote even isDynamicModules is false - // because if not global hooks installed in initZygote might not be - // propagated to processes not forked via forkAndSpecialize - mRouter.loadModulesSafely(true, true); - } - - public void forkSystemServerPost(int pid) { // in system_server process forkPostCommon(pid, true, getDataPathPrefix() + "android", "system_server"); @@ -66,13 +57,7 @@ public class NormalProxy extends BaseProxy { ConfigManager.niceName = niceName; mRouter.prepare(isSystem); mRouter.onEnterChildProcess(); - // reload module list if dynamic mode is on - if (ConfigManager.isDynamicModulesEnabled()) { - // FIXME this could be error-prone because hooks installed inside old versions - // of initZygote instances of same module are not unhooked - mRouter.loadModulesSafely(false, true); - } - mRouter.onForkFinish(); + mRouter.loadModulesSafely(true); } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java index 1467bcf3..63fcd31f 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java @@ -10,21 +10,13 @@ public interface Router { void installBootstrapHooks(boolean isSystem); - void loadModulesSafely(boolean isInZygote, boolean callInitZygote); + void loadModulesSafely(boolean callInitZygote); void startBootstrapHook(boolean isSystem); void startSystemServerHook(); - void startWorkAroundHook(); - - void onForkStart(); - - void onForkFinish(); - void onEnterChildProcess(); void injectConfig(); - - boolean isForkCompleted(); } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java index 75aa4cbc..2af555e8 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java @@ -15,10 +15,13 @@ import dalvik.system.PathClassLoader; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) public class ClassLoaderUtils { - public static final String DEXPATH = "/system/framework/edxp.jar:/system/framework/eddalvikdx.jar:/system/framework/eddexmaker.jar"; + public static final String DEXPATH = "/system/framework/edxp.dex:/system/framework/eddalvikdx.dex:/system/framework/eddexmaker.dex"; public static void replaceParentClassLoader(ClassLoader appClassLoader) { if (appClassLoader == null) { diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java index a5eb8c9e..297c20ad 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java @@ -7,9 +7,12 @@ import java.lang.reflect.Member; import java.lang.reflect.Modifier; import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; public class ClassUtils { + @ApiSensitive(Level.MIDDLE) public static int getClassStatus(Class clazz, boolean isUnsigned) { if (clazz == null) { return 0; @@ -25,8 +28,9 @@ public class ClassUtils { /** * 5.0-8.0: kInitialized = 10 int * 8.1: kInitialized = 11 int - * 9.0: kInitialized = 14 uint8_t + * 9.0+: kInitialized = 14 uint8_t */ + @ApiSensitive(Level.MIDDLE) public static boolean isInitialized(Class clazz) { if (Build.VERSION.SDK_INT >= 28) { return getClassStatus(clazz, true) == 14; diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/DexUtils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/DexUtils.java index eea9f75c..2233b6a4 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/DexUtils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/DexUtils.java @@ -8,10 +8,13 @@ import java.lang.reflect.Field; import dalvik.system.BaseDexClassLoader; import dalvik.system.DexClassLoader; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; /** * For 6.0 only. */ +@ApiSensitive(Level.LOW) @TargetApi(Build.VERSION_CODES.M) public class DexUtils { diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ProcessUtils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ProcessUtils.java index b0e8edaa..01b7054d 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ProcessUtils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ProcessUtils.java @@ -8,6 +8,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; + +@ApiSensitive(Level.LOW) public class ProcessUtils { // Copied from UserHandle, indicates range of uids allocated for a user. diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Unsafe.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Unsafe.java index ab788317..a04330f8 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Unsafe.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Unsafe.java @@ -21,6 +21,10 @@ import android.util.Log; import java.lang.reflect.Field; import java.lang.reflect.Method; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; + +@ApiSensitive(Level.LOW) public final class Unsafe { private static final String TAG = "Unsafe"; diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Utils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Utils.java index e6bcb845..b1fa3741 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Utils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Utils.java @@ -5,6 +5,8 @@ import android.util.Log; import com.elderdrivers.riru.edxp.common.BuildConfig; import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; public class Utils { @@ -45,6 +47,7 @@ public class Utils { Log.e(LOG_TAG, msg, throwable); } + @ApiSensitive(Level.LOW) public static String getSysProp(String key) { try { Class sysProps = XposedHelpers.findClassIfExists("android.os.SystemProperties", null); diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Versions.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Versions.java new file mode 100644 index 00000000..0a1bdf5b --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Versions.java @@ -0,0 +1,14 @@ +package com.elderdrivers.riru.edxp.util; + +import android.os.Build; + +public class Versions { + + public static boolean hasR() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R; + } + + public static boolean hasQ() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + } +} diff --git a/edxp-common/template_override/system/lib/libsandhook-native.so b/edxp-common/template_override/system/lib/libsandhook-native.so new file mode 100755 index 00000000..34a2ce0f Binary files /dev/null and b/edxp-common/template_override/system/lib/libsandhook-native.so differ diff --git a/edxp-common/template_override/system/lib/libwhale.edxp.so b/edxp-common/template_override/system/lib/libwhale.edxp.so deleted file mode 100755 index d718e9aa..00000000 Binary files a/edxp-common/template_override/system/lib/libwhale.edxp.so and /dev/null differ diff --git a/edxp-common/template_override/system/lib64/libsandhook-native.so b/edxp-common/template_override/system/lib64/libsandhook-native.so new file mode 100755 index 00000000..1d64ee53 Binary files /dev/null and b/edxp-common/template_override/system/lib64/libsandhook-native.so differ diff --git a/edxp-common/template_override/system/lib64/libwhale.edxp.so b/edxp-common/template_override/system/lib64/libwhale.edxp.so deleted file mode 100755 index ccd342dc..00000000 Binary files a/edxp-common/template_override/system/lib64/libwhale.edxp.so and /dev/null differ diff --git a/edxp-common/template_override/system_x86/lib/libwhale.edxp.so b/edxp-common/template_override/system_x86/lib/libwhale.edxp.so deleted file mode 100755 index 618b2f4b..00000000 Binary files a/edxp-common/template_override/system_x86/lib/libwhale.edxp.so and /dev/null differ diff --git a/edxp-common/template_override/system_x86/lib64/libwhale.edxp.so b/edxp-common/template_override/system_x86/lib64/libwhale.edxp.so deleted file mode 100755 index 35d9cf8a..00000000 Binary files a/edxp-common/template_override/system_x86/lib64/libwhale.edxp.so and /dev/null differ diff --git a/edxp-core/.gitignore b/edxp-core/.gitignore index 862c7cf2..9542b0dd 100644 --- a/edxp-core/.gitignore +++ b/edxp-core/.gitignore @@ -4,5 +4,8 @@ /obj /release /template_override/module.prop +/template_override/system /template_override/system_x86 -*.iml \ No newline at end of file +/template_override/riru/module.prop.new +*.iml +/.cxx diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index 94fb01c5..d26abba7 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -1,10 +1,20 @@ import org.apache.tools.ant.filters.FixCrLfFilter import org.gradle.internal.os.OperatingSystem +import java.security.MessageDigest + apply plugin: 'com.android.library' +static def calcSha256(file) { + def md = MessageDigest.getInstance("SHA-256") + file.eachByte 4096, { bytes, size -> + md.update(bytes, 0, size); + } + return md.digest().encodeHex() +} + // Values set here will be overriden by AppVeyor, feel free to modify during development. -def buildVersionName = 'v0.4.6.4' +def buildVersionName = 'v0.5.0.8' def buildVersionCode = 233 if (System.env.APPVEYOR_BUILD_VERSION != null) { @@ -24,20 +34,22 @@ ext { module_name = "EdXposed" jar_dest_dir = "${projectDir}/template_override/system/framework/" is_windows = OperatingSystem.current().isWindows() - backends = ["YAHFA", "SandHook", "Whale"] + backends = ["YAHFA", "SandHook"] yahfa_module_id = "riru_edxposed" sandhook_module_id = yahfa_module_id + "_sandhook" - whale_module_id = yahfa_module_id + "_whale" yahfa_authors = "solohsu, MlgmXyysd & rk700" sandhook_authors = "solohsu, MlgmXyysd & ganyao114" - whale_authors = "solohsu, MlgmXyysd & asLody" riruModuleId = "edxp" zipPathMagiskRelease = "$buildDir/tmp/release/magisk" + + moduleMinRiruApiVersion = 9 + moduleMinRiruVersionName = "v22.0" + moduleMaxRiruApiVersion = 9 } android { - compileSdkVersion 28 + compileSdkVersion androidCompileSdkVersion.toInteger() defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion @@ -45,8 +57,11 @@ android { externalNativeBuild { cmake { abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64' - cppFlags "-std=c++17 -ffixed-x18 -Qunused-arguments -frtti" - cFlags "-std=gnu99 -ffixed-x18 -Qunused-arguments -frtti" + cppFlags "-std=c++17 -ffixed-x18 -Qunused-arguments -frtti -fomit-frame-pointer" + cFlags "-std=gnu99 -ffixed-x18 -Qunused-arguments -frtti -fomit-frame-pointer" + arguments "-DRIRU_MODULE_API_VERSION=$moduleMaxRiruApiVersion", + "-DRIRU_MODULE_VERSION=$buildVersionCode", + "-DRIRU_MODULE_VERSION_NAME:STRING=\"$buildVersionName\"" } } } @@ -63,8 +78,8 @@ android { release { externalNativeBuild { cmake { - cppFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value" - cFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value" + cppFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer" + cFlags "-fvisibility=hidden -fvisibility-inlines-hidden -O2 -s -Wno-unused-value -fomit-frame-pointer" } } minifyEnabled true @@ -76,34 +91,7 @@ android { path "src/main/cpp/CMakeLists.txt" } } -} - -task copyDalvikdxJar { - def jarTask = tasks.getByPath(':dalvikdx:dexInJar') - dependsOn jarTask - doLast { - copy { - from jarTask - into jar_dest_dir - } - } - onlyIf { - !jarTask.state.upToDate || !file(jar_dest_dir + jarTask.archiveName).exists() - } -} - -task copyDexmakerJar { - def jarTask = tasks.getByPath(':dexmaker:dexInJar') - dependsOn jarTask - doLast { - copy { - from jarTask - into jar_dest_dir - } - } - onlyIf { - !jarTask.state.upToDate || !file(jar_dest_dir + jarTask.archiveName).exists() - } + ndkVersion androidCompileNdkVersion } task cleanTemplate(type: Delete) { @@ -125,8 +113,10 @@ afterEvaluate { def magiskModuleId = property("${backendLowered}" + "_module_id") def prepareJarsTask = task("prepareJars${backendCapped}${variantCapped}") { - dependsOn cleanTemplate, copyDalvikdxJar, copyDexmakerJar - dependsOn tasks.getByPath(":edxp-${backendLowered}:makeAndCopy${variantCapped}") + dependsOn cleanTemplate + dependsOn tasks.getByPath(":dexmaker:copyDex${variantCapped}") + dependsOn tasks.getByPath(":dalvikdx:copyDex${variantCapped}") + dependsOn tasks.getByPath(":edxp-${backendLowered}:copyDex${variantCapped}") } def prepareMagiskFilesTask = task("prepareMagiskFiles${backendCapped}${variantCapped}", type: Delete) { @@ -148,22 +138,40 @@ afterEvaluate { versionCode: "$versionCode", authorList: "$authorList") filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf")) } + copy { + from "${projectDir}/tpl/riru_module.prop.tpl" + into "$templateRootPath/riru" + rename "riru_module.prop.tpl", "module.prop.new" + expand(minApi: "$moduleMinRiruApiVersion", + versionName: "$version" + " ($backend)", + versionCode: "$versionCode", authorList: "$authorList") + filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf")) + } } def libPathRelease = "${buildDir}/intermediates/cmake/${variantLowered}/obj" + def exclude_list = ["riru.sh"] + if(backendLowered == "yahfa") { + exclude_list.add("system/lib/libsandhook-native.so") + exclude_list.add("system/lib64/libsandhook-native.so") + } doLast { copy { from "${projectDir}/template_override" into zipPathMagiskRelease + exclude exclude_list + } + copy { + from "${projectDir}/template_override" + into zipPathMagiskRelease + include 'riru.sh' + filter { line -> + line.replaceAll('%%%RIRU_MODULE_ID%%%', riruModuleId) + .replaceAll('%%%RIRU_MIN_API_VERSION%%%', moduleMinRiruApiVersion.toString()) + .replaceAll('%%%RIRU_MIN_VERSION_NAME%%%', moduleMinRiruVersionName) + } + filter(FixCrLfFilter.class, + eol: FixCrLfFilter.CrLf.newInstance("lf")) } -// copy { -// from "${projectDir}/template_override/util_functions.sh" -// into "${zipPathMagiskRelease}/" -// filter { line -> line -// .replaceAll('%VERSION%', "$version") -// .replaceAll('%VERSION_CODE%', "$versionCode") -// .replaceAll('%BACKEND%', "$backendCapped") } -// filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf")) -// } copy { from "$libPathRelease/armeabi-v7a" into "$zipPathMagiskRelease/system/lib" @@ -180,6 +188,13 @@ afterEvaluate { from "$libPathRelease/x86_64" into "$zipPathMagiskRelease/system_x86/lib64" } + // generate sha1sum + fileTree(zipPathMagiskRelease).matching { + exclude "README.md", "META-INF" + }.visit { f -> + if (f.directory) return + file(f.file.path + ".sha256sum").text = calcSha256(f.file) + } } } @@ -193,9 +208,30 @@ afterEvaluate { task("push${backendCapped}${variantCapped}", type: Exec) { dependsOn zipTask workingDir "${projectDir}/release" - def commands = ["adb", "push", + def commands = [android.adbExecutable, "push", "${module_name}-${backend}-${project.version}-${variantLowered}.zip", - "/sdcard/"] + "/data/local/tmp/"] + if (is_windows) { + commandLine 'cmd', '/c', commands.join(" ") + } else { + commandLine commands + } + } + task("flash${backendCapped}${variantCapped}", type: Exec) { + dependsOn tasks.getByPath("push${backendCapped}${variantCapped}") + workingDir "${projectDir}/release" + def commands = [android.adbExecutable, "shell", "su", "-c", + "magisk --install-module /data/local/tmp/${module_name}-${backend}-${project.version}-${variantLowered}.zip"] + if (is_windows) { + commandLine 'cmd', '/c', commands.join(" ") + } else { + commandLine commands + } + } + task("flashAndReboot${backendCapped}${variantCapped}", type: Exec) { + dependsOn tasks.getByPath("flash${backendCapped}${variantCapped}") + workingDir "${projectDir}/release" + def commands = [android.adbExecutable, "shell", "reboot"] if (is_windows) { commandLine 'cmd', '/c', commands.join(" ") } else { diff --git a/edxp-core/misc/EdXposedUninstaller/META-INF/com/google/android/update-binary b/edxp-core/misc/EdXposedUninstaller/META-INF/com/google/android/update-binary index af620332..3cfa5b86 100644 --- a/edxp-core/misc/EdXposedUninstaller/META-INF/com/google/android/update-binary +++ b/edxp-core/misc/EdXposedUninstaller/META-INF/com/google/android/update-binary @@ -103,7 +103,6 @@ remove_edxposed() { ui_print "- Deleting EdXposed..." rm -r -f /data/adb/modules/riru_edxposed/ rm -r -f /data/adb/modules/riru_edxposed_sandhook/ - rm -r -f /data/adb/modules/riru_edxposed_whale/ rm -r -f /data/misc/riru/modules/edxposed/ rm -r -f /data/misc/riru/modules/edxp/ ui_print "- Done" diff --git a/edxp-core/src/main/cpp/CMakeLists.txt b/edxp-core/src/main/cpp/CMakeLists.txt index 257ee6e5..7d93e156 100644 --- a/edxp-core/src/main/cpp/CMakeLists.txt +++ b/edxp-core/src/main/cpp/CMakeLists.txt @@ -2,5 +2,10 @@ cmake_minimum_required(VERSION 3.4.1) link_libraries("-ffixed-x18") +add_definitions(-DRIRU_MODULE) +add_definitions(-DRIRU_MODULE_API_VERSION=${RIRU_MODULE_API_VERSION}) +add_definitions(-DRIRU_MODULE_VERSION=${RIRU_MODULE_VERSION}) +add_definitions(-DRIRU_MODULE_VERSION_NAME=${RIRU_MODULE_VERSION_NAME}) + add_subdirectory(main) add_subdirectory(external) \ No newline at end of file diff --git a/edxp-core/src/main/cpp/external/CMakeLists.txt b/edxp-core/src/main/cpp/external/CMakeLists.txt index 79df4435..3fd40857 100644 --- a/edxp-core/src/main/cpp/external/CMakeLists.txt +++ b/edxp-core/src/main/cpp/external/CMakeLists.txt @@ -3,5 +3,13 @@ cmake_minimum_required(VERSION 3.4.1) add_subdirectory(xhook) add_subdirectory(riru) add_subdirectory(yahfa) -add_subdirectory(substrate) -add_subdirectory(android) \ No newline at end of file +add_subdirectory(android) + +macro(SET_OPTION option value) + set(${option} ${value} CACHE INTERNAL "" FORCE) +endmacro() + +SET_OPTION(DOBBY_GENERATE_SHARED OFF) +add_subdirectory(Dobby) +target_include_directories(dobby PUBLIC Dobby/include) +target_include_directories(dobby PUBLIC Dobby/builtin-plugin/AndroidRestriction) \ No newline at end of file diff --git a/edxp-core/src/main/cpp/external/Dobby b/edxp-core/src/main/cpp/external/Dobby new file mode 160000 index 00000000..bb63fbef --- /dev/null +++ b/edxp-core/src/main/cpp/external/Dobby @@ -0,0 +1 @@ +Subproject commit bb63fbeff16ee275834f3207a7a687afeed4a2b0 diff --git a/edxp-core/src/main/cpp/external/riru/src/riru.c b/edxp-core/src/main/cpp/external/riru/src/riru.c index e471e642..e69de29b 100644 --- a/edxp-core/src/main/cpp/external/riru/src/riru.c +++ b/edxp-core/src/main/cpp/external/riru/src/riru.c @@ -1,118 +0,0 @@ -#include -#include -#include - -#ifdef __LP64__ -#define LIB "/system/lib64/libmemtrack.so" -#else -#define LIB "/system/lib/libmemtrack.so" -#endif - -static void *riru_handle; -static char *riru_module_name; - -static void *get_handle() { - if (riru_handle == NULL) - riru_handle = dlopen(LIB, RTLD_NOW | RTLD_GLOBAL); - - return riru_handle; -} - -const char *riru_get_module_name() { - return riru_module_name; -} - -void riru_set_module_name(const char *name) { - riru_module_name = strdup(name); -} - -int riru_get_version() { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return -1; - if (sym == NULL) sym = dlsym(handle, "riru_get_version"); - if (sym) return ((int (*)()) sym)(); - return -1; -} - -void *riru_get_func(const char *name) { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return NULL; - if (sym == NULL) sym = dlsym(handle, "riru_get_func"); - if (sym) return ((void *(*)(const char *, const char *)) sym)(riru_get_module_name(), name); - return NULL; -} - -void *riru_get_native_method_func(const char *className, const char *name, const char *signature) { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return NULL; - if (sym == NULL) sym = dlsym(handle, "riru_get_native_method_func"); - if (sym) - return ((void *(*)(const char *, const char *, const char *, const char *)) sym)( - riru_get_module_name(), className, name, signature); - return NULL; -} - -void riru_set_func(const char *name, void *func) { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return; - if (sym == NULL) sym = dlsym(handle, "riru_set_func"); - if (sym) - ((void *(*)(const char *, const char *, void *)) sym)(riru_get_module_name(), name, func); -} - -void riru_set_native_method_func(const char *className, const char *name, const char *signature, - void *func) { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return; - if (sym == NULL) sym = dlsym(handle, "riru_set_native_method_func"); - if (sym) - ((void *(*)(const char *, const char *, const char *, const char *, void *)) sym)( - riru_get_module_name(), className, name, signature, func); -} - -const JNINativeMethod *riru_get_original_native_methods(const char *className, const char *name, - const char *signature) { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return NULL; - if (sym == NULL) sym = dlsym(handle, "riru_get_original_native_methods"); - if (sym) - return ((JNINativeMethod *(*)(const char *, const char *, const char *)) sym) - (className, name, signature); - return NULL; -} - -int riru_is_zygote_methods_replaced() { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return 0; - if (sym == NULL) sym = dlsym(handle, "riru_is_zygote_methods_replaced"); - if (sym) - return ((int (*)()) sym)(); - return 0; -} - -int riru_get_nativeForkAndSpecialize_calls_count() { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return 0; - if (sym == NULL) sym = dlsym(handle, "riru_get_nativeForkAndSpecialize_calls_count"); - if (sym) - return ((int (*)()) sym)(); - return 0; -} - -int riru_get_nativeForkSystemServer_calls_count() { - static void **sym; - void *handle; - if ((handle = get_handle()) == NULL) return 0; - if (sym == NULL) sym = dlsym(handle, "riru_get_nativeForkSystemServer_calls_count"); - if (sym) - return ((int (*)()) sym)(); - return 0; -} \ No newline at end of file diff --git a/edxp-core/src/main/cpp/external/riru/src/riru.h b/edxp-core/src/main/cpp/external/riru/src/riru.h index 601a3d60..caaaed32 100644 --- a/edxp-core/src/main/cpp/external/riru/src/riru.h +++ b/edxp-core/src/main/cpp/external/riru/src/riru.h @@ -1,93 +1,169 @@ #ifndef RIRU_H #define RIRU_H -#include - #ifdef __cplusplus extern "C" { #endif -__attribute__((visibility("default"))) void riru_set_module_name(const char *name); -/** - * Get Riru version. - * - * @return Riru version - */ -int riru_get_version(); +#include +#include +#include + +// --------------------------------------------------------- + +typedef void(onModuleLoaded_v9)(); + +typedef int(shouldSkipUid_v9)(int uid); + +typedef void(nativeForkAndSpecializePre_v9)( + JNIEnv *env, jclass cls, jint *uid, jint *gid, jintArray *gids, jint *runtimeFlags, + jobjectArray *rlimits, jint *mountExternal, jstring *seInfo, jstring *niceName, + jintArray *fdsToClose, jintArray *fdsToIgnore, jboolean *is_child_zygote, + jstring *instructionSet, jstring *appDataDir, jboolean *isTopApp, jobjectArray *pkgDataInfoList, + jobjectArray *whitelistedDataInfoList, jboolean *bindMountAppDataDirs, jboolean *bindMountAppStorageDirs); + +typedef void(nativeForkAndSpecializePost_v9)(JNIEnv *env, jclass cls, jint res); + +typedef void(nativeForkSystemServerPre_v9)( + JNIEnv *env, jclass cls, uid_t *uid, gid_t *gid, jintArray *gids, jint *runtimeFlags, + jobjectArray *rlimits, jlong *permittedCapabilities, jlong *effectiveCapabilities); + +typedef void(nativeForkSystemServerPost_v9)(JNIEnv *env, jclass cls, jint res); + +typedef void(nativeSpecializeAppProcessPre_v9)( + JNIEnv *env, jclass cls, jint *uid, jint *gid, jintArray *gids, jint *runtimeFlags, + jobjectArray *rlimits, jint *mountExternal, jstring *seInfo, jstring *niceName, + jboolean *startChildZygote, jstring *instructionSet, jstring *appDataDir, + jboolean *isTopApp, jobjectArray *pkgDataInfoList, jobjectArray *whitelistedDataInfoList, + jboolean *bindMountAppDataDirs, jboolean *bindMountAppStorageDirs); + +typedef void(nativeSpecializeAppProcessPost_v9)(JNIEnv *env, jclass cls); + +typedef struct { + int supportHide; + int version; + const char *versionName; + onModuleLoaded_v9 *onModuleLoaded; + shouldSkipUid_v9 *shouldSkipUid; + nativeForkAndSpecializePre_v9 *forkAndSpecializePre; + nativeForkAndSpecializePost_v9 *forkAndSpecializePost; + nativeForkSystemServerPre_v9 *forkSystemServerPre; + nativeForkSystemServerPost_v9 *forkSystemServerPost; + nativeSpecializeAppProcessPre_v9 *specializeAppProcessPre; + nativeSpecializeAppProcessPost_v9 *specializeAppProcessPost; +} RiruModuleInfoV9; + +// --------------------------------------------------------- + +typedef void *(RiruGetFunc_v9)(uint32_t token, const char *name); + +typedef void (RiruSetFunc_v9)(uint32_t token, const char *name, void *func); + +typedef void *(RiruGetJNINativeMethodFunc_v9)(uint32_t token, const char *className, const char *name, const char *signature); + +typedef void (RiruSetJNINativeMethodFunc_v9)(uint32_t token, const char *className, const char *name, const char *signature, void *func); + +typedef const JNINativeMethod *(RiruGetOriginalJNINativeMethodFunc_v9)(const char *className, const char *name, const char *signature); + +typedef void *(RiruGetGlobalValue_v9)(const char *key); + +typedef void(RiruPutGlobalValue_v9)(const char *key, void *value); + +typedef struct { + + uint32_t token; + RiruGetFunc_v9 *getFunc; + RiruGetJNINativeMethodFunc_v9 *getJNINativeMethodFunc; + RiruSetFunc_v9 *setFunc; + RiruSetJNINativeMethodFunc_v9 *setJNINativeMethodFunc; + RiruGetOriginalJNINativeMethodFunc_v9 *getOriginalJNINativeMethodFunc; + RiruGetGlobalValue_v9 *getGlobalValue; + RiruPutGlobalValue_v9 *putGlobalValue; +} RiruApiV9; + +typedef void *(RiruInit_t)(void *); + +#ifdef RIRU_MODULE +#define RIRU_EXPORT __attribute__((visibility("default"))) __attribute__((used)) /* - * Get new_func address from last module which hook func. - * Use this as your old_func if you want to hook func. + * Init will be called three times. + * + * The first time: + * Returns the highest version number supported by both Riru and the module. + * + * arg: (int *) Riru's API version + * returns: (int *) the highest possible API version + * + * The second time: + * Returns the RiruModuleX struct created by the module (X is the return of the first call). + * + * arg: (RiruApiVX *) RiruApi strcut, this pointer can be saved for further use + * returns: (RiruModuleX *) RiruModule strcut + * + * The second time: + * Let the module to cleanup (such as RiruModuleX struct created before). + * + * arg: null + * returns: (ignored) * - * @param name a unique name - * @return new_func from last module or null */ -void *riru_get_func(const char *name); +void* init(void *arg) RIRU_EXPORT; -/* - * Java native version of riru_get_func. - * - * @param className class name - * @param name method name - * @param signature method signature - * @return new_func address from last module or original address - */ -void *riru_get_native_method_func(const char *className, const char *name, const char *signature); +extern int riru_api_version; +extern RiruApiV9 *riru_api_v9; -/* - * Set new_func address for next module which wants to hook func. - * - * @param name a unique name - * @param func your new_func address - */ -void riru_set_func(const char *name, void *func); +inline void *riru_get_func(const char *name) { + if (riru_api_version == 9) { + return riru_api_v9->getFunc(riru_api_v9->token, name); + } + return NULL; +} -/* - * Java native method version of riru_set_func. - * - * @param className class name - * @param name method name - * @param signature method signature - * @param func your new_func address - */ -void riru_set_native_method_func(const char *className, const char *name, const char *signature, - void *func); +inline void *riru_get_native_method_func(const char *className, const char *name, const char *signature) { + if (riru_api_version == 9) { + return riru_api_v9->getJNINativeMethodFunc(riru_api_v9->token, className, name, signature); + } + return NULL; +} -/** - * Get native methods from Riru's jniRegisterNativeMethods hook. - * If both name and signature are null, all the class's methods will be returned. - * - * @param className className - * @param name method name, null for the method with specific signature - * @param signature method signature, null for the method with specific name - * @return JNINativeMethod* - */ -const JNINativeMethod *riru_get_original_native_methods(const char *className, const char *name, - const char *signature); +inline const JNINativeMethod *riru_get_original_native_methods(const char *className, const char *name, const char *signature) { + if (riru_api_version == 9) { + return riru_api_v9->getOriginalJNINativeMethodFunc(className, name, signature); + } + return NULL; +} -/** - * Return if Zygote class's native method nativeForkAndSpecialize & nativeForkSystemServer is replaced by - * Riru. - * - * @return methods replaced - */ -int riru_is_zygote_methods_replaced(); +inline void riru_set_func(const char *name, void *func) { + if (riru_api_version == 9) { + riru_api_v9->setFunc(riru_api_v9->token, name, func); + } +} -/** - * Return calls count of Zygote class's native method nativeForkAndSpecialize replaced by Riru. - * - * @return nativeForkAndSpecialize calls count - */ -int riru_get_nativeForkAndSpecialize_calls_count(); +inline void riru_set_native_method_func(const char *className, const char *name, const char *signature, + void *func) { + if (riru_api_version == 9) { + riru_api_v9->setJNINativeMethodFunc(riru_api_v9->token, className, name, signature, func); + } +} + +inline void *riru_get_global_value(const char *key) { + if (riru_api_version == 9) { + return riru_api_v9->getGlobalValue(key); + } + return NULL; +} + +inline void riru_put_global_value(const char *key, void *value) { + if (riru_api_version == 9) { + riru_api_v9->putGlobalValue(key, value); + } +} + +#endif -/** - * Return calls count of Zygote class native's method nativeForkSystemServer replaced by Riru. - * - * @return nativeForkAndSpecialize calls count - */ -int riru_get_nativeForkSystemServer_calls_count(); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif //RIRU_H \ No newline at end of file diff --git a/edxp-core/src/main/cpp/external/substrate/CMakeLists.txt b/edxp-core/src/main/cpp/external/substrate/CMakeLists.txt deleted file mode 100644 index b92c5574..00000000 --- a/edxp-core/src/main/cpp/external/substrate/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -cmake_minimum_required(VERSION 3.4.1) - -aux_source_directory(src SRC_LIST) -add_library(substrate STATIC ${SRC_LIST}) - -target_include_directories(substrate INTERFACE src) \ No newline at end of file diff --git a/edxp-core/src/main/cpp/external/substrate/src/Buffer.hpp b/edxp-core/src/main/cpp/external/substrate/src/Buffer.hpp deleted file mode 100644 index 34d9df32..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/Buffer.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#ifndef SUBSTRATE_BUFFER_HPP -#define SUBSTRATE_BUFFER_HPP - -#include - -template -_disused static _finline void MSWrite(uint8_t *&buffer, Type_ value) { - *reinterpret_cast(buffer) = value; - buffer += sizeof(Type_); -} - -_disused static _finline void MSWrite(uint8_t *&buffer, uint8_t *data, size_t size) { - memcpy(buffer, data, size); - buffer += size; -} - -#endif//SUBSTRATE_BUFFER_HPP diff --git a/edxp-core/src/main/cpp/external/substrate/src/CydiaSubstrate.h b/edxp-core/src/main/cpp/external/substrate/src/CydiaSubstrate.h deleted file mode 100644 index bb806aa9..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/CydiaSubstrate.h +++ /dev/null @@ -1,152 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#ifndef SUBSTRATE_H_ -#define SUBSTRATE_H_ - -#ifdef __APPLE__ -#ifdef __cplusplus -extern "C" { -#endif -#include -#ifdef __cplusplus -} -#endif - -#include -#include -#endif - -#include -#include - -#define _finline \ - inline __attribute__((__always_inline__)) -#define _disused \ - __attribute__((__unused__)) - -#define _extern \ - extern "C" __attribute__((__visibility__("default"))) - -#ifdef __cplusplus -#define _default(value) = value -#else -#define _default(value) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -bool MSHookProcess(pid_t pid, const char *library); - -typedef const void *MSImageRef; - -MSImageRef MSGetImageByName(const char *file); -void *MSFindSymbol(MSImageRef image, const char *name); - -void MSHookFunction(void *symbol, void *replace, void **result); - -#ifdef __APPLE__ -#ifdef __arm__ -__attribute__((__deprecated__)) -IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix _default(NULL)); -#endif -void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result); -#endif - -#ifdef SubstrateInternal -typedef void *SubstrateAllocatorRef; -typedef struct __SubstrateProcess *SubstrateProcessRef; -typedef struct __SubstrateMemory *SubstrateMemoryRef; - -SubstrateProcessRef SubstrateProcessCreate(SubstrateAllocatorRef allocator, pid_t pid); -void SubstrateProcessRelease(SubstrateProcessRef process); - -SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size); -void SubstrateMemoryRelease(SubstrateMemoryRef memory); -#endif - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -#ifdef SubstrateInternal -struct SubstrateHookMemory { - SubstrateMemoryRef handle_; - - SubstrateHookMemory(SubstrateProcessRef process, void *data, size_t size) : - handle_(SubstrateMemoryCreate(NULL, NULL, data, size)) - { - } - - ~SubstrateHookMemory() { - if (handle_ != NULL) - SubstrateMemoryRelease(handle_); - } -}; -#endif - - -template -static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) { - MSHookFunction( - reinterpret_cast(symbol), - reinterpret_cast(replace), - reinterpret_cast(result) - ); -} - -template -static inline void MSHookFunction(Type_ *symbol, Type_ *replace) { - return MSHookFunction(symbol, replace, reinterpret_cast(NULL)); -} - -template -static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) { - value = reinterpret_cast(MSFindSymbol(image, name)); -} - -template -static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) { - Type_ *symbol; - MSHookSymbol(symbol, name); - return MSHookFunction(symbol, replace, result); -} - -#endif - -#define MSHook(type, name, args...) \ - _disused static type (*_ ## name)(args); \ - static type $ ## name(args) - -#ifdef __cplusplus -#define MSHake(name) \ - &$ ## name, &_ ## name -#else -#define MSHake(name) \ - &$ ## name, (void **) &_ ## name -#endif - - -#endif//SUBSTRATE_H_ diff --git a/edxp-core/src/main/cpp/external/substrate/src/SubstrateARM.hpp b/edxp-core/src/main/cpp/external/substrate/src/SubstrateARM.hpp deleted file mode 100644 index 564b61d3..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/SubstrateARM.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#ifndef SUBSTRATE_ARM_HPP -#define SUBSTRATE_ARM_HPP - -enum A$r { - A$r0, A$r1, A$r2, A$r3, - A$r4, A$r5, A$r6, A$r7, - A$r8, A$r9, A$r10, A$r11, - A$r12, A$r13, A$r14, A$r15, - A$sp = A$r13, - A$lr = A$r14, - A$pc = A$r15 -}; - -enum A$c { - A$eq, A$ne, A$cs, A$cc, - A$mi, A$pl, A$vs, A$vc, - A$hi, A$ls, A$ge, A$lt, - A$gt, A$le, A$al, - A$hs = A$cs, - A$lo = A$cc -}; - -template static T xabs(T _Val); - -#define A$mrs_rm_cpsr(rd) /* mrs rd, cpsr */ \ - (0xe10f0000 | ((rd) << 12)) -#define A$msr_cpsr_f_rm(rm) /* msr cpsr_f, rm */ \ - (0xe128f000 | (rm)) -#define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \ - (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | xabs(im)) -#define A$str_rd_$rn_im$(rd, rn, im) /* sr rd, [rn, #im] */ \ - (0xe5000000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | xabs(im)) -#define A$sub_rd_rn_$im(rd, rn, im) /* sub, rd, rn, #im */ \ - (0xe2400000 | ((rn) << 16) | ((rd) << 12) | (im & 0xff)) -#define A$blx_rm(rm) /* blx rm */ \ - (0xe12fff30 | (rm)) -#define A$mov_rd_rm(rd, rm) /* mov rd, rm */ \ - (0xe1a00000 | ((rd) << 12) | (rm)) -#define A$ldmia_sp$_$rs$(rs) /* ldmia sp!, {rs} */ \ - (0xe8b00000 | (A$sp << 16) | (rs)) -#define A$stmdb_sp$_$rs$(rs) /* stmdb sp!, {rs} */ \ - (0xe9200000 | (A$sp << 16) | (rs)) -#define A$stmia_sp$_$r0$ 0xe8ad0001 /* stmia sp!, {r0} */ -#define A$bx_r0 0xe12fff10 /* bx r0 */ - -#endif//SUBSTRATE_ARM_HPP diff --git a/edxp-core/src/main/cpp/external/substrate/src/SubstrateDebug.cpp b/edxp-core/src/main/cpp/external/substrate/src/SubstrateDebug.cpp deleted file mode 100644 index 2df6ef48..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/SubstrateDebug.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#include "SubstrateHook.h" -#include "SubstrateDebug.hpp" - -#include -#include -#include - -_extern bool MSDebug; -bool MSDebug = false; - -static char _MSHexChar(uint8_t value) { - return value < 0x20 || value >= 0x80 ? '.' : value; -} - -#define HexWidth_ 16 -#define HexDepth_ 4 - -void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark) { - const uint8_t *data((const uint8_t *) vdata); - - size_t i(0), j; - - char d[256]; - size_t b(0); - d[0] = '\0'; - - while (i != size) { - if (i % HexWidth_ == 0) { - if (mark != NULL) - b += sprintf(d + b, "\n[%s] ", mark); - b += sprintf(d + b, "0x%.3zx:", i); - } - - b += sprintf(d + b, " "); - - for (size_t q(0); q != stride; ++q) - b += sprintf(d + b, "%.2x", data[i + stride - q - 1]); - - i += stride; - - for (size_t q(1); q != stride; ++q) - b += sprintf(d + b, " "); - - if (i % HexDepth_ == 0) - b += sprintf(d + b, " "); - - if (i % HexWidth_ == 0) { - b += sprintf(d + b, " "); - for (j = i - HexWidth_; j != i; ++j) - b += sprintf(d + b, "%c", _MSHexChar(data[j])); - - lprintf("%s", d); - b = 0; - d[0] = '\0'; - } - } - - if (i % HexWidth_ != 0) { - for (j = i % HexWidth_; j != HexWidth_; ++j) - b += sprintf(d + b, " "); - for (j = 0; j != (HexWidth_ - i % HexWidth_ + HexDepth_ - 1) / HexDepth_; ++j) - b += sprintf(d + b, " "); - b += sprintf(d + b, " "); - for (j = i / HexWidth_ * HexWidth_; j != i; ++j) - b += sprintf(d + b, "%c", _MSHexChar(data[j])); - - lprintf("%s", d); - b = 0; - d[0] = '\0'; - } -} - -void MSLogHex(const void *vdata, size_t size, const char *mark) { - return MSLogHexEx(vdata, size, 1, mark); -} diff --git a/edxp-core/src/main/cpp/external/substrate/src/SubstrateDebug.hpp b/edxp-core/src/main/cpp/external/substrate/src/SubstrateDebug.hpp deleted file mode 100644 index 9c554c85..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/SubstrateDebug.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#ifndef SUBSTRATE_DEBUG_HPP -#define SUBSTRATE_DEBUG_HPP - -#include "SubstrateLog.hpp" -#define lprintf(format, ...) \ - MSLog(MSLogLevelNotice, format, ## __VA_ARGS__) - -extern "C" bool MSDebug; -void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark = 0); -void MSLogHex(const void *vdata, size_t size, const char *mark = 0); - -#endif//SUBSTRATE_DEBUG_HPP diff --git a/edxp-core/src/main/cpp/external/substrate/src/SubstrateHook.cpp b/edxp-core/src/main/cpp/external/substrate/src/SubstrateHook.cpp deleted file mode 100644 index 7c38240f..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/SubstrateHook.cpp +++ /dev/null @@ -1,945 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#define SubstrateInternal -#include "CydiaSubstrate.h" - -#include - -#define _trace() do { \ - MSLog(MSLogLevelNotice, "_trace(%u)", __LINE__); \ -} while (false) - -#if defined(__i386__) || defined(__x86_64__) -#include "hde64.h" -#endif - -#include "SubstrateDebug.hpp" - -#include -#include -#include -#include - -#ifdef __arm__ -/* WebCore (ARM) PC-Relative: -X 1 ldr r*,[pc,r*] != - 2 fldd d*,[pc,#*] -X 5 str r*,[pc,r*] != - 8 flds s*,[pc,#*] - 400 ldr r*,[pc,r*] == - 515 add r*, pc,r* == -X 4790 ldr r*,[pc,#*] */ - -// x=0; while IFS= read -r line; do if [[ ${#line} -ne 0 && $line == +([^\;]): ]]; then x=2; elif [[ $line == ' +'* && $x -ne 0 ]]; then ((--x)); echo "$x${line}"; fi; done WebCore.pc -// grep pc WebCore.pc | cut -c 40- | sed -Ee 's/^ldr *(ip|r[0-9]*),\[pc,\#0x[0-9a-f]*\].*/ ldr r*,[pc,#*]/;s/^add *r[0-9]*,pc,r[0-9]*.*/ add r*, pc,r*/;s/^(st|ld)r *r([0-9]*),\[pc,r([0-9]*)\].*/ \1r r\2,[pc,r\3]/;s/^fld(s|d) *(s|d)[0-9]*,\[pc,#0x[0-9a-f]*].*/fld\1 \2*,[pc,#*]/' | sort | uniq -c | sort -n - -#include "SubstrateARM.hpp" - -#define T$Label(l, r) \ - (((r) - (l)) * 2 - 4 + ((l) % 2 == 0 ? 0 : 2)) - -#define T$pop_$r0$ 0xbc01 // pop {r0} -#define T$b(im) /* b im */ \ - (0xde00 | (im & 0xff)) -#define T$blx(rm) /* blx rm */ \ - (0x4780 | (rm << 3)) -#define T$bx(rm) /* bx rm */ \ - (0x4700 | (rm << 3)) -#define T$nop /* nop */ \ - (0x46c0) - -#define T$add_rd_rm(rd, rm) /* add rd, rm */ \ - (0x4400 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) -#define T$push_r(r) /* push r... */ \ - (0xb400 | (((r) & (1 << A$lr)) >> A$lr << 8) | ((r) & 0xff)) -#define T$pop_r(r) /* pop r... */ \ - (0xbc00 | (((r) & (1 << A$pc)) >> A$pc << 8) | ((r) & 0xff)) -#define T$mov_rd_rm(rd, rm) /* mov rd, rm */ \ - (0x4600 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) -#define T$ldr_rd_$rn_im_4$(rd, rn, im) /* ldr rd, [rn, #im * 4] */ \ - (0x6800 | (((im) & 0x1f) << 6) | ((rn) << 3) | (rd)) -#define T$ldr_rd_$pc_im_4$(rd, im) /* ldr rd, [PC, #im * 4] */ \ - (0x4800 | ((rd) << 8) | ((im) & 0xff)) -#define T$cmp_rn_$im(rn, im) /* cmp rn, #im */ \ - (0x2000 | ((rn) << 8) | ((im) & 0xff)) -#define T$it$_cd(cd, ms) /* it, cd */ \ - (0xbf00 | ((cd) << 4) | (ms)) -#define T$cbz$_rn_$im(op,rn,im) /* cbz rn, #im */ \ - (0xb100 | ((op) << 11) | (((im) & 0x40) >> 6 << 9) | (((im) & 0x3e) >> 1 << 3) | (rn)) -#define T$b$_$im(cond,im) /* b #im */ \ - (cond == A$al ? 0xe000 | (((im) >> 1) & 0x7ff) : 0xd000 | ((cond) << 8) | (((im) >> 1) & 0xff)) - -#define T1$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ - (0xf850 | ((im < 0 ? 0 : 1) << 7) | (rn)) - -template T xabs(T _Val) -{ - typedef int BOOL; - if(_Val>T(0))return _Val; - return -_Val; -} - -#define T2$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ - (((rt) << 12) | xabs(im)) - -#define T1$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ - (0xf3ef) -#define T2$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ - (0x8000 | ((rd) << 8)) - -#define T1$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ - (0xf380 | (rn)) -#define T2$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ - (0x8c00) -#define T$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ - (T2$msr_apsr_nzcvqg_rn(rn) << 16 | T1$msr_apsr_nzcvqg_rn(rn)) - -static inline bool A$pcrel$r(uint32_t ic) { - return (ic & 0x0c000000) == 0x04000000 && (ic & 0xf0000000) != 0xf0000000 && (ic & 0x000f0000) == 0x000f0000; -} - -static inline bool T$32bit$i(uint16_t ic) { - return ((ic & 0xe000) == 0xe000 && (ic & 0x1800) != 0x0000); -} - -static inline bool T$pcrel$cbz(uint16_t ic) { - return (ic & 0xf500) == 0xb100; -} - -static inline bool T$pcrel$b(uint16_t ic) { - return (ic & 0xf000) == 0xd000 && (ic & 0x0e00) != 0x0e00; -} - -static inline bool T2$pcrel$b(uint16_t *ic) { - return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0x9000 || (ic[1] & 0xd000) == 0x8000 && (ic[0] & 0x0380) != 0x0380); -} - -static inline bool T$pcrel$bl(uint16_t *ic) { - return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0xd000 || (ic[1] & 0xd001) == 0xc000); -} - -static inline bool T$pcrel$ldr(uint16_t ic) { - return (ic & 0xf800) == 0x4800; -} - -static inline bool T$pcrel$add(uint16_t ic) { - return (ic & 0xff78) == 0x4478; -} - -static inline bool T$pcrel$ldrw(uint16_t ic) { - return (ic & 0xff7f) == 0xf85f; -} - -static size_t MSGetInstructionWidthThumb(void *start) { - uint16_t *thumb(reinterpret_cast(start)); - return T$32bit$i(thumb[0]) ? 4 : 2; -} - -static size_t MSGetInstructionWidthARM(void *start) { - return 4; -} - -extern "C" size_t MSGetInstructionWidth(void *start) { - if ((reinterpret_cast(start) & 0x1) == 0) - return MSGetInstructionWidthARM(start); - else - return MSGetInstructionWidthThumb(reinterpret_cast(reinterpret_cast(start) & ~0x1)); -} - -static size_t SubstrateHookFunctionThumb(SubstrateProcessRef process, void *symbol, void *replace, void **result) { - if (symbol == NULL) - return 0; -printf("SubstrateHookFunctionThumb\n"); - uint16_t *area(reinterpret_cast(symbol)); - - unsigned align((reinterpret_cast(area) & 0x2) == 0 ? 0 : 1); - uint16_t *thumb(area + align); - - uint32_t *arm(reinterpret_cast(thumb + 2)); - uint16_t *trail(reinterpret_cast(arm + 2)); - - if ( - (align == 0 || area[0] == T$nop) && - thumb[0] == T$bx(A$pc) && - thumb[1] == T$nop && - arm[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8) - ) { - if (result != NULL) - *result = reinterpret_cast(arm[1]); - - SubstrateHookMemory code(process, arm + 1, sizeof(uint32_t) * 1); - - arm[1] = reinterpret_cast(replace); - - return sizeof(arm[0]); - } - - size_t required((trail - area) * sizeof(uint16_t)); - - size_t used(0); - while (used < required) - used += MSGetInstructionWidthThumb(reinterpret_cast(area) + used); - used = (used + sizeof(uint16_t) - 1) / sizeof(uint16_t) * sizeof(uint16_t); - - size_t blank((used - required) / sizeof(uint16_t)); - - uint16_t backup[used / sizeof(uint16_t)]; - memcpy(backup, area, used); - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", area); - MSLogHexEx(area, used + sizeof(uint16_t), 2, name); - } - - if (result != NULL) { - - size_t length(used); - for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) - if (T$pcrel$ldr(backup[offset])) - length += 3 * sizeof(uint16_t); - else if (T$pcrel$b(backup[offset])) - length += 6 * sizeof(uint16_t); - else if (T2$pcrel$b(backup + offset)) { - length += 5 * sizeof(uint16_t); - ++offset; - } else if (T$pcrel$bl(backup + offset)) { - length += 5 * sizeof(uint16_t); - ++offset; - } else if (T$pcrel$cbz(backup[offset])) { - length += 16 * sizeof(uint16_t); - } else if (T$pcrel$ldrw(backup[offset])) { - length += 4 * sizeof(uint16_t); - ++offset; - } else if (T$pcrel$add(backup[offset])) - length += 6 * sizeof(uint16_t); - else if (T$32bit$i(backup[offset])) - ++offset; - - unsigned pad((length & 0x2) == 0 ? 0 : 1); - length += (pad + 2) * sizeof(uint16_t) + 2 * sizeof(uint32_t); - - uint16_t *buffer(reinterpret_cast(mmap( - NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 - ))); - - if (buffer == MAP_FAILED) { - MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); - *result = NULL; - return 0; - } - - if (false) fail: { - munmap(buffer, length); - *result = NULL; - return 0; - } - - size_t start(pad), end(length / sizeof(uint16_t)); - uint32_t *trailer(reinterpret_cast(buffer + end)); - for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) { - if (T$pcrel$ldr(backup[offset])) { - union { - uint16_t value; - - struct { - uint16_t immediate : 8; - uint16_t rd : 3; - uint16_t : 5; - }; - } bits = {backup[offset+0]}; - - buffer[start+0] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+0, end-2) / 4); - buffer[start+1] = T$ldr_rd_$rn_im_4$(bits.rd, bits.rd, 0); - - // XXX: this code "works", but is "wrong": the mechanism is more complex than this - *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + bits.immediate * 4; - - start += 2; - end -= 2; - } else if (T$pcrel$b(backup[offset])) { - union { - uint16_t value; - - struct { - uint16_t imm8 : 8; - uint16_t cond : 4; - uint16_t /*1101*/ : 4; - }; - } bits = {backup[offset+0]}; - - intptr_t jump(bits.imm8 << 1); - jump |= 1; - jump <<= 23; - jump >>= 23; - - buffer[start+0] = T$b$_$im(bits.cond, (end-6 - (start+0)) * 2 - 4); - - *--trailer = reinterpret_cast(area + offset) + 4 + jump; - *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); - *--trailer = T$nop << 16 | T$bx(A$pc); - - start += 1; - end -= 6; - } else if (T2$pcrel$b(backup + offset)) { - union { - uint16_t value; - - struct { - uint16_t imm6 : 6; - uint16_t cond : 4; - uint16_t s : 1; - uint16_t : 5; - }; - } bits = {backup[offset+0]}; - - union { - uint16_t value; - - struct { - uint16_t imm11 : 11; - uint16_t j2 : 1; - uint16_t a : 1; - uint16_t j1 : 1; - uint16_t : 2; - }; - } exts = {backup[offset+1]}; - - intptr_t jump(1); - jump |= exts.imm11 << 1; - jump |= bits.imm6 << 12; - - if (exts.a) { - jump |= bits.s << 24; - jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; - jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; - jump |= bits.cond << 18; - jump <<= 7; - jump >>= 7; - } else { - jump |= bits.s << 20; - jump |= exts.j2 << 19; - jump |= exts.j1 << 18; - jump <<= 11; - jump >>= 11; - } - - buffer[start+0] = T$b$_$im(exts.a ? A$al : bits.cond, (end-6 - (start+0)) * 2 - 4); - - *--trailer = reinterpret_cast(area + offset) + 4 + jump; - *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); - *--trailer = T$nop << 16 | T$bx(A$pc); - - ++offset; - start += 1; - end -= 6; - } else if (T$pcrel$bl(backup + offset)) { - union { - uint16_t value; - - struct { - uint16_t immediate : 10; - uint16_t s : 1; - uint16_t : 5; - }; - } bits = {backup[offset+0]}; - - union { - uint16_t value; - - struct { - uint16_t immediate : 11; - uint16_t j2 : 1; - uint16_t x : 1; - uint16_t j1 : 1; - uint16_t : 2; - }; - } exts = {backup[offset+1]}; - - int32_t jump(0); - jump |= bits.s << 24; - jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; - jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; - jump |= bits.immediate << 12; - jump |= exts.immediate << 1; - jump |= exts.x; - jump <<= 7; - jump >>= 7; - - buffer[start+0] = T$push_r(1 << A$r7); - buffer[start+1] = T$ldr_rd_$pc_im_4$(A$r7, ((end-2 - (start+1)) * 2 - 4 + 2) / 4); - buffer[start+2] = T$mov_rd_rm(A$lr, A$r7); - buffer[start+3] = T$pop_r(1 << A$r7); - buffer[start+4] = T$blx(A$lr); - - *--trailer = reinterpret_cast(area + offset) + 4 + jump; - - ++offset; - start += 5; - end -= 2; - } else if (T$pcrel$cbz(backup[offset])) { - union { - uint16_t value; - - struct { - uint16_t rn : 3; - uint16_t immediate : 5; - uint16_t : 1; - uint16_t i : 1; - uint16_t : 1; - uint16_t op : 1; - uint16_t : 4; - }; - } bits = {backup[offset+0]}; - - intptr_t jump(1); - jump |= bits.i << 6; - jump |= bits.immediate << 1; - - //jump <<= 24; - //jump >>= 24; - - unsigned rn(bits.rn); - unsigned rt(rn == A$r7 ? A$r6 : A$r7); - - buffer[start+0] = T$push_r(1 << rt); - buffer[start+1] = T1$mrs_rd_apsr(rt); - buffer[start+2] = T2$mrs_rd_apsr(rt); - buffer[start+3] = T$cbz$_rn_$im(bits.op, rn, (end-10 - (start+3)) * 2 - 4); - buffer[start+4] = T1$msr_apsr_nzcvqg_rn(rt); - buffer[start+5] = T2$msr_apsr_nzcvqg_rn(rt); - buffer[start+6] = T$pop_r(1 << rt); - - *--trailer = reinterpret_cast(area + offset) + 4 + jump; - *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); - *--trailer = T$nop << 16 | T$bx(A$pc); - *--trailer = T$nop << 16 | T$pop_r(1 << rt); - *--trailer = T$msr_apsr_nzcvqg_rn(rt); - -#if 0 - if ((start & 0x1) == 0) - buffer[start++] = T$nop; - buffer[start++] = T$bx(A$pc); - buffer[start++] = T$nop; - - uint32_t *arm(reinterpret_cast(buffer + start)); - arm[0] = A$add(A$lr, A$pc, 1); - arm[1] = A$ldr_rd_$rn_im$(A$pc, A$pc, (trailer - arm) * sizeof(uint32_t) - 8); -#endif - - start += 7; - end -= 10; - } else if (T$pcrel$ldrw(backup[offset])) { - union { - uint16_t value; - - struct { - uint16_t : 7; - uint16_t u : 1; - uint16_t : 8; - }; - } bits = {backup[offset+0]}; - - union { - uint16_t value; - - struct { - uint16_t immediate : 12; - uint16_t rt : 4; - }; - } exts = {backup[offset+1]}; - - buffer[start+0] = T1$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); - buffer[start+1] = T2$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); - - buffer[start+2] = T1$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); - buffer[start+3] = T2$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); - - // XXX: this code "works", but is "wrong": the mechanism is more complex than this - *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + (bits.u == 0 ? -exts.immediate : exts.immediate); - - ++offset; - start += 4; - end -= 2; - } else if (T$pcrel$add(backup[offset])) { - union { - uint16_t value; - - struct { - uint16_t rd : 3; - uint16_t rm : 3; - uint16_t h2 : 1; - uint16_t h1 : 1; - uint16_t : 8; - }; - } bits = {backup[offset+0]}; - - if (bits.h1) { - MSLog(MSLogLevelError, "MS:Error:pcrel(%u):add (rd > r7)", offset); - goto fail; - } - - unsigned rt(bits.rd == A$r7 ? A$r6 : A$r7); - - buffer[start+0] = T$push_r(1 << rt); - buffer[start+1] = T$mov_rd_rm(rt, (bits.h1 << 3) | bits.rd); - buffer[start+2] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+2, end-2) / 4); - buffer[start+3] = T$add_rd_rm((bits.h1 << 3) | bits.rd, rt); - buffer[start+4] = T$pop_r(1 << rt); - *--trailer = reinterpret_cast(area + offset) + 4; - - start += 5; - end -= 2; - } else if (T$32bit$i(backup[offset])) { - buffer[start++] = backup[offset]; - buffer[start++] = backup[++offset]; - } else { - buffer[start++] = backup[offset]; - } - } - - buffer[start++] = T$bx(A$pc); - buffer[start++] = T$nop; - - uint32_t *transfer = reinterpret_cast(buffer + start); - transfer[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); - transfer[1] = reinterpret_cast(area + used / sizeof(uint16_t)) + 1; - - if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { - MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); - return 0; - } - - *result = reinterpret_cast(buffer + pad) + 1; - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", *result); - MSLogHexEx(buffer, length, 2, name); - } - - } - - { - SubstrateHookMemory code(process, area, used); - - if (align != 0) - area[0] = T$nop; - - thumb[0] = T$bx(A$pc); - thumb[1] = T$nop; - - arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); - arm[1] = reinterpret_cast(replace); - - for (unsigned offset(0); offset != blank; ++offset) - trail[offset] = T$nop; - } - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", area); - MSLogHexEx(area, used + sizeof(uint16_t), 2, name); - } - - return used; -} - -static size_t SubstrateHookFunctionARM(SubstrateProcessRef process, void *symbol, void *replace, void **result) { - if (symbol == NULL) - return 0; -printf("SubstrateHookFunctionARM\n"); - uint32_t *area(reinterpret_cast(symbol)); - uint32_t *arm(area); - - const size_t used(8); - - uint32_t backup[used / sizeof(uint32_t)] = {arm[0], arm[1]}; - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", area); - MSLogHexEx(area, used + sizeof(uint32_t), 4, name); - } - - if (result != NULL) { - - if (backup[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8)) { - *result = reinterpret_cast(backup[1]); - - return sizeof(backup[0]); - } - - size_t length(used); - for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) - if (A$pcrel$r(backup[offset])) { - if ((backup[offset] & 0x02000000) == 0 || (backup[offset] & 0x0000f000 >> 12) != (backup[offset] & 0x0000000f)) - length += 2 * sizeof(uint32_t); - else - length += 4 * sizeof(uint32_t); - } - - length += 2 * sizeof(uint32_t); - - uint32_t *buffer(reinterpret_cast(mmap( - NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 - ))); - - if (buffer == MAP_FAILED) { - MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); - *result = NULL; - return 0; - } - - if (false) fail: { - munmap(buffer, length); - *result = NULL; - return 0; - } - - size_t start(0), end(length / sizeof(uint32_t)); - uint32_t *trailer(reinterpret_cast(buffer + end)); - for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) - if (A$pcrel$r(backup[offset])) { - union { - uint32_t value; - - struct { - uint32_t rm : 4; - uint32_t : 1; - uint32_t shift : 2; - uint32_t shiftamount : 5; - uint32_t rd : 4; - uint32_t rn : 4; - uint32_t l : 1; - uint32_t w : 1; - uint32_t b : 1; - uint32_t u : 1; - uint32_t p : 1; - uint32_t mode : 1; - uint32_t type : 2; - uint32_t cond : 4; - }; - } bits = {backup[offset+0]}, copy(bits); - - bool guard; - if (bits.mode == 0 || bits.rd != bits.rm) { - copy.rn = bits.rd; - guard = false; - } else { - copy.rn = bits.rm != A$r0 ? A$r0 : A$r1; - guard = true; - } - - if (guard) - buffer[start++] = A$stmdb_sp$_$rs$((1 << copy.rn)); - - buffer[start+0] = A$ldr_rd_$rn_im$(copy.rn, A$pc, (end-1 - (start+0)) * 4 - 8); - buffer[start+1] = copy.value; - - start += 2; - - if (guard) - buffer[start++] = A$ldmia_sp$_$rs$((1 << copy.rn)); - - *--trailer = reinterpret_cast(area + offset) + 8; - end -= 1; - } else - buffer[start++] = backup[offset]; - - buffer[start+0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); - buffer[start+1] = reinterpret_cast(area + used / sizeof(uint32_t)); - - if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { - MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); - goto fail; - } - - *result = buffer; - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", *result); - MSLogHexEx(buffer, length, 4, name); - } - - } - - { - SubstrateHookMemory code(process, symbol, used); - - arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); - arm[1] = reinterpret_cast(replace); - } - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", area); - MSLogHexEx(area, used + sizeof(uint32_t), 4, name); - } - - return used; -} - -static size_t SubstrateHookFunction(SubstrateProcessRef process, void *symbol, void *replace, void **result) { - if (MSDebug) - MSLog(MSLogLevelNotice, "SubstrateHookFunction(%p, %p, %p, %p)\n", process, symbol, replace, result); - if ((reinterpret_cast(symbol) & 0x1) == 0) - return SubstrateHookFunctionARM(process, symbol, replace, result); - else - return SubstrateHookFunctionThumb(process, reinterpret_cast(reinterpret_cast(symbol) & ~0x1), replace, result); -} -#endif - -#if defined(__i386__) || defined(__x86_64__) - -#include "SubstrateX86.hpp" - -static size_t MSGetInstructionWidthIntel(void *start) { - hde64s decode; - return hde64_disasm(start, &decode); -} - -static void SubstrateHookFunction(SubstrateProcessRef process, void *symbol, void *replace, void **result) { - if (MSDebug) - MSLog(MSLogLevelNotice, "MSHookFunction(%p, %p, %p)\n", symbol, replace, result); - if (symbol == NULL) - return; - - uintptr_t source(reinterpret_cast(symbol)); - uintptr_t target(reinterpret_cast(replace)); - - uint8_t *area(reinterpret_cast(symbol)); - - size_t required(MSSizeOfJump(target, source)); - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", area); - MSLogHex(area, 32, name); - } - - size_t used(0); - while (used < required) { - size_t width(MSGetInstructionWidthIntel(area + used)); - if (width == 0) { - MSLog(MSLogLevelError, "MS:Error:MSGetInstructionWidthIntel(%p) == 0", area + used); - return; - } - - used += width; - } - - size_t blank(used - required); - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", area); - MSLogHex(area, used + sizeof(uint16_t), name); - } - - uint8_t backup[used]; - memcpy(backup, area, used); - - if (result != NULL) { - - if (backup[0] == 0xe9) { - *result = reinterpret_cast(source + 5 + *reinterpret_cast(backup + 1)); - return; - } - - if (!ia32 && backup[0] == 0xff && backup[1] == 0x25) { - *result = *reinterpret_cast(source + 6 + *reinterpret_cast(backup + 2)); - return; - } - - size_t length(used + MSSizeOfJump(source + used)); - - for (size_t offset(0), width; offset != used; offset += width) { - hde64s decode; - hde64_disasm(backup + offset, &decode); - width = decode.len; - //_assert(width != 0 && offset + width <= used); - -#ifdef __LP64__ - if ((decode.modrm & 0xc7) == 0x05) { - if (decode.opcode == 0x8b) { - void *destiny(area + offset + width + int32_t(decode.disp.disp32)); - uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); - length -= decode.len; - length += MSSizeOfPushPointer(destiny); - length += MSSizeOfPop(reg); - length += MSSizeOfMove64(); - } else { - MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); - continue; - } - } else -#endif - - if (backup[offset] == 0xe8) { - int32_t relative(*reinterpret_cast(backup + offset + 1)); - void *destiny(area + offset + decode.len + relative); - - if (relative == 0) { - length -= decode.len; - length += MSSizeOfPushPointer(destiny); - } else { - length += MSSizeOfSkip(); - length += MSSizeOfJump(destiny); - } - } else if (backup[offset] == 0xeb) { - length -= decode.len; - length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); - } else if (backup[offset] == 0xe9) { - length -= decode.len; - length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); - } else if ( - backup[offset] == 0xe3 || - (backup[offset] & 0xf0) == 0x70 - // XXX: opcode2 & 0xf0 is 0x80? - ) { - length += decode.len; - length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); - } - } - - uint8_t *buffer(reinterpret_cast(mmap( - NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 - ))); - - if (buffer == MAP_FAILED) { - MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); - *result = NULL; - return; - } - - if (false) fail: { - munmap(buffer, length); - *result = NULL; - return; - } - - { - uint8_t *current(buffer); - - for (size_t offset(0), width; offset != used; offset += width) { - hde64s decode; - hde64_disasm(backup + offset, &decode); - width = decode.len; - //_assert(width != 0 && offset + width <= used); - -#ifdef __LP64__ - if ((decode.modrm & 0xc7) == 0x05) { - if (decode.opcode == 0x8b) { - void *destiny(area + offset + width + int32_t(decode.disp.disp32)); - uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); - MSPushPointer(current, destiny); - MSWritePop(current, reg); - MSWriteMove64(current, reg, reg); - } else { - MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); - goto copy; - } - } else -#endif - - if (backup[offset] == 0xe8) { - int32_t relative(*reinterpret_cast(backup + offset + 1)); - if (relative == 0) - MSPushPointer(current, area + offset + decode.len); - else { - MSWrite(current, 0xe8); - MSWrite(current, MSSizeOfSkip()); - void *destiny(area + offset + decode.len + relative); - MSWriteSkip(current, MSSizeOfJump(destiny, current + MSSizeOfSkip())); - MSWriteJump(current, destiny); - } - } else if (backup[offset] == 0xeb) - MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); - else if (backup[offset] == 0xe9) - MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); - else if ( - backup[offset] == 0xe3 || - (backup[offset] & 0xf0) == 0x70 - ) { - MSWrite(current, backup[offset]); - MSWrite(current, 2); - MSWrite(current, 0xeb); - void *destiny(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); - MSWrite(current, MSSizeOfJump(destiny, current + 1)); - MSWriteJump(current, destiny); - } else -#ifdef __LP64__ - copy: -#endif - { - MSWrite(current, backup + offset, width); - } - } - - MSWriteJump(current, area + used); - } - - if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { - MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); - goto fail; - } - - *result = buffer; - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", *result); - MSLogHex(buffer, length, name); - } - - } - - { - SubstrateHookMemory code(process, area, used); - - uint8_t *current(area); - MSWriteJump(current, target); - for (unsigned offset(0); offset != blank; ++offset) - MSWrite(current, 0x90); - } - - if (MSDebug) { - char name[16]; - sprintf(name, "%p", area); - MSLogHex(area, used + sizeof(uint16_t), name); - } -} -#endif - -_extern void MSHookFunction(void *symbol, void *replace, void **result) { -#ifndef __LP64__ - SubstrateHookFunction(NULL, symbol, replace, result); -#endif -} - -#if defined(__APPLE__) && defined(__arm__) -_extern void _Z14MSHookFunctionPvS_PS_(void *symbol, void *replace, void **result) { - return MSHookFunction(symbol, replace, result); -} -#endif diff --git a/edxp-core/src/main/cpp/external/substrate/src/SubstrateHook.h b/edxp-core/src/main/cpp/external/substrate/src/SubstrateHook.h deleted file mode 100644 index 40a0296c..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/SubstrateHook.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __SUBSTRATEHOOK_H__ -#define __SUBSTRATEHOOK_H__ - - -#include - -#define _extern extern "C" __attribute__((__visibility__("default"))) - -#ifdef __cplusplus -extern "C" { -#endif - -void MSHookFunction(void *symbol, void *replace, void **result); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/edxp-core/src/main/cpp/external/substrate/src/SubstrateLog.hpp b/edxp-core/src/main/cpp/external/substrate/src/SubstrateLog.hpp deleted file mode 100644 index 3e572801..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/SubstrateLog.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#ifndef SUBSTRATE_LOG_HPP -#define SUBSTRATE_LOG_HPP - -#if 0 -#include - -#define MSLog(level, format, ...) ((void)__android_log_print(level, "NNNN", format, __VA_ARGS__)) - -#define MSLogLevelNotice ANDROID_LOG_INFO -#define MSLogLevelWarning ANDROID_LOG_WARN -#define MSLogLevelError ANDROID_LOG_ERROR - -#else - -#define MSLog(level, format, ...) printf(format, __VA_ARGS__) - -#endif - -#endif//SUBSTRATE_LOG_HPP diff --git a/edxp-core/src/main/cpp/external/substrate/src/SubstratePosixMemory.cpp b/edxp-core/src/main/cpp/external/substrate/src/SubstratePosixMemory.cpp deleted file mode 100644 index 709cb228..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/SubstratePosixMemory.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#define SubstrateInternal -#include "CydiaSubstrate.h" -#include "SubstrateLog.hpp" - -#include - -#include -#include -#include - -extern "C" void __clear_cache (void *beg, void *end); - -struct __SubstrateMemory { - void *address_; - size_t width_; - - __SubstrateMemory(void *address, size_t width) : - address_(address), - width_(width) - { - } -}; - -extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size) { - if (allocator != NULL) { - MSLog(MSLogLevelError, "MS:Error:allocator != %d", 0); - return NULL; - } - - if (size == 0) - return NULL; - - long page(sysconf(_SC_PAGESIZE)); // Portable applications should employ sysconf(_SC_PAGESIZE) instead of getpagesize - - uintptr_t base(reinterpret_cast(data) / page * page); - size_t width(((reinterpret_cast(data) + size - 1) / page + 1) * page - base); - void *address(reinterpret_cast(base)); - - if (mprotect(address, width, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { - MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); - return NULL; - } - - return new __SubstrateMemory(address, width); -} - -extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) { - if (mprotect(memory->address_, memory->width_, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) - MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); - - __clear_cache(reinterpret_cast(memory->address_), reinterpret_cast(memory->address_) + memory->width_); - - delete memory; -} diff --git a/edxp-core/src/main/cpp/external/substrate/src/SubstrateX86.hpp b/edxp-core/src/main/cpp/external/substrate/src/SubstrateX86.hpp deleted file mode 100644 index ffe2b06e..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/SubstrateX86.hpp +++ /dev/null @@ -1,200 +0,0 @@ -/* Cydia Substrate - Powerful Code Insertion Platform - * Copyright (C) 2008-2011 Jay Freeman (saurik) -*/ - -/* GNU Lesser General Public License, Version 3 {{{ */ -/* - * Substrate is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Substrate is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Substrate. If not, see . -**/ -/* }}} */ - -#ifndef SUBSTRATE_X86_HPP -#define SUBSTRATE_X86_HPP - -#include "Buffer.hpp" - -#ifdef __LP64__ -static const bool ia32 = false; -#else -static const bool ia32 = true; -#endif - -enum I$r { - I$rax, I$rcx, I$rdx, I$rbx, - I$rsp, I$rbp, I$rsi, I$rdi, - I$r8, I$r9, I$r10, I$r11, - I$r12, I$r13, I$r14, I$r15, -}; - -_disused static bool MSIs32BitOffset(uintptr_t target, uintptr_t source) { - intptr_t offset(target - source); - return int32_t(offset) == offset; -} - -_disused static size_t MSSizeOfSkip() { - return 5; -} - -_disused static size_t MSSizeOfPushPointer(uintptr_t target) { - return uint64_t(target) >> 32 == 0 ? 5 : 13; -} - -_disused static size_t MSSizeOfPushPointer(void *target) { - return MSSizeOfPushPointer(reinterpret_cast(target)); -} - -_disused static size_t MSSizeOfJump(bool blind, uintptr_t target, uintptr_t source = 0) { - if (ia32 || !blind && MSIs32BitOffset(target, source + 5)) - return MSSizeOfSkip(); - else - return MSSizeOfPushPointer(target) + 1; -} - -_disused static size_t MSSizeOfJump(uintptr_t target, uintptr_t source) { - return MSSizeOfJump(false, target, source); -} - -_disused static size_t MSSizeOfJump(uintptr_t target) { - return MSSizeOfJump(true, target); -} - -_disused static size_t MSSizeOfJump(void *target, void *source) { - return MSSizeOfJump(reinterpret_cast(target), reinterpret_cast(source)); -} - -_disused static size_t MSSizeOfJump(void *target) { - return MSSizeOfJump(reinterpret_cast(target)); -} - -_disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) { - MSWrite(current, 0xe9); - MSWrite(current, size); -} - -_disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) { - MSWrite(current, 0x68); - MSWrite(current, target); - - if (uint32_t high = uint64_t(target) >> 32) { - MSWrite(current, 0xc7); - MSWrite(current, 0x44); - MSWrite(current, 0x24); - MSWrite(current, 0x04); - MSWrite(current, high); - } -} - -_disused static void MSPushPointer(uint8_t *¤t, void *target) { - return MSPushPointer(current, reinterpret_cast(target)); -} - -_disused static void MSWriteCall(uint8_t *¤t, I$r target) { - if (target >> 3 != 0) - MSWrite(current, 0x40 | (target & 0x08) >> 3); - MSWrite(current, 0xff); - MSWrite(current, 0xd0 | target & 0x07); -} - -_disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) { - uintptr_t source(reinterpret_cast(current)); - - if (ia32 || MSIs32BitOffset(target, source + 5)) { - MSWrite(current, 0xe8); - MSWrite(current, target - (source + 5)); - } else { - MSPushPointer(current, target); - - MSWrite(current, 0x83); - MSWrite(current, 0xc4); - MSWrite(current, 0x08); - - MSWrite(current, 0x67); - MSWrite(current, 0xff); - MSWrite(current, 0x54); - MSWrite(current, 0x24); - MSWrite(current, 0xf8); - } -} - -template -_disused static void MSWriteCall(uint8_t *¤t, Type_ *target) { - return MSWriteCall(current, reinterpret_cast(target)); -} - -_disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) { - uintptr_t source(reinterpret_cast(current)); - - if (ia32 || MSIs32BitOffset(target, source + 5)) - MSWriteSkip(current, target - (source + 5)); - else { - MSPushPointer(current, target); - MSWrite(current, 0xc3); - } -} - -_disused static void MSWriteJump(uint8_t *¤t, void *target) { - return MSWriteJump(current, reinterpret_cast(target)); -} - -_disused static void MSWriteJump(uint8_t *¤t, I$r target) { - if (target >> 3 != 0) - MSWrite(current, 0x40 | (target & 0x08) >> 3); - MSWrite(current, 0xff); - MSWrite(current, 0xe0 | target & 0x07); -} - -_disused static void MSWritePop(uint8_t *¤t, uint8_t target) { - if (target >> 3 != 0) - MSWrite(current, 0x40 | (target & 0x08) >> 3); - MSWrite(current, 0x58 | target & 0x07); -} - -_disused static size_t MSSizeOfPop(uint8_t target) { - return target >> 3 != 0 ? 2 : 1; -} - -_disused static void MSWritePush(uint8_t *¤t, I$r target) { - if (target >> 3 != 0) - MSWrite(current, 0x40 | (target & 0x08) >> 3); - MSWrite(current, 0x50 | target & 0x07); -} - -_disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) { - MSWrite(current, 0x83); - MSWrite(current, 0xc4 | target & 0x07); - MSWrite(current, source); -} - -_disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) { - MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2); - MSWrite(current, 0xb8 | target & 0x7); - MSWrite(current, source); -} - -template -_disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) { - return MSWriteSet64(current, target, reinterpret_cast(source)); -} - -_disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) { - MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3); - MSWrite(current, 0x8b); - MSWrite(current, (target & 0x07) << 3 | source & 0x07); -} - -_disused static size_t MSSizeOfMove64() { - return 3; -} - -#endif//SUBSTRATE_X86_HPP diff --git a/edxp-core/src/main/cpp/external/substrate/src/hde64.c b/edxp-core/src/main/cpp/external/substrate/src/hde64.c deleted file mode 100644 index d69f0c68..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/hde64.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Hacker Disassembler Engine 64 C - * Copyright (c) 2008-2009, Vyacheslav Patkov. - * All rights reserved. - * - */ - -#include -#include - -#include "hde64.h" -#include "table64.h" - -unsigned int hde64_disasm(const void *code, hde64s *hs) -{ - uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; - uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; - uint8_t op64 = 0; - - memset(hs,0,sizeof(hde64s)); - char *tmp=(char*)hs; - - for (x = 16; x; x--) - switch (c = *p++) { - case 0xf3: - hs->p_rep = c; - pref |= PRE_F3; - break; - case 0xf2: - hs->p_rep = c; - pref |= PRE_F2; - break; - case 0xf0: - hs->p_lock = c; - pref |= PRE_LOCK; - break; - case 0x26: case 0x2e: case 0x36: - case 0x3e: case 0x64: case 0x65: - hs->p_seg = c; - pref |= PRE_SEG; - break; - case 0x66: - hs->p_66 = c; - pref |= PRE_66; - break; - case 0x67: - hs->p_67 = c; - pref |= PRE_67; - break; - default: - goto pref_done; - } - pref_done: - - hs->flags = (uint32_t)pref << 23; - - if (!pref) - pref |= PRE_NONE; - - if ((c & 0xf0) == 0x40) { - hs->flags |= F_PREFIX_REX; - if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) - op64++; - hs->rex_r = (c & 7) >> 2; - hs->rex_x = (c & 3) >> 1; - hs->rex_b = c & 1; - if (((c = *p++) & 0xf0) == 0x40) { - opcode = c; - goto error_opcode; - } - } - - if ((hs->opcode = c) == 0x0f) { - hs->opcode2 = c = *p++; - ht += DELTA_OPCODES; - } else if (c >= 0xa0 && c <= 0xa3) { - op64++; - if (pref & PRE_67) - pref |= PRE_66; - else - pref &= ~PRE_66; - } - - opcode = c; - cflags = ht[ht[opcode / 4] + (opcode % 4)]; - - if (cflags == C_ERROR) { - error_opcode: - hs->flags |= F_ERROR | F_ERROR_OPCODE; - cflags = 0; - if ((opcode & -3) == 0x24) - cflags++; - } - - x = 0; - if (cflags & C_GROUP) { - uint16_t t; - t = *(uint16_t *)(ht + (cflags & 0x7f)); - cflags = (uint8_t)t; - x = (uint8_t)(t >> 8); - } - - if (hs->opcode2) { - ht = hde64_table + DELTA_PREFIXES; - if (ht[ht[opcode / 4] + (opcode % 4)] & pref) - hs->flags |= F_ERROR | F_ERROR_OPCODE; - } - - if (cflags & C_MODRM) { - hs->flags |= F_MODRM; - hs->modrm = c = *p++; - hs->modrm_mod = m_mod = c >> 6; - hs->modrm_rm = m_rm = c & 7; - hs->modrm_reg = m_reg = (c & 0x3f) >> 3; - - if (x && ((x << m_reg) & 0x80)) - hs->flags |= F_ERROR | F_ERROR_OPCODE; - - if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { - uint8_t t = opcode - 0xd9; - if (m_mod == 3) { - ht = hde64_table + DELTA_FPU_MODRM + t*8; - t = ht[m_reg] << m_rm; - } else { - ht = hde64_table + DELTA_FPU_REG; - t = ht[t] << m_reg; - } - if (t & 0x80) - hs->flags |= F_ERROR | F_ERROR_OPCODE; - } - - if (pref & PRE_LOCK) { - if (m_mod == 3) { - hs->flags |= F_ERROR | F_ERROR_LOCK; - } else { - uint8_t *table_end, op = opcode; - if (hs->opcode2) { - ht = hde64_table + DELTA_OP2_LOCK_OK; - table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; - } else { - ht = hde64_table + DELTA_OP_LOCK_OK; - table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; - op &= -2; - } - for (; ht != table_end; ht++) - if (*ht++ == op) { - if (!((*ht << m_reg) & 0x80)) - goto no_lock_error; - else - break; - } - hs->flags |= F_ERROR | F_ERROR_LOCK; - no_lock_error: - ; - } - } - - if (hs->opcode2) { - switch (opcode) { - case 0x20: case 0x22: - m_mod = 3; - if (m_reg > 4 || m_reg == 1) - goto error_operand; - else - goto no_error_operand; - case 0x21: case 0x23: - m_mod = 3; - if (m_reg == 4 || m_reg == 5) - goto error_operand; - else - goto no_error_operand; - } - } else { - switch (opcode) { - case 0x8c: - if (m_reg > 5) - goto error_operand; - else - goto no_error_operand; - case 0x8e: - if (m_reg == 1 || m_reg > 5) - goto error_operand; - else - goto no_error_operand; - } - } - - if (m_mod == 3) { - uint8_t *table_end; - if (hs->opcode2) { - ht = hde64_table + DELTA_OP2_ONLY_MEM; - table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; - } else { - ht = hde64_table + DELTA_OP_ONLY_MEM; - table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; - } - for (; ht != table_end; ht += 2) - if (*ht++ == opcode) { - if (*ht++ & pref && !((*ht << m_reg) & 0x80)) - goto error_operand; - else - break; - } - goto no_error_operand; - } else if (hs->opcode2) { - switch (opcode) { - case 0x50: case 0xd7: case 0xf7: - if (pref & (PRE_NONE | PRE_66)) - goto error_operand; - break; - case 0xd6: - if (pref & (PRE_F2 | PRE_F3)) - goto error_operand; - break; - case 0xc5: - goto error_operand; - } - goto no_error_operand; - } else - goto no_error_operand; - - error_operand: - hs->flags |= F_ERROR | F_ERROR_OPERAND; - no_error_operand: - - c = *p++; - if (m_reg <= 1) { - if (opcode == 0xf6) - cflags |= C_IMM8; - else if (opcode == 0xf7) - cflags |= C_IMM_P66; - } - - switch (m_mod) { - case 0: - if (pref & PRE_67) { - if (m_rm == 6) - disp_size = 2; - } else - if (m_rm == 5) - disp_size = 4; - break; - case 1: - disp_size = 1; - break; - case 2: - disp_size = 2; - if (!(pref & PRE_67)) - disp_size <<= 1; - } - - if (m_mod != 3 && m_rm == 4) { - hs->flags |= F_SIB; - p++; - hs->sib = c; - hs->sib_scale = c >> 6; - hs->sib_index = (c & 0x3f) >> 3; - if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) - disp_size = 4; - } - - p--; - switch (disp_size) { - case 1: - hs->flags |= F_DISP8; - hs->disp.disp8 = *p; - break; - case 2: - hs->flags |= F_DISP16; - hs->disp.disp16 = *(uint16_t *)p; - break; - case 4: - hs->flags |= F_DISP32; - hs->disp.disp32 = *(uint32_t *)p; - } - p += disp_size; - } else if (pref & PRE_LOCK) - hs->flags |= F_ERROR | F_ERROR_LOCK; - - if (cflags & C_IMM_P66) { - if (cflags & C_REL32) { - if (pref & PRE_66) { - hs->flags |= F_IMM16 | F_RELATIVE; - hs->imm.imm16 = *(uint16_t *)p; - p += 2; - goto disasm_done; - } - goto rel32_ok; - } - if (op64) { - hs->flags |= F_IMM64; - hs->imm.imm64 = *(uint64_t *)p; - p += 8; - } else if (!(pref & PRE_66)) { - hs->flags |= F_IMM32; - hs->imm.imm32 = *(uint32_t *)p; - p += 4; - } else - goto imm16_ok; - } - - - if (cflags & C_IMM16) { - imm16_ok: - hs->flags |= F_IMM16; - hs->imm.imm16 = *(uint16_t *)p; - p += 2; - } - if (cflags & C_IMM8) { - hs->flags |= F_IMM8; - hs->imm.imm8 = *p++; - } - - if (cflags & C_REL32) { - rel32_ok: - hs->flags |= F_IMM32 | F_RELATIVE; - hs->imm.imm32 = *(uint32_t *)p; - p += 4; - } else if (cflags & C_REL8) { - hs->flags |= F_IMM8 | F_RELATIVE; - hs->imm.imm8 = *p++; - } - - disasm_done: - - if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { - hs->flags |= F_ERROR | F_ERROR_LENGTH; - hs->len = 15; - } - - return (unsigned int)hs->len; -} diff --git a/edxp-core/src/main/cpp/external/substrate/src/hde64.h b/edxp-core/src/main/cpp/external/substrate/src/hde64.h deleted file mode 100644 index 2fcc4cb2..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/hde64.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Hacker Disassembler Engine 64 - * Copyright (c) 2008-2009, Vyacheslav Patkov. - * All rights reserved. - * - * hde64.h: C/C++ header file - * - */ - -#ifndef _HDE64_H_ -#define _HDE64_H_ - -/* stdint.h - C99 standard header - * http://en.wikipedia.org/wiki/stdint.h - * - * if your compiler doesn't contain "stdint.h" header (for - * example, Microsoft Visual C++), you can download file: - * http://www.azillionmonkeys.com/qed/pstdint.h - * and change next line to: - * #include "pstdint.h" - */ -#include - -#define F_MODRM 0x00000001 -#define F_SIB 0x00000002 -#define F_IMM8 0x00000004 -#define F_IMM16 0x00000008 -#define F_IMM32 0x00000010 -#define F_IMM64 0x00000020 -#define F_DISP8 0x00000040 -#define F_DISP16 0x00000080 -#define F_DISP32 0x00000100 -#define F_RELATIVE 0x00000200 -#define F_ERROR 0x00001000 -#define F_ERROR_OPCODE 0x00002000 -#define F_ERROR_LENGTH 0x00004000 -#define F_ERROR_LOCK 0x00008000 -#define F_ERROR_OPERAND 0x00010000 -#define F_PREFIX_REPNZ 0x01000000 -#define F_PREFIX_REPX 0x02000000 -#define F_PREFIX_REP 0x03000000 -#define F_PREFIX_66 0x04000000 -#define F_PREFIX_67 0x08000000 -#define F_PREFIX_LOCK 0x10000000 -#define F_PREFIX_SEG 0x20000000 -#define F_PREFIX_REX 0x40000000 -#define F_PREFIX_ANY 0x7f000000 - -#define PREFIX_SEGMENT_CS 0x2e -#define PREFIX_SEGMENT_SS 0x36 -#define PREFIX_SEGMENT_DS 0x3e -#define PREFIX_SEGMENT_ES 0x26 -#define PREFIX_SEGMENT_FS 0x64 -#define PREFIX_SEGMENT_GS 0x65 -#define PREFIX_LOCK 0xf0 -#define PREFIX_REPNZ 0xf2 -#define PREFIX_REPX 0xf3 -#define PREFIX_OPERAND_SIZE 0x66 -#define PREFIX_ADDRESS_SIZE 0x67 - -#pragma pack(push,1) - -typedef struct { - uint8_t len; - uint8_t p_rep; - uint8_t p_lock; - uint8_t p_seg; - uint8_t p_66; - uint8_t p_67; - uint8_t rex; - uint8_t rex_w; - uint8_t rex_r; - uint8_t rex_x; - uint8_t rex_b; - uint8_t opcode; - uint8_t opcode2; - uint8_t modrm; - uint8_t modrm_mod; - uint8_t modrm_reg; - uint8_t modrm_rm; - uint8_t sib; - uint8_t sib_scale; - uint8_t sib_index; - uint8_t sib_base; - union { - uint8_t imm8; - uint16_t imm16; - uint32_t imm32; - uint64_t imm64; - } imm; - union { - uint8_t disp8; - uint16_t disp16; - uint32_t disp32; - } disp; - uint32_t flags; -} hde64s; - -#pragma pack(pop) - -#ifdef __cplusplus -extern "C" { -#endif - -/* __cdecl */ -unsigned int hde64_disasm(const void *code, hde64s *hs); - -#ifdef __cplusplus -} -#endif - -#endif /* _HDE64_H_ */ diff --git a/edxp-core/src/main/cpp/external/substrate/src/table64.h b/edxp-core/src/main/cpp/external/substrate/src/table64.h deleted file mode 100644 index 144f2907..00000000 --- a/edxp-core/src/main/cpp/external/substrate/src/table64.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Hacker Disassembler Engine 64 C - * Copyright (c) 2008-2009, Vyacheslav Patkov. - * All rights reserved. - * - */ - -#define C_NONE 0x00 -#define C_MODRM 0x01 -#define C_IMM8 0x02 -#define C_IMM16 0x04 -#define C_IMM_P66 0x10 -#define C_REL8 0x20 -#define C_REL32 0x40 -#define C_GROUP 0x80 -#define C_ERROR 0xff - -#define PRE_ANY 0x00 -#define PRE_NONE 0x01 -#define PRE_F2 0x02 -#define PRE_F3 0x04 -#define PRE_66 0x08 -#define PRE_67 0x10 -#define PRE_LOCK 0x20 -#define PRE_SEG 0x40 -#define PRE_ALL 0xff - -#define DELTA_OPCODES 0x4a -#define DELTA_FPU_REG 0xfd -#define DELTA_FPU_MODRM 0x104 -#define DELTA_PREFIXES 0x13c -#define DELTA_OP_LOCK_OK 0x1ae -#define DELTA_OP2_LOCK_OK 0x1c6 -#define DELTA_OP_ONLY_MEM 0x1d8 -#define DELTA_OP2_ONLY_MEM 0x1e7 - -unsigned char hde64_table[] = { - 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, - 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, - 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, - 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, - 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, - 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, - 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, - 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, - 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, - 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, - 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, - 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, - 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, - 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, - 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, - 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, - 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, - 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, - 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, - 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, - 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, - 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, - 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, - 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, - 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, - 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, - 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, - 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, - 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, - 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, - 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, - 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, - 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, - 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, - 0x00,0xf0,0x02,0x00 -}; diff --git a/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h b/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h index b309a46e..8ab013d9 100644 --- a/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h +++ b/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h @@ -25,6 +25,8 @@ void setNonCompilable(void *method); bool setNativeFlag(void *method, bool isNative); +void *getArtMethod(JNIEnv *env, jobject jmethod); + static void *getResolvedMethodsAddr(JNIEnv *, jobject); #ifdef __cplusplus diff --git a/edxp-core/src/main/cpp/external/yahfa/src/HookMain.c b/edxp-core/src/main/cpp/external/yahfa/src/HookMain.c index 57e0faf1..f40b53de 100644 --- a/edxp-core/src/main/cpp/external/yahfa/src/HookMain.c +++ b/edxp-core/src/main/cpp/external/yahfa/src/HookMain.c @@ -21,6 +21,8 @@ static int kAccNative = 0x0100; static int kAccCompileDontBother = 0x01000000; static int kAccFastInterpreterToInterpreterInvoke = 0x40000000; +static jfieldID fieldArtMethod = NULL; + static inline uint32_t read32(void *addr) { return *((uint32_t *) addr); } @@ -29,15 +31,19 @@ static inline void write32(void *addr, uint32_t value) { *((uint32_t *) addr) = value; } -static inline void* readAddr(void *addr) { - return *((void**) addr); +static inline void *readAddr(void *addr) { + return *((void **) addr); } void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVersion) { int i; SDKVersion = sdkVersion; + jclass classExecutable; LOGI("init to SDK %d", sdkVersion); switch (sdkVersion) { + case __ANDROID_API_R__: + classExecutable = (*env)->FindClass(env, "java/lang/reflect/Executable"); + fieldArtMethod = (*env)->GetFieldID(env, classExecutable, "artMethod", "J"); case __ANDROID_API_Q__: case __ANDROID_API_P__: kAccCompileDontBother = 0x02000000; @@ -209,6 +215,10 @@ static int doBackupAndHook(JNIEnv *env, void *targetMethod, void *hookMethod, vo static void ensureMethodCached(void *hookMethod, void *backupMethod, void *hookClassResolvedMethods) { + if (!backupMethod) { + LOGE("ensureMethodCached: backupMethod is null"); + return; + } void *dexCacheResolvedMethods; // then we get the dex method index of the static backup method int methodIndex = read32( @@ -253,6 +263,24 @@ static void ensureMethodCached(void *hookMethod, void *backupMethod, } } +void *getArtMethod(JNIEnv *env, jobject jmethod) { + void *artMethod = NULL; + + if (jmethod == NULL) { + return artMethod; + } + + if (SDKVersion == __ANDROID_API_R__) { + artMethod = (void *) (*env)->GetLongField(env, jmethod, fieldArtMethod); + } else { + artMethod = (void *) (*env)->FromReflectedMethod(env, jmethod); + } + + LOGI("ArtMethod: %p", artMethod); + return artMethod; + +} + jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env, jclass clazz, jclass targetClass, jstring methodName, jstring methodSig) { @@ -285,12 +313,13 @@ jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass jobject backup) { if (!doBackupAndHook(env, - (void *) (*env)->FromReflectedMethod(env, target), - (void *) (*env)->FromReflectedMethod(env, hook), - backup == NULL ? NULL : (void *) (*env)->FromReflectedMethod(env, backup) + getArtMethod(env, target), + getArtMethod(env, hook), + getArtMethod(env, backup) )) { (*env)->NewGlobalRef(env, hook); // keep a global ref so that the hook method would not be GCed + if (backup) (*env)->NewGlobalRef(env, backup); return JNI_TRUE; } else { return JNI_FALSE; @@ -300,8 +329,8 @@ jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass void Java_lab_galaxy_yahfa_HookMain_ensureMethodCached(JNIEnv *env, jclass clazz, jobject hook, jobject backup) { - ensureMethodCached((void *) (*env)->FromReflectedMethod(env, hook), - backup == NULL ? NULL : (void *) (*env)->FromReflectedMethod(env, backup), + ensureMethodCached(getArtMethod(env, hook), + getArtMethod(env, backup), getResolvedMethodsAddr(env, hook)); } diff --git a/edxp-core/src/main/cpp/external/yahfa/src/common.h b/edxp-core/src/main/cpp/external/yahfa/src/common.h index 570f794c..fcf840d2 100644 --- a/edxp-core/src/main/cpp/external/yahfa/src/common.h +++ b/edxp-core/src/main/cpp/external/yahfa/src/common.h @@ -15,7 +15,7 @@ #define LOGE(...) #else #define LOG_TAG "EdXposed" -#ifdef DEBUG +#ifndef NDEBUG #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) diff --git a/edxp-core/src/main/cpp/main/CMakeLists.txt b/edxp-core/src/main/cpp/main/CMakeLists.txt index 71a612cb..971a3562 100644 --- a/edxp-core/src/main/cpp/main/CMakeLists.txt +++ b/edxp-core/src/main/cpp/main/CMakeLists.txt @@ -8,4 +8,4 @@ include_directories(include src) add_library(riru_edxp SHARED ${SRC_LIST} ${SRC_JNI_LIST}) find_library(log-lib log) -target_link_libraries(riru_edxp yahfa riru xhook substrate android ${log-lib}) \ No newline at end of file +target_link_libraries(riru_edxp yahfa riru xhook android dobby ${log-lib}) \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/include/JNIHelper.h b/edxp-core/src/main/cpp/main/include/JNIHelper.h index d3dab8a2..f90162e1 100644 --- a/edxp-core/src/main/cpp/main/include/JNIHelper.h +++ b/edxp-core/src/main/cpp/main/include/JNIHelper.h @@ -4,7 +4,7 @@ #include #include "logging.h" -#define JNI_START JNIEnv *env, jclass clazz +#define JNI_START JNIEnv *env, [[maybe_unused]] jclass clazz ALWAYS_INLINE static void JNIExceptionClear(JNIEnv *env) { if (env->ExceptionCheck()) { @@ -103,3 +103,52 @@ ALWAYS_INLINE static int ClearException(JNIEnv *env) { env->RegisterNatives(class, methods, size); \ if (ClearException(env)) LOGE("RegisterNatives " #class); +class JUTFString { +public: + inline JUTFString(JNIEnv *env, jstring jstr) : JUTFString(env, jstr, nullptr) { + } + + inline JUTFString(JNIEnv *env, jstring jstr, const char *default_cstr) : env_(env), + jstr_(jstr) { + if (env_ && jstr_) cstr_ = env_->GetStringUTFChars(jstr, nullptr); + else cstr_ = default_cstr; + } + + inline operator const char *() const { return cstr_; } + + inline operator const std::string() const { return cstr_; } + + inline operator const bool() const { return cstr_ != nullptr; } + + inline auto get() const { return cstr_; } + + inline ~JUTFString() { + if (env_ && jstr_) env_->ReleaseStringUTFChars(jstr_, cstr_); + } + + JUTFString(JUTFString &&other) + : env_(std::move(other.env_)), jstr_(std::move(other.jstr_)), + cstr_(std::move(other.cstr_)) { + other.cstr_ = nullptr; + } + + JUTFString & + operator=(JUTFString &&other) { + if (&other != this) { + env_ = std::move(other.env_); + jstr_ = std::move(other.jstr_); + cstr_ = std::move(other.cstr_); + other.cstr_ = nullptr; + } + return *this; + } + +private: + JNIEnv *env_; + jstring jstr_; + const char *cstr_; + + JUTFString(const JUTFString &) = delete; + + JUTFString &operator=(const JUTFString &) = delete; +}; diff --git a/edxp-core/src/main/cpp/main/include/android_build.h b/edxp-core/src/main/cpp/main/include/android_build.h deleted file mode 100644 index 46c8c609..00000000 --- a/edxp-core/src/main/cpp/main/include/android_build.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef WHALE_ANDROID_ANDROID_BUILD_H_ -#define WHALE_ANDROID_ANDROID_BUILD_H_ - -#include -#include -#include - -static inline int32_t GetAndroidApiLevel() { - char prop_value[PROP_VALUE_MAX]; - __system_property_get("ro.build.version.sdk", prop_value); - return atoi(prop_value); -} - -#endif // WHALE_ANDROID_ANDROID_BUILD_H_ diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h b/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h index bb1e34d7..9a046e10 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h @@ -6,6 +6,7 @@ #include #include #include "runtime.h" +#include "config.h" #include "jni_env_ext.h" #include "edxp_context.h" #include "jni/edxp_pending_hooks.h" @@ -23,6 +24,7 @@ namespace art { } CREATE_HOOK_STUB_ENTRIES(void *, Constructor, void *thiz, void *intern_table) { + LOGI("ConstructorReplace called"); if (LIKELY(instance_)) instance_->Reset(thiz); else @@ -44,6 +46,15 @@ namespace art { } } + CREATE_HOOK_STUB_ENTRIES(bool, ShouldUseInterpreterEntrypoint, void *art_method, const void* quick_code) { + // TODO check hooked + bool hooked = false; + if (hooked && quick_code != nullptr) { + return false; + } + return ShouldUseInterpreterEntrypointBackup(art_method, quick_code); + } + public: ClassLinker(void *thiz) : HookedObject(thiz) {} @@ -51,7 +62,53 @@ namespace art { return instance_; } + // @ApiSensitive(Level.MIDDLE) static void Setup(void *handle, HookFunType hook_func) { + LOGD("Classlinker hook setup, handle=%p", handle); + // TODO: Maybe not compatible with Android 10- + int api_level = edxp::GetAndroidApiLevel(); + size_t OFFSET_classlinker; // Get offset from art::Runtime::RunRootClinits() call in IDA + switch(api_level) { + case __ANDROID_API_O__: + case __ANDROID_API_O_MR1__: +#ifdef __LP64__ + OFFSET_classlinker = 464 / 8; +#else + OFFSET_classlinker = 284 / 4; +#endif + break; + case __ANDROID_API_P__: +#ifdef __LP64__ + OFFSET_classlinker = 528 / 8; +#else + OFFSET_classlinker = 336 / 4; +#endif + break; + case __ANDROID_API_Q__: +#ifdef __LP64__ + OFFSET_classlinker = 480 / 8; +#else + OFFSET_classlinker = 280 / 4; +#endif + break; + default: + LOGE("No valid offset for art::Runtime::class_linker_ found. Using Android R."); + case __ANDROID_API_R__: +#ifdef __LP64__ + OFFSET_classlinker = 472 / 8; +#else + OFFSET_classlinker = 276 / 4; +#endif + break; + } + + // ClassLinker* GetClassLinker() but inlined + void* cl = reinterpret_cast( + reinterpret_cast(Runtime::Current()->Get()) + OFFSET_classlinker + ); + LOGD("Classlinker object: %p", cl); + instance_ = new ClassLinker(cl); + HOOK_FUNC(Constructor, "_ZN3art11ClassLinkerC2EPNS_11InternTableE", "_ZN3art11ClassLinkerC2EPNS_11InternTableEb"); // 10.0 RETRIEVE_FUNC_SYMBOL(SetEntryPointsToInterpreter, @@ -59,9 +116,18 @@ namespace art { HOOK_FUNC(FixupStaticTrampolines, "_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE"); + + // Sandhook will hook ShouldUseInterpreterEntrypoint, so we just skip + // edxp::Context::GetInstance()->GetVariant() will not work here, so we use smh dirty hack + if (api_level >= __ANDROID_API_R__ && access(edxp::kLibSandHookNativePath.c_str(), F_OK) == -1) { + LOGD("Not sandhook, installing _ZN3art11ClassLinker30ShouldUseInterpreterEntrypointEPNS_9ArtMethodEPKv"); + HOOK_FUNC(ShouldUseInterpreterEntrypoint, + "_ZN3art11ClassLinker30ShouldUseInterpreterEntrypointEPNS_9ArtMethodEPKv"); + } } ALWAYS_INLINE void SetEntryPointsToInterpreter(void *art_method) const { + LOGD("SetEntryPointsToInterpreter start, thiz=%p, art_method=%p", thiz_, art_method); if (LIKELY(thiz_)) SetEntryPointsToInterpreter(thiz_, art_method); } diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/gc/heap.h b/edxp-core/src/main/cpp/main/include/art/runtime/gc/heap.h index dde6e854..fbd78f8b 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/gc/heap.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/gc/heap.h @@ -37,6 +37,7 @@ namespace art { return instance_; } + // @ApiSensitive(Level.MIDDLE) static void Setup(void *handle, HookFunType hook_func) { HOOK_FUNC(PreZygoteFork, "_ZN3art2gc4Heap13PreZygoteForkEv"); RETRIEVE_FUNC_SYMBOL(WaitForGcToComplete, diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h index 0e515731..89807f3b 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h @@ -30,8 +30,9 @@ namespace art { return false; } + // @ApiSensitive(Level.HIGH) static void DisableHiddenApi(void *handle, HookFunType hook_func) { - const int api_level = GetAndroidApiLevel(); + const int api_level = edxp::GetAndroidApiLevel(); if (api_level < __ANDROID_API_P__) { return; } diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/jni_env_ext.h b/edxp-core/src/main/cpp/main/include/art/runtime/jni_env_ext.h index 015122dd..b04cd167 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/jni_env_ext.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/jni_env_ext.h @@ -20,6 +20,7 @@ namespace art { public: JNIEnvExt(void *thiz) : HookedObject(thiz) {} + // @ApiSensitive(Level.MIDDLE) static void Setup(void *handle, HookFunType hook_func) { RETRIEVE_FUNC_SYMBOL(NewLocalRef, "_ZN3art9JNIEnvExt11NewLocalRefEPNS_6mirror6ObjectE"); RETRIEVE_FUNC_SYMBOL(DeleteLocalRef, "_ZN3art9JNIEnvExt14DeleteLocalRefEP8_jobject"); diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/mirror/class.h b/edxp-core/src/main/cpp/main/include/art/runtime/mirror/class.h index 72eb8f2c..55d05dae 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/mirror/class.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/mirror/class.h @@ -46,6 +46,7 @@ namespace art { public: Class(void *thiz) : HookedObject(thiz) {} + // @ApiSensitive(Level.MIDDLE) static void Setup(void *handle, HookFunType hook_func) { RETRIEVE_FUNC_SYMBOL(GetDescriptor, "_ZN3art6mirror5Class13GetDescriptorEPNSt3__112" "basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE"); diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/oat_file_manager.h b/edxp-core/src/main/cpp/main/include/art/runtime/oat_file_manager.h index a2c1a8c1..76d4eb37 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/oat_file_manager.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/oat_file_manager.h @@ -11,16 +11,14 @@ namespace art { return; } + // @ApiSensitive(Level.LOW) // http://androidxref.com/9.0.0_r3/xref/art/runtime/oat_file_manager.cc#637 static void DisableOnlyUseSystemOatFiles(void *handle, HookFunType hook_func) { - const int api_level = GetAndroidApiLevel(); - if (api_level == __ANDROID_API_P__) { + const int api_level = edxp::GetAndroidApiLevel(); + if (api_level >= __ANDROID_API_P__) { HOOK_FUNC(SetOnlyUseSystemOatFiles, - "_ZN3art14OatFileManager24SetOnlyUseSystemOatFilesEv"); - } - if (api_level == __ANDROID_API_Q__) { - HOOK_FUNC(SetOnlyUseSystemOatFiles, - "_ZN3art14OatFileManager24SetOnlyUseSystemOatFilesEbb"); + "_ZN3art14OatFileManager24SetOnlyUseSystemOatFilesEv", // 9 & 11 + "_ZN3art14OatFileManager24SetOnlyUseSystemOatFilesEbb"); // 10 } }; diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/runtime.h b/edxp-core/src/main/cpp/main/include/art/runtime/runtime.h index 17404d6b..2e3ddc35 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/runtime.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/runtime.h @@ -36,10 +36,14 @@ namespace art { return instance_; } + // @ApiSensitive(Level.LOW) static void Setup(void *handle, HookFunType hook_func) { HOOK_FUNC(Init, "_ZN3art7Runtime4InitEONS_18RuntimeArgumentMapE"); RETRIEVE_FUNC_SYMBOL(DeoptimizeBootImage, "_ZN3art7Runtime19DeoptimizeBootImageEv"); + RETRIEVE_FIELD_SYMBOL(thiz, "_ZN3art7Runtime9instance_E"); + LOGD("_ZN3art7Runtime9instance_E = %p", thiz); + instance_ = new Runtime(thiz); } ALWAYS_INLINE void DeoptimizeBootImage() const { diff --git a/edxp-core/src/main/cpp/main/include/base/object.h b/edxp-core/src/main/cpp/main/include/base/object.h index 45806a08..f7ff2fe0 100644 --- a/edxp-core/src/main/cpp/main/include/base/object.h +++ b/edxp-core/src/main/cpp/main/include/base/object.h @@ -5,15 +5,15 @@ #include #include -#define __uintval(p) reinterpret_cast(p) -#define __ptr(p) reinterpret_cast(p) -#define __align_up(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) -#define __align_down(x, n) ((x) & -(n)) -#define __page_size 4096 -#define __page_align(n) __align_up(static_cast(n), __page_size) -#define __ptr_align(x) __ptr(__align_down(reinterpret_cast(x), __page_size)) -#define __make_rwx(p, n) ::mprotect(__ptr_align(p), \ - __page_align(__uintval(p) + n) != __page_align(__uintval(p)) ? __page_align(n) + __page_size : __page_align(n), \ +#define _uintval(p) reinterpret_cast(p) +#define _ptr(p) reinterpret_cast(p) +#define _align_up(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) +#define _align_down(x, n) ((x) & -(n)) +#define _page_size 4096 +#define _page_align(n) _align_up(static_cast(n), _page_size) +#define _ptr_align(x) _ptr(_align_down(reinterpret_cast(x), _page_size)) +#define _make_rwx(p, n) ::mprotect(_ptr_align(p), \ + _page_align(_uintval(p) + n) != _page_align(_uintval(p)) ? _page_align(n) + _page_size : _page_align(n), \ PROT_READ | PROT_WRITE | PROT_EXEC) typedef void (*HookFunType)(void *, void *, void **); @@ -97,7 +97,7 @@ namespace edxp { ALWAYS_INLINE inline static void HookFunction(HookFunType hook_fun, void *original, void *replace, void **backup) { - __make_rwx(original, __page_size); + _make_rwx(original, _page_size); hook_fun(original, replace, backup); } diff --git a/edxp-core/src/main/cpp/main/include/config.h b/edxp-core/src/main/cpp/main/include/config.h index ce52c60b..fa0f9357 100644 --- a/edxp-core/src/main/cpp/main/include/config.h +++ b/edxp-core/src/main/cpp/main/include/config.h @@ -5,7 +5,7 @@ #include #include #include "art/base/macros.h" -#include "android_build.h" +#include "utils.h" namespace edxp { @@ -18,34 +18,30 @@ namespace edxp { # define LP_SELECT(lp32, lp64) (lp32) #endif - static constexpr auto kInjectDexPath = "/system/framework/edxp.jar:" - "/system/framework/eddalvikdx.jar:" - "/system/framework/eddexmaker.jar"; + static const auto kInjectDexPath = "/system/framework/edxp.dex:" + "/system/framework/eddalvikdx.dex:" + "/system/framework/eddexmaker.dex"_str; - static constexpr auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main"; - static constexpr auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker"; - static constexpr auto kSandHookClassName = "com.swift.sandhook.SandHook"; - static constexpr auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"; + static const auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main"_str; + static const auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker"; + static const auto kSandHookClassName = "com.swift.sandhook.SandHook"_str; + static const auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"_str; - static constexpr auto kLibArtName = "libart.so"; - static constexpr auto kLibFwkName = "libandroid_runtime.so"; - static constexpr auto kLibWhaleName = "libwhale.edxp.so"; - static constexpr auto kLibSandHookName = "libsandhook.edxp.so"; + static const auto kLibArtName = "libart.so"_str; + static const auto kLibFwName = "libandroidfw.so"_str; + static const auto kLibSandHookName = "libsandhook.edxp.so"_str; + static const auto kLibDlName = "libdl.so"_str; + static const auto kLibSandHookNativeName = "libsandhook-native.so"_str; - static const auto kLibBasePath = std::string(LP_SELECT("/system/lib/", "/system/lib64/")); - static const auto kLibRuntimeBasePath = std::string( - LP_SELECT("/apex/com.android.runtime/lib/", "/apex/com.android.runtime/lib64/")); - - static const auto kLibArtPath = - (GetAndroidApiLevel() >= __ANDROID_API_Q__ ? kLibRuntimeBasePath : kLibBasePath) + kLibArtName; - - static const auto kLibWhalePath = kLibBasePath + kLibWhaleName; + static const auto kLibBasePath = std::string( + LP_SELECT("/system/lib/", + "/system/lib64/")); + static const auto kLibArtLegacyPath = kLibBasePath + kLibArtName; static const auto kLibSandHookPath = kLibBasePath + kLibSandHookName; - static const auto kLibFwPath = kLibBasePath + "libandroidfw.so"; - static const auto kLibDlPath = kLibBasePath + "libdl.so"; - static const auto kLibFwkPath = kLibBasePath + kLibFwkName; + static const auto kLibSandHookNativePath = kLibBasePath + kLibSandHookNativeName; + static const auto kLibFwPath = kLibBasePath + kLibFwName; - inline const char *const BoolToString(bool b) { + inline constexpr const char *const BoolToString(bool b) { return b ? "true" : "false"; } } \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/include/framework/androidfw/ResourceTypes.h b/edxp-core/src/main/cpp/main/include/framework/androidfw/ResourceTypes.h index de0a2907..dbced16c 100644 --- a/edxp-core/src/main/cpp/main/include/framework/androidfw/ResourceTypes.h +++ b/edxp-core/src/main/cpp/main/include/framework/androidfw/ResourceTypes.h @@ -3,6 +3,7 @@ #include +// @ApiSensitive(Level.MIDDLE) namespace android { typedef int32_t status_t; diff --git a/edxp-core/src/main/cpp/main/include/framework/fd_utils-inl.h b/edxp-core/src/main/cpp/main/include/framework/fd_utils-inl.h deleted file mode 100644 index 4bb2bc52..00000000 --- a/edxp-core/src/main/cpp/main/include/framework/fd_utils-inl.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const char *kPathPrefixWhitelist[] = { - "/data/app/", - "/data/app-private/" -}; - -static const char *kFdPath = "/proc/self/fd"; - -// todo stay up to date -// Keeps track of all relevant information (flags, offset etc.) of an -// open zygote file descriptor. -class FileDescriptorInfo { -public: - // Create a FileDescriptorInfo for a given file descriptor. Returns - // |NULL| if an error occurred. - static FileDescriptorInfo *createFromFd(int fd) { - struct stat f_stat; - // This should never happen; the zygote should always have the right set - // of permissions required to stat all its open files. - if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { - LOGE("Unable to stat fd %d : %s", fd, strerror(errno)); - return NULL; - } - - if (S_ISSOCK(f_stat.st_mode)) { - std::string socket_name; - if (!GetSocketName(fd, &socket_name)) { - return NULL; - } - - if (!IsWhitelisted(socket_name)) { - //LOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd); - return NULL; - } - - return new FileDescriptorInfo(fd); - } - - std::string file_path; - if (!Readlink(fd, &file_path)) { - return NULL; - } - - if (!IsWhitelisted(file_path)) { - //LOGE("Not whitelisted : %s", file_path.c_str()); - return NULL; - } - - // We only handle whitelisted regular files and character devices. Whitelisted - // character devices must provide a guarantee of sensible behaviour when - // reopened. - // - // S_ISDIR : Not supported. (We could if we wanted to, but it's unused). - // S_ISLINK : Not supported. - // S_ISBLK : Not supported. - // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate - // with the child process across forks but those should have been closed - // before we got to this point. - if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) { - LOGE("Unsupported st_mode %d", f_stat.st_mode); - return NULL; - } - - // File descriptor flags : currently on FD_CLOEXEC. We can set these - // using F_SETFD - we're single threaded at this point of execution so - // there won't be any races. - const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)); - if (fd_flags == -1) { - LOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno)); - return NULL; - } - - // File status flags : - // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through - // to the open() call. - // - // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can - // do about these, since the file has already been created. We shall ignore - // them here. - // - // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL - // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK. - // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for - // their presence and pass them in to open(). - int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); - if (fs_flags == -1) { - LOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno)); - return NULL; - } - - // File offset : Ignore the offset for non seekable files. - const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR)); - - // We pass the flags that open accepts to open, and use F_SETFL for - // the rest of them. - static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC); - int open_flags = fs_flags & (kOpenFlags); - fs_flags = fs_flags & (~(kOpenFlags)); - - return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, - offset); - } - - bool Detach() const { - const int dev_null_fd = open("/dev/null", O_RDWR); - if (dev_null_fd < 0) { - LOGE("Failed to open /dev/null : %s", strerror(errno)); - return false; - } - - if (dup2(dev_null_fd, fd) == -1) { - LOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno)); - return false; - } - - if (close(dev_null_fd) == -1) { - LOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno)); - return false; - } - - return true; - } - - bool Reopen() const { - if (is_sock) { - return true; - } - - // NOTE: This might happen if the file was unlinked after being opened. - // It's a common pattern in the case of temporary files and the like but - // we should not allow such usage from the zygote. - const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags)); - - if (new_fd == -1) { - LOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno)); - return false; - } - - if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) { - close(new_fd); - LOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno)); - return false; - } - - if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) { - close(new_fd); - LOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno)); - return false; - } - - if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) { - close(new_fd); - LOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno)); - return false; - } - - if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) { - close(new_fd); - LOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno)); - return false; - } - - close(new_fd); - - return true; - } - - const int fd; - const struct stat stat; - const std::string file_path; - const int open_flags; - const int fd_flags; - const int fs_flags; - const off_t offset; - const bool is_sock; - -private: - FileDescriptorInfo(int pfd) : - fd(pfd), - stat(), - open_flags(0), - fd_flags(0), - fs_flags(0), - offset(0), - is_sock(true) { - } - - FileDescriptorInfo(struct stat pstat, const std::string &pfile_path, int pfd, int popen_flags, - int pfd_flags, int pfs_flags, off_t poffset) : - fd(pfd), - stat(pstat), - file_path(pfile_path), - open_flags(popen_flags), - fd_flags(pfd_flags), - fs_flags(pfs_flags), - offset(poffset), - is_sock(false) { - } - - // Returns true iff. a given path is whitelisted. - static bool IsWhitelisted(const std::string &path) { - for (size_t i = 0; - i < (sizeof(kPathPrefixWhitelist) / sizeof(kPathPrefixWhitelist[0])); ++i) { - if (path.compare(0, strlen(kPathPrefixWhitelist[i]), kPathPrefixWhitelist[i]) == 0) { - return true; - } - } - return false; - } - - // TODO: Call android::base::Readlink instead of copying the code here. - static bool Readlink(const int fd, std::string *result) { - char path[64]; - snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); - - // Code copied from android::base::Readlink starts here : - - // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer, - // and truncates to whatever size you do supply, so it can't be used to query. - // We could call lstat first, but that would introduce a race condition that - // we couldn't detect. - // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here. - char *buf = new char[4096]; - ssize_t len = readlink(path, buf, 4096); - if (len == -1) { - delete[] buf; - return false; - } - - result->assign(buf, len); - delete[] buf; - return true; - } - - // Returns the locally-bound name of the socket |fd|. Returns true - // iff. all of the following hold : - // - // - the socket's sa_family is AF_UNIX. - // - the length of the path is greater than zero (i.e, not an unnamed socket). - // - the first byte of the path isn't zero (i.e, not a socket with an abstract - // address). - static bool GetSocketName(const int fd, std::string *result) { - sockaddr_storage ss; - sockaddr *addr = reinterpret_cast(&ss); - socklen_t addr_len = sizeof(ss); - - if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) { - LOGE("Failed getsockname(%d) : %s", fd, strerror(errno)); - return false; - } - -#if PLATFORM_SDK_VERSION <= 23 - if (addr->sa_family == AF_NETLINK) { - (*result) = "@netlink@"; - return true; - } -#endif - - if (addr->sa_family != AF_UNIX) { - //LOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family); - return false; - } - - const sockaddr_un *unix_addr = reinterpret_cast(&ss); - - size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path); - // This is an unnamed local socket, we do not accept it. - if (path_len == 0) { - //LOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd); - return false; - } - - // This is a local socket with an abstract address, we do not accept it. - if (unix_addr->sun_path[0] == '\0') { - //LOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd); - return false; - } - - // If we're here, sun_path must refer to a null terminated filesystem - // pathname (man 7 unix). Remove the terminator before assigning it to an - // std::string. - if (unix_addr->sun_path[path_len - 1] == '\0') { - --path_len; - } - - result->assign(unix_addr->sun_path, path_len); - return true; - } - - - // DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo); - FileDescriptorInfo(const FileDescriptorInfo &); - - void operator=(const FileDescriptorInfo &); -}; - -// A FileDescriptorTable is a collection of FileDescriptorInfo objects -// keyed by their FDs. -class FileDescriptorTable { -public: - // Creates a new FileDescriptorTable. This function scans - // /proc/self/fd for the list of open file descriptors and collects - // information about them. Returns NULL if an error occurs. - static FileDescriptorTable *Create() { - DIR *d = opendir(kFdPath); - if (d == NULL) { - LOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); - return NULL; - } - int dir_fd = dirfd(d); - dirent *e; - - std::unordered_map open_fd_map; - while ((e = readdir(d)) != NULL) { - const int fd = ParseFd(e, dir_fd); - if (fd == -1) { - continue; - } - - FileDescriptorInfo *info = FileDescriptorInfo::createFromFd(fd); - if (info == NULL) { - continue; - } - info->Detach(); - open_fd_map[fd] = info; - } - - if (closedir(d) == -1) { - LOGE("Unable to close directory : %s", strerror(errno)); - return NULL; - } - return new FileDescriptorTable(open_fd_map); - } - - // Reopens all file descriptors that are contained in the table. - void Reopen() { - std::unordered_map::const_iterator it; - for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { - const FileDescriptorInfo *info = it->second; - if (info != NULL) { - info->Reopen(); - delete info; - } - } - } - -private: - FileDescriptorTable(const std::unordered_map &map) - : open_fd_map_(map) { - } - - static int ParseFd(dirent *e, int dir_fd) { - char *end; - const int fd = strtol(e->d_name, &end, 10); - if ((*end) != '\0') { - return -1; - } - - // Don't bother with the standard input/output/error, they're handled - // specially post-fork anyway. - if (fd <= STDERR_FILENO || fd == dir_fd) { - return -1; - } - - return fd; - } - - // Invariant: All values in this unordered_map are non-NULL. - std::unordered_map open_fd_map_; - - // DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable); - FileDescriptorTable(const FileDescriptorTable &); - - void operator=(const FileDescriptorTable &); -}; \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/include/framework/fd_utils.h b/edxp-core/src/main/cpp/main/include/framework/fd_utils.h deleted file mode 100644 index a576337d..00000000 --- a/edxp-core/src/main/cpp/main/include/framework/fd_utils.h +++ /dev/null @@ -1,37 +0,0 @@ - -#pragma once - -#include -#include "base/object.h" - -namespace android { - - // Static whitelist of open paths that the zygote is allowed to keep open. - static const char *kPathWhitelist[] = { - "/data/app/", - "/data/app-private/" - }; - - class FileDescriptorWhitelist : public edxp::HookedObject { - - public: - FileDescriptorWhitelist(void *thiz) : HookedObject(thiz) {} - - static void Setup(void *handle, HookFunType hook_func) { - HOOK_FUNC(IsAllowed, - "_ZNK23FileDescriptorWhitelist9IsAllowedERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE"); - } - - private: - - CREATE_HOOK_STUB_ENTRIES(bool, IsAllowed, void *thiz, const std::string &path) { - for (const auto &whitelist_path : kPathWhitelist) { - if (android::base::StartsWith(path, whitelist_path)) - return true; - } - return IsAllowedBackup(thiz, path); - } - - }; - -} \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/include/logging.h b/edxp-core/src/main/cpp/main/include/logging.h index 4a009af2..5c7625b4 100644 --- a/edxp-core/src/main/cpp/main/include/logging.h +++ b/edxp-core/src/main/cpp/main/include/logging.h @@ -1,15 +1,12 @@ #ifndef _LOGGING_H #define _LOGGING_H -#include -#include "android/log.h" +#include #ifndef LOG_TAG #define LOG_TAG "EdXposed" #endif -#include "config.h" - #ifdef LOG_DISABLED #define LOGD(...) #define LOGV(...) @@ -17,7 +14,7 @@ #define LOGW(...) #define LOGE(...) #else -#ifdef DEBUG +#ifndef NDEBUG #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #else #define LOGD(...) diff --git a/edxp-core/src/main/cpp/main/include/utils.h b/edxp-core/src/main/cpp/main/include/utils.h new file mode 100644 index 00000000..bbedf14a --- /dev/null +++ b/edxp-core/src/main/cpp/main/include/utils.h @@ -0,0 +1,31 @@ +// +// Created by loves on 11/13/2020. +// +#pragma once + +#include +#include +#include "logging.h" +#include + +namespace edxp { + + static inline int32_t GetAndroidApiLevel() { + char prop_value[PROP_VALUE_MAX]; + __system_property_get("ro.build.version.sdk", prop_value); + return atoi(prop_value); + } + + inline const std::string operator ""_str(const char *str, std::size_t size) { + return {str, size}; + } + + inline bool path_exists(const std::filesystem::path &path) { + try { + return std::filesystem::exists(path); + } catch (const std::filesystem::filesystem_error &e) { + LOGE("%s", e.what()); + return false; + } + } +} diff --git a/edxp-core/src/main/cpp/main/src/config_manager.cpp b/edxp-core/src/main/cpp/main/src/config_manager.cpp index b0a1425c..9ec80252 100644 --- a/edxp-core/src/main/cpp/main/src/config_manager.cpp +++ b/edxp-core/src/main/cpp/main/src/config_manager.cpp @@ -12,70 +12,64 @@ #include #include -#include #include -#include -#include +#include +#include +#include #include "art/runtime/native/native_util.h" #include "config_manager.h" - -using namespace std; -using namespace art; +#include "utils.h" namespace edxp { + namespace fs = std::filesystem; std::string ConfigManager::RetrieveInstallerPkgName() const { - std::string data_test_path = data_path_prefix_ + kPrimaryInstallerPkgName; - if (access(data_test_path.c_str(), F_OK) == 0) { - LOGI("using installer %s", kPrimaryInstallerPkgName); + std::string data_test_path = data_path_prefix_ / kPrimaryInstallerPkgName; + if (path_exists(data_test_path)) { + LOGI("using installer %s", kPrimaryInstallerPkgName.c_str()); return kPrimaryInstallerPkgName; } - data_test_path = data_path_prefix_ + kLegacyInstallerPkgName; - if (access(data_test_path.c_str(), F_OK) == 0) { - LOGI("using installer %s", kLegacyInstallerPkgName); + data_test_path = data_path_prefix_ / kLegacyInstallerPkgName; + if (path_exists(data_test_path)) { + LOGI("using installer %s", kLegacyInstallerPkgName.c_str()); return kLegacyInstallerPkgName; } - LOGE("no supported installer app found, using default: %s", kPrimaryInstallerPkgName); + LOGE("no supported installer app found, using default: %s", + kPrimaryInstallerPkgName.c_str()); return kPrimaryInstallerPkgName; } void ConfigManager::SnapshotBlackWhiteList() { - DIR *dir; - struct dirent *dent; - dir = opendir(whitelist_path_.c_str()); - if (dir != nullptr) { - while ((dent = readdir(dir)) != nullptr) { - if (dent->d_type == DT_REG) { - const char *fileName = dent->d_name; - LOGI(" whitelist: %s", fileName); - white_list_default_.emplace_back(fileName); + white_list_default_.clear(); + black_list_default_.clear(); + try { + for (auto &item: fs::directory_iterator(whitelist_path_)) { + if (item.is_regular_file()) { + const auto &file_name = item.path().filename(); + LOGI(" whitelist: %s", file_name.c_str()); + white_list_default_.emplace(file_name); } } - closedir(dir); - } - dir = opendir(blacklist_path_.c_str()); - if (dir != nullptr) { - while ((dent = readdir(dir)) != nullptr) { - if (dent->d_type == DT_REG) { - const char *fileName = dent->d_name; - LOGI(" blacklist: %s", fileName); - black_list_default_.emplace_back(fileName); + for (auto &item: fs::directory_iterator(blacklist_path_)) { + if (item.is_regular_file()) { + const auto &file_name = item.path().filename(); + LOGI(" blacklist: %s", file_name.c_str()); + black_list_default_.emplace(file_name); } } - closedir(dir); + } catch (const fs::filesystem_error &e) { + LOGE("%s", e.what()); } } void ConfigManager::UpdateConfigPath(const uid_t user) { - if (last_user_ != user) { - LOGI("updating config data paths from %u to %u...", last_user_, user); - last_user_ = user; - } + if (LIKELY(last_user_ == user && instance_)) return; - const char *format = use_prot_storage_ ? "/data/user_de/%u/" : "/data/user/%u/"; - char buff[PATH_MAX]; - snprintf(buff, sizeof(buff), format, last_user_); - data_path_prefix_ = buff; + LOGI("updating config data paths from %u to %u...", last_user_, user); + last_user_ = user; + + data_path_prefix_ = use_prot_storage_ ? "/data/user_de" : "/data/user"; + data_path_prefix_ /= std::to_string(last_user_); installer_pkg_name_ = RetrieveInstallerPkgName(); base_config_path_ = GetConfigPath(""); @@ -83,15 +77,20 @@ namespace edxp { whitelist_path_ = GetConfigPath("whitelist/"); use_whitelist_path_ = GetConfigPath("usewhitelist"); - dynamic_modules_enabled_ = access(GetConfigPath("dynamicmodules").c_str(), F_OK) == 0; - black_white_list_enabled_ = access(GetConfigPath("blackwhitelist").c_str(), F_OK) == 0; - deopt_boot_image_enabled_ = access(GetConfigPath("deoptbootimage").c_str(), F_OK) == 0; - resources_hook_enabled_ = access(GetConfigPath("disable_resources").c_str(), F_OK) != 0; - no_module_log_enabled_ = access(GetConfigPath("disable_modules_log").c_str(), F_OK) == 0; - hidden_api_bypass_enabled_ = access(GetConfigPath("disable_hidden_api_bypass").c_str(), F_OK) != 0; + dynamic_modules_enabled_ = path_exists(GetConfigPath("dynamicmodules")); + black_white_list_enabled_ = path_exists(GetConfigPath("blackwhitelist")); + deopt_boot_image_enabled_ = path_exists(GetConfigPath("deoptbootimage")); + resources_hook_enabled_ = path_exists(GetConfigPath("enable_resources")); + no_module_log_enabled_ = path_exists(GetConfigPath("disable_modules_log")); + hidden_api_bypass_enabled_ = + !path_exists(GetConfigPath("disable_hidden_api_bypass")); + modules_list_.clear(); + app_modules_list_.clear(); + + UpdateModuleList(); // use_white_list snapshot - use_white_list_snapshot_ = access(use_whitelist_path_.c_str(), F_OK) == 0; + use_white_list_snapshot_ = path_exists(use_whitelist_path_); LOGI("data path prefix: %s", data_path_prefix_.c_str()); LOGI(" application list mode: %s", BoolToString(black_white_list_enabled_)); LOGI(" using whitelist: %s", BoolToString(use_white_list_snapshot_)); @@ -105,118 +104,130 @@ namespace edxp { } } - bool ConfigManager::IsAppNeedHook(const std::string &app_data_dir) { + std::string ConfigManager::GetPackageNameFromBaseApkPath(const fs::path &path) { + std::vector paths(path.begin(), path.end()); + auto base_apk = paths.back(); // base.apk + if (base_apk != "base.apk") return {}; + paths.pop_back(); + auto pkg_name_with_obfuscation = paths.back(); + if (auto pos = pkg_name_with_obfuscation.find('-'); pos != std::string::npos) { + return pkg_name_with_obfuscation.substr(0, pos); + } + return {}; + } + + // TODO ignore unrelated processes + bool ConfigManager::IsAppNeedHook(const uid_t user, const std::string &package_name) { // zygote always starts with `uid == 0` and then fork into different user. // so we have to check if we are the correct user or not. - uid_t user = 0; - char package_name[PATH_MAX]; - if (sscanf(app_data_dir.c_str(), "/data/%*[^/]/%u/%s", &user, package_name) != 2) { - if (sscanf(app_data_dir.c_str(), "/data/%*[^/]/%s", package_name) != 1) { - package_name[0] = '\0'; - LOGE("can't parse %s", app_data_dir.c_str()); - return false; // default to no hooking for safety - } - } - - if (last_user_ != user) { - UpdateConfigPath(user); - } + UpdateConfigPath(user); if (!black_white_list_enabled_) { return true; } - bool can_access_app_data = access(base_config_path_.c_str(), F_OK) == 0; + bool can_access_app_data = path_exists(base_config_path_); bool use_white_list; if (can_access_app_data) { - use_white_list = access(use_whitelist_path_.c_str(), F_OK) == 0; + use_white_list = path_exists(use_whitelist_path_); } else { LOGE("can't access config path, using snapshot use_white_list: %s", - app_data_dir.c_str()); + package_name.c_str()); use_white_list = use_white_list_snapshot_; } - if (strcmp(package_name, kPrimaryInstallerPkgName) == 0 - || strcmp(package_name, kLegacyInstallerPkgName) == 0) { + if (package_name == kPrimaryInstallerPkgName + || package_name == kLegacyInstallerPkgName) { // always hook installer apps return true; } if (use_white_list) { if (!can_access_app_data) { LOGE("can't access config path, using snapshot white list: %s", - app_data_dir.c_str()); - return !(find(white_list_default_.begin(), white_list_default_.end(), - package_name) == - white_list_default_.end()); + package_name.c_str()); + return white_list_default_.count(package_name); } - std::string target_path = whitelist_path_ + package_name; - bool res = access(target_path.c_str(), F_OK) == 0; - LOGD("using whitelist, %s -> %d", app_data_dir.c_str(), res); + std::string target_path = whitelist_path_ / package_name; + bool res = path_exists(target_path); + LOGD("using whitelist, %s -> %d", package_name.c_str(), res); return res; } else { if (!can_access_app_data) { LOGE("can't access config path, using snapshot black list: %s", - app_data_dir.c_str()); - return find(black_list_default_.begin(), black_list_default_.end(), package_name) == - black_list_default_.end(); + package_name.c_str()); + return black_list_default_.count(package_name) == 0; } - std::string target_path = blacklist_path_ + package_name; - bool res = access(target_path.c_str(), F_OK) != 0; - LOGD("using blacklist, %s -> %d", app_data_dir.c_str(), res); + std::string target_path = blacklist_path_ / package_name; + bool res = !path_exists(target_path); + LOGD("using blacklist, %s -> %d", package_name.c_str(), res); return res; } } - ALWAYS_INLINE bool ConfigManager::IsBlackWhiteListEnabled() const { - return black_white_list_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsDynamicModulesEnabled() const { - return dynamic_modules_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsNoModuleLogEnabled() const { - return no_module_log_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsResourcesHookEnabled() const { - return resources_hook_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsDeoptBootImageEnabled() const { - return deopt_boot_image_enabled_; - } - - ALWAYS_INLINE bool ConfigManager::IsHiddenAPIBypassEnabled() const { - return hidden_api_bypass_enabled_; - } - - ALWAYS_INLINE std::string ConfigManager::GetInstallerPackageName() const { - return installer_pkg_name_; - } - - ALWAYS_INLINE std::string ConfigManager::GetXposedPropPath() const { - return kXposedPropPath; - } - - ALWAYS_INLINE std::string ConfigManager::GetLibSandHookName() const { - return kLibSandHookName; - } - - ALWAYS_INLINE std::string ConfigManager::GetLibWhaleName() const { - return kLibWhaleName; - } - - ALWAYS_INLINE std::string ConfigManager::GetDataPathPrefix() const { - return data_path_prefix_; - } - - ALWAYS_INLINE std::string ConfigManager::GetConfigPath(const std::string &suffix) const { - return data_path_prefix_ + installer_pkg_name_ + "/conf/" + suffix; - }; - ConfigManager::ConfigManager() { use_prot_storage_ = GetAndroidApiLevel() >= __ANDROID_API_N__; last_user_ = 0; UpdateConfigPath(last_user_); } + bool ConfigManager::UpdateModuleList() { + if (LIKELY(!modules_list_.empty()) && !IsDynamicModulesEnabled()) + return true; + modules_list_.clear(); + auto global_modules_list = GetConfigPath("modules.list"); + if (!path_exists(global_modules_list)) { + LOGE("Cannot access path %s", global_modules_list.c_str()); + return false; + } + + if (auto last_write_time = fs::last_write_time(global_modules_list); + LIKELY(last_write_time < last_write_time_)) { + return true; + } else { + last_write_time_ = last_write_time; + } + + std::ifstream ifs(global_modules_list); + if (!ifs.good()) { + LOGE("Cannot access path %s", global_modules_list.c_str()); + return false; + } + std::string module; + while (std::getline(ifs, module)) { + const auto &module_pkg_name = GetPackageNameFromBaseApkPath(module); + modules_list_.emplace_back(std::move(module), std::unordered_set{}); + const auto &module_scope_conf = GetConfigPath(module_pkg_name + ".conf"); + if (!path_exists(module_scope_conf)) { + LOGD("module scope is not set for %s", module_pkg_name.c_str()); + continue; + } + std::ifstream ifs_c(module_scope_conf); + if (!ifs_c.good()) { + LOGE("Cannot access path %s", module_scope_conf.c_str()); + continue; + } + auto &scope = modules_list_.back().second; + std::string app_pkg_name; + while (std::getline(ifs_c, app_pkg_name)) { + if (!app_pkg_name.empty()) + scope.emplace(std::move(app_pkg_name)); + } + scope.insert(module_pkg_name); // Always add module itself + LOGD("scope of %s is:\n%s", module_pkg_name.c_str(), ([&scope]() { + std::ostringstream join; + std::copy(scope.begin(), scope.end(), + std::ostream_iterator(join, "\n")); + return join.str(); + })().c_str()); + } + return true; + } + + bool ConfigManager::UpdateAppModuleList(const uid_t user, const std::string &pkg_name) { + UpdateConfigPath(user); + app_modules_list_.clear(); + for (const auto&[module, scope]: modules_list_) { + if (scope.empty() || scope.count(pkg_name)) app_modules_list_.push_back(module); + } + return !app_modules_list_.empty() || pkg_name == installer_pkg_name_; + } + } \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/src/config_manager.h b/edxp-core/src/main/cpp/main/src/config_manager.h index f1b9faf1..45815473 100644 --- a/edxp-core/src/main/cpp/main/src/config_manager.h +++ b/edxp-core/src/main/cpp/main/src/config_manager.h @@ -3,71 +3,91 @@ #include #include -#include +#include "JNIHelper.h" +#include #include +#include +#include +#include +#include "config.h" namespace edxp { - static constexpr const char *kPrimaryInstallerPkgName = "org.meowcat.edxposed.manager"; - static constexpr const char *kLegacyInstallerPkgName = "de.robv.android.xposed.installer"; - static constexpr auto kXposedPropPath = "/system/framework/edconfig.jar"; + static const std::string kPrimaryInstallerPkgName = "org.meowcat.edxposed.manager"; + static const std::string kLegacyInstallerPkgName = "de.robv.android.xposed.installer"; + static const std::string kXposedPropPath = "/system/framework/edconfig.jar"; class ConfigManager { public: - - static ConfigManager *GetInstance() { - if (instance_ == 0) { - instance_ = new ConfigManager(); + inline static ConfigManager *GetInstance() { + if (!instance_) { + instance_ = std::make_unique(); } - return instance_; + return instance_.get(); } - bool IsBlackWhiteListEnabled() const; + inline static std::unique_ptr ReleaseInstance() { + return std::move(instance_); + } - bool IsDynamicModulesEnabled() const; + inline auto IsBlackWhiteListEnabled() const { return black_white_list_enabled_; } - bool IsResourcesHookEnabled() const; + inline auto IsDynamicModulesEnabled() const { return dynamic_modules_enabled_; } - bool IsDeoptBootImageEnabled() const; + inline auto IsResourcesHookEnabled() const { return resources_hook_enabled_; } - bool IsNoModuleLogEnabled() const; + inline auto IsDeoptBootImageEnabled() const { return deopt_boot_image_enabled_; } - bool IsHiddenAPIBypassEnabled() const; + inline auto IsNoModuleLogEnabled() const { return no_module_log_enabled_; } - std::string GetInstallerPackageName() const; + inline auto IsHiddenAPIBypassEnabled() const { return hidden_api_bypass_enabled_; } - std::string GetXposedPropPath() const; + inline auto GetInstallerPackageName() const { return installer_pkg_name_; } - std::string GetLibSandHookName() const; + inline auto GetXposedPropPath() const { return kXposedPropPath; } - std::string GetLibWhaleName() const; + inline auto GetLibSandHookName() const { return kLibSandHookName; } - std::string GetDataPathPrefix() const; + inline auto GetDataPathPrefix() const { return data_path_prefix_; } - std::string GetConfigPath(const std::string &suffix) const; + inline auto GetConfigPath(const std::string &suffix) const { + return data_path_prefix_ / installer_pkg_name_ / "conf" / suffix; + } - bool IsAppNeedHook(const std::string &app_data_dir); + inline auto GetAppModulesList() const { return app_modules_list_; }; + + bool UpdateAppModuleList(const uid_t user, const std::string &pkg_name); + + bool IsAppNeedHook(const uid_t user, const std::string &pkg_name); + + bool UpdateModuleList(); - bool hidden_api_bypass_enabled_ = false; private: - inline static ConfigManager *instance_; - uid_t last_user_ = false; + inline static std::unique_ptr instance_ = nullptr; + uid_t last_user_ = 0; bool use_prot_storage_ = true; - std::string data_path_prefix_; - std::string installer_pkg_name_; - std::string base_config_path_; - std::string blacklist_path_; - std::string whitelist_path_; - std::string use_whitelist_path_; + std::filesystem::path data_path_prefix_; + std::filesystem::path installer_pkg_name_; + std::filesystem::path base_config_path_; + std::filesystem::path blacklist_path_; + std::filesystem::path whitelist_path_; + std::filesystem::path use_whitelist_path_; bool black_white_list_enabled_ = false; bool dynamic_modules_enabled_ = false; bool deopt_boot_image_enabled_ = false; bool no_module_log_enabled_ = false; - bool resources_hook_enabled_ = true; + bool resources_hook_enabled_ = false; // snapshot at boot bool use_white_list_snapshot_ = false; - std::vector white_list_default_; - std::vector black_list_default_; + std::unordered_set white_list_default_; + std::unordered_set black_list_default_; + bool hidden_api_bypass_enabled_ = false; + + std::vector>> modules_list_; + + std::vector app_modules_list_; + + std::filesystem::file_time_type last_write_time_; ConfigManager(); @@ -76,6 +96,11 @@ namespace edxp { void SnapshotBlackWhiteList(); std::string RetrieveInstallerPkgName() const; + + static std::string GetPackageNameFromBaseApkPath(const std::filesystem::path &path); + + friend std::unique_ptr std::make_unique(); + }; } // namespace edxp diff --git a/edxp-core/src/main/cpp/main/src/edxp_context.cpp b/edxp-core/src/main/cpp/main/src/edxp_context.cpp index e6a3a38d..f9d2d604 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.cpp +++ b/edxp-core/src/main/cpp/main/src/edxp_context.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -15,6 +14,8 @@ #include #include #include +#include +#include #include "edxp_context.h" #include "config_manager.h" @@ -22,27 +23,14 @@ #pragma clang diagnostic ignored "-Wunused-value" namespace edxp { + namespace fs = std::filesystem; - Context *Context::instance_ = nullptr; - - Context *Context::GetInstance() { - if (instance_ == nullptr) { - instance_ = new Context(); - } - return instance_; - } - - ALWAYS_INLINE bool Context::IsInitialized() const { - return initialized_; - } - - ALWAYS_INLINE Variant Context::GetVariant() const { - return variant_; - } - - ALWAYS_INLINE jobject Context::GetCurrentClassLoader() const { - return inject_class_loader_; - } + constexpr int FIRST_ISOLATED_UID = 99000; + constexpr int LAST_ISOLATED_UID = 99999; + constexpr int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; + constexpr int LAST_APP_ZYGOTE_ISOLATED_UID = 98999; + constexpr int SHARED_RELRO_UID = 1037; + constexpr int PER_USER_RANGE = 100000; void Context::CallPostFixupStaticTrampolinesCallback(void *class_ptr, jmethodID callback_mid) { if (UNLIKELY(!callback_mid || !class_linker_class_)) { @@ -68,7 +56,28 @@ namespace edxp { CallPostFixupStaticTrampolinesCallback(class_ptr, post_fixup_static_mid_); } - void Context::LoadDexAndInit(JNIEnv *env, const char *dex_path) { + void Context::PreLoadDex(JNIEnv *env, const std::string &dex_path) { + if (LIKELY(!dexes.empty())) return; + std::vector paths; + { + std::istringstream is(dex_path); + std::string path; + while (std::getline(is, path, ':')) { + paths.emplace_back(std::move(path)); + } + } + for (const auto &path: paths) { + std::ifstream is(path, std::ios::binary); + if (!is.good()) { + LOGE("Cannot load path %s", path.c_str()); + } + dexes.emplace_back(std::istreambuf_iterator(is), + std::istreambuf_iterator()); + LOGD("Loaded %s with size %zu", path.c_str(), dexes.back().size()); + } + } + + void Context::InjectDexAndInit(JNIEnv *env) { if (LIKELY(initialized_)) { return; } @@ -78,26 +87,37 @@ namespace edxp { env, classloader, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); jobject sys_classloader = JNI_CallStaticObjectMethod(env, classloader, getsyscl_mid); if (UNLIKELY(!sys_classloader)) { - LOG(ERROR) << "getSystemClassLoader failed!!!"; + LOGE("getSystemClassLoader failed!!!"); return; } - jclass path_classloader = JNI_FindClass(env, "dalvik/system/PathClassLoader"); - jmethodID initMid = JNI_GetMethodID(env, path_classloader, "", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V"); - jobject my_cl = JNI_NewObject(env, path_classloader, initMid, env->NewStringUTF(dex_path), - nullptr, sys_classloader); - + jclass in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader"); + jmethodID initMid = JNI_GetMethodID(env, in_memory_classloader, "", + "([Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V"); + jclass byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer"); + jmethodID byte_buffer_wrap = JNI_GetStaticMethodID(env, byte_buffer_class, "wrap", + "([B)Ljava/nio/ByteBuffer;"); + auto buffer_array = env->NewObjectArray(dexes.size(), byte_buffer_class, nullptr); + for (size_t i = 0; i != dexes.size(); ++i) { + const auto dex = dexes.at(i); + auto byte_array = env->NewByteArray(dex.size()); + env->SetByteArrayRegion(byte_array, 0, dex.size(), + dex.data()); + auto buffer = JNI_CallStaticObjectMethod(env, byte_buffer_class, byte_buffer_wrap, + byte_array); + env->SetObjectArrayElement(buffer_array, i, buffer); + } + jobject my_cl = env->NewObject(in_memory_classloader, initMid, + buffer_array, sys_classloader); env->DeleteLocalRef(classloader); env->DeleteLocalRef(sys_classloader); - env->DeleteLocalRef(path_classloader); + env->DeleteLocalRef(in_memory_classloader); + env->DeleteLocalRef(byte_buffer_class); if (UNLIKELY(my_cl == nullptr)) { - LOG(ERROR) << "PathClassLoader creation failed!!!"; + LOGE("InMemoryDexClassLoader creation failed!!!"); return; } - // TODO clear up all these global refs if blacklisted? - inject_class_loader_ = env->NewGlobalRef(my_cl); env->DeleteLocalRef(my_cl); @@ -117,7 +137,6 @@ namespace edxp { FindClassFromLoader(env, GetCurrentClassLoader(), kEntryClassName))); RegisterEdxpResourcesHook(env); - RegisterFrameworkZygote(env); RegisterConfigManagerMethods(env); RegisterArtClassLinker(env); RegisterArtHeap(env); @@ -159,7 +178,7 @@ namespace edxp { } jclass - Context::FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name) const { + Context::FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name) { jclass clz = JNI_GetObjectClass(env, class_loader); jmethodID mid = JNI_GetMethodID(env, clz, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); @@ -174,21 +193,17 @@ namespace edxp { return (jclass) target; } } else { - LOG(ERROR) << "No loadClass/findClass method found"; + LOGE("No loadClass/findClass method found"); } - LOG(ERROR) << "Class %s not found: " << class_name; + LOGE("Class %s not found", class_name); return ret; } - jclass Context::FindClassFromLoader(JNIEnv *env, const char *className) const { - return FindClassFromLoader(env, GetCurrentClassLoader(), className); - } inline void Context::PrepareJavaEnv(JNIEnv *env) { - LoadDexAndInit(env, kInjectDexPath); + InjectDexAndInit(env); } - inline void Context::FindAndCall(JNIEnv *env, const char *method_name, const char *method_sig, ...) const { if (UNLIKELY(!entry_class_)) { @@ -206,45 +221,38 @@ namespace edxp { } } - ALWAYS_INLINE JavaVM *Context::GetJavaVM() const { - return vm_; - } - - ALWAYS_INLINE void Context::SetAppDataDir(jstring app_data_dir) { - app_data_dir_ = app_data_dir; - } - - ALWAYS_INLINE jstring Context::GetAppDataDir() const { - return app_data_dir_; - } - - ALWAYS_INLINE void Context::SetNiceName(jstring nice_name) { - nice_name_ = nice_name; - } - - ALWAYS_INLINE jstring Context::GetNiceName() const { - return nice_name_; - } - void - Context::OnNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid, + Context::OnNativeForkSystemServerPre(JNIEnv *env, [[maybe_unused]] jclass clazz, uid_t uid, + gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) { - app_data_dir_ = env->NewStringUTF(SYSTEM_SERVER_DATA_DIR); - PrepareJavaEnv(env); - // jump to java code - FindAndCall(env, "forkSystemServerPre", "(II[II[[IJJ)V", uid, gid, gids, runtime_flags, - rlimits, permitted_capabilities, effective_capabilities); + ConfigManager::GetInstance()->UpdateModuleList(); // I don't think we need this, but anyway + skip_ = false; + if (!ConfigManager::GetInstance()->IsAppNeedHook(0, "android")) { + skip_ = true; + LOGW("skip injecting xposed into android because it's whitelisted/blacklisted"); + } + if (!skip_ && !ConfigManager::GetInstance()->UpdateAppModuleList(0, "android")) { + skip_ = true; + LOGW("skip injecting into android because no module hooks it"); + } + PreLoadDex(env, kInjectDexPath); } int Context::OnNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) { if (res == 0) { - PrepareJavaEnv(env); - // only do work in child since FindAndCall would print log - FindAndCall(env, "forkSystemServerPost", "(I)V", res); + if (!skip_) { + PrepareJavaEnv(env); + // only do work in child since FindAndCall would print log + FindAndCall(env, "forkSystemServerPost", "(I)V", res); + } else { + auto config_manager = ConfigManager::ReleaseInstance(); + auto context = Context::ReleaseInstance(); + LOGD("skipped android"); + } } else { // in zygote process, res is child zygote pid // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66 @@ -252,6 +260,64 @@ namespace edxp { return 0; } + std::tuple + Context::GetAppInfoFromDir(JNIEnv *env, jstring dir) { + uid_t uid = 0; + JUTFString app_data_dir(env, dir); + if (!app_data_dir) return {false, 0, {}}; + fs::path path(app_data_dir.get()); + std::vector splits(path.begin(), path.end()); + if (splits.size() < 5u) { + LOGE("can't parse %s", path.c_str()); + return {false, uid, {}}; + } + const auto &uid_str = splits[3]; + const auto &package_name = splits[4]; + try { + uid = stol(uid_str); + } catch (const std::invalid_argument &ignored) { + LOGE("can't parse %s", app_data_dir.get()); + return {false, uid, {}}; + } + return {true, uid, package_name}; + } + + bool Context::ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid, + jboolean is_child_zygote) { + const auto app_id = uid % PER_USER_RANGE; + const auto&[res, user, package_name] = GetAppInfoFromDir(env, data_dir); + bool skip = false; + if (!res) { + LOGW("skip injecting into %s because it has no data dir", package_name.c_str()); + skip = true; + } + if (!skip && is_child_zygote) { + skip = true; + LOGW("skip injecting into %s because it's a child zygote", package_name.c_str()); + } + + if (!skip && ((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) || + (app_id >= FIRST_APP_ZYGOTE_ISOLATED_UID && + app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) || + app_id == SHARED_RELRO_UID)) { + skip = true; + LOGW("skip injecting into %s because it's isolated", package_name.c_str()); + } + + if (!skip && !ConfigManager::GetInstance()->IsAppNeedHook(user, package_name)) { + skip = true; + LOGW("skip injecting xposed into %s because it's whitelisted/blacklisted", + package_name.c_str()); + } + + if (!skip && !ConfigManager::GetInstance()->UpdateAppModuleList(user, package_name)) { + skip = true; + LOGW("skip injecting xposed into %s because no module hooks it", + package_name.c_str()); + } + return skip; + } + void Context::OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, @@ -265,21 +331,31 @@ namespace edxp { jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir) { + ConfigManager::GetInstance()->UpdateModuleList(); + skip_ = ShouldSkipInject(env, nice_name, app_data_dir, uid, + is_child_zygote); + const JUTFString dir(env, app_data_dir, ""); app_data_dir_ = app_data_dir; nice_name_ = nice_name; - PrepareJavaEnv(env); - FindAndCall(env, "forkAndSpecializePre", - "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)V", - uid, gid, gids, runtime_flags, rlimits, - mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, - is_child_zygote, instruction_set, app_data_dir); + PreLoadDex(env, kInjectDexPath); } - int Context::OnNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) { + int + Context::OnNativeForkAndSpecializePost(JNIEnv *env, [[maybe_unused]]jclass clazz, jint res) { if (res == 0) { - PrepareJavaEnv(env); - FindAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;Ljava/lang/String;)V", - res, app_data_dir_, nice_name_); + const JUTFString process_name(env, nice_name_); + if (!skip_) { + PrepareJavaEnv(env); + LOGD("Done prepare"); + FindAndCall(env, "forkAndSpecializePost", + "(ILjava/lang/String;Ljava/lang/String;)V", + res, app_data_dir_, nice_name_); + LOGD("injected xposed into %s", process_name.get()); + } else { + auto config_manager = ConfigManager::ReleaseInstance(); + auto context = Context::ReleaseInstance(); + LOGD("skipped %s", process_name.get()); + } } else { // in zygote process, res is child zygote pid // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66 diff --git a/edxp-core/src/main/cpp/main/src/edxp_context.h b/edxp-core/src/main/cpp/main/src/edxp_context.h index c5cc8042..a89f488a 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.h +++ b/edxp-core/src/main/cpp/main/src/edxp_context.h @@ -1,26 +1,37 @@ #pragma once +#include #include -#include +#include +#include +#include +#include +#include "utils.h" namespace edxp { - -#define SYSTEM_SERVER_DATA_DIR "/data/user/0/android" - + static const auto SYSTEM_SERVER_DATA_DIR = "/data/user/0/android"_str; enum Variant { NONE = 0, YAHFA = 1, SANDHOOK = 2, - WHALE = 3 }; class Context { public: - static Context *GetInstance(); + inline static Context *GetInstance() { + if (!instance_) { + instance_ = std::make_unique(); + } + return instance_.get(); + } - jobject GetCurrentClassLoader() const; + inline static std::unique_ptr ReleaseInstance() { + return std::move(instance_); + } + + inline auto GetCurrentClassLoader() const { return inject_class_loader_; } void CallOnPreFixupStaticTrampolines(void *class_ptr); @@ -30,17 +41,23 @@ namespace edxp { void FindAndCall(JNIEnv *env, const char *method_name, const char *method_sig, ...) const; - JavaVM *GetJavaVM() const; + inline auto *GetJavaVM() const { return vm_; } - void SetAppDataDir(jstring app_data_dir); + inline void SetAppDataDir(jstring app_data_dir) { app_data_dir_ = app_data_dir; } - void SetNiceName(jstring nice_name); + inline void SetNiceName(jstring nice_name) { nice_name_ = nice_name; } - jstring GetAppDataDir() const; + inline auto GetAppDataDir() const { return app_data_dir_; } - jstring GetNiceName() const; + inline auto GetNiceName() const { return nice_name_; } - jclass FindClassFromLoader(JNIEnv *env, const char *className) const; + inline jclass FindClassFromLoader(JNIEnv *env, const std::string &className) const { + return FindClassFromLoader(env, className.c_str()); + }; + + inline jclass FindClassFromLoader(JNIEnv *env, const char *className) const { + return FindClassFromLoader(env, GetCurrentClassLoader(), className); + } void OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, @@ -58,12 +75,12 @@ namespace edxp { jlong permitted_capabilities, jlong effective_capabilities); - bool IsInitialized() const; + inline auto IsInitialized() const { return initialized_; } - Variant GetVariant() const; + inline auto GetVariant() const { return variant_; }; private: - static Context *instance_; + inline static std::unique_ptr instance_; bool initialized_ = false; Variant variant_ = NONE; jobject inject_class_loader_ = nullptr; @@ -74,16 +91,31 @@ namespace edxp { jclass class_linker_class_ = nullptr; jmethodID pre_fixup_static_mid_ = nullptr; jmethodID post_fixup_static_mid_ = nullptr; + bool skip_ = false; + std::vector> dexes; Context() {} - ~Context() {} + void PreLoadDex(JNIEnv *env, const std::string &dex_path); - void LoadDexAndInit(JNIEnv *env, const char *dex_path); + void InjectDexAndInit(JNIEnv *env); - jclass FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name) const; + inline jclass FindClassFromLoader(JNIEnv *env, jobject class_loader, + const std::string &class_name) const { + return FindClassFromLoader(env, class_loader, class_name.c_str()); + } + + static jclass + FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name); void CallPostFixupStaticTrampolinesCallback(void *class_ptr, jmethodID mid); + + static bool ShouldSkipInject(JNIEnv *env, jstring nice_name, jstring data_dir, jint uid, + jboolean is_child_zygote); + + static std::tuple GetAppInfoFromDir(JNIEnv *env, jstring dir); + + friend std::unique_ptr std::make_unique(); }; } diff --git a/edxp-core/src/main/cpp/main/src/jni/art_class_linker.cpp b/edxp-core/src/main/cpp/main/src/jni/art_class_linker.cpp index 5ad62d20..f234b49d 100644 --- a/edxp-core/src/main/cpp/main/src/jni/art_class_linker.cpp +++ b/edxp-core/src/main/cpp/main/src/jni/art_class_linker.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "art_class_linker.h" namespace edxp { @@ -11,7 +12,7 @@ namespace edxp { static std::vector deopted_methods; static void ClassLinker_setEntryPointsToInterpreter(JNI_START, jobject method) { - void *reflected_method = env->FromReflectedMethod(method); + void *reflected_method = getArtMethod(env, method); if (std::find(deopted_methods.begin(), deopted_methods.end(), reflected_method) != deopted_methods.end()) { LOGD("method %p has been deopted before, skip...", reflected_method); diff --git a/edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp b/edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp index 21983d4c..1190ce4d 100644 --- a/edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp +++ b/edxp-core/src/main/cpp/main/src/jni/edxp_config_manager.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "edxp_config_manager.h" namespace edxp { @@ -34,10 +35,6 @@ namespace edxp { return env->NewStringUTF(ConfigManager::GetInstance()->GetXposedPropPath().c_str()); } - static jstring ConfigManager_getLibWhaleName(JNI_START) { - return env->NewStringUTF(ConfigManager::GetInstance()->GetLibWhaleName().c_str()); - } - static jstring ConfigManager_getLibSandHookName(JNI_START) { return env->NewStringUTF(ConfigManager::GetInstance()->GetLibSandHookName().c_str()); } @@ -54,11 +51,13 @@ namespace edxp { } - static jboolean ConfigManager_isAppNeedHook(JNI_START, jstring appDataDir) { - const char *app_data_dir = env->GetStringUTFChars(appDataDir, JNI_FALSE); - auto result = (jboolean) ConfigManager::GetInstance()->IsAppNeedHook(app_data_dir); - env->ReleaseStringUTFChars(appDataDir, app_data_dir); - return result; + static jstring ConfigManager_getModulesList(JNI_START) { + auto module_list = ConfigManager::GetInstance()->GetAppModulesList(); + std::ostringstream join; + std::copy(module_list.begin(), module_list.end(), std::ostream_iterator(join, "\n")); + const auto &list = join.str(); + LOGD("module list: %s", list.c_str()); + return env->NewStringUTF(list.c_str()); } static JNINativeMethod gMethods[] = { @@ -70,10 +69,10 @@ namespace edxp { NATIVE_METHOD(ConfigManager, getInstallerPackageName, "()Ljava/lang/String;"), NATIVE_METHOD(ConfigManager, getXposedPropPath, "()Ljava/lang/String;"), NATIVE_METHOD(ConfigManager, getLibSandHookName, "()Ljava/lang/String;"), - NATIVE_METHOD(ConfigManager, getLibWhaleName, "()Ljava/lang/String;"), NATIVE_METHOD(ConfigManager, getDataPathPrefix, "()Ljava/lang/String;"), - NATIVE_METHOD(ConfigManager, getInstallerConfigPath, "(Ljava/lang/String;)Ljava/lang/String;"), - NATIVE_METHOD(ConfigManager, isAppNeedHook, "(Ljava/lang/String;)Z"), + NATIVE_METHOD(ConfigManager, getInstallerConfigPath, + "(Ljava/lang/String;)Ljava/lang/String;"), + NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"), }; void RegisterConfigManagerMethods(JNIEnv *env) { diff --git a/edxp-core/src/main/cpp/main/src/jni/edxp_resources_hook.cpp b/edxp-core/src/main/cpp/main/src/jni/edxp_resources_hook.cpp index 17c20939..a426f78a 100644 --- a/edxp-core/src/main/cpp/main/src/jni/edxp_resources_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/jni/edxp_resources_hook.cpp @@ -11,6 +11,7 @@ namespace edxp { return XposedBridge_initXResourcesNative(env, clazz); } + // @ApiSensitive(Level.MIDDLE) static jboolean ResourcesHook_removeFinalFlagNative(JNI_START, jclass target_class) { if (target_class) { jclass class_clazz = JNI_FindClass(env, "java/lang/Class"); diff --git a/edxp-core/src/main/cpp/main/src/jni/edxp_yahfa.cpp b/edxp-core/src/main/cpp/main/src/jni/edxp_yahfa.cpp index ef8fd37f..26012788 100644 --- a/edxp-core/src/main/cpp/main/src/jni/edxp_yahfa.cpp +++ b/edxp-core/src/main/cpp/main/src/jni/edxp_yahfa.cpp @@ -31,7 +31,8 @@ namespace edxp { LOGE("setNonCompilableNative: member is null"); return; } - void *art_method = env->FromReflectedMethod(member); + void *art_method = getArtMethod(env, member); + if (!art_method) { LOGE("setNonCompilableNative: art_method is null"); return; @@ -44,7 +45,7 @@ namespace edxp { LOGE("setNativeFlagNative: member is null"); return JNI_FALSE; } - void *art_method = env->FromReflectedMethod(member); + void *art_method = getArtMethod(env, member); if (!art_method) { LOGE("setNativeFlagNative: art_method is null"); return JNI_FALSE; diff --git a/edxp-core/src/main/cpp/main/src/jni/framework_zygote.cpp b/edxp-core/src/main/cpp/main/src/jni/framework_zygote.cpp deleted file mode 100644 index fbafd933..00000000 --- a/edxp-core/src/main/cpp/main/src/jni/framework_zygote.cpp +++ /dev/null @@ -1,36 +0,0 @@ - -#include -#include -#include -#include -#include "framework_zygote.h" - -namespace edxp { - - static FileDescriptorTable *gClosedFdTable = nullptr; - - static void Zygote_closeFilesBeforeFork(JNI_START) { - // FIXME what if gClosedFdTable is not null - gClosedFdTable = FileDescriptorTable::Create(); - } - - static void Zygote_reopenFilesAfterFork(JNI_START) { - if (!gClosedFdTable) { - LOGE("gClosedFdTable is null when reopening files"); - return; - } - gClosedFdTable->Reopen(); - delete gClosedFdTable; - gClosedFdTable = nullptr; - } - - static JNINativeMethod gMethods[] = { - NATIVE_METHOD(Zygote, closeFilesBeforeFork, "()V"), - NATIVE_METHOD(Zygote, reopenFilesAfterFork, "()V") - }; - - void RegisterFrameworkZygote(JNIEnv *env) { - REGISTER_EDXP_NATIVE_METHODS("com.elderdrivers.riru.edxp.framework.Zygote"); - } - -} \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/src/jni/framework_zygote.h b/edxp-core/src/main/cpp/main/src/jni/framework_zygote.h deleted file mode 100644 index ab15e267..00000000 --- a/edxp-core/src/main/cpp/main/src/jni/framework_zygote.h +++ /dev/null @@ -1,10 +0,0 @@ - -#pragma once - -#include "jni.h" - -namespace edxp { - - void RegisterFrameworkZygote(JNIEnv *); - -} // namespace edxp diff --git a/edxp-core/src/main/cpp/main/src/main.cpp b/edxp-core/src/main/cpp/main/src/main.cpp index 94b24eb8..5119aedc 100644 --- a/edxp-core/src/main/cpp/main/src/main.cpp +++ b/edxp-core/src/main/cpp/main/src/main.cpp @@ -15,33 +15,31 @@ #include "logging.h" #include "config.h" #include "edxp_context.h" +#include "riru.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" -#define EXPORT extern "C" __attribute__((visibility("default"))) - namespace edxp { - - EXPORT void onModuleLoaded() { + // TODO exclude unrelated processes + static void onModuleLoaded() { LOG(INFO) << "onModuleLoaded: welcome to EdXposed!"; InstallInlineHooks(); } - EXPORT int shouldSkipUid(int uid) { + static int shouldSkipUid(int uid) { return 0; } - EXPORT void nativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint *_uid, jint *gid, + static void nativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint *_uid, jint *gid, jintArray *gids, jint *runtime_flags, jobjectArray *rlimits, jint *mount_external, jstring *se_info, jstring *nice_name, jintArray *fds_to_close, jintArray *fds_to_ignore, jboolean *start_child_zygote, jstring *instruction_set, - jstring *app_data_dir, - /* parameters added in Android Q */ - jstring *package_name, jobjectArray *packages_for_uid, - jstring *sandbox_id) { + jstring *app_data_dir, jboolean *is_top_app, jobjectArray *pkg_data_info_list, + jobjectArray *whitelisted_data_info_list, jboolean *bind_mount_app_data_dirs, + jboolean *bind_mount_app_storage_dirs) { Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *_uid, *gid, *gids, *runtime_flags, *rlimits, *mount_external, *se_info, *nice_name, @@ -51,11 +49,11 @@ namespace edxp { *app_data_dir); } - EXPORT int nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) { - return Context::GetInstance()->OnNativeForkAndSpecializePost(env, clazz, res); + static void nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) { + Context::GetInstance()->OnNativeForkAndSpecializePost(env, clazz, res); } - EXPORT void nativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid, + static void nativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid, jintArray *gids, jint *runtime_flags, jobjectArray *rlimits, jlong *permitted_capabilities, jlong *effective_capabilities) { @@ -66,17 +64,18 @@ namespace edxp { ); } - EXPORT int nativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) { - return Context::GetInstance()->OnNativeForkSystemServerPost(env, clazz, res); + static void nativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) { + Context::GetInstance()->OnNativeForkSystemServerPost(env, clazz, res); } /* method added in Android Q */ - EXPORT void specializeAppProcessPre(JNIEnv *env, jclass clazz, jint *uid, jint *gid, + static void specializeAppProcessPre(JNIEnv *env, jclass clazz, jint *uid, jint *gid, jintArray *gids, jint *runtime_flags, jobjectArray *rlimits, jint *mount_external, jstring *se_info, jstring *nice_name, jboolean *start_child_zygote, jstring *instruction_set, - jstring *app_data_dir, jstring *package_name, - jobjectArray *packages_for_uid, jstring *sandbox_id) { + jstring *app_data_dir, jboolean *is_top_app, jobjectArray *pkg_data_info_list, + jobjectArray *whitelisted_data_info_list, jboolean *bind_mount_app_data_dirs, + jboolean *bind_mount_app_storage_dirs) { Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *uid, *gid, *gids, *runtime_flags, *rlimits, *mount_external, *se_info, *nice_name, @@ -85,10 +84,62 @@ namespace edxp { *app_data_dir); } - EXPORT int specializeAppProcessPost(JNIEnv *env, jclass clazz) { - return Context::GetInstance()->OnNativeForkAndSpecializePost(env, clazz, 0); + static void specializeAppProcessPost(JNIEnv *env, jclass clazz) { + Context::GetInstance()->OnNativeForkAndSpecializePost(env, clazz, 0); } +} +int riru_api_version; +RiruApiV9 *riru_api_v9; + +RIRU_EXPORT void *init(void *arg) { + static int step = 0; + step += 1; + + static void *_module; + + switch (step) { + case 1: { + auto core_max_api_version = *(int *) arg; + riru_api_version = core_max_api_version <= RIRU_MODULE_API_VERSION ? core_max_api_version : RIRU_MODULE_API_VERSION; + return &riru_api_version; + } + case 2: { + switch (riru_api_version) { + case 9: { + riru_api_v9 = (RiruApiV9 *) arg; + + auto module = (RiruModuleInfoV9 *) malloc(sizeof(RiruModuleInfoV9)); + memset(module, 0, sizeof(RiruModuleInfoV9)); + _module = module; + + module->supportHide = true; + + module->version = RIRU_MODULE_VERSION; + module->versionName = STRINGIFY(RIRU_MODULE_VERSION_NAME); + module->onModuleLoaded = edxp::onModuleLoaded; + module->shouldSkipUid = edxp::shouldSkipUid; + module->forkAndSpecializePre = edxp::nativeForkAndSpecializePre; + module->forkAndSpecializePost = edxp::nativeForkAndSpecializePost; + module->specializeAppProcessPre = edxp::specializeAppProcessPre; + module->specializeAppProcessPost = edxp::specializeAppProcessPost; + module->forkSystemServerPre = edxp::nativeForkSystemServerPre; + module->forkSystemServerPost = edxp::nativeForkSystemServerPost; + return module; + } + default: { + return nullptr; + } + } + } + case 3: { + free(_module); + return nullptr; + } + default: { + return nullptr; + } + } } #pragma clang diagnostic pop \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/src/native_hook.cpp b/edxp-core/src/main/cpp/main/src/native_hook.cpp index 582bef64..c03bb8ab 100644 --- a/edxp-core/src/main/cpp/main/src/native_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/native_hook.cpp @@ -1,14 +1,14 @@ #include -#include #include #include -#include #include #include #include #include - +#include +#include "android_restriction.h" // from Dobby +#include "utils.h" #include "logging.h" #include "native_hook.h" #include "riru_hook.h" @@ -17,33 +17,23 @@ #include "art/runtime/gc/heap.h" #include "art/runtime/hidden_api.h" #include "art/runtime/oat_file_manager.h" -#include "framework/fd_utils.h" + +std::vector linker_get_solist(); // Dobby but not in .h namespace edxp { - static bool installed = false; - static bool art_hooks_installed = false; - static bool fwk_hooks_installed = false; + static volatile bool installed = false; + static volatile bool art_hooks_installed = false; static HookFunType hook_func = nullptr; void InstallArtHooks(void *art_handle); - void InstallFwkHooks(void *fwk_handle); - - CREATE_HOOK_STUB_ENTRIES(void *, mydlopen, const char *file_name, int flags, - const void *caller) { - void *handle = mydlopenBackup(file_name, flags, caller); - if (file_name != nullptr && std::string(file_name).find(kLibArtName) != std::string::npos) { - InstallArtHooks(handle); - } - return handle; - } - void InstallInlineHooks() { if (installed) { LOGI("Inline hooks have been installed, skip"); return; } + installed = true; LOGI("Start to install inline hooks"); int api_level = GetAndroidApiLevel(); if (UNLIKELY(api_level < __ANDROID_API_L__)) { @@ -52,38 +42,38 @@ namespace edxp { } LOGI("Using api level %d", api_level); InstallRiruHooks(); -#ifdef __LP64__ - ScopedDlHandle whale_handle(kLibWhalePath.c_str()); - if (!whale_handle.IsValid()) { - return; - } - void *hook_func_symbol = whale_handle.DlSym("WInlineHookFunction"); -#else - void *hook_func_symbol = (void *) MSHookFunction; -#endif - if (!hook_func_symbol) { - return; - } - hook_func = reinterpret_cast(hook_func_symbol); + hook_func = reinterpret_cast(DobbyHook); - if (api_level > __ANDROID_API_P__) { - ScopedDlHandle dl_handle(kLibDlPath.c_str()); - void *handle = dl_handle.Get(); - HOOK_FUNC(mydlopen, "__loader_dlopen"); + // install ART hooks + if (api_level >= __ANDROID_API_Q__) { + // From Riru v22 we can't get ART handle by hooking dlopen, so we get libart.so from soinfo. + // Ref: https://android.googlesource.com/platform/bionic/+/master/linker/linker_soinfo.h + auto solist = linker_get_solist(); + bool found = false; + for (auto & it : solist) { + const char* real_path = linker_soinfo_get_realpath(it); + if (real_path != nullptr && std::string(real_path).find(kLibArtName) != std::string::npos) { + found = true; + InstallArtHooks(it); + break; + } + } + if(!found) { + LOGE("Android 10+ detected and libart.so can't be found in memory."); + return; + } } else { - ScopedDlHandle art_handle(kLibArtPath.c_str()); + // do dlopen directly in Android 9- + ScopedDlHandle art_handle(kLibArtLegacyPath.c_str()); InstallArtHooks(art_handle.Get()); } - - ScopedDlHandle fwk_handle(kLibFwkPath.c_str()); - InstallFwkHooks(fwk_handle.Get()); } void InstallArtHooks(void *art_handle) { if (art_hooks_installed) { return; } - if (ConfigManager::GetInstance() -> IsHiddenAPIBypassEnabled()) { + if (ConfigManager::GetInstance()->IsHiddenAPIBypassEnabled()) { art::hidden_api::DisableHiddenApi(art_handle, hook_func); } art::Runtime::Setup(art_handle, hook_func); @@ -96,13 +86,5 @@ namespace edxp { art_hooks_installed = true; LOGI("ART hooks installed"); } - - void InstallFwkHooks(void *fwk_handle) { - if (fwk_hooks_installed) { - return; - } - android::FileDescriptorWhitelist::Setup(fwk_handle, hook_func); - } - } diff --git a/edxp-core/src/main/cpp/main/src/resource_hook.cpp b/edxp-core/src/main/cpp/main/src/resource_hook.cpp index 1a5563d2..ad960f54 100644 --- a/edxp-core/src/main/cpp/main/src/resource_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/resource_hook.cpp @@ -14,7 +14,9 @@ #include "framework/androidfw/ResourceTypes.h" #include "resource_hook.h" #include "dl_util.h" +#include "config.h" +// @ApiSensitive(Level.HIGH) namespace edxp { static constexpr const char *kXResourcesClassName = "android/content/res/XResources"; diff --git a/edxp-core/src/main/cpp/main/src/riru_hook.cpp b/edxp-core/src/main/cpp/main/src/riru_hook.cpp index b21a14a6..45d18f30 100644 --- a/edxp-core/src/main/cpp/main/src/riru_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/riru_hook.cpp @@ -8,52 +8,42 @@ #include #include #include -#include +#include "utils.h" #include "riru_hook.h" namespace edxp { static int api_level = 0; - + //Max length of property values //Ref https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/SystemProperties.java //static const int PROP_VALUE_MAX = 91; NEW_FUNC_DEF(int, __system_property_get, const char *key, char *value) { int res = old___system_property_get(key, value); - + if (key) { - /* if (strcmp(kPropKeyCompilerFilter, key) == 0) { - strcpy(value, kPropValueCompilerFilter); - LOGI("system_property_get: %s -> %s", key, value); - } else if (strcmp(kPropKeyCompilerFlags, key) == 0) { - strcpy(value, kPropValueCompilerFlags); +// strcpy(value, kPropValueCompilerFilter); LOGI("system_property_get: %s -> %s", key, value); } - */ - - if(strcmp(kPropKeyCompilerFlags, key) == 0) { - if(strcmp(value,"") == 0) + + if (strcmp(kPropKeyCompilerFlags, key) == 0) { + if (strcmp(value, "") == 0) strcpy(value, kPropValueCompilerFlags); - else { - if(strstr(value,kPropValueCompilerFlags) == NULL) { - if(strlen(value) + strlen(kPropValueCompilerFlagsWS) > PROP_VALUE_MAX) { - //just fallback,why not - LOGI("Cannot add option to disable inline opt!Fall back to replace.."); - strcpy(value, kPropValueCompilerFlags); - }else { - strcat(value,kPropValueCompilerFlagsWS); - } + else if (strstr(value, kPropValueCompilerFlags) == nullptr) { + if (strlen(value) + strlen(kPropValueCompilerFlagsWS) > PROP_VALUE_MAX) { + //just fallback, why not + LOGI("Cannot add option to disable inline opt! Fall back to replace.."); + strcpy(value, kPropValueCompilerFlags); + } else { + strcat(value, kPropValueCompilerFlagsWS); } } - if(strstr(value,kPropValueCompilerFlags) != NULL) - LOGI("system_property_get: %s -> %s", key, value); + LOGI("system_property_get: %s -> %s", key, value); } - - - - + + if (api_level == __ANDROID_API_O_MR1__) { // https://android.googlesource.com/platform/art/+/f5516d38736fb97bfd0435ad03bbab17ddabbe4e // Android 8.1 add a fatal check for debugging (removed in Android 9.0), @@ -77,35 +67,27 @@ namespace edxp { const std::string &key, const std::string &default_value) { std::string res = old__ZN7android4base11GetPropertyERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_( key, default_value); - /* + if (strcmp(kPropKeyCompilerFilter, key.c_str()) == 0) { - res = kPropValueCompilerFilter; - LOGI("android::base::GetProperty: %s -> %s", key.c_str(), res.c_str()); - } else if (strcmp(kPropKeyCompilerFlags, key.c_str()) == 0) { - res = kPropValueCompilerFlags; +// res = kPropValueCompilerFilter; LOGI("android::base::GetProperty: %s -> %s", key.c_str(), res.c_str()); } - */ - - if(strcmp(kPropKeyCompilerFlags, key.c_str()) == 0) { - if(strcmp(res.c_str(),"") == 0) + + if (strcmp(kPropKeyCompilerFlags, key.c_str()) == 0) { + if (strcmp(res.c_str(), "") == 0) res = kPropValueCompilerFlags; - else{ - if(strstr(res.c_str(),kPropValueCompilerFlags) == NULL) { - if(strlen(res.c_str()) + strlen(kPropValueCompilerFlagsWS) > PROP_VALUE_MAX) { - //just fallback,why not - LOGI("Cannot add option to disable inline opt!Fall back to replace.."); - res = kPropValueCompilerFlags; - }else { - res.append(kPropValueCompilerFlagsWS); - } + else if (strstr(res.c_str(), kPropValueCompilerFlags) == nullptr) { + if (strlen(res.c_str()) + strlen(kPropValueCompilerFlagsWS) > PROP_VALUE_MAX) { + //just fallback, why not + LOGI("Cannot add option to disable inline opt! Fall back to replace.."); + res = kPropValueCompilerFlags; + } else { + res.append(kPropValueCompilerFlagsWS); } } - if(strstr(res.c_str(),kPropValueCompilerFlags) != NULL) - LOGI("android::base::GetProperty: %s -> %s", key.c_str(), res.c_str()); + LOGI("android::base::GetProperty: %s -> %s", key.c_str(), res.c_str()); } - - + if (api_level == __ANDROID_API_O_MR1__) { // see __system_property_get hook above for explanations if (strcmp(kPropKeyUseJitProfiles, key.c_str()) == 0) { diff --git a/edxp-core/src/main/cpp/main/src/riru_hook.h b/edxp-core/src/main/cpp/main/src/riru_hook.h index 0f551bc6..01d80456 100644 --- a/edxp-core/src/main/cpp/main/src/riru_hook.h +++ b/edxp-core/src/main/cpp/main/src/riru_hook.h @@ -3,13 +3,11 @@ #define XHOOK_REGISTER(NAME) \ if (xhook_register(".*", #NAME, (void*) new_##NAME, (void **) &old_##NAME) == 0) { \ - if (riru_get_version() >= 8) { \ - void *f = riru_get_func(#NAME); \ - if (f != nullptr) { \ - memcpy(&old_##NAME, &f, sizeof(void *)); \ - } \ - riru_set_func(#NAME, (void *) new_##NAME); \ + void *f = riru_get_func(#NAME); \ + if (f != nullptr) { \ + memcpy(&old_##NAME, &f, sizeof(void *)); \ } \ + riru_set_func(#NAME, (void *) new_##NAME); \ } else { \ LOGE("failed to register riru hook " #NAME "."); \ } @@ -20,6 +18,7 @@ namespace edxp { + // @ApiSensitive(Level.HIGH) static constexpr const char *kPropKeyCompilerFilter = "dalvik.vm.dex2oat-filter"; static constexpr const char *kPropKeyCompilerFlags = "dalvik.vm.dex2oat-flags"; static constexpr const char *kPropKeyUseJitProfiles = "dalvik.vm.usejitprofiles"; diff --git a/edxp-core/template_override/META-INF/com/google/android/update-binary b/edxp-core/template_override/META-INF/com/google/android/update-binary index 29240cda..ea4889e7 100644 --- a/edxp-core/template_override/META-INF/com/google/android/update-binary +++ b/edxp-core/template_override/META-INF/com/google/android/update-binary @@ -6,168 +6,28 @@ umask 022 -# Global vars -TMPDIR=/dev/tmp -PERSISTDIR=/sbin/.magisk/mirror/persist - -rm -rf $TMPDIR 2>/dev/null -mkdir -p $TMPDIR - # echo before loading util_functions ui_print() { echo "$1"; } require_new_magisk() { ui_print "*******************************" - ui_print " Please install Magisk v19.0+! " + ui_print " Please install Magisk v20.4+! " ui_print "*******************************" exit 1 } -is_legacy_script() { - unzip -l "$ZIPFILE" install.sh | grep -q install.sh - return $? -} - -print_modname() { - local len - len=`echo -n $MODNAME | wc -c` - len=$((len + 2)) - local pounds=`printf "%${len}s" | tr ' ' '*'` - ui_print "$pounds" - ui_print " $MODNAME " - ui_print "$pounds" - ui_print "*******************" - ui_print " Powered by Magisk " - ui_print "*******************" -} - -############## -# Environment -############## +######################### +# Load util_functions.sh +######################### OUTFD=$2 ZIPFILE=$3 mount /data 2>/dev/null -# Load utility functions [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk . /data/adb/magisk/util_functions.sh -[ $MAGISK_VER_CODE -gt 18100 ] || require_new_magisk +[ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk -# Preperation for flashable zips -setup_flashable - -# Mount partitions -mount_partitions - -# Detect version and architecture -api_level_arch_detect - -# Setup busybox and binaries -$BOOTMODE && boot_actions || recovery_actions - -############## -# Preparation -############## - -# Extract prop file -unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2 -[ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!" - -$BOOTMODE && MODDIRNAME=modules_update || MODDIRNAME=modules -MODULEROOT=$NVBASE/$MODDIRNAME -MODID=`grep_prop id $TMPDIR/module.prop` -MODPATH=$MODULEROOT/$MODID -MODNAME=`grep_prop name $TMPDIR/module.prop` - -# Create mod paths -rm -rf $MODPATH 2>/dev/null -mkdir -p $MODPATH - -########## -# Install -########## - -if is_legacy_script; then - unzip -oj "$ZIPFILE" module.prop install.sh uninstall.sh 'common/*' -d $TMPDIR >&2 - - # Load install script - . $TMPDIR/install.sh - - # Callbacks - print_modname - on_install - - # Custom uninstaller - [ -f $TMPDIR/uninstall.sh ] && cp -af $TMPDIR/uninstall.sh $MODPATH/uninstall.sh - - # Skip mount - $SKIPMOUNT && touch $MODPATH/skip_mount - - # prop file - $PROPFILE && cp -af $TMPDIR/system.prop $MODPATH/system.prop - - # Module info - cp -af $TMPDIR/module.prop $MODPATH/module.prop - - # post-fs-data scripts - $POSTFSDATA && cp -af $TMPDIR/post-fs-data.sh $MODPATH/post-fs-data.sh - - # service scripts - $LATESTARTSERVICE && cp -af $TMPDIR/service.sh $MODPATH/service.sh - - ui_print "- Setting permissions" - set_permissions -else - print_modname - - unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2 - - if ! grep -q '^SKIPUNZIP=1$' $MODPATH/customize.sh 2>/dev/null; then - ui_print "- Extracting module files" - unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2 - - # Default permissions - set_perm_recursive $MODPATH 0 0 0755 0644 - fi - - # Load customization script - [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh -fi - -# Handle replace folders -for TARGET in $REPLACE; do - ui_print "- Replace target: $TARGET" - mktouch $MODPATH$TARGET/.replace -done - -if $BOOTMODE; then - # Update info for Magisk Manager - mktouch $NVBASE/modules/$MODID/update - cp -af $MODPATH/module.prop $NVBASE/modules/$MODID/module.prop -fi - -# Copy over custom sepolicy rules -if [ -f $MODPATH/sepolicy.rule -a -e $PERSISTDIR ]; then - ui_print "- Installing custom sepolicy patch" - PERSISTMOD=$PERSISTDIR/magisk/$MODID - mkdir -p $PERSISTMOD - cp -af $MODPATH/sepolicy.rule $PERSISTMOD/sepolicy.rule -fi - -# Remove stuffs that don't belong to modules -rm -rf \ -$MODPATH/system/placeholder $MODPATH/customize.sh \ -$MODPATH/README.md $MODPATH/.git* 2>/dev/null - -############## -# Finalizing -############## - -cd / -$BOOTMODE || recovery_cleanup -rm -rf $TMPDIR - -ui_print "- Done" -exit 0 +install_module +exit 0 \ No newline at end of file diff --git a/edxp-core/template_override/customize.sh b/edxp-core/template_override/customize.sh index 8c5ed26f..672da68f 100644 --- a/edxp-core/template_override/customize.sh +++ b/edxp-core/template_override/customize.sh @@ -19,7 +19,7 @@ getRandomNameExist() { fi } -RIRU_PATH="/data/misc/riru" +RIRU_PATH="/data/adb/riru" RIRU_EDXP="$(getRandomNameExist 4 "libriru_" ".so" " /system/lib /system/lib64 @@ -36,23 +36,19 @@ PROP_PRODUCT=$(getprop ro.build.product) PROP_BRAND=$(getprop ro.product.brand) PROP_MANUFACTURER=$(getprop ro.product.manufacturer) -JAR_EDXP="$(getRandomNameExist 8 "" ".jar" " +JAR_EDXP="$(getRandomNameExist 8 "" ".dex" " /system/framework -").jar" -JAR_EDDALVIKDX="$(getRandomNameExist 8 "" ".jar" " +").dex" +JAR_EDDALVIKDX="$(getRandomNameExist 8 "" ".dex" " /system/framework -").jar" -JAR_EDDEXMAKER="$(getRandomNameExist 8 "" ".jar" " +").dex" +JAR_EDDEXMAKER="$(getRandomNameExist 8 "" ".dex" " /system/framework -").jar" +").dex" JAR_EDCONFIG="$(getRandomNameExist 8 "" ".jar" " /system/framework ").jar" LIB_RIRU_EDXP="libriru_${RIRU_EDXP}.so" -LIB_WHALE_EDXP="lib$(getRandomNameExist 10 "lib" ".so" " -/system/lib -/system/lib64 -").so" LIB_SANDHOOK_EDXP="lib$(getRandomNameExist 13 "lib" ".so" " /system/lib /system/lib64 @@ -114,21 +110,6 @@ update_new_magisk() { ui_print "******************************" } -require_riru() { - ui_print "******************************" - ui_print "! Requirement module 'Riru - Core' is not installed" - ui_print "! You can download from 'Magisk Manager' or https://github.com/RikkaApps/Riru/releases" - abortC "******************************" -} - -require_new_riru() { - ui_print "******************************" - ui_print "! Old Riru ${1} (below v19) detected" - ui_print "! The latest version of 'Riru - Core' is required" - ui_print "! You can download from 'Magisk Manager' or https://github.com/RikkaApps/Riru/releases" - abortC "******************************" -} - require_yahfa() { ui_print "******************************" ui_print "! Architecture x86 or x86_64 detected" @@ -193,19 +174,7 @@ check_magisk_version() { [[ ${MAGISK_VER_CODE} -eq 20101 ]] && update_new_magisk } -check_riru_version() { - if [[ ! -f "${RIRU_PATH}/api_version" ]] && [[ ! -f "${RIRU_PATH}/api_version.new" ]]; then - require_riru - fi - RIRU_API_VERSION=$(cat "${RIRU_PATH}/api_version.new") || RIRU_API_VERSION=$(cat "${RIRU_PATH}/api_version") || RIRU_API_VERSION=0 - [[ "${RIRU_API_VERSION}" -eq "${RIRU_API_VERSION}" ]] || RIRU_API_VERSION=0 - ui_print "- Riru API version: ${RIRU_API_VERSION}" - if [[ "${RIRU_API_VERSION}" -lt ${RIRU_MIN_API_VERSION} ]]; then - require_new_riru ${RIRU_API_VERSION} - fi -} - -check_architecture() { +edxp_check_architecture() { if [[ "${MODID}" == "riru_edxposed_sandhook" ]]; then VARIANTS="SandHook" else @@ -240,28 +209,64 @@ check_android_version() { ui_print "- EdXposed Version ${VERSION}" +# extract verify.sh +ui_print "- Extracting verify.sh" +unzip -o "$ZIPFILE" 'verify.sh' -d "$TMPDIR" >&2 +if [ ! -f "$TMPDIR/verify.sh" ]; then + ui_print "*********************************************************" + ui_print "! Unable to extract verify.sh!" + ui_print "! This zip may be corrupted, please try downloading again" + abort "*********************************************************" +fi +. $TMPDIR/verify.sh + +# extract riru.sh +extract "$ZIPFILE" riru.sh "$MODPATH" +. $MODPATH/riru.sh + #check_persist check_android_version check_magisk_version check_riru_version -check_architecture +edxp_check_architecture ui_print "- Extracting module files" -unzip -o "${ZIPFILE}" EdXposed.apk module.prop post-fs-data.sh sepolicy.rule system.prop uninstall.sh 'system/*' -d "${MODPATH}" >&2 +extract "${ZIPFILE}" 'EdXposed.apk' "${MODPATH}" +extract "${ZIPFILE}" 'module.prop' "${MODPATH}" +extract "${ZIPFILE}" 'system.prop' "${MODPATH}" +extract "${ZIPFILE}" 'sepolicy.rule' "${MODPATH}" +extract "${ZIPFILE}" 'post-fs-data.sh' "${MODPATH}" +extract "${ZIPFILE}" 'uninstall.sh' "${MODPATH}" -if [[ "${ARCH}" == "x86" || "${ARCH}" == "x64" ]]; then - ui_print "- Replacing x86 and x86_64 libraries" - unzip -o "${ZIPFILE}" 'system_x86/*' -d "${MODPATH}" >&2 - rm -rf "${MODPATH}/system/lib" - rm -rf "${MODPATH}/system/lib64" - mv "${MODPATH}/system_x86/lib" "${MODPATH}/system/lib" - mv "${MODPATH}/system_x86/lib64" "${MODPATH}/system/lib64" - rm -rf "${MODPATH}/system_x86" -fi +extract "${ZIPFILE}" 'system/framework/edconfig.jar' "${MODPATH}" +extract "${ZIPFILE}" 'system/framework/eddalvikdx.dex' "${MODPATH}" +extract "${ZIPFILE}" 'system/framework/eddexmaker.dex' "${MODPATH}" +extract "${ZIPFILE}" 'system/framework/edxp.dex' "${MODPATH}" -if [[ "${IS64BIT}" == false ]]; then - ui_print "- Removing 64-bit libraries" - rm -rf "${MODPATH}/system/lib64" +if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then + ui_print "- Extracting x86 libraries" + extract "$ZIPFILE" 'system_x86/lib/libriru_edxp.so' "$MODPATH" + mv "$MODPATH/system_x86/" "$MODPATH/system/" + + if [ "$IS64BIT" = true ]; then + ui_print "- Extracting x64 libraries" + extract "$ZIPFILE" 'system_x86/lib64/libriru_edxp.so' "$MODPATH" + mv "$MODPATH/system_x86/lib64" "$MODPATH/system/lib64" + fi +else + ui_print "- Extracting arm libraries" + extract "$ZIPFILE" 'system/lib/libriru_edxp.so' "$MODPATH" + if [[ "${VARIANTS}" == "SandHook" ]]; then + extract "$ZIPFILE" 'system/lib/libsandhook-native.so' "$MODPATH" + fi + + if [ "$IS64BIT" = true ]; then + ui_print "- Extracting arm64 libraries" + extract "$ZIPFILE" 'system/lib64/libriru_edxp.so' "$MODPATH" + if [[ "${VARIANTS}" == "SandHook" ]]; then + extract "$ZIPFILE" 'system/lib/libsandhook-native.so' "$MODPATH" + fi + fi fi if [[ "$(pm path org.meowcat.edxposed.manager)" == "" && "$(pm path de.robv.android.xposed.installer)" == "" ]]; then @@ -290,16 +295,14 @@ fi ui_print "- Copying framework libraries" -mv "${MODPATH}/system/framework/eddalvikdx.jar" "${MODPATH}/system/framework/${JAR_EDDALVIKDX}" -mv "${MODPATH}/system/framework/edxp.jar" "${MODPATH}/system/framework/${JAR_EDXP}" -mv "${MODPATH}/system/framework/eddexmaker.jar" "${MODPATH}/system/framework/${JAR_EDDEXMAKER}" +mv "${MODPATH}/system/framework/eddalvikdx.dex" "${MODPATH}/system/framework/${JAR_EDDALVIKDX}" +mv "${MODPATH}/system/framework/edxp.dex" "${MODPATH}/system/framework/${JAR_EDXP}" +mv "${MODPATH}/system/framework/eddexmaker.dex" "${MODPATH}/system/framework/${JAR_EDDEXMAKER}" mv "${MODPATH}/system/framework/edconfig.jar" "${MODPATH}/system/framework/${JAR_EDCONFIG}" mv "${MODPATH}/system/lib/libriru_edxp.so" "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" -mv "${MODPATH}/system/lib/libwhale.edxp.so" "${MODPATH}/system/lib/${LIB_WHALE_EDXP}" if [[ "${IS64BIT}" == true ]]; then mv "${MODPATH}/system/lib64/libriru_edxp.so" "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" - mv "${MODPATH}/system/lib64/libwhale.edxp.so" "${MODPATH}/system/lib64/${LIB_WHALE_EDXP}" fi if [[ "${VARIANTS}" == "SandHook" ]]; then @@ -311,17 +314,15 @@ fi ui_print "- Resetting libraries path" -sed -i 's:/system/framework/edxp.jar\:/system/framework/eddalvikdx.jar\:/system/framework/eddexmaker.jar:/system/framework/'"${JAR_EDXP}"'\:/system/framework/'"${JAR_EDDALVIKDX}"'\:/system/framework/'"${JAR_EDDEXMAKER}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" +sed -i 's:/system/framework/edxp.dex\:/system/framework/eddalvikdx.dex\:/system/framework/eddexmaker.dex:/system/framework/'"${JAR_EDXP}"'\:/system/framework/'"${JAR_EDDALVIKDX}"'\:/system/framework/'"${JAR_EDDEXMAKER}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" sed -i 's:/system/framework/edconfig.jar:/system/framework/'"${JAR_EDCONFIG}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" sed -i 's:libriru_edxp.so:'"${LIB_RIRU_EDXP}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" -sed -i 's:libwhale.edxp.so:'"${LIB_WHALE_EDXP}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" sed -i 's:libsandhook.edxp.so:'"${LIB_SANDHOOK_EDXP}"':g' "${MODPATH}/system/lib/${LIB_RIRU_EDXP}" if [[ "${IS64BIT}" == true ]]; then - sed -i 's:/system/framework/edxp.jar\:/system/framework/eddalvikdx.jar\:/system/framework/eddexmaker.jar:/system/framework/'"${JAR_EDXP}"'\:/system/framework/'"${JAR_EDDALVIKDX}"'\:/system/framework/'"${JAR_EDDEXMAKER}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" + sed -i 's:/system/framework/edxp.dex\:/system/framework/eddalvikdx.dex\:/system/framework/eddexmaker.dex:/system/framework/'"${JAR_EDXP}"'\:/system/framework/'"${JAR_EDDALVIKDX}"'\:/system/framework/'"${JAR_EDDEXMAKER}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" sed -i 's:/system/framework/edconfig.jar:/system/framework/'"${JAR_EDCONFIG}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" sed -i 's:libriru_edxp.so:'"${LIB_RIRU_EDXP}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" - sed -i 's:libwhale.edxp.so:'"${LIB_WHALE_EDXP}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" sed -i 's:libsandhook.edxp.so:'"${LIB_SANDHOOK_EDXP}"':g' "${MODPATH}/system/lib64/${LIB_RIRU_EDXP}" fi @@ -336,6 +337,16 @@ if [[ -e "${RIRU_MODULES}/edxp" ]]; then rm -rf "${RIRU_MODULES}/edxp" fi +# extract Riru files +ui_print "- Extracting Riru files" +[ -d "$RIRU_TARGET" ] || mkdir -p "$RIRU_TARGET" || abort "! Can't create $RIRU_TARGET" + +rm -f "$RIRU_TARGET/module.prop.new" +extract "$ZIPFILE" 'riru/module.prop.new' "$RIRU_TARGET" +mv "$RIRU_TARGET/riru/module.prop.new" "$RIRU_TARGET/module.prop" +rm -rf "$RIRU_TARGET/riru/" +set_perm "$RIRU_TARGET/module.prop" 0 0 0600 $RIRU_SECONTEXT + ui_print "- Copying extra files" [[ -d "${RIRU_TARGET}" ]] || mkdir -p "${RIRU_TARGET}" || abort "! Can't mkdir -p ${RIRU_TARGET}" @@ -349,3 +360,11 @@ cp "${MODPATH}/module.prop" "${RIRU_TARGET}/module.prop" || abort "! Can't creat set_perm_recursive "${MODPATH}" 0 0 0755 0644 ui_print "- Welcome to EdXposed ${VERSION}!" + +# before Magisk 16e4c67, sepolicy.rule is copied on the second reboot +if [ "$MAGISK_VER_CODE" -lt 21006 ]; then + ui_print "*******************************" + ui_print "- Magisk version below 21006." + ui_print "- You have to manually reboot twice." + ui_print "*******************************" +fi \ No newline at end of file diff --git a/edxp-core/template_override/module.prop.new b/edxp-core/template_override/module.prop.new new file mode 100644 index 00000000..69bd5bd1 --- /dev/null +++ b/edxp-core/template_override/module.prop.new @@ -0,0 +1,6 @@ +name=Riru - EdXposed +version=v0.5.0.6 (YAHFA) +versionCode=233 +author=solohsu, MlgmXyysd & rk700 +description=Another enhanced implementation of Xposed Framework. Supports Android 8.0, 8.1, 9, 10 or above. Requires Riru - Core v19 or above installed. Telegram: @EdXposed +minApi=9 diff --git a/edxp-core/template_override/post-fs-data.sh b/edxp-core/template_override/post-fs-data.sh index 84deebdf..b0de9130 100644 --- a/edxp-core/template_override/post-fs-data.sh +++ b/edxp-core/template_override/post-fs-data.sh @@ -10,7 +10,7 @@ grep_prop() { MODDIR=${0%/*} -RIRU_PATH="/data/misc/riru" +RIRU_PATH="/data/adb/riru" TARGET="${RIRU_PATH}/modules" [[ "$(getenforce)" == "Enforcing" ]] && ENFORCE=true || ENFORCE=false @@ -41,17 +41,11 @@ PATH_PREFIX="/data/user_de/0/" #PATH_PREFIX_LEGACY="/data/user/0/" sepolicy() { - # necessary for using mmap in system_server process - # read configs set in our app - # for built-in apps // TODO: maybe narrow down the target classes - # read module apk file in zygote - # TODO: remove coredomain sepolicy - supolicy --live "allow system_server system_server process { execmem }"\ - "allow system_server system_server memprotect { mmap_zero }"\ - "allow coredomain coredomain process { execmem }"\ - "allow coredomain app_data_file * *"\ - "attradd { system_app platform_app } mlstrustedsubject"\ - "allow zygote apk_data_file * *" + # Should be deprecated now. This is for debug only. + supolicy --live "allow system_server system_server process execmem" \ + "allow system_server system_server memprotect mmap_zero" \ + "allow zygote app_data_file dir { getattr search read open }" \ + "allow zygote app_data_file file { getattr read open }" } #if [[ ${ANDROID_SDK} -ge 24 ]]; then diff --git a/edxp-core/template_override/riru.sh b/edxp-core/template_override/riru.sh new file mode 100644 index 00000000..bd1d6ba8 --- /dev/null +++ b/edxp-core/template_override/riru.sh @@ -0,0 +1,34 @@ +#!/sbin/sh +RIRU_PATH="/data/adb/riru" +RIRU_MODULE_ID="%%%RIRU_MODULE_ID%%%" +RIRU_MODULE_PATH="$RIRU_PATH/modules/$RIRU_MODULE_ID" +RIRU_SECONTEXT="u:object_r:magisk_file:s0" + +check_riru_version() { + RIRU_MIN_API_VERSION=%%%RIRU_MIN_API_VERSION%%% + RIRU_MIN_VERSION_NAME="%%%RIRU_MIN_VERSION_NAME%%%" + + if [ ! -f "$RIRU_PATH/api_version" ] && [ ! -f "$RIRU_PATH/api_version.new" ]; then + ui_print "*********************************************************" + ui_print "! Riru is not installed" + ui_print "! Please install Riru from Magisk Manager or https://github.com/RikkaApps/Riru/releases" + abort "*********************************************************" + fi + RIRU_API_VERSION=$(cat "$RIRU_PATH/api_version.new") || RIRU_API_VERSION=$(cat "$RIRU_PATH/api_version") || RIRU_API_VERSION=0 + [ "$RIRU_API_VERSION" -eq "$RIRU_API_VERSION" ] || RIRU_API_VERSION=0 + ui_print "- Riru API version: $RIRU_API_VERSION" + if [ "$RIRU_API_VERSION" -lt $RIRU_MIN_API_VERSION ]; then + ui_print "*********************************************************" + ui_print "! Riru $RIRU_MIN_VERSION_NAME or above is required" + ui_print "! Please upgrade Riru from Magisk Manager or https://github.com/RikkaApps/Riru/releases" + abort "*********************************************************" + fi +} + +check_architecture() { + if [ "$ARCH" != "arm" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "x64" ]; then + abort "! Unsupported platform: $ARCH" + else + ui_print "- Device platform: $ARCH" + fi +} \ No newline at end of file diff --git a/edxp-core/template_override/sepolicy.rule b/edxp-core/template_override/sepolicy.rule index 3b02a68c..3a9f6385 100644 --- a/edxp-core/template_override/sepolicy.rule +++ b/edxp-core/template_override/sepolicy.rule @@ -1,6 +1,4 @@ -allow system_server system_server process {execmem} -allow system_server system_server memprotect {mmap_zero} -allow coredomain coredomain process {execmem} -allow coredomain app_data_file * * -attradd {system_app platform_app} mlstrustedsubject -allow zygote apk_data_file * * +allow system_server system_server process execmem +allow system_server system_server memprotect mmap_zero +allow zygote app_data_file dir { getattr search read open } +allow zygote app_data_file file { getattr read open } \ No newline at end of file diff --git a/edxp-core/template_override/system.prop b/edxp-core/template_override/system.prop index e7264828..0735313f 100644 --- a/edxp-core/template_override/system.prop +++ b/edxp-core/template_override/system.prop @@ -1,3 +1,4 @@ +# TODO ensure quicken is not essential #dalvik.vm.dex2oat-filter=quicken dalvik.vm.dex2oat-flags=--inline-max-code-units=0 #dalvik.vm.image-dex2oat-flags=--inline-max-code-units=0 --compiler-filter=speed diff --git a/edxp-core/template_override/uninstall.sh b/edxp-core/template_override/uninstall.sh index 9710469f..6e74769b 100644 --- a/edxp-core/template_override/uninstall.sh +++ b/edxp-core/template_override/uninstall.sh @@ -14,6 +14,11 @@ fi if [[ "${REMOVE}" == true ]]; then rm -rf /data/misc/riru/modules/edxp + if [[ -f "/data/adb/riru/modules/edxp.prop" ]]; then + OLD_CONFIG=$(cat "/data/adb/riru/modules/edxp.prop") + rm -rf "/data/adb/riru/modules/${OLD_CONFIG}" + rm "/data/adb/riru/modules/edxp.prop" + fi if [[ -f "/data/misc/riru/modules/edxp.prop" ]]; then OLD_CONFIG=$(cat "/data/misc/riru/modules/edxp.prop") rm -rf "/data/misc/riru/modules/${OLD_CONFIG}" diff --git a/edxp-core/template_override/verify.sh b/edxp-core/template_override/verify.sh new file mode 100644 index 00000000..b04a9ea3 --- /dev/null +++ b/edxp-core/template_override/verify.sh @@ -0,0 +1,39 @@ +TMPDIR_FOR_VERIFY="$TMPDIR/.vunzip" +mkdir "$TMPDIR_FOR_VERIFY" + +abort_verify() { + ui_print "*********************************************************" + ui_print "! $1" + ui_print "! This zip may be corrupted, please try downloading again" + abort "*********************************************************" +} + +# extract +extract() { + zip=$1 + file=$2 + dir=$3 + junk_paths=$4 + [ -z "$junk_paths" ] && junk_paths=false + opts="-o" + [ $junk_paths = true ] && opts="-oj" + + file_path="" + hash_path="" + if [ $junk_paths = true ]; then + file_path="$dir/$(basename "$file")" + hash_path="$TMPDIR_FOR_VERIFY/$(basename "$file").sha256sum" + else + file_path="$dir/$file" + hash_path="$TMPDIR_FOR_VERIFY/$file.sha256sum" + fi + + unzip $opts "$zip" "$file" -d "$dir" >&2 + [ -f "$file_path" ] || abort_verify "$file not exists" + + unzip $opts "$zip" "$file.sha256sum" -d "$TMPDIR_FOR_VERIFY" >&2 + [ -f "$hash_path" ] || abort_verify "$file.sha256sum not exists" + + (echo "$(cat "$hash_path") $file_path" | sha256sum -c -s -) || abort_verify "Failed to verify $file" + ui_print "- Verified $file" >&1 +} \ No newline at end of file diff --git a/edxp-core/tpl/edconfig.tpl b/edxp-core/tpl/edconfig.tpl index 922618cd..41f74354 100644 --- a/edxp-core/tpl/edconfig.tpl +++ b/edxp-core/tpl/edconfig.tpl @@ -1,4 +1,4 @@ -version=91.0-$version ($backend) +version=92.0-$version ($backend) arch=arm64 minsdk=26 maxsdk=29 diff --git a/edxp-core/tpl/module.prop.tpl b/edxp-core/tpl/module.prop.tpl index 6f22cd1f..833cd7ff 100644 --- a/edxp-core/tpl/module.prop.tpl +++ b/edxp-core/tpl/module.prop.tpl @@ -4,4 +4,3 @@ version=${versionName} versionCode=${versionCode} author=${authorList} description=Another enhanced implementation of Xposed Framework. Supports Android 8.0, 8.1, 9, 10 or above. Requires Riru - Core v19 or above installed. Telegram: @EdXposed -api=4 diff --git a/edxp-core/tpl/riru_module.prop.tpl b/edxp-core/tpl/riru_module.prop.tpl new file mode 100644 index 00000000..661febb7 --- /dev/null +++ b/edxp-core/tpl/riru_module.prop.tpl @@ -0,0 +1,6 @@ +name=Riru - EdXposed +version=${versionName} +versionCode=${versionCode} +author=${authorList} +description=Another enhanced implementation of Xposed Framework. Supports Android 8.0, 8.1, 9, 10 or above. Requires Riru - Core v19 or above installed. Telegram: @EdXposed +minApi=${minApi} diff --git a/edxp-sandhook/.gitignore b/edxp-sandhook/.gitignore index 845f9980..3a66a198 100644 --- a/edxp-sandhook/.gitignore +++ b/edxp-sandhook/.gitignore @@ -1,2 +1,2 @@ /build -/template_override/system/framework/edxp.jar \ No newline at end of file +/template_override/system/framework \ No newline at end of file diff --git a/edxp-sandhook/build.gradle b/edxp-sandhook/build.gradle index 8612f93f..38956080 100644 --- a/edxp-sandhook/build.gradle +++ b/edxp-sandhook/build.gradle @@ -4,7 +4,7 @@ sourceCompatibility = "7" targetCompatibility = "7" android { - compileSdkVersion 28 + compileSdkVersion androidCompileSdkVersion.toInteger() defaultConfig { applicationId "com.elderdrivers.riru.edxp.sandhook" @@ -22,14 +22,14 @@ android { } } + ndkVersion androidCompileNdkVersion } dependencies { - compileOnly files("${hiddenApiStubJarFilePath}") + compileOnly project(':hiddenapi-stubs') implementation project(':edxp-common') - implementation project(':xposed-bridge') - implementation 'com.swift.sandhook:hooklib:4.1.6' - compileOnly project(':dexmaker') + implementation 'com.swift.sandhook:hooklib:4.2.1' + compileOnly files(project(":dexmaker").tasks.getByName("makeJarRelease").outputs) } @@ -58,23 +58,16 @@ afterEvaluate { def variantNameCapped = variant.name.capitalize() def variantNameLowered = variant.name.toLowerCase() - def myTemplatePath = "${projectDir}/template_override/" - - task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - def dexOutPath = variant.name.contains("release") ? - "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : - "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" - from dexOutPath, "${projectDir}/src/main/resources/" - destinationDir file(myTemplatePath + "system/framework/") - baseName "edxp" - doLast { - copy { - from file(myTemplatePath) - into file(templateRootPath) - } + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") } + destinationDir file(templateRootPath + "system/framework/") outputs.upToDateWhen { false } } + } } \ No newline at end of file diff --git a/edxp-sandhook/proguard-rules.pro b/edxp-sandhook/proguard-rules.pro index 520e46fd..45557ede 100644 --- a/edxp-sandhook/proguard-rules.pro +++ b/edxp-sandhook/proguard-rules.pro @@ -20,6 +20,7 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile +-dontoptimize -dontobfuscate -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } @@ -32,6 +33,6 @@ -keep class com.swift.sandhook.** {*;} --keepclasseswithmember class * { +-keepclasseswithmembers class * { native ; } \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java index 9f621f80..b5a9a792 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java @@ -7,7 +7,6 @@ import com.elderdrivers.riru.edxp.sandhook.config.SandHookProvider; import com.elderdrivers.riru.edxp.sandhook.entry.AppBootstrapHookInfo; import com.elderdrivers.riru.edxp.sandhook.entry.SysBootstrapHookInfo; import com.elderdrivers.riru.edxp.sandhook.entry.SysInnerHookInfo; -import com.elderdrivers.riru.edxp.sandhook.entry.WorkAroundHookInfo; import com.elderdrivers.riru.edxp.sandhook.hooker.SystemMainHooker; import com.elderdrivers.riru.edxp.util.Utils; import com.swift.sandhook.xposedcompat.XposedCompat; @@ -45,14 +44,6 @@ public class SandHookRouter extends BaseRouter { } } - public void startWorkAroundHook() { - if (useSandHook) { - XposedCompat.addHookers(XposedBridge.BOOTCLASSLOADER, WorkAroundHookInfo.hookItems); - } else { - super.startWorkAroundHook(); - } - } - public void onEnterChildProcess() { SandHookXposedBridge.onForkPost(); //enable compile in child process diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java index 35d215ca..c976a6c2 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java @@ -3,11 +3,9 @@ package com.elderdrivers.riru.edxp.sandhook.entry; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp.sandhook.hooker.HandleBindAppHooker; import com.elderdrivers.riru.edxp.sandhook.hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; public class AppBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName(), HandleBindAppHooker.class.getName(), LoadedApkConstructorHooker.class.getName(), }; @@ -15,6 +13,5 @@ public class AppBootstrapHookInfo implements KeepMembers { public static Class[] hookItems = { HandleBindAppHooker.class, LoadedApkConstructorHooker.class, - OnePlusWorkAroundHooker.class }; } diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java index 434a9f34..25e9d9fc 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java @@ -3,12 +3,10 @@ package com.elderdrivers.riru.edxp.sandhook.entry; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp.sandhook.hooker.HandleBindAppHooker; import com.elderdrivers.riru.edxp.sandhook.hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; import com.elderdrivers.riru.edxp.sandhook.hooker.SystemMainHooker; public class SysBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName(), HandleBindAppHooker.class.getName(), SystemMainHooker.class.getName(), LoadedApkConstructorHooker.class.getName() @@ -18,6 +16,5 @@ public class SysBootstrapHookInfo implements KeepMembers { HandleBindAppHooker.class, SystemMainHooker.class, LoadedApkConstructorHooker.class, - OnePlusWorkAroundHooker.class }; } diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysInnerHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysInnerHookInfo.java index 4c912089..c5df312c 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysInnerHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysInnerHookInfo.java @@ -2,13 +2,22 @@ package com.elderdrivers.riru.edxp.sandhook.entry; import com.elderdrivers.riru.common.KeepMembers; import com.elderdrivers.riru.edxp.sandhook.hooker.StartBootstrapServicesHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.StartBootstrapServicesHooker11; +import com.elderdrivers.riru.edxp.util.Versions; public class SysInnerHookInfo implements KeepMembers { + + public static Class getSysInnerHookerClass() { + return Versions.hasR() ? + StartBootstrapServicesHooker11.class : + StartBootstrapServicesHooker.class; + } + public static String[] hookItemNames = { - StartBootstrapServicesHooker.class.getName() + getSysInnerHookerClass().getName() }; public static Class[] hookItems = { - StartBootstrapServicesHooker.class + getSysInnerHookerClass() }; } diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java deleted file mode 100644 index cb7031bb..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.entry; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; - -public class WorkAroundHookInfo implements KeepMembers { - public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName() - }; - - public static Class[] hookItems = { - OnePlusWorkAroundHooker.class - }; -} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/HandleBindAppHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/HandleBindAppHooker.java index 60cb6fd2..496b2bc2 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/HandleBindAppHooker.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/HandleBindAppHooker.java @@ -15,7 +15,10 @@ import com.swift.sandhook.annotation.ThisObject; import java.lang.reflect.Method; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) @HookClass(ActivityThread.class) public class HandleBindAppHooker implements KeepMembers { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/LoadedApkConstructorHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/LoadedApkConstructorHooker.java index 29c6d0e1..efa05afb 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/LoadedApkConstructorHooker.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/LoadedApkConstructorHooker.java @@ -17,7 +17,10 @@ import com.swift.sandhook.annotation.ThisObject; import java.lang.reflect.Method; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) @HookClass(LoadedApk.class) public class LoadedApkConstructorHooker implements KeepMembers { public static String className = "android.app.LoadedApk"; diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java deleted file mode 100644 index 48b0ba61..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.hooker; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; -import com.elderdrivers.riru.edxp.core.yahfa.HookMain; -import com.swift.sandhook.SandHook; -import com.swift.sandhook.annotation.HookClass; -import com.swift.sandhook.annotation.HookMethod; -import com.swift.sandhook.annotation.HookMethodBackup; -import com.swift.sandhook.annotation.SkipParamCheck; - -import java.lang.reflect.Method; - -import dalvik.system.BaseDexClassLoader; -import de.robv.android.xposed.XC_MethodHook; - -@HookClass(BaseDexClassLoader.class) -public class OnePlusWorkAroundHooker implements KeepMembers { - - static { - HookMain.addHookItemWhiteList(OnePlusWorkAroundHooker.class.getName()); - } - - public static String className = "dalvik.system.BaseDexClassLoader"; - public static String methodName = "inCompatConfigList"; - public static String methodSig = "(ILjava/lang/String;)Z"; - - @HookMethodBackup("inCompatConfigList") - @SkipParamCheck - static Method backup; - - @HookMethod("inCompatConfigList") - public static boolean hook(int type, String packageName) throws Throwable { - final XC_MethodHook methodHook = new OneplusWorkaround(); - final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); - param.thisObject = null; - param.args = new Object[]{type, packageName}; - methodHook.callBeforeHookedMethod(param); - if (!param.returnEarly) { - param.setResult(backup(type, packageName)); - } - methodHook.callAfterHookedMethod(param); - return (boolean) param.getResult(); - } - - public static boolean backup(int type, String packageName) throws Throwable { - return (boolean) SandHook.callOriginByBackup(backup, null, type, packageName); - } -} \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/StartBootstrapServicesHooker11.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/StartBootstrapServicesHooker11.java new file mode 100644 index 00000000..eb4bcb88 --- /dev/null +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/StartBootstrapServicesHooker11.java @@ -0,0 +1,46 @@ +package com.elderdrivers.riru.edxp.sandhook.hooker; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.StartBootstrapServices; +import com.swift.sandhook.SandHook; +import com.swift.sandhook.annotation.HookMethod; +import com.swift.sandhook.annotation.HookMethodBackup; +import com.swift.sandhook.annotation.HookReflectClass; +import com.swift.sandhook.annotation.Param; +import com.swift.sandhook.annotation.SkipParamCheck; +import com.swift.sandhook.annotation.ThisObject; + +import java.lang.reflect.Method; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; + +@ApiSensitive(Level.LOW) +@HookReflectClass("com.android.server.SystemServer") +public class StartBootstrapServicesHooker11 implements KeepMembers { + public static String className = "com.android.server.SystemServer"; + public static String methodName = "startBootstrapServices"; + public static String methodSig = "(Lcom/android/server/utils/TimingsTraceAndSlog;)V"; + + @HookMethodBackup("startBootstrapServices") + @SkipParamCheck + static Method backup; + + @HookMethod("startBootstrapServices") + public static void hook(@ThisObject Object systemServer, @Param("com.android.server.utils.TimingsTraceAndSlog") Object traceAndSlog) throws Throwable { + final XC_MethodHook methodHook = new StartBootstrapServices(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = systemServer; + param.args = new Object[]{traceAndSlog}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + backup(systemServer, traceAndSlog); + } + methodHook.callAfterHookedMethod(param); + } + + public static void backup(Object systemServer, Object traceAndSlog) throws Throwable { + SandHook.callOriginByBackup(backup, systemServer, traceAndSlog); + } +} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/SystemMainHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/SystemMainHooker.java index 2280ca53..1c0d5d95 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/SystemMainHooker.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/SystemMainHooker.java @@ -12,8 +12,11 @@ import com.swift.sandhook.annotation.HookMethodBackup; import java.lang.reflect.Method; import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; +@ApiSensitive(Level.LOW) // system_server initialization // ed: only support sdk >= 21 for now @HookClass(ActivityThread.class) diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookStubManager.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookStubManager.java index eb7e80cf..a46c11fb 100644 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookStubManager.java +++ b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookStubManager.java @@ -281,6 +281,7 @@ public class HookStubManager { ((XC_MethodHook) snapshot[beforeIdx]).callBeforeHookedMethod(param); } catch (Throwable t) { // reset result (ignoring what the unexpectedly exiting callback did) + XposedBridge.log(t); param.setResult(null); param.returnEarly = false; continue; @@ -304,6 +305,7 @@ public class HookStubManager { param.setResult(SandHook.callOriginMethod(originMethod, entity.backup, thiz, param.args)); } } catch (Throwable e) { + XposedBridge.log(e); param.setThrowable(e); } } @@ -317,6 +319,7 @@ public class HookStubManager { try { ((XC_MethodHook) snapshot[afterIdx]).callAfterHookedMethod(param); } catch (Throwable t) { + XposedBridge.log(t); if (lastThrowable == null) param.setResult(lastResult); else @@ -375,6 +378,7 @@ public class HookStubManager { try { param.setResult(SandHook.callOriginMethod(true, origin, backup, thiz, param.args)); } catch (Throwable e) { + XposedBridge.log(e); param.setThrowable(e); } } diff --git a/edxp-sandhook/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl b/edxp-sandhook/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl deleted file mode 100644 index 7d797c04..00000000 --- a/edxp-sandhook/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl +++ /dev/null @@ -1 +0,0 @@ -com.elderdrivers.riru.edxp.sandhook.core.SandHookEdxpImpl \ No newline at end of file diff --git a/edxp-sandhook/template_override/system/lib/libsandhook.edxp.so b/edxp-sandhook/template_override/system/lib/libsandhook.edxp.so index 56b24621..f8ff8905 100644 Binary files a/edxp-sandhook/template_override/system/lib/libsandhook.edxp.so and b/edxp-sandhook/template_override/system/lib/libsandhook.edxp.so differ diff --git a/edxp-sandhook/template_override/system/lib64/libsandhook.edxp.so b/edxp-sandhook/template_override/system/lib64/libsandhook.edxp.so index 273fecdc..3e0cdc56 100644 Binary files a/edxp-sandhook/template_override/system/lib64/libsandhook.edxp.so and b/edxp-sandhook/template_override/system/lib64/libsandhook.edxp.so differ diff --git a/edxp-whale/.gitignore b/edxp-whale/.gitignore deleted file mode 100644 index 845f9980..00000000 --- a/edxp-whale/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/build -/template_override/system/framework/edxp.jar \ No newline at end of file diff --git a/edxp-whale/build.gradle b/edxp-whale/build.gradle deleted file mode 100644 index 93e8a4f6..00000000 --- a/edxp-whale/build.gradle +++ /dev/null @@ -1,79 +0,0 @@ -apply plugin: 'com.android.application' - -sourceCompatibility = "7" -targetCompatibility = "7" - -android { - compileSdkVersion 28 - - defaultConfig { - applicationId "com.elderdrivers.riru.edxp.whale" - minSdkVersion 26 - targetSdkVersion 28 - versionCode 1 - versionName "1.0" - multiDexEnabled false - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - -} - -dependencies { - compileOnly files("${hiddenApiStubJarFilePath}") - implementation project(':edxp-common') - implementation project(':xposed-bridge') - compileOnly project(':dexmaker') -} - - -preBuild.doLast { - def imlFile = file(project.name + ".iml") - try { - def parsedXml = (new groovy.util.XmlParser()).parse(imlFile) - def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' } - parsedXml.component[1].remove(jdkNode) - def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform" - new groovy.util.Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK']) - groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile)) - } catch (FileNotFoundException e) { - // nop, iml not found - } -} - -afterEvaluate { - - tasks.withType(JavaCompile) { - options.compilerArgs.add("-Xbootclasspath/p:${hiddenApiStubJarFilePath}") - } - - android.applicationVariants.all { variant -> - - def variantNameCapped = variant.name.capitalize() - def variantNameLowered = variant.name.toLowerCase() - - def myTemplatePath = "${projectDir}/template_override/" - - task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { - dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - def dexOutPath = variant.name.contains("release") ? - "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : - "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" - from dexOutPath, "${projectDir}/src/main/resources/" - destinationDir file(myTemplatePath + "system/framework/") - baseName "edxp" - doLast { - copy { - from file(myTemplatePath) - into file(templateRootPath) - } - } - outputs.upToDateWhen { false } - } - } -} \ No newline at end of file diff --git a/edxp-whale/proguard-rules.pro b/edxp-whale/proguard-rules.pro deleted file mode 100644 index 503061cb..00000000 --- a/edxp-whale/proguard-rules.pro +++ /dev/null @@ -1,37 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile - --dontobfuscate --keep class de.robv.android.xposed.** {*;} --keep class android.** { *; } - --keep interface com.elderdrivers.riru.common.KeepAll --keep interface com.elderdrivers.riru.common.KeepMembers - --keep class * implements com.elderdrivers.riru.common.KeepAll { *; } --keepclassmembers class * implements com.elderdrivers.riru.common.KeepMembers { *; } - --keep class com.lody.** {*;} - --keepclasseswithmember class * { - native ; -} \ No newline at end of file diff --git a/edxp-whale/src/main/AndroidManifest.xml b/edxp-whale/src/main/AndroidManifest.xml deleted file mode 100644 index 38b7acf3..00000000 --- a/edxp-whale/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleEdxpConfig.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleEdxpConfig.java deleted file mode 100644 index c02808d7..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleEdxpConfig.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.config; - -import com.elderdrivers.riru.edxp.config.BaseEdxpConfig; - -public class WhaleEdxpConfig extends BaseEdxpConfig { - -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java deleted file mode 100644 index 534f4d37..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.config; - -import com.elderdrivers.riru.edxp.art.ClassLinker; -import com.elderdrivers.riru.edxp.art.Heap; -import com.elderdrivers.riru.edxp.config.BaseHookProvider; -import com.elderdrivers.riru.edxp.core.ResourcesHook; -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.util.Utils; -import com.lody.whale.WhaleRuntime; - -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.Map; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; - -import static com.elderdrivers.riru.edxp.util.ClassUtils.shouldDelayHook; - -public class WhaleHookProvider extends BaseHookProvider { - - private static final Map sHookedMethodSlotMap = new HashMap<>(); - - @Override - public void unhookMethod(Member method) { - synchronized (sHookedMethodSlotMap) { - sHookedMethodSlotMap.remove(method); - } - } - - @Override - public void hookMethod(Member method, XposedBridge.AdditionalHookInfo additionalInfo) { -// resolveStaticMethod(method); - long slot = WhaleRuntime.hookMethodNative(method.getDeclaringClass(), method, additionalInfo); - synchronized (sHookedMethodSlotMap) { - sHookedMethodSlotMap.put(method, slot); - } - } - - @Override - public Object invokeOriginalMethod(Member method, long methodId, Object thisObject, Object[] args) throws Throwable { - long slot = sHookedMethodSlotMap.get(method); - return WhaleRuntime.invokeOriginalMethodNative(slot, thisObject, args); - } - - @Override - public Member findMethodNative(Member hookMethod) { - return shouldDelayHook(hookMethod) ? null : hookMethod; - } - - @Override - public Object findMethodNative(Class clazz, String methodName, String methodSig) { - return Yahfa.findMethodNative(clazz, methodName, methodSig); - } - - @Override - public void deoptMethodNative(Object method) { - ClassLinker.setEntryPointsToInterpreter((Member) method); - } - - @Override - public long getMethodId(Member member) { - return WhaleRuntime.getMethodSlot(member); - } - - @Override - public boolean initXResourcesNative() { - return ResourcesHook.initXResourcesNative(); - } - - @Override - public boolean removeFinalFlagNative(Class clazz) { - return ResourcesHook.removeFinalFlagNative(clazz); - } - - - /** - * the static method is lazy resolved, when not resolved, the entry point is a trampoline of - * a bridge, we can not hook these entry. this method force the static method to be resolved. - */ - public static void resolveStaticMethod(Member method) { - //ignore result, just call to trigger resolve - if (method == null) - return; - try { - if (method instanceof Method && Modifier.isStatic(method.getModifiers())) { - ((Method) method).setAccessible(true); - ((Method) method).invoke(new Object(), getFakeArgs((Method) method)); - } - } catch (Exception ignored) { - // we should never make a successful call. - } - } - - private static Object[] getFakeArgs(Method method) { - return method.getParameterTypes().length == 0 ? new Object[]{new Object()} : null; - } -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleEdxpImpl.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleEdxpImpl.java deleted file mode 100644 index be000b0c..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleEdxpImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.core; - -import android.os.Build; - -import com.elderdrivers.riru.edxp.core.BaseEdxpImpl; -import com.elderdrivers.riru.edxp.core.EdxpImpl; -import com.elderdrivers.riru.edxp.core.Main; -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.core.yahfa.HookMethodResolver; -import com.elderdrivers.riru.edxp.proxy.Router; - -public class WhaleEdxpImpl extends BaseEdxpImpl { - - static { - final EdxpImpl edxpImpl = new WhaleEdxpImpl(); - if (Main.setEdxpImpl(edxpImpl)) { - edxpImpl.init(); - } - } - - @Override - protected Router createRouter() { - return new WhaleRouter(); - } - - @Override - public int getVariant() { - return WHALE; - } - - @Override - public void init() { - Yahfa.init(Build.VERSION.SDK_INT); - HookMethodResolver.init(); - getRouter().injectConfig(); - setInitialized(); - } - -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleRouter.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleRouter.java deleted file mode 100644 index e58290d3..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleRouter.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.core; - -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; -import com.elderdrivers.riru.edxp.framework.Zygote; -import com.elderdrivers.riru.edxp.proxy.BaseRouter; -import com.elderdrivers.riru.edxp.whale.config.WhaleEdxpConfig; -import com.elderdrivers.riru.edxp.whale.config.WhaleHookProvider; - -public class WhaleRouter extends BaseRouter { - - public void onEnterChildProcess() { - - } - - public void injectConfig() { - BaseRouter.useXposedApi = true; - EdXpConfigGlobal.sConfig = new WhaleEdxpConfig(); - EdXpConfigGlobal.sHookProvider = new WhaleHookProvider(); -// Zygote.allowFileAcrossFork("/system/lib/libwhale.edxp.so"); -// Zygote.allowFileAcrossFork("/system/lib64/libwhale.edxp.so"); - Zygote.allowFileAcrossFork("/system/lib/" + ConfigManager.getLibWhaleName()); - Zygote.allowFileAcrossFork("/system/lib64/" + ConfigManager.getLibWhaleName()); - Zygote.allowFileAcrossFork("/system/lib/libart.so"); - Zygote.allowFileAcrossFork("/system/lib64/libart.so"); - } - -} diff --git a/edxp-whale/src/main/java/com/lody/whale/VMHelper.java b/edxp-whale/src/main/java/com/lody/whale/VMHelper.java deleted file mode 100644 index 392d7fef..00000000 --- a/edxp-whale/src/main/java/com/lody/whale/VMHelper.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.lody.whale; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.util.HashMap; - -/** - * @author Lody - */ -class VMHelper { - - // Holds a mapping from Java type names to native type codes. - private static final HashMap, String> PRIMITIVE_TO_SIGNATURE; - - static { - PRIMITIVE_TO_SIGNATURE = new HashMap<>(9); - PRIMITIVE_TO_SIGNATURE.put(byte.class, "B"); - PRIMITIVE_TO_SIGNATURE.put(char.class, "C"); - PRIMITIVE_TO_SIGNATURE.put(short.class, "S"); - PRIMITIVE_TO_SIGNATURE.put(int.class, "I"); - PRIMITIVE_TO_SIGNATURE.put(long.class, "J"); - PRIMITIVE_TO_SIGNATURE.put(float.class, "F"); - PRIMITIVE_TO_SIGNATURE.put(double.class, "D"); - PRIMITIVE_TO_SIGNATURE.put(void.class, "V"); - PRIMITIVE_TO_SIGNATURE.put(boolean.class, "Z"); - } - - /** - * Returns the internal name of {@code clazz} (also known as the - * descriptor). - */ - private static String getSignature(final Class clazz) { - final String primitiveSignature = PRIMITIVE_TO_SIGNATURE.get(clazz); - if (primitiveSignature != null) { - return primitiveSignature; - } else if (clazz.isArray()) { - return "[" + getSignature(clazz.getComponentType()); - } else { - return "L" + clazz.getName().replace('.', '/') + ";"; - } - } - - /** - * Returns the native type codes of {@code clazz}. - */ - private static String getShortyType(final Class clazz) { - final String primitiveSignature = PRIMITIVE_TO_SIGNATURE.get(clazz); - if (primitiveSignature != null) { - return primitiveSignature; - } - return "L"; - } - - // @SuppressWarnings("ConstantConditions") - private static String getSignature(final Class retType, - final Class[] parameterTypes) { - final StringBuilder result = new StringBuilder(); - - result.append('('); - for (final Class parameterType : parameterTypes) { - result.append(getSignature(parameterType)); - } - result.append(")"); - result.append(getSignature(retType)); - - return result.toString(); - } - - private static String getShorty(final Class retType, - final Class[] parameterTypes) { - final StringBuilder result = new StringBuilder(); - - result.append(getShortyType(retType)); - for (final Class parameterType : parameterTypes) { - result.append(getShortyType(parameterType)); - } - - return result.toString(); - } - - static String getSignature(final Member m) { - if (m instanceof Method) { - final Method md = (Method) m; - return getSignature(md.getReturnType(), md.getParameterTypes()); - } - if (m instanceof Constructor) { - final Constructor c = (Constructor) m; - return getSignature(void.class, c.getParameterTypes()); - } - return null; - } - - static String getShorty(final Member m) { - if (m instanceof Method) { - final Method md = (Method) m; - return getShorty(md.getReturnType(), md.getParameterTypes()); - } - if (m instanceof Constructor) { - final Constructor c = (Constructor) m; - return getShorty(void.class, c.getParameterTypes()); - } - return null; - } -} diff --git a/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java b/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java deleted file mode 100644 index 2c0904e4..00000000 --- a/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.lody.whale; - -import android.os.Build; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Member; -import java.lang.reflect.Method; - -import de.robv.android.xposed.XposedBridge; - -/** - * @author Lody - *

- * NOTICE: Do not move or rename any methods in this class. - */ -public class WhaleRuntime { - - static { - System.loadLibrary("whale.edxp"); - } - - private static String getShorty(Member member) { - return VMHelper.getShorty(member); - } - - public static long[] countInstancesOfClasses(Class[] classes, boolean assignable) { - if (Build.VERSION.SDK_INT < 27) { - throw new UnsupportedOperationException("Not support countInstancesOfClasses on your device yet."); - } - try { - Class clazz = Class.forName("dalvik.system.VMDebug"); - Method method = clazz.getDeclaredMethod("countInstancesOfClasses", Class[].class, boolean.class); - return (long[]) method.invoke(null, classes, assignable); - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - public static Object[][] getInstancesOfClasses(Class[] classes, boolean assignable) { - if (Build.VERSION.SDK_INT < 28) { - throw new UnsupportedOperationException("Not support getInstancesOfClasses on your device yet."); - } - try { - Class clazz = Class.forName("dalvik.system.VMDebug"); - Method method = clazz.getDeclaredMethod("getInstancesOfClasses", Class[].class, boolean.class); - return (Object[][]) method.invoke(null, classes, assignable); - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - public static Object handleHookedMethod(Member member, long slot, Object additionInfo, Object thisObject, Object[] args) throws Throwable { - return XposedBridge.handleHookedMethod(member, slot, additionInfo, thisObject, args); - } - - public static native Object invokeOriginalMethodNative(long slot, Object thisObject, Object[] args) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; - - public static native long getMethodSlot(Member member) throws IllegalArgumentException; - - public static native long hookMethodNative(Class declClass, Member method, Object additionInfo); - - public static native void setObjectClassNative(Object object, Class parent); - - public static native Object cloneToSubclassNative(Object object, Class subClass); - - public static native void removeFinalFlagNative(Class cl); - - public static native void enforceDisableHiddenAPIPolicy(); - - private static native void reserved0(); - - private static native void reserved1(); -} diff --git a/edxp-whale/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl b/edxp-whale/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl deleted file mode 100644 index aa3d9d26..00000000 --- a/edxp-whale/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl +++ /dev/null @@ -1 +0,0 @@ -com.elderdrivers.riru.edxp.whale.core.WhaleEdxpImpl \ No newline at end of file diff --git a/edxp-whale/template_override/system/etc/public.libraries-edxp.txt b/edxp-whale/template_override/system/etc/public.libraries-edxp.txt deleted file mode 100644 index 55a4cc17..00000000 --- a/edxp-whale/template_override/system/etc/public.libraries-edxp.txt +++ /dev/null @@ -1 +0,0 @@ -libwhale.edxp.so diff --git a/edxp-whale/template_override/system/framework/edxp.dex b/edxp-whale/template_override/system/framework/edxp.dex new file mode 100644 index 00000000..9a517a23 Binary files /dev/null and b/edxp-whale/template_override/system/framework/edxp.dex differ diff --git a/edxp-yahfa/.gitignore b/edxp-yahfa/.gitignore index 845f9980..3a66a198 100644 --- a/edxp-yahfa/.gitignore +++ b/edxp-yahfa/.gitignore @@ -1,2 +1,2 @@ /build -/template_override/system/framework/edxp.jar \ No newline at end of file +/template_override/system/framework \ No newline at end of file diff --git a/edxp-yahfa/build.gradle b/edxp-yahfa/build.gradle index 3e68e503..28b18bc9 100644 --- a/edxp-yahfa/build.gradle +++ b/edxp-yahfa/build.gradle @@ -4,7 +4,7 @@ sourceCompatibility = "7" targetCompatibility = "7" android { - compileSdkVersion 28 + compileSdkVersion androidCompileSdkVersion.toInteger() defaultConfig { applicationId "com.elderdrivers.riru.edxp.yahfa" @@ -22,13 +22,13 @@ android { } } + ndkVersion androidCompileNdkVersion } dependencies { - compileOnly files("${hiddenApiStubJarFilePath}") + compileOnly project(':hiddenapi-stubs') implementation project(':edxp-common') - implementation project(':xposed-bridge') - compileOnly project(':dexmaker') + compileOnly files(project(":dexmaker").tasks.getByName("makeJarRelease").outputs) } @@ -57,23 +57,16 @@ afterEvaluate { def variantNameCapped = variant.name.capitalize() def variantNameLowered = variant.name.toLowerCase() - def myTemplatePath = "${projectDir}/template_override/" - - task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { + task("copyDex${variantNameCapped}", type: Copy) { + dependsOn "assemble${variantNameCapped}" dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - def dexOutPath = variant.name.contains("release") ? - "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" : - "${buildDir}/intermediates/dex/${variantNameLowered}/mergeDex${variantNameCapped}/out/" - from dexOutPath, "${projectDir}/src/main/resources/" - destinationDir file(myTemplatePath + "system/framework/") - baseName "edxp" - doLast { - copy { - from file(myTemplatePath) - into file(templateRootPath) - } + def dexOutPath = "${buildDir}/intermediates/dex/${variantNameLowered}/minify${variantNameCapped}WithR8" + from (dexOutPath){ + rename("classes.dex", "edxp.dex") } + destinationDir file(templateRootPath + "system/framework/") outputs.upToDateWhen { false } } + } } \ No newline at end of file diff --git a/edxp-yahfa/proguard-rules.pro b/edxp-yahfa/proguard-rules.pro index c600fee6..50e9b797 100644 --- a/edxp-yahfa/proguard-rules.pro +++ b/edxp-yahfa/proguard-rules.pro @@ -20,6 +20,7 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile +-dontoptimize -dontobfuscate -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } @@ -30,6 +31,6 @@ -keep class * implements com.elderdrivers.riru.common.KeepAll { *; } -keepclassmembers class * implements com.elderdrivers.riru.common.KeepMembers { *; } --keepclasseswithmember class * { +-keepclasseswithmembers class * { native ; -} \ No newline at end of file +} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java index 8a05b27d..628dbde6 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java @@ -8,7 +8,6 @@ import com.elderdrivers.riru.edxp.core.Main; import com.elderdrivers.riru.edxp.core.Proxy; import com.elderdrivers.riru.edxp.core.Yahfa; import com.elderdrivers.riru.edxp.core.yahfa.HookMethodResolver; -import com.elderdrivers.riru.edxp.proxy.BlackWhiteListProxy; import com.elderdrivers.riru.edxp.proxy.NormalProxy; import com.elderdrivers.riru.edxp.proxy.Router; @@ -35,11 +34,6 @@ public class YahfaEdxpImpl extends BaseEdxpImpl { setInitialized(); } - @Override - protected Proxy createBlackWhiteListProxy() { - return new BlackWhiteListProxy(getRouter()); - } - @Override protected Proxy createNormalProxy() { return new NormalProxy(getRouter()); diff --git a/edxp-yahfa/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl b/edxp-yahfa/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl deleted file mode 100644 index 3d3af179..00000000 --- a/edxp-yahfa/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl +++ /dev/null @@ -1 +0,0 @@ -com.elderdrivers.riru.edxp.yahfa.core.YahfaEdxpImpl \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index fffbac40..6eeb58e9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,2 @@ -android.enableR8=false \ No newline at end of file +androidCompileSdkVersion=30 +androidCompileNdkVersion=22.0.6917172 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 797f6b0c..208ce983 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Apr 20 12:28:06 CST 2019 +#Fri Nov 13 15:00:57 CST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip diff --git a/hiddenapi-stubs/.gitignore b/hiddenapi-stubs/.gitignore index 796b96d1..97873191 100644 --- a/hiddenapi-stubs/.gitignore +++ b/hiddenapi-stubs/.gitignore @@ -1 +1,2 @@ /build +/libs diff --git a/hiddenapi-stubs/build.gradle b/hiddenapi-stubs/build.gradle index 14de44ba..31adb017 100644 --- a/hiddenapi-stubs/build.gradle +++ b/hiddenapi-stubs/build.gradle @@ -1,22 +1,15 @@ -import com.android.builder.core.BuilderConstants - apply plugin: 'com.android.library' android { - compileSdkVersion 28 + compileSdkVersion androidCompileSdkVersion.toInteger() + ndkVersion androidCompileNdkVersion } task makeStubJar(type: Jar){ + dependsOn assemble baseName 'framework-stub' - from("${projectDir}/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/") - into('') - destinationDir file("${projectDir}/libs") + from("${buildDir}/intermediates/javac/release/classes/") exclude('BuildConfig.class', 'R.class') exclude{ it.name.startsWith('R$')} -} - -afterEvaluate { - tasks.withType(JavaCompile) { - it.finalizedBy(makeStubJar) - } + outputs.file(archivePath) } diff --git a/hiddenapi-stubs/libs/framework-stub.jar b/hiddenapi-stubs/libs/framework-stub.jar deleted file mode 100644 index 2c94a740..00000000 Binary files a/hiddenapi-stubs/libs/framework-stub.jar and /dev/null differ diff --git a/settings.gradle b/settings.gradle index c40d4f51..c96662e1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':edxp-core', ':xposed-bridge', ':hiddenapi-stubs', ':dexmaker', ':dalvikdx', ':edxp-common', ':edxp-yahfa', ':edxp-sandhook', ':edxp-whale' \ No newline at end of file +include ':edxp-core', ':xposed-bridge', ':hiddenapi-stubs', ':dexmaker', ':dalvikdx', ':edxp-common', ':edxp-yahfa', ':edxp-sandhook' \ No newline at end of file diff --git a/xposed-bridge/build.gradle b/xposed-bridge/build.gradle index 0d9a288a..831afc02 100644 --- a/xposed-bridge/build.gradle +++ b/xposed-bridge/build.gradle @@ -1,8 +1,8 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 28 - buildToolsVersion '28.0.3' + compileSdkVersion androidCompileSdkVersion.toInteger() + ndkVersion androidCompileNdkVersion defaultConfig { minSdkVersion 26 @@ -39,8 +39,8 @@ preBuild.doLast { } dependencies { - compileOnly project(':hiddenapi-stubs') - compileOnly project(':dexmaker') + compileOnly files(project(":dexmaker").tasks.getByName("makeJarRelease").outputs) + compileOnly files(project(":hiddenapi-stubs").tasks.getByName("makeStubJar").outputs) } afterEvaluate { diff --git a/xposed-bridge/proguard-rules.pro b/xposed-bridge/proguard-rules.pro index e72d685a..867f7975 100644 --- a/xposed-bridge/proguard-rules.pro +++ b/xposed-bridge/proguard-rules.pro @@ -21,5 +21,6 @@ #-renamesourcefileattribute SourceFile -dontobfuscate +-dontoptimize -keep class de.robv.android.xposed.** {*;} -keep class android.** { *; } \ No newline at end of file diff --git a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdxpConfig.java b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdxpConfig.java index a8959cfd..fde28f5c 100644 --- a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdxpConfig.java +++ b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdxpConfig.java @@ -12,8 +12,6 @@ public interface EdxpConfig { String getLibSandHookName(); - String getLibWhaleName(); - boolean isDynamicModulesMode(); boolean isNoModuleLogEnabled(); @@ -21,4 +19,6 @@ public interface EdxpConfig { boolean isResourcesHookEnabled(); boolean isBlackWhiteListMode(); + + String getModulesList(); } diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index dd1a718c..103bea8c 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -21,6 +21,8 @@ import java.util.Set; import dalvik.system.InMemoryDexClassLoader; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; import de.robv.android.xposed.callbacks.XC_InitPackageResources; import de.robv.android.xposed.callbacks.XC_InitZygote; import de.robv.android.xposed.callbacks.XC_LoadPackage; @@ -92,6 +94,7 @@ public final class XposedBridge { public static volatile ClassLoader dummyClassLoader = null; + @ApiSensitive(Level.MIDDLE) public static void initXResources() { if (dummyClassLoader != null) { return; @@ -143,7 +146,7 @@ public final class XposedBridge { */ public static int getXposedVersion() { // ed: fixed value for now - return 91; + return 92; } /** diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java index c763fb2e..3d63c66a 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java @@ -17,10 +17,12 @@ import com.android.internal.os.ZygoteInit; import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.StringBufferInputStream; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.ArrayList; @@ -34,6 +36,8 @@ import java.util.zip.ZipFile; import dalvik.system.DexFile; import dalvik.system.PathClassLoader; +import de.robv.android.xposed.annotation.ApiSensitive; +import de.robv.android.xposed.annotation.Level; import de.robv.android.xposed.callbacks.XC_InitPackageResources; import de.robv.android.xposed.callbacks.XC_InitZygote; import de.robv.android.xposed.callbacks.XC_LoadPackage; @@ -91,6 +95,7 @@ public final class XposedInit { hookResources(); } + @ApiSensitive(Level.MIDDLE) private static void hookResources() throws Throwable { if (!EdXpConfigGlobal.getConfig().isResourcesHookEnabled() || disableResources) { return; @@ -265,6 +270,7 @@ public final class XposedInit { XResources.init(latestResKey); } + @ApiSensitive(Level.MIDDLE) private static XResources cloneToXResources(XC_MethodHook.MethodHookParam param, String resDir) { Object result = param.getResult(); if (result == null || result instanceof XResources || @@ -303,38 +309,21 @@ public final class XposedInit { private static final Object moduleLoadLock = new Object(); // @GuardedBy("moduleLoadLock") private static final ArraySet loadedModules = new ArraySet<>(); - // @GuardedBy("moduleLoadLock") - private static long lastModuleListModifiedTime = -1; - public static boolean loadModules(boolean isInZygote, boolean callInitZygote) throws IOException { + public static boolean loadModules(boolean callInitZygote) throws IOException { boolean hasLoaded = !modulesLoaded.compareAndSet(false, true); if (hasLoaded && !EdXpConfigGlobal.getConfig().isDynamicModulesMode()) { return false; } synchronized (moduleLoadLock) { - final String filename = EdXpConfigGlobal.getConfig().getInstallerConfigPath("modules.list"); - BaseService service = SELinuxHelper.getAppDataFileService(); - if (!service.checkFileExists(filename)) { - Log.e(TAG, "Cannot load any modules because " + filename + " was not found"); - // FIXME module list is cleared but never could be reload again - // when using dynamic-module-list under multi-user environment - clearAllCallbacks(); - return false; - } - - long moduleListModifiedTime = service.getFileModificationTime(filename); - if (lastModuleListModifiedTime == moduleListModifiedTime) { - // module list has not changed - return false; - } - ClassLoader topClassLoader = XposedBridge.BOOTCLASSLOADER; ClassLoader parent; while ((parent = topClassLoader.getParent()) != null) { topClassLoader = parent; } - InputStream stream = service.getFileInputStream(filename); + String moduleList = EdXpConfigGlobal.getConfig().getModulesList(); + InputStream stream = new ByteArrayInputStream(moduleList.getBytes()); BufferedReader apks = new BufferedReader(new InputStreamReader(stream)); ArraySet newLoadedApk = new ArraySet<>(); String apk; @@ -354,9 +343,6 @@ public final class XposedInit { // refresh callback according to current loaded module list pruneCallbacks(loadedModules); - - lastModuleListModifiedTime = moduleListModifiedTime; - } return true; } diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/annotation/ApiSensitive.java b/xposed-bridge/src/main/java/de/robv/android/xposed/annotation/ApiSensitive.java new file mode 100644 index 00000000..75466f60 --- /dev/null +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/annotation/ApiSensitive.java @@ -0,0 +1,17 @@ +package de.robv.android.xposed.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation that indicates a element is sensitive to Android API level. + *

+ * Annotated elements' compatibility should be checked when adapting to new Android versions. + */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) +public @interface ApiSensitive { + Level value() default Level.HIGH; +} diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/annotation/Level.java b/xposed-bridge/src/main/java/de/robv/android/xposed/annotation/Level.java new file mode 100644 index 00000000..54d5869e --- /dev/null +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/annotation/Level.java @@ -0,0 +1,9 @@ +package de.robv.android.xposed.annotation; + +public enum Level { + LOW, MIDDLE, HIGH; + + private Level() { + + } +} \ No newline at end of file