mirror of
https://github.com/SuspiciousActivity/ByteEdit.git
synced 2026-08-13 17:56:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a73814a81 | ||
|
|
08af91a3f7 | ||
|
|
ad975e67db | ||
|
|
4beaab1283 | ||
|
|
cfa278cd3b | ||
|
|
46c0596768 | ||
|
|
74e9491fcf | ||
|
|
198c76823b | ||
|
|
1c6a72d951 | ||
|
|
ed9b6a177b | ||
|
|
a9612c058c | ||
|
|
b86e8658e2 |
No files matched your search
@@ -15,6 +15,8 @@ import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
@@ -122,7 +124,13 @@ public class CompilationBox extends JFrame {
|
||||
ClassNode node = new ClassNode();
|
||||
read.accept(node, 0);
|
||||
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", node);
|
||||
File[] files = tmpFolder.listFiles();
|
||||
if (files != null)
|
||||
for (File f : files) {
|
||||
@@ -137,21 +145,26 @@ public class CompilationBox extends JFrame {
|
||||
read = new ClassReader(baos.toByteArray());
|
||||
node = new ClassNode();
|
||||
read.accept(node, 0);
|
||||
dis += "\n" + decompiler.getDecompiler().decompile(node);
|
||||
classNodes.put(node.name, node);
|
||||
}
|
||||
compSuccess.textArea.setText(dis);
|
||||
compSuccess.textArea
|
||||
.setText(decompiler.getDecompiler().decompile(mainNode, classNodes));
|
||||
compSuccess.setVisible(true);
|
||||
} catch (IOException e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
try {
|
||||
for (File f : tmpFolder.listFiles()) {
|
||||
Files.delete(f.toPath());
|
||||
}
|
||||
Files.delete(tmpFolder.toPath());
|
||||
} catch (IOException e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
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) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -37,12 +37,10 @@ public class GlobalSearchOpenBox extends JFrame {
|
||||
JList<Info> list = new JList(model);
|
||||
list.addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
SingleThreadedExecutor.submit(() -> {
|
||||
Info val = list.getSelectedValue();
|
||||
if (val != null && !val.owner.equals(Main.currentNodeName)) {
|
||||
Main.selectFile(val.nodePath);
|
||||
}
|
||||
});
|
||||
Info val = list.getSelectedValue();
|
||||
if (!e.getValueIsAdjusting() && val != null && !val.owner.equals(Main.currentNodeName)) {
|
||||
SingleThreadedExecutor.submit(() -> Main.selectFile(val.owner + ".class"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -59,14 +57,12 @@ public class GlobalSearchOpenBox extends JFrame {
|
||||
String name;
|
||||
String desc;
|
||||
MethodNode mn;
|
||||
String nodePath;
|
||||
|
||||
public Info(String owner, String name, String desc, MethodNode mn) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
this.mn = mn;
|
||||
nodePath = Main.getFullName(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -79,7 +79,7 @@ public class RenameBox extends JFrame {
|
||||
JOptionPane.showMessageDialog(null, "Desc not set!", "Error!", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
ClassNode clazz = Main.classNodes.get(Main.getFullName(className));
|
||||
ClassNode clazz = Main.classNodes.get(className);
|
||||
if (clazz == null) {
|
||||
JOptionPane.showMessageDialog(null, "ClassNode not found!", "Error!", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
@@ -94,7 +94,7 @@ public class RenameBox extends JFrame {
|
||||
if (newDesc.startsWith("(")) { // method
|
||||
ClassNode lastHit = clazz;
|
||||
while (clazz != null && clazz.superName != null) {
|
||||
ClassNode tmp = Main.classNodes.get(Main.getFullName(clazz.superName));
|
||||
ClassNode tmp = Main.classNodes.get(clazz.superName);
|
||||
if (tmp != null) {
|
||||
boolean found = false;
|
||||
for (MethodNode mn : clazz.methods) {
|
||||
@@ -127,7 +127,7 @@ public class RenameBox extends JFrame {
|
||||
extendsMyClass = true;
|
||||
break;
|
||||
}
|
||||
ClassNode tmp = Main.classNodes.get(Main.getFullName(checkCN.superName));
|
||||
ClassNode tmp = Main.classNodes.get(checkCN.superName);
|
||||
if (tmp != null) {
|
||||
checkCN = tmp;
|
||||
} else {
|
||||
|
||||
@@ -43,8 +43,8 @@ public class TypeOpenBox extends JFrame {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
String val = list.getSelectedValue();
|
||||
if (val != null && !val.equals(Main.currentNodeName)) {
|
||||
SingleThreadedExecutor.submit(() -> Main.selectFile(val));
|
||||
if (!e.getValueIsAdjusting() && val != null && !val.equals(Main.currentNodeName)) {
|
||||
SingleThreadedExecutor.submit(() -> Main.selectFile(val + ".class"));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -79,19 +79,17 @@ public class TypeOpenBox extends JFrame {
|
||||
}
|
||||
String search = UnicodeUtils.unescape(null, txtSearch.getText(), true).toLowerCase();
|
||||
if (search.contains("/")) {
|
||||
for (String s : Main.classNodes.keySet()) {
|
||||
String className = s.substring(0, s.length() - 6);
|
||||
if (!className.contains("$") && className.toLowerCase().startsWith(search)) {
|
||||
model.addElement(s);
|
||||
for (String fullName : Main.classNodes.keySet()) {
|
||||
if (!fullName.contains("$") && fullName.toLowerCase().startsWith(search)) {
|
||||
model.addElement(fullName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (String s : Main.classNodes.keySet()) {
|
||||
String[] split = s.split("/");
|
||||
for (String fullName : Main.classNodes.keySet()) {
|
||||
String[] split = fullName.split("/");
|
||||
String className = split[split.length - 1];
|
||||
className = className.substring(0, className.length() - 6);
|
||||
if (!className.contains("$") && className.toLowerCase().startsWith(search)) {
|
||||
model.addElement(s);
|
||||
model.addElement(fullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,18 @@ package me.ByteEdit.decompiler;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.benf.cfr.reader.PluginRunner;
|
||||
import org.benf.cfr.reader.api.ClassFileSource;
|
||||
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;
|
||||
|
||||
public class CFRDecompiler implements IDecompiler {
|
||||
@@ -68,17 +74,24 @@ public class CFRDecompiler implements IDecompiler {
|
||||
options.put("sugarenums", "true");
|
||||
options.put("tidymonitors", "true");
|
||||
options.put("usenametable", "true");
|
||||
|
||||
try {
|
||||
Field f = Version.class.getDeclaredField("version");
|
||||
f.setAccessible(true);
|
||||
f.set(null, "ByteEdit");
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decompile(ClassNode cn) {
|
||||
return doDecompilation(cn, getBytes(cn));
|
||||
public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
|
||||
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 {
|
||||
HashMap<String, String> ops = options;
|
||||
ClassFileSource cfs = new ClassFileSource() {
|
||||
ClassFileSource cfs = new ClassFileSourceImpl(new OptionsImpl(Collections.EMPTY_MAP)) {
|
||||
|
||||
@Override
|
||||
public void informAnalysisRelativePathDetail(String a, String b) {
|
||||
@@ -92,10 +105,16 @@ public class CFRDecompiler implements IDecompiler {
|
||||
@Override
|
||||
public Pair<byte[], String> getClassFileContent(String path) throws IOException {
|
||||
String name = path.substring(0, path.length() - 6);
|
||||
if (name.equals(cn.name)) {
|
||||
if (name.equals(cn.name))
|
||||
return Pair.make(b, name);
|
||||
// try loading other classes from jar
|
||||
ClassNode node;
|
||||
synchronized (classNodes) {
|
||||
node = classNodes.get(name);
|
||||
}
|
||||
return null; // cfr loads unnecessary classes
|
||||
if (node != null)
|
||||
return Pair.make(IDecompiler.getBytes(node), name);
|
||||
return super.getClassFileContent(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,8 +6,7 @@ import me.ByteEdit.edit.Disassembler;
|
||||
|
||||
public enum EnumDecompiler {
|
||||
BYTEEDIT("ByteEdit", new Disassembler(), false), PROCYON("Procyon", new ProcyonDecompiler()),
|
||||
FERNFLOWER("FernFlower", new FernflowerDecompiler()), JD_GUI("JD-GUI", new JDDecompiler()),
|
||||
CFR("CFR", new CFRDecompiler());
|
||||
JD_GUI("JD-GUI", new JDDecompiler()), CFR("CFR", new CFRDecompiler());
|
||||
|
||||
private final String name;
|
||||
private final IDecompiler decompiler;
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
package me.ByteEdit.decompiler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.Fernflower;
|
||||
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
|
||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
|
||||
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
|
||||
import org.jetbrains.java.decompiler.struct.ContextUnit;
|
||||
import org.jetbrains.java.decompiler.struct.StructClass;
|
||||
import org.jetbrains.java.decompiler.struct.StructContext;
|
||||
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
public class FernflowerDecompiler implements IBytecodeProvider, IResultSaver, IDecompiler {
|
||||
|
||||
private byte[] bytes;
|
||||
private String returned;
|
||||
|
||||
public static final HashMap<String, Boolean> options = new HashMap<>();
|
||||
|
||||
static {
|
||||
options.put("rbr", true);
|
||||
options.put("rsy", false);
|
||||
options.put("din", true);
|
||||
options.put("dc4", true);
|
||||
options.put("das", true);
|
||||
options.put("hes", true);
|
||||
options.put("hdc", true);
|
||||
options.put("dgs", false);
|
||||
options.put("ner", true);
|
||||
options.put("den", true);
|
||||
options.put("rgn", true);
|
||||
options.put("lit", false);
|
||||
options.put("asc", true);
|
||||
options.put("bto", true);
|
||||
options.put("nns", false);
|
||||
options.put("uto", true);
|
||||
options.put("udv", true);
|
||||
options.put("rer", true);
|
||||
options.put("fdi", true);
|
||||
options.put("ren", false);
|
||||
options.put("inn", true);
|
||||
options.put("lac", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decompile(ClassNode cn) {
|
||||
return doDecompilation(cn, getBytes(cn));
|
||||
}
|
||||
|
||||
public String doDecompilation(ClassNode cn, byte[] b) {
|
||||
try {
|
||||
// TODO decompile method only
|
||||
this.bytes = b;
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
for (Entry<String, Boolean> entry : options.entrySet()) {
|
||||
map.put(entry.getKey(), entry.getValue() ? "1" : "0");
|
||||
}
|
||||
map.put("ind", " ");
|
||||
Fernflower f = new Fernflower(this, this, map, new IFernflowerLogger() {
|
||||
@Override
|
||||
public void writeMessage(String message, Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeMessage(String message, Severity severity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(Severity severity) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
StructContext sc = f.getStructContext();
|
||||
StructClass cl = new StructClass(b, true, sc.getLoader());
|
||||
sc.getClasses().put(cn.name, cl);
|
||||
// instead of loading a file use custom bridge, created a few getters
|
||||
String fakePath = new File("none.class").getAbsolutePath();
|
||||
ContextUnit unit = new ContextUnit(ContextUnit.TYPE_FOLDER, null, fakePath, true, sc.getSaver(),
|
||||
sc.getDecompiledData());
|
||||
sc.getUnits().put(fakePath, unit);
|
||||
unit.addClass(cl, "none.class");
|
||||
sc.getLoader().addClassLink(cn.name, new LazyLoader.Link(LazyLoader.Link.CLASS, fakePath, null));
|
||||
|
||||
f.decompileContext();
|
||||
return returned;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
e.printStackTrace(pw);
|
||||
return sw.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytecode(String externalPath, String internalPath) throws IOException {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// we can ignore most of those methods because we do not want to save the output
|
||||
// as a file
|
||||
@Override
|
||||
public void saveFolder(String path) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyFile(String source, String path, String entryName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) {
|
||||
this.returned = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createArchive(String path, String archiveName, Manifest manifest) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveDirEntry(String path, String archiveName, String entryName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyEntry(String source, String path, String archiveName, String entry) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName,
|
||||
String content) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeArchive(String path, String archiveName) {
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
package me.ByteEdit.decompiler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
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);
|
||||
cn.accept(classWriter);
|
||||
return classWriter.toByteArray();
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
package me.ByteEdit.decompiler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jd.core.v1.ClassFileToJavaSourceDecompiler;
|
||||
import org.jd.core.v1.api.loader.Loader;
|
||||
import org.jd.core.v1.api.loader.LoaderException;
|
||||
import org.jd.core.v1.api.printer.Printer;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import me.ByteEdit.main.Main;
|
||||
|
||||
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
|
||||
public String decompile(ClassNode cn) {
|
||||
public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
|
||||
this.classNodes = classNodes;
|
||||
ClassFileToJavaSourceDecompiler decompiler = new ClassFileToJavaSourceDecompiler();
|
||||
try {
|
||||
decompiler.decompile(this, this, cn.name);
|
||||
@@ -32,23 +40,22 @@ public class JDDecompiler implements Loader, Printer, IDecompiler {
|
||||
|
||||
@Override
|
||||
public boolean canLoad(String internalName) {
|
||||
return Main.classNodes.containsKey(internalName + ".class");
|
||||
synchronized (classNodes) {
|
||||
return classNodes.containsKey(internalName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] load(String internalName) throws LoaderException {
|
||||
ClassNode cl = Main.classNodes.get(internalName + ".class");
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
cl.accept(cw);
|
||||
return cw.toByteArray();
|
||||
ClassNode node;
|
||||
synchronized (classNodes) {
|
||||
node = classNodes.get(internalName);
|
||||
}
|
||||
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
|
||||
public String toString() {
|
||||
return sb.toString();
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.ByteEdit.decompiler;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
@@ -19,11 +20,11 @@ import com.strobel.decompiler.PlainTextOutput;
|
||||
public class ProcyonDecompiler implements IDecompiler {
|
||||
|
||||
@Override
|
||||
public String decompile(ClassNode cn) {
|
||||
return doDecompilation(cn, getBytes(cn));
|
||||
public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
|
||||
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 {
|
||||
// TODO decompile method only
|
||||
DecompilerSettings settings = new DecompilerSettings();
|
||||
@@ -48,6 +49,16 @@ public class ProcyonDecompiler implements IDecompiler {
|
||||
buffer.position(0);
|
||||
return true;
|
||||
}
|
||||
ClassNode node;
|
||||
synchronized (classNodes) {
|
||||
node = classNodes.get(s);
|
||||
}
|
||||
if (node != null) {
|
||||
byte[] data = IDecompiler.getBytes(node);
|
||||
buffer.putByteArray(data, 0, data.length);
|
||||
buffer.position(0);
|
||||
return true;
|
||||
}
|
||||
return backLoader.tryLoadType(s, buffer);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -573,7 +574,9 @@ public class Assembler {
|
||||
String value = split2[1];
|
||||
if (value.endsWith("]"))
|
||||
value = value.substring(0, value.length() - 1);
|
||||
if (value.startsWith("{ ")) {
|
||||
if (value.equals("{ }")) {
|
||||
node.values.add(Collections.EMPTY_LIST);
|
||||
} else if (value.startsWith("{ ")) {
|
||||
String split3[] = splitWithStrings(value.substring(2, value.length() - 2));
|
||||
List<Object> list = new ArrayList<>();
|
||||
for (String rofl : split3) {
|
||||
@@ -771,14 +774,8 @@ public class Assembler {
|
||||
String str = consolidateStrings(split, 1);
|
||||
Object val;
|
||||
try {
|
||||
if (str.startsWith("Type: ")) {
|
||||
str = str.substring(8, str.length() - 2);
|
||||
String[] split2 = str.split("\n\t");
|
||||
String type = split2[0].substring(7);
|
||||
// Reflection
|
||||
val = new Type(ClassUtil.getIDFromClassNameForType(type),
|
||||
UnicodeUtils.unescape(hsr, split2[3].substring(6, split2[3].length() - 1)),
|
||||
Integer.parseInt(split2[1].substring(7)), Integer.parseInt(split2[2].substring(5)));
|
||||
if (str.startsWith("Type ")) {
|
||||
val = Type.getType(UnicodeUtils.unescape(hsr, str.substring(6, str.length() - 1), true));
|
||||
} else if (str.startsWith("\"") && str.endsWith("\"")) {
|
||||
val = UnicodeUtils.unescape(hsr, str.substring(1, str.length() - 1), true);
|
||||
} else if (str.startsWith("#")) {
|
||||
@@ -1456,17 +1453,7 @@ public class Assembler {
|
||||
for (int i = 10; i < sp.length - 1; i++) {
|
||||
String st = sp[i].substring(1);
|
||||
if (st.equals("]")) {
|
||||
if (stage == 1) {
|
||||
try {
|
||||
// Reflection
|
||||
args.add(new Type(ClassUtil.getIDFromClassNameForType(vals.get(0).substring(6)),
|
||||
UnicodeUtils.unescape(hsr, vals.get(3).substring(6, vals.get(3).length() - 1)),
|
||||
Integer.parseInt(vals.get(1).substring(7)),
|
||||
Integer.parseInt(vals.get(2).substring(5))));
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
} else if (stage == 2) {
|
||||
if (stage == 2) {
|
||||
args.add(new Handle(OpcodesReverse.getHandleOpcode(vals.get(4).substring(5)),
|
||||
UnicodeUtils.unescape(hsr, vals.get(1).substring(7)),
|
||||
UnicodeUtils.unescape(hsr, vals.get(0).substring(6)),
|
||||
@@ -1475,11 +1462,8 @@ public class Assembler {
|
||||
vals.clear();
|
||||
}
|
||||
stage = 0;
|
||||
} else if (st.equals("Type: [")) {
|
||||
stage = 1;
|
||||
} else if (stage == 1) {
|
||||
st = st.substring(1);
|
||||
vals.add(st);
|
||||
} else if (st.startsWith("Type ")) {
|
||||
args.add(Type.getType(UnicodeUtils.unescape(hsr, st.substring(6, st.length() - 1), true)));
|
||||
} else if (st.equals("Handle: [")) {
|
||||
vals.clear();
|
||||
stage = 2;
|
||||
|
||||
@@ -21,6 +21,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -69,8 +71,21 @@ public class Disassembler implements IDecompiler {
|
||||
.newFixedThreadPool((Runtime.getRuntime().availableProcessors() + 1) / 2);
|
||||
|
||||
@Override
|
||||
public String decompile(ClassNode cn) {
|
||||
return disassemble(cn);
|
||||
public String decompile(ClassNode cn, Map<String, ClassNode> classNodes) {
|
||||
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) {
|
||||
@@ -187,8 +202,12 @@ public class Disassembler implements IDecompiler {
|
||||
}
|
||||
s += ", ";
|
||||
}
|
||||
s = s.substring(0, s.length() - 2);
|
||||
s += " }], ";
|
||||
if (s.endsWith(", ")) {
|
||||
s = s.substring(0, s.length() - 2);
|
||||
s += " }], ";
|
||||
} else {
|
||||
s += "}], ";
|
||||
}
|
||||
} else if (o instanceof String) {
|
||||
s += "\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"], ";
|
||||
} else {
|
||||
@@ -292,6 +311,7 @@ public class Disassembler implements IDecompiler {
|
||||
|
||||
InsnList insnList = mn.instructions;
|
||||
boolean deobfNumbers = Main.INSTANCE.mntmNumbers.isSelected();
|
||||
boolean deobfNops = Main.INSTANCE.mntmNops.isSelected();
|
||||
|
||||
ArrayList<Label> labelsReversed = deobfNumbers ? new ArrayList<>() : null;
|
||||
|
||||
@@ -343,6 +363,8 @@ public class Disassembler implements IDecompiler {
|
||||
|
||||
StringContext ctx = new StringContext(insnList.size());
|
||||
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||
if (deobfNops && n.getOpcode() == Opcodes.NOP)
|
||||
continue;
|
||||
ctx.next(disassembleInstruction(n, labels, hs));
|
||||
}
|
||||
return new String[] { ctx.finish(), localVarTable, tryCatchTable };
|
||||
@@ -394,15 +416,7 @@ public class Disassembler implements IDecompiler {
|
||||
+ "\n\t\t\t]\n\t\t\targs: [\n";
|
||||
for (Object l : node.bsmArgs) {
|
||||
if (l instanceof Type) {
|
||||
Type type = (Type) l;
|
||||
int valueBegin = type.valueBegin;
|
||||
int valueEnd = type.valueEnd;
|
||||
String buf = type.valueBuffer;
|
||||
// Reflection
|
||||
s += "\t\t\t\tType: [\n\t\t\t\t\ttype: " + ClassUtil.getClassNameFromType(type)
|
||||
+ "\n\t\t\t\t\tstart: " + valueBegin + "\n\t\t\t\t\tend: " + valueEnd + "\n\t\t\t\t\tbuf: "
|
||||
+ ClassUtil.getDecompiledValue(buf, "", hs);
|
||||
s += "\n\t\t\t\t]\n";
|
||||
s += "\t\t\t\tType " + ClassUtil.getDecompiledValue(((Type) l).getDescriptor(), "", hs) + "\n";
|
||||
} else if (l instanceof Handle) {
|
||||
Handle h = (Handle) l;
|
||||
s += "\t\t\t\tHandle: [\n\t\t\t\t\tname: "
|
||||
@@ -431,16 +445,8 @@ public class Disassembler implements IDecompiler {
|
||||
case LDC_INSN: {
|
||||
LdcInsnNode node = (LdcInsnNode) n;
|
||||
if (node.cst instanceof Type) {
|
||||
Type type = (Type) node.cst;
|
||||
int valueBegin = type.valueBegin;
|
||||
int valueEnd = type.valueEnd;
|
||||
String buf = type.valueBuffer;
|
||||
// Reflection
|
||||
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " Type: [\n\t\t\ttype: "
|
||||
+ ClassUtil.getClassNameFromType(type) + "\n\t\t\tstart: " + valueBegin + "\n\t\t\tend: "
|
||||
+ valueEnd + "\n\t\t\tbuf: " + ClassUtil.getDecompiledValue(buf, "", hs);
|
||||
s += "\n\t\t]\n";
|
||||
return s;
|
||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " Type "
|
||||
+ ClassUtil.getDecompiledValue(((Type) node.cst).getDescriptor(), "", hs) + "\n";
|
||||
}
|
||||
String decomp = ClassUtil.getDecompiledValue(node.cst, "", hs);
|
||||
if (node.cst instanceof String) {
|
||||
|
||||
@@ -580,8 +580,10 @@ public class StackBasedCalculator implements Opcodes, Runnable {
|
||||
change(node);
|
||||
return false;
|
||||
case POP2:
|
||||
stack.pop();
|
||||
stack.pop();
|
||||
Number val = stack.pop();
|
||||
if (!(val instanceof Long) && !(val instanceof Double)) {
|
||||
stack.pop();
|
||||
}
|
||||
change(node);
|
||||
return false;
|
||||
case SWAP: {
|
||||
|
||||
@@ -40,7 +40,7 @@ public class ArchiveTreeModel extends DefaultTreeModel {
|
||||
super(new ByteEditTreeNode(jar.getName().split(File.separator.equals("\\") ? "\\\\"
|
||||
: File.separator)[jar.getName().split(File.separator.equals("\\") ? "\\\\" : File.separator).length
|
||||
- 1]));
|
||||
this.newCreated = true;
|
||||
this.newCreated = false;
|
||||
this.jar = jar;
|
||||
this.classNodes = classNodes;
|
||||
this.otherFiles = otherFiles;
|
||||
@@ -61,7 +61,7 @@ public class ArchiveTreeModel extends DefaultTreeModel {
|
||||
ClassReader reader = new ClassReader(data);
|
||||
ClassNode node = new ClassNode();
|
||||
reader.accept(node, 0);
|
||||
classNodes.put(Main.getFullName(node.name), node);
|
||||
classNodes.put(node.name, node);
|
||||
|
||||
if ((next.getName().contains("/")
|
||||
? (!Main.patternSlash
|
||||
@@ -70,7 +70,7 @@ public class ArchiveTreeModel extends DefaultTreeModel {
|
||||
: (!next.getName().contains("$")))
|
||||
|| (next.getName().startsWith("$") || next.getName().contains("$$")
|
||||
|| next.getName().endsWith("$"))) {
|
||||
paths.add(Main.getFullName(node.name));
|
||||
paths.add(node.name + ".class");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
otherFiles.put(next.getName(), data);
|
||||
|
||||
@@ -89,6 +89,7 @@ import me.ByteEdit.utils.ClassUtil;
|
||||
import me.ByteEdit.utils.OpcodesReverse;
|
||||
import me.ByteEdit.utils.UnicodeUtils;
|
||||
|
||||
// ASM 9.2
|
||||
public class Main extends JFrame {
|
||||
|
||||
public static Main INSTANCE;
|
||||
@@ -142,7 +143,7 @@ public class Main extends JFrame {
|
||||
private JMenuItem rdbtnmntm10000;
|
||||
public JCheckBoxMenuItem mntmMultithreaded;
|
||||
private JMenu mnDeobfuscation;
|
||||
public JCheckBoxMenuItem mntmNumbers;
|
||||
public JCheckBoxMenuItem mntmNumbers, mntmNops;
|
||||
|
||||
public static final Object treeLock = new Object();
|
||||
|
||||
@@ -425,6 +426,9 @@ public class Main extends JFrame {
|
||||
mntmNumbers = new JCheckBoxMenuItem("Numbers");
|
||||
mnDeobfuscation.add(mntmNumbers);
|
||||
|
||||
mntmNops = new JCheckBoxMenuItem("Nops");
|
||||
mnDeobfuscation.add(mntmNops);
|
||||
|
||||
contentPane = new JPanel();
|
||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
setContentPane(contentPane);
|
||||
@@ -483,19 +487,19 @@ public class Main extends JFrame {
|
||||
String s = ((ByteEditTreeNode) tree.getSelectionPath().getLastPathComponent()).path;
|
||||
if (JOptionPane.showConfirmDialog(INSTANCE, "Do you want to delete\n\"" + s + "\"?", "Delete",
|
||||
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
|
||||
String substr = s.substring(0, s.length() - 6);
|
||||
s = s.substring(0, s.length() - 6);
|
||||
ArrayList<String> toRemove = new ArrayList<>();
|
||||
for (String key : Main.classNodes.keySet()) {
|
||||
if (key.contains("$")) {
|
||||
String[] split = key.split("\\$");
|
||||
if (split[0].equals(substr)) {
|
||||
if (split[0].equals(s)) {
|
||||
toRemove.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
ArchiveTreeModel model = (ArchiveTreeModel) tree.getModel();
|
||||
classNodes.remove(s);
|
||||
model.paths.remove(s);
|
||||
model.paths.remove(s + ".class");
|
||||
for (String rem : toRemove) {
|
||||
classNodes.remove(rem);
|
||||
}
|
||||
@@ -757,15 +761,15 @@ public class Main extends JFrame {
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
if (classNodes.replace(getFullName(node.name), node) == null) {
|
||||
classNodes.put(getFullName(node.name), node);
|
||||
if (classNodes.replace(node.name, node) == null) {
|
||||
classNodes.put(node.name, node);
|
||||
ArchiveTreeModel model;
|
||||
if (tree.getModel().getClass().equals(DefaultTreeModel.class)) {
|
||||
tree.setModel(model = new ArchiveTreeModel(classNodes, otherFiles));
|
||||
} else {
|
||||
model = (ArchiveTreeModel) tree.getModel();
|
||||
}
|
||||
String name = getFullName(node.name);
|
||||
String name = node.name + ".class";
|
||||
if (name.contains("/") ? (!name.split("/")[name.split("/").length - 1].contains("$"))
|
||||
: (!name.contains("$"))) {
|
||||
model.paths.add(name);
|
||||
@@ -786,23 +790,11 @@ public class Main extends JFrame {
|
||||
String current = currentNodeName;
|
||||
ClassNode classNode = classNodes.get(current);
|
||||
int prev = txtByteEditView.getCaretPosition();
|
||||
String dis = decompiler.getDecompiler().decompile(classNode);
|
||||
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;
|
||||
String dis = decompiler.getDecompiler().decompile(classNode, Main.classNodes);
|
||||
EventQueue.invokeAndWait(() -> {
|
||||
synchronized (treeLock) {
|
||||
txtByteEditView.setText(fdis);
|
||||
if (fdis.length() > prev)
|
||||
txtByteEditView.setText(dis);
|
||||
if (dis.length() > prev)
|
||||
txtByteEditView.setCaretPosition(prev);
|
||||
}
|
||||
});
|
||||
@@ -813,6 +805,7 @@ public class Main extends JFrame {
|
||||
|
||||
public static void selectFile(String s) {
|
||||
if (s != null && s.endsWith(".class")) {
|
||||
s = s.substring(0, s.length() - 6);
|
||||
currentNodeName = s;
|
||||
decompileCurrentNode();
|
||||
txtByteEditView.setCaretPosition(0);
|
||||
@@ -867,10 +860,8 @@ public class Main extends JFrame {
|
||||
try {
|
||||
EventQueue.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
synchronized (treeLock) {
|
||||
isChangingFile = false;
|
||||
Main.this.setTitle("ByteEdit");
|
||||
}
|
||||
isChangingFile = false;
|
||||
Main.this.setTitle("ByteEdit");
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
@@ -929,7 +920,7 @@ public class Main extends JFrame {
|
||||
for (ClassNode node : classes) {
|
||||
ClassWriter writer = new ClassWriter(computeFlags);
|
||||
node.accept(writer);
|
||||
output.putNextEntry(new ZipEntry(getFullName(node.name)));
|
||||
output.putNextEntry(new ZipEntry(node.name + ".class"));
|
||||
output.write(writer.toByteArray());
|
||||
output.closeEntry();
|
||||
}
|
||||
@@ -955,8 +946,4 @@ public class Main extends JFrame {
|
||||
public static void showError(String s) {
|
||||
JOptionPane.showMessageDialog(INSTANCE, s, "Error!", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
public static String getFullName(String s) {
|
||||
return s + ".class";
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user