Black/White mode: postpone initZygote callbacks

in case some modules hook methods in zygote, which would be
propagated into blacklisted processes
This commit is contained in:
solohsu 2019-06-17 16:13:21 +08:00
parent 6dccef53d3
commit 661a675a09
13 changed files with 149 additions and 77 deletions

View File

@ -1,4 +1,4 @@
version: '0.4.4.5_alpha({build})'
version: '0.4.4.6_alpha({build})'
environment:
ANDROID_HOME: C:\android-sdk-windows

View File

@ -0,0 +1,31 @@
package com.elderdrivers.riru.edxp.config;
import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker;
public class BaseEdxpConfig implements EdxpConfig {
@Override
public String getInstallerBaseDir() {
return InstallerChooser.INSTALLER_DATA_BASE_DIR;
}
@Override
public String getBlackListModulePackageName() {
return XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
}
@Override
public boolean isDynamicModulesMode() {
return ConfigManager.isDynamicModulesEnabled();
}
@Override
public boolean isResourcesHookEnabled() {
return ConfigManager.isResourcesHookEnabled();
}
@Override
public boolean isBlackWhiteListMode() {
return ConfigManager.isBlackWhiteListEnabled();
}
}

View File

@ -106,6 +106,9 @@ public class BlackWhiteListProxy extends BaseProxy {
mRouter.installBootstrapHooks(isSystemServer);
if (isDynamicModulesMode) {
mRouter.loadModulesSafely(false);
} else {
XposedBridge.callInitZygotes();
XposedBridge.clearInitZygotes(); // one-time use
}
mRouter.onForkFinish();
}
@ -130,5 +133,6 @@ public class BlackWhiteListProxy extends BaseProxy {
private static void onBlackListed() {
XposedBridge.clearLoadedPackages();
XposedBridge.clearInitPackageResources();
XposedBridge.clearInitZygotes();
}
}

View File

