fix: load files also by extension (#1391)
This commit is contained in:
+12
-7
@@ -13,9 +13,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.plugins.utils.CommonFileUtils;
|
||||
import jadx.api.plugins.utils.ZipSecurity;
|
||||
import jadx.plugins.input.dex.sections.DexConsts;
|
||||
import jadx.plugins.input.dex.utils.DexCheckSum;
|
||||
@@ -45,31 +47,34 @@ public class DexFileLoader {
|
||||
|
||||
private List<DexReader> loadDexFromFile(File file) {
|
||||
try (InputStream inputStream = new FileInputStream(file)) {
|
||||
return checkFileMagic(file, inputStream, file.getAbsolutePath());
|
||||
return load(file, inputStream, file.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
LOG.error("File open error: {}", file.getAbsolutePath(), e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private List<DexReader> checkFileMagic(File file, InputStream inputStream, String inputFileName) throws IOException {
|
||||
private List<DexReader> load(@Nullable File file, InputStream inputStream, String fileName) throws IOException {
|
||||
try (InputStream in = inputStream.markSupported() ? inputStream : new BufferedInputStream(inputStream)) {
|
||||
byte[] magic = new byte[DexConsts.MAX_MAGIC_SIZE];
|
||||
in.mark(magic.length);
|
||||
if (in.read(magic) != magic.length) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (isStartWithBytes(magic, DexConsts.DEX_FILE_MAGIC)) {
|
||||
if (isStartWithBytes(magic, DexConsts.DEX_FILE_MAGIC) || fileName.endsWith(".dex")) {
|
||||
in.reset();
|
||||
byte[] content = readAllBytes(in);
|
||||
if (options.isVerifyChecksum()) {
|
||||
DexCheckSum.verify(content);
|
||||
}
|
||||
DexReader dexReader = new DexReader(getNextUniqId(), inputFileName, content);
|
||||
DexReader dexReader = new DexReader(getNextUniqId(), fileName, content);
|
||||
return Collections.singletonList(dexReader);
|
||||
}
|
||||
if (file != null && isStartWithBytes(magic, DexConsts.ZIP_FILE_MAGIC)) {
|
||||
return collectDexFromZip(file);
|
||||
if (file != null) {
|
||||
// allow only top level zip files
|
||||
if (isStartWithBytes(magic, DexConsts.ZIP_FILE_MAGIC) || CommonFileUtils.isZipFileExt(fileName)) {
|
||||
return collectDexFromZip(file);
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -80,7 +85,7 @@ public class DexFileLoader {
|
||||
try {
|
||||
ZipSecurity.readZipEntries(file, (entry, in) -> {
|
||||
try {
|
||||
result.addAll(checkFileMagic(null, in, entry.getName()));
|
||||
result.addAll(load(null, in, entry.getName()));
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to read zip entry: {}", entry, e);
|
||||
}
|
||||
|
||||
+5
-3
@@ -52,18 +52,20 @@ public class JavaFileLoader {
|
||||
if (in.read(magic) != magic.length) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (isStartWithBytes(magic, JAVA_CLASS_FILE_MAGIC)) {
|
||||
if (isStartWithBytes(magic, JAVA_CLASS_FILE_MAGIC) || name.endsWith(".class")) {
|
||||
byte[] data = CommonFileUtils.loadBytes(magic, in);
|
||||
String source = concatSource(parentFileName, name);
|
||||
JavaClassReader reader = new JavaClassReader(getNextUniqId(), source, data);
|
||||
return Collections.singletonList(reader);
|
||||
}
|
||||
if (isStartWithBytes(magic, ZIP_FILE_MAGIC)) {
|
||||
if (isStartWithBytes(magic, ZIP_FILE_MAGIC) || CommonFileUtils.isZipFileExt(name)) {
|
||||
if (file != null) {
|
||||
return collectFromZip(file, name);
|
||||
}
|
||||
File zipFile = CommonFileUtils.saveToTempFile(magic, in, ".zip").toFile();
|
||||
return collectFromZip(zipFile, concatSource(parentFileName, name));
|
||||
List<JavaClassReader> readers = collectFromZip(zipFile, concatSource(parentFileName, name));
|
||||
CommonFileUtils.safeDeleteFile(zipFile);
|
||||
return readers;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
+35
-1
@@ -7,9 +7,15 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CommonFileUtils {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CommonFileUtils.class);
|
||||
public static final File CWD = getCWD();
|
||||
public static final Path CWD_PATH = CWD.toPath();
|
||||
|
||||
@@ -38,6 +44,15 @@ public class CommonFileUtils {
|
||||
return tempFile;
|
||||
}
|
||||
|
||||
public static boolean safeDeleteFile(File file) {
|
||||
try {
|
||||
return file.delete();
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Failed to delete file: {}", file, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] loadBytes(InputStream input) throws IOException {
|
||||
return loadBytes(null, input);
|
||||
}
|
||||
@@ -56,7 +71,7 @@ public class CommonFileUtils {
|
||||
}
|
||||
|
||||
public static void copyStream(InputStream input, OutputStream output) throws IOException {
|
||||
byte[] buffer = new byte[8 * 1024];
|
||||
byte[] buffer = new byte[8192];
|
||||
while (true) {
|
||||
int count = input.read(buffer);
|
||||
if (count == -1) {
|
||||
@@ -65,4 +80,23 @@ public class CommonFileUtils {
|
||||
output.write(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getFileExtension(String fileName) {
|
||||
int dotIndex = fileName.lastIndexOf('.');
|
||||
if (dotIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
return fileName.substring(dotIndex + 1);
|
||||
}
|
||||
|
||||
private static final Set<String> ZIP_FILE_EXTS = Utils.constSet("zip", "jar", "apk");
|
||||
|
||||
public static boolean isZipFileExt(String fileName) {
|
||||
String ext = getFileExtension(fileName);
|
||||
if (ext == null) {
|
||||
return false;
|
||||
}
|
||||
return ZIP_FILE_EXTS.contains(ext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package jadx.api.plugins.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
@@ -87,4 +89,9 @@ public class Utils {
|
||||
public static String formatOffset(int offset) {
|
||||
return String.format("0x%04x", offset);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <T> Set<T> constSet(T... arr) {
|
||||
return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(arr)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user