Fixed subclasses in decompilers

This commit is contained in:
SuspiciousActivity committed 2021-03-12 23:04:10 +01:00
1 parent a0b955a6ae
commit b86e8658e2
8 files changed
+110 -53

No files matched your search

+20 -7
View File
@@ -15,6 +15,8 @@ import java.io.StringWriter;
import java.net.URI; import java.net.URI;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JFrame; import javax.swing.JFrame;
@@ -122,7 +124,13 @@ public class CompilationBox extends JFrame {
ClassNode node = new ClassNode(); ClassNode node = new ClassNode();
read.accept(node, 0); read.accept(node, 0);
EnumDecompiler decompiler = EnumDecompiler.BYTEEDIT; EnumDecompiler decompiler = EnumDecompiler.BYTEEDIT;
String dis = decompiler.getDecompiler().decompile(node); ClassNode mainNode = node;
Map<String, ClassNode> classNodes;
synchronized (Main.classNodes) {
classNodes = new HashMap<>(Main.classNodes);
}
classNodes.put("Compiled.class", node);
File[] files = tmpFolder.listFiles(); File[] files = tmpFolder.listFiles();
if (files != null) if (files != null)
for (File f : files) { for (File f : files) {
@@ -137,21 +145,26 @@ public class CompilationBox extends JFrame {
read = new ClassReader(baos.toByteArray()); read = new ClassReader(baos.toByteArray());
node = new ClassNode(); node = new ClassNode();
read.accept(node, 0); read.accept(node, 0);
dis += "\n" + decompiler.getDecompiler().decompile(node); classNodes.put(f.getName(), node);
} }
compSuccess.textArea.setText(dis); compSuccess.textArea
.setText(decompiler.getDecompiler().decompile(mainNode, classNodes));
compSuccess.setVisible(true); compSuccess.setVisible(true);
} catch (IOException e2) { } catch (IOException e2) {
e2.printStackTrace(); e2.printStackTrace();
} }
try {
for (File f : tmpFolder.listFiles()) {
Files.delete(f.toPath());
}
Files.delete(tmpFolder.toPath());
} catch (IOException e2) {
e2.printStackTrace();
}
}); });
} else { } else {
JOptionPane.showMessageDialog(CompilationBox.this, res, "Error!", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(CompilationBox.this, res, "Error!", JOptionPane.ERROR_MESSAGE);
} }
for (File f : tmpFolder.listFiles()) {
Files.delete(f.toPath());
}
Files.delete(tmpFolder.toPath());
} catch (IOException e1) { } catch (IOException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
+25 -6
View File
@@ -3,12 +3,18 @@ package me.ByteEdit.decompiler;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import org.benf.cfr.reader.PluginRunner; import org.benf.cfr.reader.PluginRunner;
import org.benf.cfr.reader.api.ClassFileSource; import org.benf.cfr.reader.api.ClassFileSource;
import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair;
import org.benf.cfr.reader.state.ClassFileSourceImpl;
import org.benf.cfr.reader.util.MiscConstants.Version;
import org.benf.cfr.reader.util.getopt.OptionsImpl;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
public class CFRDecompiler implements IDecompiler { public class CFRDecompiler implements IDecompiler {
@@ -68,17 +74,24 @@ public class CFRDecompiler implements IDecompiler {
options.put("sugarenums", "true"); options.put("sugarenums", "true");
options.put("tidymonitors", "true"); options.put("tidymonitors", "true");
options.put("usenametable", "true"); options.put("usenametable", "true");
try {
Field f = Version.class.getDeclaredField("version");
f.setAccessible(true);
f.set(null, "ByteEdit");
} catch (Exception ex) {
}
} }
@Override @Override
public String decompile(ClassNode cn) { public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
return doDecompilation(cn, getBytes(cn)); return doDecompilation(cn, IDecompiler.getBytes(cn), classNodes);
} }
private static String doDecompilation(ClassNode cn, byte[] b) { private static String doDecompilation(ClassNode cn, byte[] b, Map<String, ClassNode> classNodes) {
try { try {
HashMap<String, String> ops = options; HashMap<String, String> ops = options;
ClassFileSource cfs = new ClassFileSource() { ClassFileSource cfs = new ClassFileSourceImpl(new OptionsImpl(Collections.EMPTY_MAP)) {
@Override @Override
public void informAnalysisRelativePathDetail(String a, String b) { public void informAnalysisRelativePathDetail(String a, String b) {
@@ -92,10 +105,16 @@ public class CFRDecompiler implements IDecompiler {
@Override @Override
public Pair<byte[], String> getClassFileContent(String path) throws IOException { public Pair<byte[], String> getClassFileContent(String path) throws IOException {
String name = path.substring(0, path.length() - 6); String name = path.substring(0, path.length() - 6);
if (name.equals(cn.name)) { if (name.equals(cn.name))
return Pair.make(b, name); return Pair.make(b, name);
// try loading other classes from jar
ClassNode node;
synchronized (classNodes) {
node = classNodes.get(name + ".class");
} }
return null; // cfr loads unnecessary classes if (node != null)
return Pair.make(IDecompiler.getBytes(node), name);
return super.getClassFileContent(path);
} }
@Override @Override
@@ -5,6 +5,7 @@ import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.jar.Manifest; import java.util.jar.Manifest;
@@ -51,11 +52,11 @@ public class FernflowerDecompiler implements IBytecodeProvider, IResultSaver, ID
} }
@Override @Override
public String decompile(ClassNode cn) { public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
return doDecompilation(cn, getBytes(cn)); return doDecompilation(cn, IDecompiler.getBytes(cn), classNodes);
} }
public String doDecompilation(ClassNode cn, byte[] b) { public String doDecompilation(ClassNode cn, byte[] b, Map<String, ClassNode> classNodes) {
try { try {
// TODO decompile method only // TODO decompile method only
this.bytes = b; this.bytes = b;
@@ -87,7 +88,7 @@ public class FernflowerDecompiler implements IBytecodeProvider, IResultSaver, ID
sc.getDecompiledData()); sc.getDecompiledData());
sc.getUnits().put(fakePath, unit); sc.getUnits().put(fakePath, unit);
unit.addClass(cl, "none.class"); unit.addClass(cl, "none.class");
sc.getLoader().addClassLink(cn.name, new LazyLoader.Link(LazyLoader.Link.CLASS, fakePath, null)); sc.getLoader().addClassLink(cn.name, new LazyLoader.Link(LazyLoader.Link.CLASS, fakePath, cn.name));
f.decompileContext(); f.decompileContext();
return returned; return returned;
+4 -2
View File
@@ -1,13 +1,15 @@
package me.ByteEdit.decompiler; package me.ByteEdit.decompiler;
import java.util.Map;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
public interface IDecompiler { public interface IDecompiler {
String decompile(ClassNode cn); String decompile(ClassNode cn, Map<String, ClassNode> classNodes);
default byte[] getBytes(ClassNode cn) { static byte[] getBytes(ClassNode cn) {
ClassWriter classWriter = new ClassWriter(0); ClassWriter classWriter = new ClassWriter(0);
cn.accept(classWriter); cn.accept(classWriter);
return classWriter.toByteArray(); return classWriter.toByteArray();
+22 -14
View File
@@ -1,5 +1,7 @@
package me.ByteEdit.decompiler; package me.ByteEdit.decompiler;
import java.util.Map;
import org.jd.core.v1.ClassFileToJavaSourceDecompiler; import org.jd.core.v1.ClassFileToJavaSourceDecompiler;
import org.jd.core.v1.api.loader.Loader; import org.jd.core.v1.api.loader.Loader;
import org.jd.core.v1.api.loader.LoaderException; import org.jd.core.v1.api.loader.LoaderException;
@@ -7,12 +9,19 @@ import org.jd.core.v1.api.printer.Printer;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import me.ByteEdit.main.Main;
public class JDDecompiler implements Loader, Printer, IDecompiler { public class JDDecompiler implements Loader, Printer, IDecompiler {
protected static final String TAB = " ";
protected static final String NEWLINE = "\n";
protected int indentationCount = 0;
protected StringBuilder sb = new StringBuilder();
private Map<String, ClassNode> classNodes;
@Override @Override
public String decompile(ClassNode cn) { public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
this.classNodes = classNodes;
ClassFileToJavaSourceDecompiler decompiler = new ClassFileToJavaSourceDecompiler(); ClassFileToJavaSourceDecompiler decompiler = new ClassFileToJavaSourceDecompiler();
try { try {
decompiler.decompile(this, this, cn.name); decompiler.decompile(this, this, cn.name);
@@ -32,22 +41,21 @@ public class JDDecompiler implements Loader, Printer, IDecompiler {
@Override @Override
public boolean canLoad(String internalName) { public boolean canLoad(String internalName) {
return Main.classNodes.containsKey(internalName + ".class"); synchronized (classNodes) {
return classNodes.containsKey(internalName + ".class");
}
} }
@Override @Override
public byte[] load(String internalName) throws LoaderException { public byte[] load(String internalName) throws LoaderException {
ClassNode cl = Main.classNodes.get(internalName + ".class"); ClassNode node;
ClassWriter cw = new ClassWriter(0); synchronized (classNodes) {
cl.accept(cw); node = classNodes.get(internalName + ".class");
return cw.toByteArray(); }
if (node != null)
return IDecompiler.getBytes(node);
throw new LoaderException("Failed to load '" + internalName + "'");
} }
protected static final String TAB = " ";
protected static final String NEWLINE = "\n";
protected int indentationCount = 0;
protected StringBuilder sb = new StringBuilder();
@Override @Override
public String toString() { public String toString() {
@@ -3,6 +3,7 @@ package me.ByteEdit.decompiler;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Map;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
@@ -19,11 +20,11 @@ import com.strobel.decompiler.PlainTextOutput;
public class ProcyonDecompiler implements IDecompiler { public class ProcyonDecompiler implements IDecompiler {
@Override @Override
public String decompile(ClassNode cn) { public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
return doDecompilation(cn, getBytes(cn)); return doDecompilation(cn, IDecompiler.getBytes(cn), classNodes);
} }
private static String doDecompilation(ClassNode cn, byte[] b) { private static String doDecompilation(ClassNode cn, byte[] b, Map<String, ClassNode> classNodes) {
try { try {
// TODO decompile method only // TODO decompile method only
DecompilerSettings settings = new DecompilerSettings(); DecompilerSettings settings = new DecompilerSettings();
@@ -48,6 +49,16 @@ public class ProcyonDecompiler implements IDecompiler {
buffer.position(0); buffer.position(0);
return true; return true;
} }
ClassNode node;
synchronized (classNodes) {
node = classNodes.get(s + ".class");
}
if (node != null) {
byte[] data = IDecompiler.getBytes(node);
buffer.putByteArray(data, 0, data.length);
buffer.position(0);
return true;
}
return backLoader.tryLoadType(s, buffer); return backLoader.tryLoadType(s, buffer);
} }
}); });
+17 -2
View File
@@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -69,8 +71,21 @@ public class Disassembler implements IDecompiler {
.newFixedThreadPool((Runtime.getRuntime().availableProcessors() + 1) / 2); .newFixedThreadPool((Runtime.getRuntime().availableProcessors() + 1) / 2);
@Override @Override
public String decompile(ClassNode cn) { public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
return disassemble(cn); String name = cn.name;
StringBuilder dis = new StringBuilder(disassemble(cn));
synchronized (classNodes) {
for (Entry<String, ClassNode> entry : classNodes.entrySet()) {
if (entry.getKey().contains("$")) {
String[] split = entry.getKey().split("\\$");
if (split[0].equals(name)) {
dis.append('\n');
dis.append(disassemble(entry.getValue()));
}
}
}
}
return dis.toString();
} }
private static String disassemble(ClassNode classNode) { private static String disassemble(ClassNode classNode) {
+3 -15
View File
@@ -786,23 +786,11 @@ public class Main extends JFrame {
String current = currentNodeName; String current = currentNodeName;
ClassNode classNode = classNodes.get(current); ClassNode classNode = classNodes.get(current);
int prev = txtByteEditView.getCaretPosition(); int prev = txtByteEditView.getCaretPosition();
String dis = decompiler.getDecompiler().decompile(classNode); String dis = decompiler.getDecompiler().decompile(classNode, Main.classNodes);
String substr = current.substring(0, current.length() - 6);
synchronized (Main.classNodes) {
for (Entry<String, ClassNode> entry : Main.classNodes.entrySet()) {
if (entry.getKey().contains("$")) {
String[] split = entry.getKey().split("\\$");
if (split[0].equals(substr)) {
dis += "\n" + decompiler.getDecompiler().decompile(entry.getValue());
}
}
}
}
String fdis = dis;
EventQueue.invokeAndWait(() -> { EventQueue.invokeAndWait(() -> {
synchronized (treeLock) { synchronized (treeLock) {
txtByteEditView.setText(fdis); txtByteEditView.setText(dis);
if (fdis.length() > prev) if (dis.length() > prev)
txtByteEditView.setCaretPosition(prev); txtByteEditView.setCaretPosition(prev);
} }
}); });