Fix loading embedded module so

This commit is contained in:
Nullptr 2021-09-03 20:02:20 +08:00
parent c7b8cd30b5
commit 813802d18c
3 changed files with 46 additions and 23 deletions

View File

@ -241,7 +241,7 @@ public class LSPApplication extends ApplicationServiceClient {
final var new_modules = new JSONArray(); final var new_modules = new JSONArray();
LSPApplication.modules.forEach(m -> { LSPApplication.modules.forEach(m -> {
try { try {
m.file = loadModule(m.apkPath); m.file = loadModule(context, m.apkPath);
var module = new JSONObject(); var module = new JSONObject();
module.put("name", m.packageName); module.put("name", m.packageName);
module.put("enabled", !disabled_modules.contains(m.packageName)); module.put("enabled", !disabled_modules.contains(m.packageName));
@ -297,7 +297,7 @@ public class LSPApplication extends ApplicationServiceClient {
} }
} }
private static PreLoadedApk loadModule(String path) { private static PreLoadedApk loadModule(Context context, String path) {
var file = new PreLoadedApk(); var file = new PreLoadedApk();
var preLoadedDexes = new ArrayList<SharedMemory>(); var preLoadedDexes = new ArrayList<SharedMemory>();
var moduleClassNames = new ArrayList<String>(1); var moduleClassNames = new ArrayList<String>(1);
@ -312,6 +312,7 @@ public class LSPApplication extends ApplicationServiceClient {
} }
if (preLoadedDexes.isEmpty()) return null; if (preLoadedDexes.isEmpty()) return null;
if (moduleClassNames.isEmpty()) return null; if (moduleClassNames.isEmpty()) return null;
file.hostApk = context.getApplicationInfo().sourceDir;
file.preLoadedDexes = preLoadedDexes; file.preLoadedDexes = preLoadedDexes;
file.moduleClassNames = moduleClassNames; file.moduleClassNames = moduleClassNames;
file.moduleLibraryNames = moduleLibraryNames; file.moduleLibraryNames = moduleLibraryNames;

2
core

@ -1 +1 @@
Subproject commit 52c8d1c89d658cf4083ec528caa12a7fd0113638 Subproject commit a2e57ddfe9477933e6540ce9dad4c1dac1991d32

View File

@ -36,6 +36,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.jar.JarFile; import java.util.jar.JarFile;
public class LSPatch { public class LSPatch {
@ -91,6 +92,12 @@ public class LSPatch {
private static final String SIGNATURE_INFO_ASSET_PATH = "assets/original_signature_info.ini"; private static final String SIGNATURE_INFO_ASSET_PATH = "assets/original_signature_info.ini";
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 ANDROID_MANIFEST_XML = "AndroidManifest.xml"; private static final String ANDROID_MANIFEST_XML = "AndroidManifest.xml";
private static final HashSet<String> ARCHES = new HashSet<>(Arrays.asList(
"armeabi-v7a",
"arm64-v8a",
"x86",
"x86_64"
));
private static final HashSet<String> APK_LIB_PATH_ARRAY = new HashSet<>(Arrays.asList( private static final HashSet<String> APK_LIB_PATH_ARRAY = new HashSet<>(Arrays.asList(
"arm", "arm",
"arm64", "arm64",
@ -240,8 +247,7 @@ public class LSPatch {
for (String arch : APK_LIB_PATH_ARRAY) { for (String arch : APK_LIB_PATH_ARRAY) {
String entryName = "assets/lib/lspd/" + arch + "/liblspd.so"; String entryName = "assets/lib/lspd/" + arch + "/liblspd.so";
try (var is = getClass().getClassLoader().getResourceAsStream("assets/so/" + (arch.equals("arm") ? "armeabi-v7a" : (arch.equals("arm64") ? "arm64-v8a" : arch)) + "/liblspd.so")) { try (var is = getClass().getClassLoader().getResourceAsStream("assets/so/" + (arch.equals("arm") ? "armeabi-v7a" : (arch.equals("arm64") ? "arm64-v8a" : arch)) + "/liblspd.so")) {
var entry = dstZFile.add(entryName, is, false); // no compress for so dstZFile.add(entryName, is, false); // no compress for so
dstZFile.addLink(entry, "assets/lib/lspd/test/" + arch + "/liblspd.so");
} catch (Throwable e) { } catch (Throwable e) {
// More exception info // More exception info
throw new PatchError("Error when adding native lib", e); throw new PatchError("Error when adding native lib", e);
@ -272,6 +278,27 @@ public class LSPatch {
throw new PatchError("Error when saving signature bypass level", e); throw new PatchError("Error when saving signature bypass level", e);
} }
Set<String> apkArchs = new HashSet<>();
if (verbose)
System.out.println("Search target apk library arch...");
for (StoredEntry storedEntry : srcZFile.entries()) {
var name = storedEntry.getCentralDirectoryHeader().getName();
if (name.startsWith("lib/") && name.length() >= 5) {
var arch = name.substring(4, name.indexOf('/', 5));
apkArchs.add(arch);
}
}
if (apkArchs.isEmpty()) apkArchs.addAll(ARCHES);
apkArchs.removeIf((arch) -> {
if (!ARCHES.contains(arch) && !arch.equals("armeabi")) {
System.err.println("Warning: unsupported arch " + arch + ". Skipping...");
return true;
}
return false;
});
// create zip link // create zip link
if (verbose) if (verbose)
System.out.println("Creating nested apk link..."); System.out.println("Creating nested apk link...");
@ -290,28 +317,21 @@ public class LSPatch {
return "assets/modules/" + moduleManifest[0].packageName + ".bin"; return "assets/modules/" + moduleManifest[0].packageName + ".bin";
}, new File(moduleFile), false)) { }, new File(moduleFile), false)) {
var packageName = moduleManifest[0].packageName; var packageName = moduleManifest[0].packageName;
for (var nestedEntry : nested.entries()) { for (var arch : apkArchs) {
var name = nestedEntry.getCentralDirectoryHeader().getName(); dstZFile.addLink(nested.getEntry(), "lib/" + arch + "/" + packageName + ".so");
if (name.startsWith("lib/")) {
var dstName = "assets/lib/" + packageName + name.substring(3);
System.out.println("add link: " + dstName);
if (!nested.addFileLink(nestedEntry, dstName)) {
throw new PatchError("module " + packageName + " is too large to embed");
}
}
} }
} }
} }
// for (StoredEntry entry : srcZFile.entries()) { for (StoredEntry entry : srcZFile.entries()) {
// String name = entry.getCentralDirectoryHeader().getName(); String name = entry.getCentralDirectoryHeader().getName();
// if (name.startsWith("classes") && name.endsWith(".dex")) continue; if (name.startsWith("classes") && name.endsWith(".dex")) continue;
// if (dstZFile.get(name) != null) continue; if (dstZFile.get(name) != null) continue;
// if (name.equals("AndroidManifest.xml")) continue; if (name.equals("AndroidManifest.xml")) continue;
// if (name.startsWith("META-INF/CERT")) continue; if (name.startsWith("META-INF/CERT")) continue;
// if (name.equals("META-INF/MANIFEST.MF")) continue; if (name.equals("META-INF/MANIFEST.MF")) continue;
// srcZFile.addFileLink(name, name); srcZFile.addFileLink(name, name);
// } }
dstZFile.realign(); dstZFile.realign();
@ -330,6 +350,8 @@ public class LSPatch {
private byte[] modifyManifestFile(InputStream is) throws IOException { private byte[] modifyManifestFile(InputStream is) throws IOException {
ModificationProperty property = new ModificationProperty(); ModificationProperty property = new ModificationProperty();
if (!modules.isEmpty())
property.addApplicationAttribute(new AttributeItem("extractNativeLibs", true));
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));
property.addApplicationAttribute(new AttributeItem("appComponentFactory", PROXY_APP_COMPONENT_FACTORY)); property.addApplicationAttribute(new AttributeItem("appComponentFactory", PROXY_APP_COMPONENT_FACTORY));