From 444ea9ec7e5c28a30fe46f93afbe619436321c4e Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 10 Aug 2020 12:20:42 +0100 Subject: [PATCH] fix: load .class files --- .../src/test/java/jadx/cli/TestInput.java | 5 + .../test/resources/samples/HelloWorld.class | Bin 0 -> 426 bytes .../java/jadx/api/impl/InMemoryCodeCache.java | 5 + .../java/jadx/api/impl/NoOpCodeCache.java | 5 + jadx-plugins/jadx-java-convert/build.gradle | 2 + .../input/javaconvert/JavaConvertLoader.java | 98 +++++++++++++++--- 6 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 jadx-cli/src/test/resources/samples/HelloWorld.class diff --git a/jadx-cli/src/test/java/jadx/cli/TestInput.java b/jadx-cli/src/test/java/jadx/cli/TestInput.java index 3289dbd1b..de0a439b1 100644 --- a/jadx-cli/src/test/java/jadx/cli/TestInput.java +++ b/jadx-cli/src/test/java/jadx/cli/TestInput.java @@ -33,6 +33,11 @@ public class TestInput { decompile("smali", "samples/HelloWorld.smali"); } + @Test + public void testClassInput() throws Exception { + decompile("class", "samples/HelloWorld.class"); + } + private void decompile(String tmpDirName, String inputSample) throws URISyntaxException, IOException { StringBuilder args = new StringBuilder(); Path tempDir = FileUtils.createTempDir(tmpDirName); diff --git a/jadx-cli/src/test/resources/samples/HelloWorld.class b/jadx-cli/src/test/resources/samples/HelloWorld.class new file mode 100644 index 0000000000000000000000000000000000000000..30cee9d25d74e6a88d221b02bd022303a78e8a16 GIT binary patch literal 426 zcmZvY%}T>S6otCsp+9< input) { ConvertResult result = new ConvertResult(); - for (Path path : input) { - if (isJavaFile(path)) { - try { - convert(result, path); - } catch (Exception e) { - LOG.error("Failed to convert file: " + path.toAbsolutePath(), e); - } - } - } + processJars(input, result); + processClassFiles(input, result); return result; } - private static boolean isJavaFile(Path path) { - String fileName = path.getFileName().toString(); - return fileName.endsWith(".jar") - || fileName.endsWith(".class"); + private static void processJars(List input, ConvertResult result) { + PathMatcher jarMatcher = FileSystems.getDefault().getPathMatcher("glob:**.jar"); + input.stream() + .filter(path -> Files.isRegularFile(path, LinkOption.NOFOLLOW_LINKS)) + .filter(jarMatcher::matches) + .forEach(path -> { + try { + convertJar(result, path); + } catch (Exception e) { + LOG.error("Failed to convert file: " + path.toAbsolutePath(), e); + } + }); } - private static void convert(ConvertResult result, Path path) throws Exception { + private static void processClassFiles(List input, ConvertResult result) { + PathMatcher jarMatcher = FileSystems.getDefault().getPathMatcher("glob:**.class"); + List clsFiles = input.stream() + .filter(path -> Files.isRegularFile(path, LinkOption.NOFOLLOW_LINKS)) + .filter(jarMatcher::matches) + .collect(Collectors.toList()); + if (clsFiles.isEmpty()) { + return; + } + try { + Path jarFile = Files.createTempFile("jadx-", ".jar"); + try (JarOutputStream jo = new JarOutputStream(Files.newOutputStream(jarFile))) { + for (Path file : clsFiles) { + String clsName = getNameFromClassFile(file); + if (clsName == null || !ZipSecurity.isValidZipEntryName(clsName)) { + throw new IOException("Can't read class name from file: " + file); + } + addFileToJar(jo, file, clsName + ".class"); + } + } + result.addTempPath(jarFile); + LOG.debug("Packed class files {} into jar {}", clsFiles, jarFile); + convertJar(result, jarFile); + } catch (Exception e) { + LOG.error("Error process class files", e); + } + } + + public static String getNameFromClassFile(Path file) throws IOException { + try (InputStream in = Files.newInputStream(file)) { + ClassReader classReader = new ClassReader(in); + return classReader.getClassName(); + } + } + + private static void convertJar(ConvertResult result, Path path) throws Exception { Path tempDirectory = Files.createTempDirectory("jadx-"); result.addTempPath(tempDirectory); @@ -45,10 +91,34 @@ public class JavaConvertLoader { } private static List collectFilesInDir(Path tempDirectory) throws IOException { + PathMatcher dexMatcher = FileSystems.getDefault().getPathMatcher("glob:**.dex"); try (Stream pathStream = Files.walk(tempDirectory, 1)) { return pathStream .filter(p -> Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS)) + .filter(dexMatcher::matches) .collect(Collectors.toList()); } } + + public static void addFileToJar(JarOutputStream jar, Path source, String entryName) throws IOException { + try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(source))) { + JarEntry entry = new JarEntry(entryName); + entry.setTime(Files.getLastModifiedTime(source, LinkOption.NOFOLLOW_LINKS).toMillis()); + jar.putNextEntry(entry); + + copyStream(in, jar); + jar.closeEntry(); + } + } + + public static void copyStream(InputStream input, OutputStream output) throws IOException { + byte[] buffer = new byte[8 * 1024]; + while (true) { + int count = input.read(buffer); + if (count == -1) { + break; + } + output.write(buffer, 0, count); + } + } }