@ -4,7 +4,7 @@ import org.gradle.internal.os.OperatingSystem
apply plugin: 'com.android.library'
// Values set here will be overriden by AppVeyor, feel free to modify during development.
def buildVersionName = 'v0.4.4.5_alpha'
def buildVersionName = 'v0.4.4.6_alpha'
def buildVersionCode = 10000
if (System.env.APPVEYOR_BUILD_VERSION != null) {

View File

@ -1,28 +1,7 @@
package com.elderdrivers.riru.edxp.sandhook.config;
import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.config.EdXpConfig;
import com.elderdrivers.riru.edxp.config.InstallerChooser;
import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker;
import com.elderdrivers.riru.edxp.config.BaseEdxpConfig;
public class SandHookEdxpConfig implements EdXpConfig {
@Override
public String getInstallerBaseDir() {
return InstallerChooser.INSTALLER_DATA_BASE_DIR;
}
public class SandHookEdxpConfig extends BaseEdxpConfig {
@Override
public String getBlackListModulePackageName() {
return XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
}
@Override
public boolean isDynamicModulesMode() {
return ConfigManager.isDynamicModulesEnabled();
}
@Override
public boolean isResourcesHookEnabled() {
return ConfigManager.isResourcesHookEnabled();
}
}

View File

@ -1,28 +1,7 @@
package com.elderdrivers.riru.edxp.whale.config;
import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.config.EdXpConfig;
import com.elderdrivers.riru.edxp.config.InstallerChooser;
import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker;
import com.elderdrivers.riru.edxp.config.BaseEdxpConfig;
public class WhaleEdxpConfig implements EdXpConfig {
@Override
public String getInstallerBaseDir() {
return InstallerChooser.INSTALLER_DATA_BASE_DIR;
}
@Override
public String getBlackListModulePackageName() {
return XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
}
@Override
public boolean isDynamicModulesMode() {
return ConfigManager.isDynamicModulesEnabled();
}
@Override
public boolean isResourcesHookEnabled() {
return ConfigManager.isResourcesHookEnabled();
}
public class WhaleEdxpConfig extends BaseEdxpConfig {
}

View File

@ -1,28 +1,7 @@
package com.elderdrivers.riru.edxp.yahfa.config;
import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.config.EdXpConfig;
import com.elderdrivers.riru.edxp.config.InstallerChooser;
import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker;
import com.elderdrivers.riru.edxp.config.BaseEdxpConfig;
public class YahfaEdxpConfig implements EdXpConfig {
@Override
public String getInstallerBaseDir() {
return InstallerChooser.INSTALLER_DATA_BASE_DIR;
}
public class YahfaEdxpConfig extends BaseEdxpConfig {
@Override
public String getBlackListModulePackageName() {
return XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
}
@Override
public boolean isDynamicModulesMode() {
return ConfigManager.isDynamicModulesEnabled();
}
@Override
public boolean isResourcesHookEnabled() {
return ConfigManager.isResourcesHookEnabled();
}
}

View File

@ -4,10 +4,10 @@ import com.elderdrivers.riru.edxp.hook.HookProvider;
public class EdXpConfigGlobal {
public static volatile EdXpConfig sConfig;
public static volatile EdxpConfig sConfig;
public static volatile HookProvider sHookProvider;
public static EdXpConfig getConfig() {
public static EdxpConfig getConfig() {
if (sConfig == null) {
throw new IllegalArgumentException("sConfig should not be null.");
}

View File

@ -1,6 +1,6 @@
package com.elderdrivers.riru.edxp.config;
public interface EdXpConfig {
public interface EdxpConfig {
String getInstallerBaseDir();
@ -10,4 +10,5 @@ public interface EdXpConfig {
boolean isResourcesHookEnabled();
boolean isBlackWhiteListMode();
}

View File

@ -1,5 +1,8 @@
package de.robv.android.xposed;
import de.robv.android.xposed.callbacks.XC_InitZygote;
import de.robv.android.xposed.callbacks.XCallback;
/**
* Hook the initialization of Zygote process(es), from which all the apps are forked.
*
@ -20,9 +23,17 @@ public interface IXposedHookZygoteInit extends IXposedMod {
void initZygote(StartupParam startupParam) throws Throwable;
/** Data holder for {@link #initZygote}. */
final class StartupParam {
final class StartupParam extends XCallback.Param {
/*package*/ StartupParam() {}
/**
* @param callbacks
* @hide
*/
public StartupParam(XposedBridge.CopyOnWriteSortedSet<? extends XCallback> callbacks) {
super(callbacks);
}
/** The path to the module's APK. */
public String modulePath;
@ -32,4 +43,24 @@ public interface IXposedHookZygoteInit extends IXposedMod {
*/
public boolean startsSystemServer;
}
/**
* @hide
*/
final class Wrapper extends XC_InitZygote {
private final IXposedHookZygoteInit instance;
private final StartupParam startupParam;
public Wrapper(IXposedHookZygoteInit instance, StartupParam startupParam) {
this.instance = instance;
this.startupParam = startupParam;
}
@Override
public void initZygote(StartupParam startupParam) throws Throwable {
// NOTE: parameter startupParam not used
// cause startupParam info is generated and saved along with instance here
instance.initZygote(this.startupParam);
}
}
}

View File

@ -22,7 +22,9 @@ import java.util.Set;
import dalvik.system.InMemoryDexClassLoader;
import de.robv.android.xposed.XC_MethodHook.MethodHookParam;
import de.robv.android.xposed.callbacks.XC_InitPackageResources;
import de.robv.android.xposed.callbacks.XC_InitZygote;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import de.robv.android.xposed.callbacks.XCallback;
import external.com.android.dx.DexMaker;
import external.com.android.dx.TypeId;
@ -67,6 +69,7 @@ public final class XposedBridge {
public static final Map<Member, CopyOnWriteSortedSet<XC_MethodHook>> sHookedMethodCallbacks = new HashMap<>();
public static final CopyOnWriteSortedSet<XC_LoadPackage> sLoadedPackageCallbacks = new CopyOnWriteSortedSet<>();
/*package*/ static final CopyOnWriteSortedSet<XC_InitPackageResources> sInitPackageResourcesCallbacks = new CopyOnWriteSortedSet<>();
/*package*/ static final CopyOnWriteSortedSet<XC_InitZygote> sInitZygoteCallbacks = new CopyOnWriteSortedSet<>();
private XposedBridge() {}
@ -427,6 +430,22 @@ public final class XposedBridge {
}
}
public static void hookInitZygote(XC_InitZygote callback) {
synchronized (sInitZygoteCallbacks) {
sInitZygoteCallbacks.add(callback);
}
}
public static void clearInitZygotes() {
synchronized (sInitZygoteCallbacks) {
sInitZygoteCallbacks.clear();
}
}
public static void callInitZygotes() {
XCallback.callAll(new IXposedHookZygoteInit.StartupParam(sInitZygoteCallbacks));
}
/**
* Intercept every call to the specified method and call a handler function instead.
* @param method The method to intercept

View File

@ -414,7 +414,17 @@ public final class XposedInit {
IXposedHookZygoteInit.StartupParam param = new IXposedHookZygoteInit.StartupParam();
param.modulePath = apk;
param.startsSystemServer = startsSystemServer;
((IXposedHookZygoteInit) moduleInstance).initZygote(param);
if (EdXpConfigGlobal.getConfig().isBlackWhiteListMode()
&& !EdXpConfigGlobal.getConfig().isDynamicModulesMode()) {
// postpone initZygote callbacks under black/white list mode
// if dynamic modules mode is on, callback directly cause we
// are already in app process here
XposedBridge.hookInitZygote(new IXposedHookZygoteInit.Wrapper(
(IXposedHookZygoteInit) moduleInstance, param));
} else {
// FIXME under dynamic modules mode, initZygote is called twice
((IXposedHookZygoteInit) moduleInstance).initZygote(param);
}
}
if (moduleInstance instanceof IXposedHookLoadPackage)

View File

@ -0,0 +1,39 @@
package de.robv.android.xposed.callbacks;
import de.robv.android.xposed.IXposedHookZygoteInit;
/**
* This class is only used for internal purposes, except for the {@link StartupParam}
* subclass.
*/
public abstract class XC_InitZygote extends XCallback implements IXposedHookZygoteInit {
/**
* Creates a new callback with default priority.
*
* @hide
*/
@SuppressWarnings("deprecation")
public XC_InitZygote() {
super();
}
/**
* Creates a new callback with a specific priority.
*
* @param priority See {@link XCallback#priority}.
* @hide
*/
public XC_InitZygote(int priority) {
super(priority);
}
/**
* @hide
*/
@Override
protected void call(Param param) throws Throwable {
if (param instanceof StartupParam)
initZygote((StartupParam) param);
}
}