mirror of
https://github.com/SuspiciousActivity/ByteEdit.git
synced 2026-08-13 17:56:17 +00:00
Fixed subclasses in decompilers
This commit is contained in:
1 parent
a0b955a6ae
commit
b86e8658e2
8 files changed
+110
-53
No files matched your search
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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,23 +41,22 @@ 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() {
|
||||||
return sb.toString();
|
return sb.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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user