feat: custom zip reader implementation to fight tampering
fix(zip): use size info from CD if LFH entry is incorrect refactor: move custom zip implementation into new module feat: move ZipSecurity into jadx-zip module
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
package jadx.cli;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.security.JadxSecurityFlag;
|
||||
import jadx.api.security.impl.JadxSecurity;
|
||||
import jadx.commons.app.JadxCommonEnv;
|
||||
import jadx.zip.security.DisabledZipSecurity;
|
||||
import jadx.zip.security.IJadxZipSecurity;
|
||||
import jadx.zip.security.JadxZipSecurity;
|
||||
|
||||
public class JadxAppCommon {
|
||||
|
||||
public static void applyEnvVars(JadxArgs jadxArgs) {
|
||||
Set<JadxSecurityFlag> flags = JadxSecurityFlag.all();
|
||||
IJadxZipSecurity zipSecurity;
|
||||
|
||||
boolean disableXmlSecurity = JadxCommonEnv.getBool("JADX_DISABLE_XML_SECURITY", false);
|
||||
if (disableXmlSecurity) {
|
||||
flags.remove(JadxSecurityFlag.SECURE_XML_PARSER);
|
||||
// TODO: not related to 'xml security', but kept for compatibility
|
||||
flags.remove(JadxSecurityFlag.VERIFY_APP_PACKAGE);
|
||||
}
|
||||
|
||||
boolean disableZipSecurity = JadxCommonEnv.getBool("JADX_DISABLE_ZIP_SECURITY", false);
|
||||
if (disableZipSecurity) {
|
||||
flags.remove(JadxSecurityFlag.SECURE_ZIP_READER);
|
||||
zipSecurity = DisabledZipSecurity.INSTANCE;
|
||||
} else {
|
||||
JadxZipSecurity jadxZipSecurity = new JadxZipSecurity();
|
||||
int maxZipEntriesCount = JadxCommonEnv.getInt("JADX_ZIP_MAX_ENTRIES_COUNT", -2);
|
||||
if (maxZipEntriesCount != -2) {
|
||||
jadxZipSecurity.setMaxEntriesCount(maxZipEntriesCount);
|
||||
}
|
||||
int zipBombMinUncompressedSize = JadxCommonEnv.getInt("JADX_ZIP_BOMB_MIN_UNCOMPRESSED_SIZE", -2);
|
||||
if (zipBombMinUncompressedSize != -2) {
|
||||
jadxZipSecurity.setZipBombMinUncompressedSize(zipBombMinUncompressedSize);
|
||||
}
|
||||
int setZipBombDetectionFactor = JadxCommonEnv.getInt("JADX_ZIP_BOMB_DETECTION_FACTOR", -2);
|
||||
if (setZipBombDetectionFactor != -2) {
|
||||
jadxZipSecurity.setZipBombDetectionFactor(setZipBombDetectionFactor);
|
||||
}
|
||||
zipSecurity = jadxZipSecurity;
|
||||
}
|
||||
jadxArgs.setSecurity(new JadxSecurity(flags, zipSecurity));
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package jadx.cli;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -10,11 +8,8 @@ import jadx.api.JadxDecompiler;
|
||||
import jadx.api.impl.AnnotatedCodeWriter;
|
||||
import jadx.api.impl.NoOpCodeCache;
|
||||
import jadx.api.impl.SimpleCodeWriter;
|
||||
import jadx.api.security.JadxSecurityFlag;
|
||||
import jadx.api.security.impl.JadxSecurity;
|
||||
import jadx.cli.LogHelper.LogLevelEnum;
|
||||
import jadx.cli.plugins.JadxFilesGetter;
|
||||
import jadx.commons.app.JadxCommonEnv;
|
||||
import jadx.core.utils.exceptions.JadxArgsValidateException;
|
||||
import jadx.plugins.tools.JadxExternalPluginsLoader;
|
||||
|
||||
@@ -54,7 +49,7 @@ public class JadxCLI {
|
||||
jadxArgs.setPluginLoader(new JadxExternalPluginsLoader());
|
||||
jadxArgs.setFilesGetter(JadxFilesGetter.INSTANCE);
|
||||
initCodeWriterProvider(jadxArgs);
|
||||
applyEnvVars(jadxArgs);
|
||||
JadxAppCommon.applyEnvVars(jadxArgs);
|
||||
try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
|
||||
jadx.load();
|
||||
if (checkForErrors(jadx)) {
|
||||
@@ -87,22 +82,6 @@ public class JadxCLI {
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyEnvVars(JadxArgs jadxArgs) {
|
||||
Set<JadxSecurityFlag> flags = JadxSecurityFlag.all();
|
||||
boolean modified = false;
|
||||
boolean disableXmlSecurity = JadxCommonEnv.getBool("JADX_DISABLE_XML_SECURITY", false);
|
||||
if (disableXmlSecurity) {
|
||||
flags.remove(JadxSecurityFlag.SECURE_XML_PARSER);
|
||||
// TODO: not related to 'xml security', but kept for compatibility
|
||||
flags.remove(JadxSecurityFlag.VERIFY_APP_PACKAGE);
|
||||
modified = true;
|
||||
}
|
||||
// TODO: migrate 'ZipSecurity'
|
||||
if (modified) {
|
||||
jadxArgs.setSecurity(new JadxSecurity(flags));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkForErrors(JadxDecompiler jadx) {
|
||||
if (jadx.getRoot().getClasses().isEmpty()) {
|
||||
if (jadx.getArgs().isSkipResources()) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -18,8 +17,10 @@ import org.slf4j.LoggerFactory;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.android.TextResMapFile;
|
||||
import jadx.core.utils.files.ZipFile;
|
||||
import jadx.core.xmlgen.ResTableBinaryParser;
|
||||
import jadx.zip.IZipEntry;
|
||||
import jadx.zip.ZipContent;
|
||||
import jadx.zip.ZipReader;
|
||||
|
||||
import static jadx.core.utils.files.FileUtils.expandDirs;
|
||||
|
||||
@@ -53,18 +54,19 @@ public class ConvertArscFile {
|
||||
LOG.info("Input entries count: {}", resMap.size());
|
||||
|
||||
RootNode root = new RootNode(new JadxArgs()); // not really needed
|
||||
ZipReader zipReader = new ZipReader();
|
||||
rewritesCount = 0;
|
||||
for (Path resFile : inputResFiles) {
|
||||
ResTableBinaryParser resTableParser = new ResTableBinaryParser(root, true);
|
||||
if (resFile.getFileName().toString().endsWith(".jar")) {
|
||||
// Load resources.arsc from android.jar
|
||||
try (ZipFile zip = new ZipFile(resFile.toFile())) {
|
||||
ZipEntry entry = zip.getEntry("resources.arsc");
|
||||
try (ZipContent zip = zipReader.open(resFile.toFile())) {
|
||||
IZipEntry entry = zip.searchEntry("resources.arsc");
|
||||
if (entry == null) {
|
||||
LOG.error("Failed to load \"resources.arsc\" from {}", resFile);
|
||||
continue;
|
||||
}
|
||||
try (InputStream inputStream = zip.getInputStream(entry)) {
|
||||
try (InputStream inputStream = entry.getInputStream()) {
|
||||
resTableParser.decode(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user