Use AppComponentFactoryStub to instantiate LSPApplication and original application
This commit is contained in:
parent
ed6eaec32c
commit
8cbf468d59
|
|
@ -116,9 +116,6 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, "Do hook", e);
|
Log.e(TAG, "Do hook", e);
|
||||||
}
|
}
|
||||||
if (isApplicationProxied()) {
|
|
||||||
instance.createOriginalApplication();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void disableProfile(Context context) {
|
public static void disableProfile(Context context) {
|
||||||
|
|
@ -265,17 +262,7 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
try {
|
try {
|
||||||
Object mBoundApplication = XposedHelpers.getObjectField(getActivityThread(), "mBoundApplication");
|
Object mBoundApplication = XposedHelpers.getObjectField(getActivityThread(), "mBoundApplication");
|
||||||
Object loadedApkObj = XposedHelpers.getObjectField(mBoundApplication, "info");
|
Object loadedApkObj = XposedHelpers.getObjectField(mBoundApplication, "info");
|
||||||
var mClassLoader = (ClassLoader) XposedHelpers.getObjectField(loadedApkObj, "mClassLoader");
|
appClassLoader = (ClassLoader) XposedHelpers.getObjectField(loadedApkObj, "mClassLoader");
|
||||||
|
|
||||||
final String cacheApkPath = context.getCacheDir().getAbsolutePath() + "/origin_apk.bin";
|
|
||||||
try (InputStream inputStream = context.getAssets().open("origin_apk.bin")) {
|
|
||||||
Files.copy(inputStream, Paths.get(cacheApkPath));
|
|
||||||
} catch (FileAlreadyExistsException ignored) {
|
|
||||||
}
|
|
||||||
appClassLoader = new PathClassLoader(cacheApkPath, mClassLoader.getParent());
|
|
||||||
XposedHelpers.setObjectField(loadedApkObj, "mClassLoader", appClassLoader);
|
|
||||||
|
|
||||||
Log.d(TAG, "appClassLoader is now switched to " + appClassLoader);
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, "initAppClassLoader", e);
|
Log.e(TAG, "initAppClassLoader", e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,21 @@ import dalvik.system.PathClassLoader;
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
||||||
private static final String TAG = "LSPatch";
|
private static final String TAG = "LSPatch";
|
||||||
|
private static final String PROXY_APPLICATION = "org.lsposed.lspatch.appstub.LSPApplicationStub";
|
||||||
private static final String ORIGINAL_APK_ASSET_PATH = "assets/origin_apk.bin";
|
private static final String ORIGINAL_APK_ASSET_PATH = "assets/origin_apk.bin";
|
||||||
private static final String ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH = "assets/original_app_component_factory.ini";
|
private static final String ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH = "assets/original_app_component_factory.ini";
|
||||||
|
|
||||||
|
private ClassLoader appClassLoader = null;
|
||||||
|
private ClassLoader baseClassLoader = null;
|
||||||
private AppComponentFactory originalAppComponentFactory = null;
|
private AppComponentFactory originalAppComponentFactory = null;
|
||||||
|
|
||||||
// Proxy appComponentFactory to load the original one
|
/**
|
||||||
private void initOrigin(ClassLoader cl, ApplicationInfo aInfo) {
|
* Instantiate original AppComponentFactory<br/>
|
||||||
|
* This method will be called at <b>instantiateClassLoader</b> by <b>createOrUpdateClassLoaderLocked</b>
|
||||||
|
*
|
||||||
|
* @param cl PathClassLoader(originalApk)
|
||||||
|
**/
|
||||||
|
private void initOriginalAppComponentFactory(ClassLoader cl, ApplicationInfo aInfo) {
|
||||||
final String cacheApkPath = aInfo.dataDir + "/cache/origin_apk.bin";
|
final String cacheApkPath = aInfo.dataDir + "/cache/origin_apk.bin";
|
||||||
final String originalAppComponentFactoryClass = FileUtils.readTextFromInputStream(cl.getResourceAsStream(ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH));
|
final String originalAppComponentFactoryClass = FileUtils.readTextFromInputStream(cl.getResourceAsStream(ORIGINAL_APP_COMPONENT_FACTORY_ASSET_PATH));
|
||||||
|
|
||||||
|
|
@ -38,22 +46,27 @@ public class LSPAppComponentFactoryStub extends AppComponentFactory {
|
||||||
Files.copy(inputStream, Paths.get(cacheApkPath));
|
Files.copy(inputStream, Paths.get(cacheApkPath));
|
||||||
} catch (FileAlreadyExistsException ignored) {
|
} catch (FileAlreadyExistsException ignored) {
|
||||||
}
|
}
|
||||||
ClassLoader appClassLoader = new PathClassLoader(cacheApkPath, cl.getParent());
|
appClassLoader = new PathClassLoader(cacheApkPath, cl.getParent());
|
||||||
originalAppComponentFactory = (AppComponentFactory) appClassLoader.loadClass(originalAppComponentFactoryClass).newInstance();
|
if (originalAppComponentFactoryClass == null || originalAppComponentFactoryClass.isEmpty())
|
||||||
Log.d(TAG, "appComponentFactory is now switched to " + originalAppComponentFactory);
|
originalAppComponentFactory = new AppComponentFactory();
|
||||||
|
else
|
||||||
|
originalAppComponentFactory = (AppComponentFactory) appClassLoader.loadClass(originalAppComponentFactoryClass).newInstance();
|
||||||
|
Log.d(TAG, "Instantiate original AppComponentFactory: " + originalAppComponentFactory);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, "initOrigin", e);
|
Log.e(TAG, "initOriginalAppComponentFactory", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassLoader instantiateClassLoader(ClassLoader cl, ApplicationInfo aInfo) {
|
public ClassLoader instantiateClassLoader(ClassLoader cl, ApplicationInfo aInfo) {
|
||||||
if (originalAppComponentFactory == null) initOrigin(cl, aInfo);
|
baseClassLoader = cl;
|
||||||
return originalAppComponentFactory.instantiateClassLoader(cl, aInfo);
|
initOriginalAppComponentFactory(cl, aInfo);
|
||||||
|
return originalAppComponentFactory.instantiateClassLoader(appClassLoader, aInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Application instantiateApplication(ClassLoader cl, String className) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
|
public Application instantiateApplication(ClassLoader cl, String className) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
|
||||||
|
baseClassLoader.loadClass(PROXY_APPLICATION).newInstance();
|
||||||
return originalAppComponentFactory.instantiateApplication(cl, className);
|
return originalAppComponentFactory.instantiateApplication(cl, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ buildscript {
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.0-beta04'
|
classpath 'com.android.tools.build:gradle:7.0.0-beta05'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,6 @@ public class LSPatch {
|
||||||
));
|
));
|
||||||
|
|
||||||
private static JCommander jCommander;
|
private static JCommander jCommander;
|
||||||
private boolean hasAppComponentFactory;
|
|
||||||
|
|
||||||
public static void main(String... args) throws IOException {
|
public static void main(String... args) throws IOException {
|
||||||
LSPatch lsPatch = new LSPatch();
|
LSPatch lsPatch = new LSPatch();
|
||||||
|
|
@ -193,8 +192,7 @@ public class LSPatch {
|
||||||
if (triple == null)
|
if (triple == null)
|
||||||
throw new PatchError("Failed to parse AndroidManifest.xml");
|
throw new PatchError("Failed to parse AndroidManifest.xml");
|
||||||
String applicationName = triple.applicationName == null ? "" : triple.applicationName;
|
String applicationName = triple.applicationName == null ? "" : triple.applicationName;
|
||||||
String appComponentFactory = triple.appComponentFactory;
|
String appComponentFactory = triple.appComponentFactory == null ? "" : triple.appComponentFactory;
|
||||||
hasAppComponentFactory = appComponentFactory != null;
|
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
System.out.println("original application name: " + applicationName);
|
System.out.println("original application name: " + applicationName);
|
||||||
|
|
@ -210,12 +208,11 @@ public class LSPatch {
|
||||||
}
|
}
|
||||||
|
|
||||||
// save original appComponentFactory name to asset file even its empty
|
// save original appComponentFactory name to asset file even its empty
|
||||||
if (appComponentFactory != null)
|
try (var is = new ByteArrayInputStream(appComponentFactory.getBytes(StandardCharsets.UTF_8))) {
|
||||||
try (var is = new ByteArrayInputStream(appComponentFactory.getBytes(StandardCharsets.UTF_8))) {
|
zFile.add(APP_COMPONENT_FACTORY_ASSET_PATH, is);
|
||||||
zFile.add(APP_COMPONENT_FACTORY_ASSET_PATH, is);
|
} catch (Throwable e) {
|
||||||
} catch (Throwable e) {
|
throw new PatchError("Error when saving appComponentFactory class: " + e);
|
||||||
throw new PatchError("Error when saving appComponentFactory class: " + e);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// save original main application name to asset file even its empty
|
// save original main application name to asset file even its empty
|
||||||
try (var is = new ByteArrayInputStream(applicationName.getBytes(StandardCharsets.UTF_8))) {
|
try (var is = new ByteArrayInputStream(applicationName.getBytes(StandardCharsets.UTF_8))) {
|
||||||
|
|
@ -350,9 +347,8 @@ public class LSPatch {
|
||||||
ModificationProperty property = new ModificationProperty();
|
ModificationProperty property = new ModificationProperty();
|
||||||
|
|
||||||
property.addApplicationAttribute(new AttributeItem(NodeValue.Application.DEBUGGABLE, debuggableFlag));
|
property.addApplicationAttribute(new AttributeItem(NodeValue.Application.DEBUGGABLE, debuggableFlag));
|
||||||
property.addApplicationAttribute(new AttributeItem(NodeValue.Application.NAME, PROXY_APPLICATION));
|
//property.addApplicationAttribute(new AttributeItem(NodeValue.Application.NAME, PROXY_APPLICATION));
|
||||||
if (hasAppComponentFactory)
|
property.addApplicationAttribute(new AttributeItem("appComponentFactory", PROXY_APP_COMPONENT_FACTORY));
|
||||||
property.addApplicationAttribute(new AttributeItem("appComponentFactory", PROXY_APP_COMPONENT_FACTORY));
|
|
||||||
|
|
||||||
var os = new ByteArrayOutputStream();
|
var os = new ByteArrayOutputStream();
|
||||||
(new ManifestEditor(is, os, property)).processManifest();
|
(new ManifestEditor(is, os, property)).processManifest();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue