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 | ||
|
|
a0b955a6ae | ||
|
|
97422300c8 | ||
|
|
8832d67d8b | ||
|
|
71c224f83f | ||
|
|
71437eac81 |
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;
|
||||||
@@ -106,7 +108,7 @@ public class CompilationBox extends JFrame {
|
|||||||
null, Arrays.asList(new JavaSourceFromString("Compiled", source))).call();
|
null, Arrays.asList(new JavaSourceFromString("Compiled", source))).call();
|
||||||
String res = out.toString();
|
String res = out.toString();
|
||||||
if (res.isEmpty()) {
|
if (res.isEmpty()) {
|
||||||
SingleThreadedExecutor.execute(() -> {
|
SingleThreadedExecutor.submit(() -> {
|
||||||
try {
|
try {
|
||||||
File clazz = new File(tmpFolder, "Compiled.class");
|
File clazz = new File(tmpFolder, "Compiled.class");
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
@@ -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", node);
|
||||||
File[] files = tmpFolder.listFiles();
|
File[] files = tmpFolder.listFiles();
|
||||||
if (files != null)
|
if (files != null)
|
||||||
for (File f : files) {
|
for (File f : files) {
|
||||||
@@ -137,22 +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(node.name, 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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package me.ByteEdit.boxes;
|
package me.ByteEdit.boxes;
|
||||||
|
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -60,13 +58,7 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
contentPane.add(lblFind);
|
contentPane.add(lblFind);
|
||||||
txtString = new JTextField();
|
txtString = new JTextField();
|
||||||
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
|
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
|
||||||
txtString.registerKeyboardAction(new ActionListener() {
|
txtString.registerKeyboardAction(e -> find(), enter, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
find();
|
|
||||||
}
|
|
||||||
}, enter, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
|
||||||
txtString.setBounds(91, 22, 149, 20);
|
txtString.setBounds(91, 22, 149, 20);
|
||||||
contentPane.add(txtString);
|
contentPane.add(txtString);
|
||||||
txtString.setColumns(10);
|
txtString.setColumns(10);
|
||||||
@@ -74,12 +66,7 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
chckbxCaseSensitive.setBounds(10, 199, 114, 23);
|
chckbxCaseSensitive.setBounds(10, 199, 114, 23);
|
||||||
contentPane.add(chckbxCaseSensitive);
|
contentPane.add(chckbxCaseSensitive);
|
||||||
JButton btnFind = new JButton("Find");
|
JButton btnFind = new JButton("Find");
|
||||||
btnFind.addActionListener(new ActionListener() {
|
btnFind.addActionListener(e -> find());
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
find();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
btnFind.setBounds(130, 199, 110, 23);
|
btnFind.setBounds(130, 199, 110, 23);
|
||||||
contentPane.add(btnFind);
|
contentPane.add(btnFind);
|
||||||
|
|
||||||
@@ -92,12 +79,7 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
contentPane.add(lblOwner);
|
contentPane.add(lblOwner);
|
||||||
|
|
||||||
txtOwner = new JTextField();
|
txtOwner = new JTextField();
|
||||||
txtOwner.addActionListener(new ActionListener() {
|
txtOwner.addActionListener(e -> find());
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
find();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
txtOwner.setColumns(10);
|
txtOwner.setColumns(10);
|
||||||
txtOwner.setBounds(91, 78, 149, 20);
|
txtOwner.setBounds(91, 78, 149, 20);
|
||||||
contentPane.add(txtOwner);
|
contentPane.add(txtOwner);
|
||||||
@@ -107,12 +89,7 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
contentPane.add(lblName);
|
contentPane.add(lblName);
|
||||||
|
|
||||||
txtName = new JTextField();
|
txtName = new JTextField();
|
||||||
txtName.addActionListener(new ActionListener() {
|
txtName.addActionListener(e -> find());
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
find();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
txtName.setColumns(10);
|
txtName.setColumns(10);
|
||||||
txtName.setBounds(91, 106, 149, 20);
|
txtName.setBounds(91, 106, 149, 20);
|
||||||
contentPane.add(txtName);
|
contentPane.add(txtName);
|
||||||
@@ -122,12 +99,7 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
contentPane.add(lblDesc);
|
contentPane.add(lblDesc);
|
||||||
|
|
||||||
txtDesc = new JTextField();
|
txtDesc = new JTextField();
|
||||||
txtDesc.addActionListener(new ActionListener() {
|
txtDesc.addActionListener(e -> find());
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
find();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
txtDesc.setColumns(10);
|
txtDesc.setColumns(10);
|
||||||
txtDesc.setBounds(91, 134, 149, 20);
|
txtDesc.setBounds(91, 134, 149, 20);
|
||||||
contentPane.add(txtDesc);
|
contentPane.add(txtDesc);
|
||||||
@@ -194,9 +166,7 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Info s : set) {
|
set.forEach(openBox.model::addElement);
|
||||||
openBox.model.addElement(s);
|
|
||||||
}
|
|
||||||
openBox.setVisible(true);
|
openBox.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,12 +37,10 @@ public class GlobalSearchOpenBox extends JFrame {
|
|||||||
JList<Info> list = new JList(model);
|
JList<Info> list = new JList(model);
|
||||||
list.addListSelectionListener(new ListSelectionListener() {
|
list.addListSelectionListener(new ListSelectionListener() {
|
||||||
public void valueChanged(ListSelectionEvent e) {
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
SingleThreadedExecutor.execute(() -> {
|
Info val = list.getSelectedValue();
|
||||||
Info val = list.getSelectedValue();
|
if (!e.getValueIsAdjusting() && val != null && !val.owner.equals(Main.currentNodeName)) {
|
||||||
if (val != null && !val.owner.equals(Main.currentNodeName)) {
|
SingleThreadedExecutor.submit(() -> Main.selectFile(val.owner + ".class"));
|
||||||
Main.selectFile(val.nodePath);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -59,14 +57,12 @@ public class GlobalSearchOpenBox extends JFrame {
|
|||||||
String name;
|
String name;
|
||||||
String desc;
|
String desc;
|
||||||
MethodNode mn;
|
MethodNode mn;
|
||||||
String nodePath;
|
|
||||||
|
|
||||||
public Info(String owner, String name, String desc, MethodNode mn) {
|
public Info(String owner, String name, String desc, MethodNode mn) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
this.mn = mn;
|
this.mn = mn;
|
||||||
nodePath = Main.getFullName(owner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class RenameBox extends JFrame {
|
|||||||
JOptionPane.showMessageDialog(null, "Desc not set!", "Error!", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(null, "Desc not set!", "Error!", JOptionPane.ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ClassNode clazz = Main.classNodes.get(Main.getFullName(className));
|
ClassNode clazz = Main.classNodes.get(className);
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
JOptionPane.showMessageDialog(null, "ClassNode not found!", "Error!", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(null, "ClassNode not found!", "Error!", JOptionPane.ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
@@ -94,7 +94,7 @@ public class RenameBox extends JFrame {
|
|||||||
if (newDesc.startsWith("(")) { // method
|
if (newDesc.startsWith("(")) { // method
|
||||||
ClassNode lastHit = clazz;
|
ClassNode lastHit = clazz;
|
||||||
while (clazz != null && clazz.superName != null) {
|
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) {
|
if (tmp != null) {
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (MethodNode mn : clazz.methods) {
|
for (MethodNode mn : clazz.methods) {
|
||||||
@@ -127,7 +127,7 @@ public class RenameBox extends JFrame {
|
|||||||
extendsMyClass = true;
|
extendsMyClass = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ClassNode tmp = Main.classNodes.get(Main.getFullName(checkCN.superName));
|
ClassNode tmp = Main.classNodes.get(checkCN.superName);
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
checkCN = tmp;
|
checkCN = tmp;
|
||||||
} else {
|
} else {
|
||||||
@@ -211,7 +211,7 @@ public class RenameBox extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleThreadedExecutor.execute(() -> {
|
SingleThreadedExecutor.submit(() -> {
|
||||||
// refresh
|
// refresh
|
||||||
Main.decompileCurrentNode();
|
Main.decompileCurrentNode();
|
||||||
name = newName;
|
name = newName;
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ public class SearchBox extends JFrame {
|
|||||||
public void replace() {
|
public void replace() {
|
||||||
if (!Main.decompiler.isEditable())
|
if (!Main.decompiler.isEditable())
|
||||||
return;
|
return;
|
||||||
String txt = Main.txtByteEditView.getText();
|
|
||||||
int startPos = Main.txtByteEditView.getSelectionStart();
|
int startPos = Main.txtByteEditView.getSelectionStart();
|
||||||
Main.txtByteEditView.replaceSelection(txtReplace.getText());
|
Main.txtByteEditView.replaceSelection(txtReplace.getText());
|
||||||
Main.txtByteEditView.select(startPos, startPos + txtReplace.getText().length());
|
Main.txtByteEditView.select(startPos, startPos + txtReplace.getText().length());
|
||||||
|
|||||||
@@ -40,12 +40,11 @@ public class TypeOpenBox extends JFrame {
|
|||||||
DefaultListModel<String> model = new DefaultListModel<>();
|
DefaultListModel<String> model = new DefaultListModel<>();
|
||||||
JList<String> list = new JList(model);
|
JList<String> list = new JList(model);
|
||||||
list.addListSelectionListener(new ListSelectionListener() {
|
list.addListSelectionListener(new ListSelectionListener() {
|
||||||
|
@Override
|
||||||
public void valueChanged(ListSelectionEvent e) {
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
String val = list.getSelectedValue();
|
String val = list.getSelectedValue();
|
||||||
if (val != null && !val.equals(Main.currentNodeName)) {
|
if (!e.getValueIsAdjusting() && val != null && !val.equals(Main.currentNodeName)) {
|
||||||
|
SingleThreadedExecutor.submit(() -> Main.selectFile(val + ".class"));
|
||||||
SingleThreadedExecutor.execute(() -> Main.selectFile(val));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -80,19 +79,17 @@ public class TypeOpenBox extends JFrame {
|
|||||||
}
|
}
|
||||||
String search = UnicodeUtils.unescape(null, txtSearch.getText(), true).toLowerCase();
|
String search = UnicodeUtils.unescape(null, txtSearch.getText(), true).toLowerCase();
|
||||||
if (search.contains("/")) {
|
if (search.contains("/")) {
|
||||||
for (String s : Main.classNodes.keySet()) {
|
for (String fullName : Main.classNodes.keySet()) {
|
||||||
String className = s.substring(0, s.length() - 6);
|
if (!fullName.contains("$") && fullName.toLowerCase().startsWith(search)) {
|
||||||
if (!className.contains("$") && className.toLowerCase().startsWith(search)) {
|
model.addElement(fullName);
|
||||||
model.addElement(s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (String s : Main.classNodes.keySet()) {
|
for (String fullName : Main.classNodes.keySet()) {
|
||||||
String[] split = s.split("/");
|
String[] split = fullName.split("/");
|
||||||
String className = split[split.length - 1];
|
String className = split[split.length - 1];
|
||||||
className = className.substring(0, className.length() - 6);
|
|
||||||
if (!className.contains("$") && className.toLowerCase().startsWith(search)) {
|
if (!className.contains("$") && className.toLowerCase().startsWith(search)) {
|
||||||
model.addElement(s);
|
model.addElement(fullName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,22 +5,17 @@ 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.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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.entities.ClassFile;
|
|
||||||
import org.benf.cfr.reader.entities.Method;
|
|
||||||
import org.benf.cfr.reader.entities.constantpool.ConstantPool;
|
|
||||||
import org.benf.cfr.reader.state.ClassFileSourceImpl;
|
import org.benf.cfr.reader.state.ClassFileSourceImpl;
|
||||||
import org.benf.cfr.reader.state.DCCommonState;
|
import org.benf.cfr.reader.util.MiscConstants.Version;
|
||||||
import org.benf.cfr.reader.util.bytestream.BaseByteData;
|
|
||||||
import org.benf.cfr.reader.util.getopt.OptionsImpl;
|
import org.benf.cfr.reader.util.getopt.OptionsImpl;
|
||||||
import org.benf.cfr.reader.util.output.ToStringDumper;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import org.objectweb.asm.tree.MethodNode;
|
|
||||||
|
|
||||||
public class CFRDecompiler implements IDecompiler {
|
public class CFRDecompiler implements IDecompiler {
|
||||||
|
|
||||||
@@ -79,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), null);
|
return doDecompilation(cn, IDecompiler.getBytes(cn), classNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String doDecompilation(ClassNode cn, byte[] b, MethodNode mn) {
|
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) {
|
||||||
@@ -103,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);
|
||||||
}
|
}
|
||||||
return null; // cfr loads unnecessary classes
|
if (node != null)
|
||||||
|
return Pair.make(IDecompiler.getBytes(node), name);
|
||||||
|
return super.getClassFileContent(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -114,24 +122,7 @@ public class CFRDecompiler implements IDecompiler {
|
|||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PluginRunner runner = new PluginRunner(ops, cfs);
|
String decompilation = new PluginRunner(ops, cfs).getDecompilationFor(cn.name);
|
||||||
if (mn != null) {
|
|
||||||
BaseByteData data = new BaseByteData(b);
|
|
||||||
ClassFile cf = new ClassFile(data, "", initDCState(ops, cfs));
|
|
||||||
Field cpf = Method.class.getDeclaredField("cp");
|
|
||||||
Field descI = Method.class.getDeclaredField("descriptorIndex");
|
|
||||||
descI.setAccessible(true);
|
|
||||||
cpf.setAccessible(true);
|
|
||||||
for (Method m : cf.getMethodByName(mn.name)) {
|
|
||||||
ConstantPool cp = (ConstantPool) cpf.get(m);
|
|
||||||
if (cp.getUTF8Entry(descI.getInt(m)).getValue().equals(mn.desc)) {
|
|
||||||
ToStringDumper tsd = new ToStringDumper();
|
|
||||||
m.dump(tsd, true);
|
|
||||||
return tsd.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String decompilation = runner.getDecompilationFor(cn.name);
|
|
||||||
System.gc(); // cfr has a performance bug
|
System.gc(); // cfr has a performance bug
|
||||||
return decompilation;
|
return decompilation;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -142,12 +133,4 @@ public class CFRDecompiler implements IDecompiler {
|
|||||||
return sw.toString();
|
return sw.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DCCommonState initDCState(Map<String, String> optionsMap, ClassFileSource classFileSource) {
|
|
||||||
OptionsImpl options = new OptionsImpl(optionsMap);
|
|
||||||
if (classFileSource == null)
|
|
||||||
classFileSource = new ClassFileSourceImpl(options);
|
|
||||||
DCCommonState dcCommonState = new DCCommonState(options, classFileSource);
|
|
||||||
return dcCommonState;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,7 @@ import me.ByteEdit.edit.Disassembler;
|
|||||||
|
|
||||||
public enum EnumDecompiler {
|
public enum EnumDecompiler {
|
||||||
BYTEEDIT("ByteEdit", new Disassembler(), false), PROCYON("Procyon", new ProcyonDecompiler()),
|
BYTEEDIT("ByteEdit", new Disassembler(), false), PROCYON("Procyon", new ProcyonDecompiler()),
|
||||||
FERNFLOWER("FernFlower", new FernflowerDecompiler()), JD_GUI("JD-GUI", new JDDecompiler()),
|
JD_GUI("JD-GUI", new JDDecompiler()), CFR("CFR", new CFRDecompiler());
|
||||||
CFR("CFR", new CFRDecompiler());
|
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final IDecompiler decompiler;
|
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;
|
|
||||||
import org.objectweb.asm.tree.MethodNode;
|
|
||||||
|
|
||||||
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), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String doDecompilation(ClassNode cn, byte[] b, MethodNode mn) {
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
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;
|
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,18 +1,26 @@
|
|||||||
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;
|
||||||
import org.jd.core.v1.api.printer.Printer;
|
import org.jd.core.v1.api.printer.Printer;
|
||||||
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 +40,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
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,9 +3,9 @@ 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;
|
||||||
import org.objectweb.asm.tree.MethodNode;
|
|
||||||
|
|
||||||
import com.strobel.assembler.InputTypeLoader;
|
import com.strobel.assembler.InputTypeLoader;
|
||||||
import com.strobel.assembler.metadata.Buffer;
|
import com.strobel.assembler.metadata.Buffer;
|
||||||
@@ -20,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), null);
|
return doDecompilation(cn, IDecompiler.getBytes(cn), classNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String doDecompilation(ClassNode cn, byte[] b, MethodNode mn) {
|
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,9 +48,18 @@ public class ProcyonDecompiler implements IDecompiler {
|
|||||||
buffer.putByteArray(b, 0, b.length);
|
buffer.putByteArray(b, 0, b.length);
|
||||||
buffer.position(0);
|
buffer.position(0);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
return backLoader.tryLoadType(s, buffer);
|
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
TypeReference type = metadataSystem.lookupType(cn.name);
|
TypeReference type = metadataSystem.lookupType(cn.name);
|
||||||
|
|||||||
@@ -4,15 +4,29 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
|
|
||||||
public class SingleThreadedExecutor {
|
public class SingleThreadedExecutor {
|
||||||
|
|
||||||
|
// We don't need to run every Runnable,
|
||||||
|
// we only care about the last submitted Runnable.
|
||||||
|
private static final Object lock = new Object();
|
||||||
|
private static Runnable runnable;
|
||||||
private static final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
private static final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
private static final Thread thread = new Thread(() -> {
|
private static final Thread thread = new Thread(() -> {
|
||||||
while (true) {
|
try {
|
||||||
try {
|
while (true) {
|
||||||
queue.take().run();
|
Runnable r = null;
|
||||||
} catch (Throwable e) {
|
synchronized (lock) {
|
||||||
e.printStackTrace();
|
while (runnable == null)
|
||||||
|
lock.wait();
|
||||||
|
r = runnable;
|
||||||
|
runnable = null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
r.run();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
}, "SingleThreadedExecutor");
|
}, "SingleThreadedExecutor");
|
||||||
|
|
||||||
@@ -21,7 +35,10 @@ public class SingleThreadedExecutor {
|
|||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void execute(Runnable r) {
|
public static void submit(Runnable r) {
|
||||||
queue.add(r);
|
synchronized (lock) {
|
||||||
|
runnable = r;
|
||||||
|
lock.notifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import java.io.BufferedReader;
|
|||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -339,6 +340,8 @@ public class Assembler {
|
|||||||
tryCatchBlocksToParse.clear();
|
tryCatchBlocksToParse.clear();
|
||||||
stage = 0;
|
stage = 0;
|
||||||
} else if (s.startsWith("// #Signature: ")) {
|
} else if (s.startsWith("// #Signature: ")) {
|
||||||
|
if (node == null)
|
||||||
|
throw new IllegalStateException("node is null");
|
||||||
node.signature = UnicodeUtils.unescape(hsr, s.substring(15));
|
node.signature = UnicodeUtils.unescape(hsr, s.substring(15));
|
||||||
} else if (s.equals("// #TryCatch:")) {
|
} else if (s.equals("// #TryCatch:")) {
|
||||||
stage = 1;
|
stage = 1;
|
||||||
@@ -352,6 +355,8 @@ public class Assembler {
|
|||||||
localVarsToParse.add(s);
|
localVarsToParse.add(s);
|
||||||
}
|
}
|
||||||
} else if (s.equals("}")) {
|
} else if (s.equals("}")) {
|
||||||
|
if (node == null)
|
||||||
|
throw new IllegalStateException("node is null");
|
||||||
if (!annotationsForNext.isEmpty()) {
|
if (!annotationsForNext.isEmpty()) {
|
||||||
if (node.visibleAnnotations == null) {
|
if (node.visibleAnnotations == null) {
|
||||||
node.visibleAnnotations = new ArrayList<>();
|
node.visibleAnnotations = new ArrayList<>();
|
||||||
@@ -404,6 +409,8 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
clazz.methods.add(node);
|
clazz.methods.add(node);
|
||||||
} else if (!s.startsWith("\t")) {
|
} else if (!s.startsWith("\t")) {
|
||||||
|
if (node == null)
|
||||||
|
throw new IllegalStateException("node is null");
|
||||||
s = s.substring(0, s.length() - 2);
|
s = s.substring(0, s.length() - 2);
|
||||||
if (s.contains(" throws ")) {
|
if (s.contains(" throws ")) {
|
||||||
String exceptions = s.substring(s.lastIndexOf(" throws ") + 8);
|
String exceptions = s.substring(s.lastIndexOf(" throws ") + 8);
|
||||||
@@ -477,6 +484,8 @@ public class Assembler {
|
|||||||
s = s.substring(1);
|
s = s.substring(1);
|
||||||
if (!temp.isEmpty()) {
|
if (!temp.isEmpty()) {
|
||||||
if (s.equals("]")) {
|
if (s.equals("]")) {
|
||||||
|
if (node == null)
|
||||||
|
throw new IllegalStateException("node is null");
|
||||||
temp += s;
|
temp += s;
|
||||||
node.instructions.add(getNode(hsr, temp, methodLabelMap));
|
node.instructions.add(getNode(hsr, temp, methodLabelMap));
|
||||||
temp = "";
|
temp = "";
|
||||||
@@ -487,6 +496,8 @@ public class Assembler {
|
|||||||
if (s.endsWith("[")) {
|
if (s.endsWith("[")) {
|
||||||
temp += s + "\n";
|
temp += s + "\n";
|
||||||
} else {
|
} else {
|
||||||
|
if (node == null)
|
||||||
|
throw new IllegalStateException("node is null");
|
||||||
node.instructions.add(getNode(hsr, s, methodLabelMap));
|
node.instructions.add(getNode(hsr, s, methodLabelMap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,7 +519,8 @@ public class Assembler {
|
|||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
read.close();
|
if (read != null)
|
||||||
|
read.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,7 +574,9 @@ public class Assembler {
|
|||||||
String value = split2[1];
|
String value = split2[1];
|
||||||
if (value.endsWith("]"))
|
if (value.endsWith("]"))
|
||||||
value = value.substring(0, value.length() - 1);
|
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));
|
String split3[] = splitWithStrings(value.substring(2, value.length() - 2));
|
||||||
List<Object> list = new ArrayList<>();
|
List<Object> list = new ArrayList<>();
|
||||||
for (String rofl : split3) {
|
for (String rofl : split3) {
|
||||||
@@ -760,14 +774,8 @@ public class Assembler {
|
|||||||
String str = consolidateStrings(split, 1);
|
String str = consolidateStrings(split, 1);
|
||||||
Object val;
|
Object val;
|
||||||
try {
|
try {
|
||||||
if (str.startsWith("Type: ")) {
|
if (str.startsWith("Type ")) {
|
||||||
str = str.substring(8, str.length() - 2);
|
val = Type.getType(UnicodeUtils.unescape(hsr, str.substring(6, str.length() - 1), true));
|
||||||
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)));
|
|
||||||
} else if (str.startsWith("\"") && str.endsWith("\"")) {
|
} else if (str.startsWith("\"") && str.endsWith("\"")) {
|
||||||
val = UnicodeUtils.unescape(hsr, str.substring(1, str.length() - 1), true);
|
val = UnicodeUtils.unescape(hsr, str.substring(1, str.length() - 1), true);
|
||||||
} else if (str.startsWith("#")) {
|
} else if (str.startsWith("#")) {
|
||||||
@@ -1445,17 +1453,7 @@ public class Assembler {
|
|||||||
for (int i = 10; i < sp.length - 1; i++) {
|
for (int i = 10; i < sp.length - 1; i++) {
|
||||||
String st = sp[i].substring(1);
|
String st = sp[i].substring(1);
|
||||||
if (st.equals("]")) {
|
if (st.equals("]")) {
|
||||||
if (stage == 1) {
|
if (stage == 2) {
|
||||||
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) {
|
|
||||||
args.add(new Handle(OpcodesReverse.getHandleOpcode(vals.get(4).substring(5)),
|
args.add(new Handle(OpcodesReverse.getHandleOpcode(vals.get(4).substring(5)),
|
||||||
UnicodeUtils.unescape(hsr, vals.get(1).substring(7)),
|
UnicodeUtils.unescape(hsr, vals.get(1).substring(7)),
|
||||||
UnicodeUtils.unescape(hsr, vals.get(0).substring(6)),
|
UnicodeUtils.unescape(hsr, vals.get(0).substring(6)),
|
||||||
@@ -1464,11 +1462,8 @@ public class Assembler {
|
|||||||
vals.clear();
|
vals.clear();
|
||||||
}
|
}
|
||||||
stage = 0;
|
stage = 0;
|
||||||
} else if (st.equals("Type: [")) {
|
} else if (st.startsWith("Type ")) {
|
||||||
stage = 1;
|
args.add(Type.getType(UnicodeUtils.unescape(hsr, st.substring(6, st.length() - 1), true)));
|
||||||
} else if (stage == 1) {
|
|
||||||
st = st.substring(1);
|
|
||||||
vals.add(st);
|
|
||||||
} else if (st.equals("Handle: [")) {
|
} else if (st.equals("Handle: [")) {
|
||||||
vals.clear();
|
vals.clear();
|
||||||
stage = 2;
|
stage = 2;
|
||||||
@@ -1559,38 +1554,37 @@ public class Assembler {
|
|||||||
private static Object[] parseFrameList(HugeStringsRev hsr, String str, HashMap<LabelNode, Integer> labels) {
|
private static Object[] parseFrameList(HugeStringsRev hsr, String str, HashMap<LabelNode, Integer> labels) {
|
||||||
ArrayList<Object> list = new ArrayList<>();
|
ArrayList<Object> list = new ArrayList<>();
|
||||||
String l = str.substring(1, str.length() - 1);
|
String l = str.substring(1, str.length() - 1);
|
||||||
if (l.isEmpty()) {
|
if (l.isEmpty())
|
||||||
return EMPTY_OBJECT_ARRAY;
|
return EMPTY_OBJECT_ARRAY;
|
||||||
} else {
|
|
||||||
for (String asd : l.split(", ")) {
|
for (String asd : l.split(", ")) {
|
||||||
if (!asd.startsWith("(")) {
|
if (!asd.startsWith("(")) {
|
||||||
int frameType = ClassUtil.getFrameTypeByName(asd);
|
int frameType = ClassUtil.getFrameTypeByName(asd);
|
||||||
if (frameType != -1)
|
if (frameType != -1)
|
||||||
list.add(Integer.valueOf(frameType));
|
list.add(Integer.valueOf(frameType));
|
||||||
else
|
else
|
||||||
list.add(UnicodeUtils.unescape(hsr, asd.substring(1, asd.length() - 1)));
|
list.add(UnicodeUtils.unescape(hsr, asd.substring(1, asd.length() - 1)));
|
||||||
} else {
|
} else {
|
||||||
if (asd.startsWith("(label) ")) {
|
if (asd.startsWith("(label) ")) {
|
||||||
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
list.add(entry.getKey());
|
list.add(entry.getKey());
|
||||||
found = true;
|
found = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!found) {
|
|
||||||
LabelNode ln = new LabelNode(new Label());
|
|
||||||
labels.put(ln, labelNr);
|
|
||||||
list.add(ln);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
list.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
|
||||||
}
|
}
|
||||||
|
if (!found) {
|
||||||
|
LabelNode ln = new LabelNode(new Label());
|
||||||
|
labels.put(ln, labelNr);
|
||||||
|
list.add(ln);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list.toArray(new Object[list.size()]);
|
|
||||||
}
|
}
|
||||||
|
return list.toArray(new Object[list.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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) {
|
||||||
@@ -127,7 +142,7 @@ public class Disassembler implements IDecompiler {
|
|||||||
ctx.next("\n// #Fields\n");
|
ctx.next("\n// #Fields\n");
|
||||||
ctx.next(doFields(classNode.fields, hs));
|
ctx.next(doFields(classNode.fields, hs));
|
||||||
ctx.next("\n// #Methods\n");
|
ctx.next("\n// #Methods\n");
|
||||||
ctx.next(doMethods(classNode.methods, classNode.name, hs));
|
ctx.next(doMethods(classNode.methods, hs));
|
||||||
ctx.next("}\n");
|
ctx.next("}\n");
|
||||||
|
|
||||||
if (!hs.isEmpty())
|
if (!hs.isEmpty())
|
||||||
@@ -154,48 +169,51 @@ public class Disassembler implements IDecompiler {
|
|||||||
s += o + " = [";
|
s += o + " = [";
|
||||||
valBefore = false;
|
valBefore = false;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
}
|
||||||
if (o instanceof String[]) {
|
if (o instanceof String[]) {
|
||||||
String[] arr = (String[]) o;
|
String[] arr = (String[]) o;
|
||||||
boolean w8ing = false;
|
boolean w8ing = false;
|
||||||
for (String rofl : arr) {
|
for (String rofl : arr) {
|
||||||
if (!w8ing) {
|
if (!w8ing) {
|
||||||
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
||||||
w8ing = true;
|
w8ing = true;
|
||||||
} else {
|
} else {
|
||||||
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "]";
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s += ", ";
|
||||||
|
} else if (o instanceof List) {
|
||||||
|
List list = (List) o;
|
||||||
|
s += "{ ";
|
||||||
|
for (Object obj : list) {
|
||||||
|
if (obj instanceof String[]) {
|
||||||
|
String[] arr = (String[]) obj;
|
||||||
|
boolean w8ing = false;
|
||||||
|
for (String rofl : arr) {
|
||||||
|
if (!w8ing) {
|
||||||
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
||||||
|
w8ing = true;
|
||||||
|
} else {
|
||||||
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
s += "\"" + UnicodeUtils.escape(hs, String.valueOf(obj)) + "\"";
|
||||||
}
|
}
|
||||||
s += ", ";
|
s += ", ";
|
||||||
} else if (o instanceof List) {
|
}
|
||||||
List list = (List) o;
|
if (s.endsWith(", ")) {
|
||||||
s += "{ ";
|
|
||||||
for (Object obj : list) {
|
|
||||||
if (obj instanceof String[]) {
|
|
||||||
String[] arr = (String[]) obj;
|
|
||||||
boolean w8ing = false;
|
|
||||||
for (String rofl : arr) {
|
|
||||||
if (!w8ing) {
|
|
||||||
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
|
||||||
w8ing = true;
|
|
||||||
} else {
|
|
||||||
s += UnicodeUtils.escapeWithSpaces(hs, rofl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s += "\"" + UnicodeUtils.escape(hs, String.valueOf(obj)) + "\"";
|
|
||||||
}
|
|
||||||
s += ", ";
|
|
||||||
}
|
|
||||||
s = s.substring(0, s.length() - 2);
|
s = s.substring(0, s.length() - 2);
|
||||||
s += " }], ";
|
s += " }], ";
|
||||||
} else if (o instanceof String) {
|
|
||||||
s += "\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"], ";
|
|
||||||
} else {
|
} else {
|
||||||
s += "(" + o.getClass().getName().replace(".", "/") + ") " + o + "], ";
|
s += "}], ";
|
||||||
}
|
}
|
||||||
valBefore = true;
|
} else if (o instanceof String) {
|
||||||
|
s += "\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"], ";
|
||||||
|
} else {
|
||||||
|
s += "(" + o.getClass().getName().replace(".", "/") + ") " + o + "], ";
|
||||||
}
|
}
|
||||||
|
valBefore = true;
|
||||||
}
|
}
|
||||||
if (s.endsWith(", "))
|
if (s.endsWith(", "))
|
||||||
s = s.substring(0, s.length() - 2);
|
s = s.substring(0, s.length() - 2);
|
||||||
@@ -207,7 +225,7 @@ public class Disassembler implements IDecompiler {
|
|||||||
return ctx.finish();
|
return ctx.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String doMethods(List<MethodNode> methods, String className, HugeStrings hs)
|
private static String doMethods(List<MethodNode> methods, HugeStrings hs)
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
boolean multithreaded = Main.INSTANCE.mntmMultithreaded.isSelected();
|
boolean multithreaded = Main.INSTANCE.mntmMultithreaded.isSelected();
|
||||||
Future<String>[] futures = new Future[methods.size()];
|
Future<String>[] futures = new Future[methods.size()];
|
||||||
@@ -221,7 +239,7 @@ public class Disassembler implements IDecompiler {
|
|||||||
ms += "\t// #Max: l:" + mn.maxLocals + " s:" + mn.maxStack + "\n";
|
ms += "\t// #Max: l:" + mn.maxLocals + " s:" + mn.maxStack + "\n";
|
||||||
if (mn.signature != null)
|
if (mn.signature != null)
|
||||||
ms += "\t// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, mn.signature) + "\n";
|
ms += "\t// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, mn.signature) + "\n";
|
||||||
String[] dis = disassembleMethod(className, mn, hs);
|
String[] dis = disassembleMethod(mn, hs);
|
||||||
ms += dis[2];
|
ms += dis[2];
|
||||||
ms += dis[1];
|
ms += dis[1];
|
||||||
if (mn.visibleAnnotations != null && !mn.visibleAnnotations.isEmpty())
|
if (mn.visibleAnnotations != null && !mn.visibleAnnotations.isEmpty())
|
||||||
@@ -286,20 +304,21 @@ public class Disassembler implements IDecompiler {
|
|||||||
return ctx.finish();
|
return ctx.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] disassembleMethod(String className, MethodNode mn, HugeStrings hs) {
|
private static String[] disassembleMethod(MethodNode mn, HugeStrings hs) {
|
||||||
HashMap<Label, Integer> labels = new HashMap<Label, Integer>();
|
HashMap<Label, Integer> labels = new HashMap<Label, Integer>();
|
||||||
String localVarTable;
|
String localVarTable;
|
||||||
String tryCatchTable;
|
String tryCatchTable;
|
||||||
|
|
||||||
InsnList insnList = mn.instructions;
|
InsnList insnList = mn.instructions;
|
||||||
boolean deobfNumbers = Main.INSTANCE.mntmNumbers.isSelected();
|
boolean deobfNumbers = Main.INSTANCE.mntmNumbers.isSelected();
|
||||||
|
boolean deobfNops = Main.INSTANCE.mntmNops.isSelected();
|
||||||
|
|
||||||
ArrayList<Label> labelsReversed = deobfNumbers ? new ArrayList<>() : null;
|
ArrayList<Label> labelsReversed = deobfNumbers ? new ArrayList<>() : null;
|
||||||
|
|
||||||
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
if (n instanceof LabelNode) {
|
if (n instanceof LabelNode) {
|
||||||
int id = labels.size() + 1;
|
int id = labels.size() + 1;
|
||||||
if (deobfNumbers)
|
if (deobfNumbers && labelsReversed != null)
|
||||||
labelsReversed.add(((LabelNode) n).getLabel());
|
labelsReversed.add(((LabelNode) n).getLabel());
|
||||||
labels.put(((LabelNode) n).getLabel(), id);
|
labels.put(((LabelNode) n).getLabel(), id);
|
||||||
}
|
}
|
||||||
@@ -336,7 +355,7 @@ public class Disassembler implements IDecompiler {
|
|||||||
insnList = calc.get();
|
insnList = calc.get();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
if (n instanceof LabelNode) {
|
if (n instanceof LabelNode && labelsReversed != null) {
|
||||||
((LabelNode) n).setLabel(labelsReversed.get(i++));
|
((LabelNode) n).setLabel(labelsReversed.get(i++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,6 +363,8 @@ public class Disassembler implements IDecompiler {
|
|||||||
|
|
||||||
StringContext ctx = new StringContext(insnList.size());
|
StringContext ctx = new StringContext(insnList.size());
|
||||||
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
|
if (deobfNops && n.getOpcode() == Opcodes.NOP)
|
||||||
|
continue;
|
||||||
ctx.next(disassembleInstruction(n, labels, hs));
|
ctx.next(disassembleInstruction(n, labels, hs));
|
||||||
}
|
}
|
||||||
return new String[] { ctx.finish(), localVarTable, tryCatchTable };
|
return new String[] { ctx.finish(), localVarTable, tryCatchTable };
|
||||||
@@ -359,9 +380,8 @@ public class Disassembler implements IDecompiler {
|
|||||||
if (n.getOpcode() == Opcodes.NEWARRAY) {
|
if (n.getOpcode() == Opcodes.NEWARRAY) {
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
||||||
+ ClassUtil.getArrayTypeByID(node.operand) + "\n";
|
+ ClassUtil.getArrayTypeByID(node.operand) + "\n";
|
||||||
} else {
|
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n";
|
|
||||||
}
|
}
|
||||||
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n";
|
||||||
}
|
}
|
||||||
case VAR_INSN: {
|
case VAR_INSN: {
|
||||||
VarInsnNode node = (VarInsnNode) n;
|
VarInsnNode node = (VarInsnNode) n;
|
||||||
@@ -396,15 +416,7 @@ public class Disassembler implements IDecompiler {
|
|||||||
+ "\n\t\t\t]\n\t\t\targs: [\n";
|
+ "\n\t\t\t]\n\t\t\targs: [\n";
|
||||||
for (Object l : node.bsmArgs) {
|
for (Object l : node.bsmArgs) {
|
||||||
if (l instanceof Type) {
|
if (l instanceof Type) {
|
||||||
Type type = (Type) l;
|
s += "\t\t\t\tType " + ClassUtil.getDecompiledValue(((Type) l).getDescriptor(), "", hs) + "\n";
|
||||||
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";
|
|
||||||
} else if (l instanceof Handle) {
|
} else if (l instanceof Handle) {
|
||||||
Handle h = (Handle) l;
|
Handle h = (Handle) l;
|
||||||
s += "\t\t\t\tHandle: [\n\t\t\t\t\tname: "
|
s += "\t\t\t\tHandle: [\n\t\t\t\t\tname: "
|
||||||
@@ -433,26 +445,17 @@ public class Disassembler implements IDecompiler {
|
|||||||
case LDC_INSN: {
|
case LDC_INSN: {
|
||||||
LdcInsnNode node = (LdcInsnNode) n;
|
LdcInsnNode node = (LdcInsnNode) n;
|
||||||
if (node.cst instanceof Type) {
|
if (node.cst instanceof Type) {
|
||||||
Type type = (Type) node.cst;
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " Type "
|
||||||
int valueBegin = type.valueBegin;
|
+ ClassUtil.getDecompiledValue(((Type) node.cst).getDescriptor(), "", hs) + "\n";
|
||||||
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;
|
|
||||||
} else {
|
|
||||||
String decomp = ClassUtil.getDecompiledValue(node.cst, "", hs);
|
|
||||||
if (node.cst instanceof String) {
|
|
||||||
if (decomp.startsWith("\"#") && decomp.endsWith("\""))
|
|
||||||
decomp = decomp.substring(1, decomp.length() - 1);
|
|
||||||
else if (decomp.startsWith("\"\\u0023"))
|
|
||||||
decomp = "\"#" + decomp.substring(7);
|
|
||||||
}
|
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + decomp + "\n";
|
|
||||||
}
|
}
|
||||||
|
String decomp = ClassUtil.getDecompiledValue(node.cst, "", hs);
|
||||||
|
if (node.cst instanceof String) {
|
||||||
|
if (decomp.startsWith("\"#") && decomp.endsWith("\""))
|
||||||
|
decomp = decomp.substring(1, decomp.length() - 1);
|
||||||
|
else if (decomp.startsWith("\"\\u0023"))
|
||||||
|
decomp = "\"#" + decomp.substring(7);
|
||||||
|
}
|
||||||
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + decomp + "\n";
|
||||||
}
|
}
|
||||||
case IINC_INSN: {
|
case IINC_INSN: {
|
||||||
IincInsnNode node = (IincInsnNode) n;
|
IincInsnNode node = (IincInsnNode) n;
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
package me.ByteEdit.edit;
|
|
||||||
|
|
||||||
import java.awt.EventQueue;
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
|
|
||||||
import javax.swing.JCheckBox;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
|
||||||
|
|
||||||
public class OptionBox extends JFrame {
|
|
||||||
|
|
||||||
private JPanel contentPane;
|
|
||||||
public JCheckBox chckbxComputeFrames;
|
|
||||||
public JCheckBox chckbxComputeMax;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch the application.
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) {
|
|
||||||
EventQueue.invokeLater(new Runnable() {
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
OptionBox frame = new OptionBox();
|
|
||||||
frame.setVisible(true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the frame.
|
|
||||||
*/
|
|
||||||
public OptionBox() {
|
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setResizable(false);
|
|
||||||
setTitle("Options");
|
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
|
||||||
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 150),
|
|
||||||
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 100), 300, 200);
|
|
||||||
contentPane = new JPanel();
|
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
|
||||||
setContentPane(contentPane);
|
|
||||||
contentPane.setLayout(null);
|
|
||||||
chckbxComputeFrames = new JCheckBox("Compute Frames");
|
|
||||||
chckbxComputeFrames.setBounds(6, 7, 138, 23);
|
|
||||||
contentPane.add(chckbxComputeFrames);
|
|
||||||
chckbxComputeMax = new JCheckBox("Compute Max");
|
|
||||||
chckbxComputeMax.setBounds(6, 33, 138, 23);
|
|
||||||
contentPane.add(chckbxComputeMax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
package me.ByteEdit.edit;
|
|
||||||
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JCheckBox;
|
|
||||||
import javax.swing.JComponent;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JTextField;
|
|
||||||
import javax.swing.KeyStroke;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
|
||||||
|
|
||||||
import me.ByteEdit.main.Main;
|
|
||||||
|
|
||||||
public class SearchBox extends JFrame {
|
|
||||||
|
|
||||||
public JPanel contentPane;
|
|
||||||
public JTextField txtFind;
|
|
||||||
public JTextField txtReplace;
|
|
||||||
public JCheckBox chckbxCaseSensitive;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the frame.
|
|
||||||
*/
|
|
||||||
public SearchBox() {
|
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setResizable(false);
|
|
||||||
setTitle("Find/Replace");
|
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
|
||||||
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 128),
|
|
||||||
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 181), 256, 262);
|
|
||||||
contentPane = new JPanel();
|
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
|
||||||
setContentPane(contentPane);
|
|
||||||
contentPane.setLayout(null);
|
|
||||||
JLabel lblFind = new JLabel("Find:");
|
|
||||||
lblFind.setBounds(10, 25, 71, 14);
|
|
||||||
contentPane.add(lblFind);
|
|
||||||
txtFind = new JTextField();
|
|
||||||
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
|
|
||||||
txtFind.registerKeyboardAction(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
find();
|
|
||||||
}
|
|
||||||
}, enter, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
|
||||||
txtFind.setBounds(91, 22, 149, 20);
|
|
||||||
contentPane.add(txtFind);
|
|
||||||
txtFind.setColumns(10);
|
|
||||||
JLabel lblReplaceWith = new JLabel("Replace with:");
|
|
||||||
lblReplaceWith.setBounds(10, 53, 71, 14);
|
|
||||||
contentPane.add(lblReplaceWith);
|
|
||||||
txtReplace = new JTextField();
|
|
||||||
txtReplace.setColumns(10);
|
|
||||||
txtReplace.setBounds(91, 50, 149, 20);
|
|
||||||
contentPane.add(txtReplace);
|
|
||||||
chckbxCaseSensitive = new JCheckBox("Case sensitive");
|
|
||||||
chckbxCaseSensitive.setBounds(10, 103, 230, 23);
|
|
||||||
contentPane.add(chckbxCaseSensitive);
|
|
||||||
JButton btnFind = new JButton("Find");
|
|
||||||
btnFind.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
find();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
btnFind.setBounds(10, 150, 110, 23);
|
|
||||||
contentPane.add(btnFind);
|
|
||||||
JButton btnReplacefind = new JButton("Replace/Find");
|
|
||||||
btnReplacefind.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
replaceFind();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
btnReplacefind.setBounds(130, 150, 110, 23);
|
|
||||||
contentPane.add(btnReplacefind);
|
|
||||||
JButton btnReplace = new JButton("Replace");
|
|
||||||
btnReplace.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
replace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
btnReplace.setBounds(10, 184, 110, 23);
|
|
||||||
contentPane.add(btnReplace);
|
|
||||||
JButton btnReplaceAll = new JButton("Replace All");
|
|
||||||
btnReplaceAll.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
replaceAll();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
btnReplaceAll.setBounds(130, 184, 110, 23);
|
|
||||||
contentPane.add(btnReplaceAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void find() {
|
|
||||||
int startPos = Main.txtByteEditView.getCaretPosition();
|
|
||||||
String toFind = txtFind.getText();
|
|
||||||
String txt = chckbxCaseSensitive.isSelected() ? Main.txtByteEditView.getText().substring(startPos)
|
|
||||||
: Main.txtByteEditView.getText().substring(startPos).toLowerCase();
|
|
||||||
int index = txt.indexOf(chckbxCaseSensitive.isSelected() ? toFind : toFind.toLowerCase());
|
|
||||||
if (index == -1) {
|
|
||||||
txt = chckbxCaseSensitive.isSelected() ? Main.txtByteEditView.getText()
|
|
||||||
: Main.txtByteEditView.getText().toLowerCase();
|
|
||||||
index = txt.indexOf(chckbxCaseSensitive.isSelected() ? toFind : toFind.toLowerCase());
|
|
||||||
startPos = 0;
|
|
||||||
if (index == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Main.txtByteEditView.select(startPos + index, startPos + index + toFind.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replaceFind() {
|
|
||||||
replace();
|
|
||||||
find();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replace() {
|
|
||||||
String txt = Main.txtByteEditView.getText();
|
|
||||||
int startPos = Main.txtByteEditView.getSelectionStart();
|
|
||||||
Main.txtByteEditView.replaceSelection(txtReplace.getText());
|
|
||||||
Main.txtByteEditView.select(startPos, startPos + txtReplace.getText().length());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replaceAll() {
|
|
||||||
String toFind = txtFind.getText();
|
|
||||||
String toReplace = txtReplace.getText();
|
|
||||||
String txt = Main.txtByteEditView.getText();
|
|
||||||
int prev = Main.txtByteEditView.getCaretPosition();
|
|
||||||
if (chckbxCaseSensitive.isSelected()) {
|
|
||||||
Main.txtByteEditView.replaceRange(txt.replace(toFind, toReplace), 0, txt.length());
|
|
||||||
} else {
|
|
||||||
Main.txtByteEditView.replaceRange(txt.replaceAll("(?i)" + Pattern.quote(toFind), toReplace), 0,
|
|
||||||
txt.length());
|
|
||||||
}
|
|
||||||
Main.txtByteEditView.setCaretPosition(prev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -580,8 +580,10 @@ public class StackBasedCalculator implements Opcodes, Runnable {
|
|||||||
change(node);
|
change(node);
|
||||||
return false;
|
return false;
|
||||||
case POP2:
|
case POP2:
|
||||||
stack.pop();
|
Number val = stack.pop();
|
||||||
stack.pop();
|
if (!(val instanceof Long) && !(val instanceof Double)) {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
change(node);
|
change(node);
|
||||||
return false;
|
return false;
|
||||||
case SWAP: {
|
case SWAP: {
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
package me.ByteEdit.edit;
|
|
||||||
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
|
|
||||||
import javax.swing.DefaultListModel;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JList;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JScrollPane;
|
|
||||||
import javax.swing.JTextField;
|
|
||||||
import javax.swing.ListSelectionModel;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
|
||||||
import javax.swing.event.DocumentEvent;
|
|
||||||
import javax.swing.event.DocumentListener;
|
|
||||||
import javax.swing.event.ListSelectionEvent;
|
|
||||||
import javax.swing.event.ListSelectionListener;
|
|
||||||
|
|
||||||
import me.ByteEdit.decompiler.SingleThreadedExecutor;
|
|
||||||
import me.ByteEdit.main.Main;
|
|
||||||
|
|
||||||
public class TypeOpenBox extends JFrame {
|
|
||||||
|
|
||||||
public JPanel contentPane;
|
|
||||||
public JTextField txtSearch;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the frame.
|
|
||||||
*/
|
|
||||||
public TypeOpenBox() {
|
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setResizable(false);
|
|
||||||
setTitle("Open Type");
|
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
|
||||||
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 200),
|
|
||||||
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 140), 400, 280);
|
|
||||||
contentPane = new JPanel();
|
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
|
||||||
setContentPane(contentPane);
|
|
||||||
contentPane.setLayout(null);
|
|
||||||
|
|
||||||
DefaultListModel<String> model = new DefaultListModel<>();
|
|
||||||
JList<String> list = new JList(model);
|
|
||||||
list.addListSelectionListener(new ListSelectionListener() {
|
|
||||||
|
|
||||||
public void valueChanged(ListSelectionEvent e) {
|
|
||||||
String val = list.getSelectedValue();
|
|
||||||
if (val != null && !val.equals(Main.currentNodeName)) {
|
|
||||||
|
|
||||||
SingleThreadedExecutor.execute(() -> Main.selectFile(val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
txtSearch = new JTextField();
|
|
||||||
txtSearch.addActionListener(new ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
if (model.size() == 1) {
|
|
||||||
list.setSelectedIndex(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
txtSearch.getDocument().addDocumentListener(new DocumentListener() {
|
|
||||||
|
|
||||||
public void changedUpdate(DocumentEvent e) {
|
|
||||||
updateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeUpdate(DocumentEvent e) {
|
|
||||||
updateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insertUpdate(DocumentEvent e) {
|
|
||||||
updateList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateList() {
|
|
||||||
model.clear();
|
|
||||||
if (txtSearch.getText().isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String search = txtSearch.getText().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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (String s : Main.classNodes.keySet()) {
|
|
||||||
String[] split = s.split("/");
|
|
||||||
String className = split[split.length - 1];
|
|
||||||
className = className.substring(0, className.length() - 6);
|
|
||||||
if (!className.contains("$") && className.toLowerCase().startsWith(search)) {
|
|
||||||
model.addElement(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
txtSearch.setBounds(10, 11, 374, 20);
|
|
||||||
contentPane.add(txtSearch);
|
|
||||||
txtSearch.setColumns(10);
|
|
||||||
|
|
||||||
JScrollPane scrollPane = new JScrollPane();
|
|
||||||
scrollPane.setBounds(10, 46, 374, 194);
|
|
||||||
contentPane.add(scrollPane);
|
|
||||||
|
|
||||||
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
|
||||||
scrollPane.setViewportView(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -40,7 +40,7 @@ public class ArchiveTreeModel extends DefaultTreeModel {
|
|||||||
super(new ByteEditTreeNode(jar.getName().split(File.separator.equals("\\") ? "\\\\"
|
super(new ByteEditTreeNode(jar.getName().split(File.separator.equals("\\") ? "\\\\"
|
||||||
: File.separator)[jar.getName().split(File.separator.equals("\\") ? "\\\\" : File.separator).length
|
: File.separator)[jar.getName().split(File.separator.equals("\\") ? "\\\\" : File.separator).length
|
||||||
- 1]));
|
- 1]));
|
||||||
this.newCreated = true;
|
this.newCreated = false;
|
||||||
this.jar = jar;
|
this.jar = jar;
|
||||||
this.classNodes = classNodes;
|
this.classNodes = classNodes;
|
||||||
this.otherFiles = otherFiles;
|
this.otherFiles = otherFiles;
|
||||||
@@ -61,7 +61,7 @@ public class ArchiveTreeModel extends DefaultTreeModel {
|
|||||||
ClassReader reader = new ClassReader(data);
|
ClassReader reader = new ClassReader(data);
|
||||||
ClassNode node = new ClassNode();
|
ClassNode node = new ClassNode();
|
||||||
reader.accept(node, 0);
|
reader.accept(node, 0);
|
||||||
classNodes.put(Main.getFullName(node.name), node);
|
classNodes.put(node.name, node);
|
||||||
|
|
||||||
if ((next.getName().contains("/")
|
if ((next.getName().contains("/")
|
||||||
? (!Main.patternSlash
|
? (!Main.patternSlash
|
||||||
@@ -70,7 +70,7 @@ public class ArchiveTreeModel extends DefaultTreeModel {
|
|||||||
: (!next.getName().contains("$")))
|
: (!next.getName().contains("$")))
|
||||||
|| (next.getName().startsWith("$") || next.getName().contains("$$")
|
|| (next.getName().startsWith("$") || next.getName().contains("$$")
|
||||||
|| next.getName().endsWith("$"))) {
|
|| next.getName().endsWith("$"))) {
|
||||||
paths.add(Main.getFullName(node.name));
|
paths.add(node.name + ".class");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
otherFiles.put(next.getName(), data);
|
otherFiles.put(next.getName(), data);
|
||||||
@@ -89,7 +89,7 @@ public class ArchiveTreeModel extends DefaultTreeModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getSlashCount(String s) {
|
private static int getSlashCount(String s) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (char c : s.toCharArray()) {
|
for (char c : s.toCharArray()) {
|
||||||
if (c == '/')
|
if (c == '/')
|
||||||
|
|||||||
@@ -85,9 +85,8 @@ public class HugeStringsToolTips implements ToolTipSupplier {
|
|||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
len += asm.length();
|
|
||||||
}
|
}
|
||||||
|
len += asm.length();
|
||||||
}
|
}
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ import javax.swing.JSplitPane;
|
|||||||
import javax.swing.JTree;
|
import javax.swing.JTree;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.event.TreeSelectionEvent;
|
|
||||||
import javax.swing.event.TreeSelectionListener;
|
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||||
@@ -91,6 +89,7 @@ import me.ByteEdit.utils.ClassUtil;
|
|||||||
import me.ByteEdit.utils.OpcodesReverse;
|
import me.ByteEdit.utils.OpcodesReverse;
|
||||||
import me.ByteEdit.utils.UnicodeUtils;
|
import me.ByteEdit.utils.UnicodeUtils;
|
||||||
|
|
||||||
|
// ASM 9.2
|
||||||
public class Main extends JFrame {
|
public class Main extends JFrame {
|
||||||
|
|
||||||
public static Main INSTANCE;
|
public static Main INSTANCE;
|
||||||
@@ -144,7 +143,7 @@ public class Main extends JFrame {
|
|||||||
private JMenuItem rdbtnmntm10000;
|
private JMenuItem rdbtnmntm10000;
|
||||||
public JCheckBoxMenuItem mntmMultithreaded;
|
public JCheckBoxMenuItem mntmMultithreaded;
|
||||||
private JMenu mnDeobfuscation;
|
private JMenu mnDeobfuscation;
|
||||||
public JCheckBoxMenuItem mntmNumbers;
|
public JCheckBoxMenuItem mntmNumbers, mntmNops;
|
||||||
|
|
||||||
public static final Object treeLock = new Object();
|
public static final Object treeLock = new Object();
|
||||||
|
|
||||||
@@ -168,7 +167,7 @@ public class Main extends JFrame {
|
|||||||
/**
|
/**
|
||||||
* Create a simple provider that adds some Java-related completions.
|
* Create a simple provider that adds some Java-related completions.
|
||||||
*/
|
*/
|
||||||
private CompletionProvider createCompletionProvider() {
|
private static CompletionProvider createCompletionProvider() {
|
||||||
DefaultCompletionProvider provider = new DefaultCompletionProvider();
|
DefaultCompletionProvider provider = new DefaultCompletionProvider();
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < 200; i++) {
|
||||||
String s = OpcodesReverse.reverseOpcode(i);
|
String s = OpcodesReverse.reverseOpcode(i);
|
||||||
@@ -290,7 +289,6 @@ public class Main extends JFrame {
|
|||||||
if (action == 0) {
|
if (action == 0) {
|
||||||
final File file = fileChooser.getSelectedFile();
|
final File file = fileChooser.getSelectedFile();
|
||||||
saveFolder = file.getParentFile();
|
saveFolder = file.getParentFile();
|
||||||
boolean shouldSave = false;
|
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
synchronized (treeLock) {
|
synchronized (treeLock) {
|
||||||
jarFile = file;
|
jarFile = file;
|
||||||
@@ -306,7 +304,7 @@ public class Main extends JFrame {
|
|||||||
try {
|
try {
|
||||||
ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile), classNodes,
|
ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile), classNodes,
|
||||||
otherFiles);
|
otherFiles);
|
||||||
EventQueue.invokeLater(new Runnable() {
|
EventQueue.invokeAndWait(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
synchronized (treeLock) {
|
synchronized (treeLock) {
|
||||||
tree.setModel(model);
|
tree.setModel(model);
|
||||||
@@ -323,7 +321,7 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -428,6 +426,9 @@ public class Main extends JFrame {
|
|||||||
mntmNumbers = new JCheckBoxMenuItem("Numbers");
|
mntmNumbers = new JCheckBoxMenuItem("Numbers");
|
||||||
mnDeobfuscation.add(mntmNumbers);
|
mnDeobfuscation.add(mntmNumbers);
|
||||||
|
|
||||||
|
mntmNops = new JCheckBoxMenuItem("Nops");
|
||||||
|
mnDeobfuscation.add(mntmNops);
|
||||||
|
|
||||||
contentPane = new JPanel();
|
contentPane = new JPanel();
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
setContentPane(contentPane);
|
setContentPane(contentPane);
|
||||||
@@ -461,7 +462,7 @@ public class Main extends JFrame {
|
|||||||
try {
|
try {
|
||||||
ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile), classNodes,
|
ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile), classNodes,
|
||||||
otherFiles);
|
otherFiles);
|
||||||
EventQueue.invokeLater(new Runnable() {
|
EventQueue.invokeAndWait(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
synchronized (treeLock) {
|
synchronized (treeLock) {
|
||||||
tree.setModel(model);
|
tree.setModel(model);
|
||||||
@@ -470,7 +471,7 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,19 +487,19 @@ public class Main extends JFrame {
|
|||||||
String s = ((ByteEditTreeNode) tree.getSelectionPath().getLastPathComponent()).path;
|
String s = ((ByteEditTreeNode) tree.getSelectionPath().getLastPathComponent()).path;
|
||||||
if (JOptionPane.showConfirmDialog(INSTANCE, "Do you want to delete\n\"" + s + "\"?", "Delete",
|
if (JOptionPane.showConfirmDialog(INSTANCE, "Do you want to delete\n\"" + s + "\"?", "Delete",
|
||||||
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
|
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<>();
|
ArrayList<String> toRemove = new ArrayList<>();
|
||||||
for (String key : Main.classNodes.keySet()) {
|
for (String key : Main.classNodes.keySet()) {
|
||||||
if (key.contains("$")) {
|
if (key.contains("$")) {
|
||||||
String[] split = key.split("\\$");
|
String[] split = key.split("\\$");
|
||||||
if (split[0].equals(substr)) {
|
if (split[0].equals(s)) {
|
||||||
toRemove.add(key);
|
toRemove.add(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArchiveTreeModel model = (ArchiveTreeModel) tree.getModel();
|
ArchiveTreeModel model = (ArchiveTreeModel) tree.getModel();
|
||||||
classNodes.remove(s);
|
classNodes.remove(s);
|
||||||
model.paths.remove(s);
|
model.paths.remove(s + ".class");
|
||||||
for (String rem : toRemove) {
|
for (String rem : toRemove) {
|
||||||
classNodes.remove(rem);
|
classNodes.remove(rem);
|
||||||
}
|
}
|
||||||
@@ -515,17 +516,8 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
scrollPane.setViewportView(tree);
|
scrollPane.setViewportView(tree);
|
||||||
tree.addTreeSelectionListener(new TreeSelectionListener() {
|
tree.addTreeSelectionListener(e -> SingleThreadedExecutor
|
||||||
|
.submit(() -> selectFile(((ByteEditTreeNode) e.getPath().getLastPathComponent()).path)));
|
||||||
public void valueChanged(TreeSelectionEvent e) {
|
|
||||||
synchronized (treeLock) {
|
|
||||||
if (!isChangingFile) {
|
|
||||||
SingleThreadedExecutor.execute(
|
|
||||||
() -> selectFile(((ByteEditTreeNode) e.getPath().getLastPathComponent()).path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
new DropTarget(tree, new DropTargetListener() {
|
new DropTarget(tree, new DropTargetListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -557,7 +549,7 @@ public class Main extends JFrame {
|
|||||||
try {
|
try {
|
||||||
ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile),
|
ArchiveTreeModel model = new ArchiveTreeModel(new ZipFile(jarFile),
|
||||||
classNodes, otherFiles);
|
classNodes, otherFiles);
|
||||||
EventQueue.invokeLater(new Runnable() {
|
EventQueue.invokeAndWait(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
synchronized (treeLock) {
|
synchronized (treeLock) {
|
||||||
tree.setModel(model);
|
tree.setModel(model);
|
||||||
@@ -574,7 +566,7 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -618,7 +610,7 @@ public class Main extends JFrame {
|
|||||||
@Override
|
@Override
|
||||||
public void keyReleased(KeyEvent e) {
|
public void keyReleased(KeyEvent e) {
|
||||||
if (e.getKeyCode() == 116 && currentNodeName != null) { // F5
|
if (e.getKeyCode() == 116 && currentNodeName != null) { // F5
|
||||||
SingleThreadedExecutor.execute(Main::decompileCurrentNode);
|
SingleThreadedExecutor.submit(Main::decompileCurrentNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -673,22 +665,22 @@ public class Main extends JFrame {
|
|||||||
public void itemStateChanged(ItemEvent e) {
|
public void itemStateChanged(ItemEvent e) {
|
||||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
EnumDecompiler selected = (EnumDecompiler) e.getItem();
|
EnumDecompiler selected = (EnumDecompiler) e.getItem();
|
||||||
SingleThreadedExecutor.execute(() -> {
|
SingleThreadedExecutor.submit(() -> {
|
||||||
decompiler = selected;
|
decompiler = selected;
|
||||||
if (currentNodeName != null) {
|
decompileCurrentNode();
|
||||||
decompileCurrentNode();
|
try {
|
||||||
try {
|
EventQueue.invokeAndWait(() -> {
|
||||||
EventQueue.invokeAndWait(() -> {
|
synchronized (treeLock) {
|
||||||
txtByteEditView.setCaretPosition(0);
|
txtByteEditView.setCaretPosition(0);
|
||||||
try {
|
try {
|
||||||
txtByteEditView.setSyntaxEditingStyle(decompiler.getSyntaxStyle());
|
txtByteEditView.setSyntaxEditingStyle(decompiler.getSyntaxStyle());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
}
|
}
|
||||||
txtByteEditView.setEditable(decompiler.isEditable());
|
txtByteEditView.setEditable(decompiler.isEditable());
|
||||||
});
|
}
|
||||||
} catch (Exception e1) {
|
});
|
||||||
e1.printStackTrace();
|
} catch (Exception e1) {
|
||||||
}
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -760,7 +752,7 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveCurrentClassNode() {
|
private static void saveCurrentClassNode() {
|
||||||
String txt = txtByteEditView.getText();
|
String txt = txtByteEditView.getText();
|
||||||
for (String s : txt.split("\\/\\/ #Annotations:\n")) {
|
for (String s : txt.split("\\/\\/ #Annotations:\n")) {
|
||||||
if (s.isEmpty())
|
if (s.isEmpty())
|
||||||
@@ -769,15 +761,15 @@ public class Main extends JFrame {
|
|||||||
if (node == null) {
|
if (node == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (classNodes.replace(getFullName(node.name), node) == null) {
|
if (classNodes.replace(node.name, node) == null) {
|
||||||
classNodes.put(getFullName(node.name), node);
|
classNodes.put(node.name, node);
|
||||||
ArchiveTreeModel model;
|
ArchiveTreeModel model;
|
||||||
if (tree.getModel().getClass().equals(DefaultTreeModel.class)) {
|
if (tree.getModel().getClass().equals(DefaultTreeModel.class)) {
|
||||||
tree.setModel(model = new ArchiveTreeModel(classNodes, otherFiles));
|
tree.setModel(model = new ArchiveTreeModel(classNodes, otherFiles));
|
||||||
} else {
|
} else {
|
||||||
model = (ArchiveTreeModel) tree.getModel();
|
model = (ArchiveTreeModel) tree.getModel();
|
||||||
}
|
}
|
||||||
String name = getFullName(node.name);
|
String name = node.name + ".class";
|
||||||
if (name.contains("/") ? (!name.split("/")[name.split("/").length - 1].contains("$"))
|
if (name.contains("/") ? (!name.split("/")[name.split("/").length - 1].contains("$"))
|
||||||
: (!name.contains("$"))) {
|
: (!name.contains("$"))) {
|
||||||
model.paths.add(name);
|
model.paths.add(name);
|
||||||
@@ -791,26 +783,21 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void decompileCurrentNode() {
|
public static void decompileCurrentNode() {
|
||||||
|
if (currentNodeName == null)
|
||||||
|
return;
|
||||||
try {
|
try {
|
||||||
EnumDecompiler decompiler = Main.decompiler;
|
EnumDecompiler decompiler = Main.decompiler;
|
||||||
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);
|
EventQueue.invokeAndWait(() -> {
|
||||||
synchronized (Main.classNodes) {
|
synchronized (treeLock) {
|
||||||
for (Entry<String, ClassNode> entry : Main.classNodes.entrySet()) {
|
txtByteEditView.setText(dis);
|
||||||
if (entry.getKey().contains("$")) {
|
if (dis.length() > prev)
|
||||||
String[] split = entry.getKey().split("\\$");
|
txtByteEditView.setCaretPosition(prev);
|
||||||
if (split[0].equals(substr)) {
|
|
||||||
dis += "\n" + decompiler.getDecompiler().decompile(entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
txtByteEditView.setText(dis);
|
|
||||||
if (dis.length() > prev)
|
|
||||||
txtByteEditView.setCaretPosition(prev);
|
|
||||||
} catch (Exception e2) {
|
} catch (Exception e2) {
|
||||||
e2.printStackTrace();
|
e2.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -818,6 +805,7 @@ public class Main extends JFrame {
|
|||||||
|
|
||||||
public static void selectFile(String s) {
|
public static void selectFile(String s) {
|
||||||
if (s != null && s.endsWith(".class")) {
|
if (s != null && s.endsWith(".class")) {
|
||||||
|
s = s.substring(0, s.length() - 6);
|
||||||
currentNodeName = s;
|
currentNodeName = s;
|
||||||
decompileCurrentNode();
|
decompileCurrentNode();
|
||||||
txtByteEditView.setCaretPosition(0);
|
txtByteEditView.setCaretPosition(0);
|
||||||
@@ -869,14 +857,16 @@ public class Main extends JFrame {
|
|||||||
public void run() {
|
public void run() {
|
||||||
synchronized (treeLock) {
|
synchronized (treeLock) {
|
||||||
save(file, classNodes.values());
|
save(file, classNodes.values());
|
||||||
EventQueue.invokeLater(new Runnable() {
|
try {
|
||||||
public void run() {
|
EventQueue.invokeAndWait(new Runnable() {
|
||||||
synchronized (treeLock) {
|
public void run() {
|
||||||
isChangingFile = false;
|
isChangingFile = false;
|
||||||
Main.this.setTitle("ByteEdit");
|
Main.this.setTitle("ByteEdit");
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
@@ -930,7 +920,7 @@ public class Main extends JFrame {
|
|||||||
for (ClassNode node : classes) {
|
for (ClassNode node : classes) {
|
||||||
ClassWriter writer = new ClassWriter(computeFlags);
|
ClassWriter writer = new ClassWriter(computeFlags);
|
||||||
node.accept(writer);
|
node.accept(writer);
|
||||||
output.putNextEntry(new ZipEntry(getFullName(node.name)));
|
output.putNextEntry(new ZipEntry(node.name + ".class"));
|
||||||
output.write(writer.toByteArray());
|
output.write(writer.toByteArray());
|
||||||
output.closeEntry();
|
output.closeEntry();
|
||||||
}
|
}
|
||||||
@@ -956,8 +946,4 @@ public class Main extends JFrame {
|
|||||||
public static void showError(String s) {
|
public static void showError(String s) {
|
||||||
JOptionPane.showMessageDialog(INSTANCE, s, "Error!", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(INSTANCE, s, "Error!", JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFullName(String s) {
|
|
||||||
return s + ".class";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -320,11 +320,9 @@ public class ClassUtil {
|
|||||||
s += "enum ";
|
s += "enum ";
|
||||||
acc ^= ACC_ENUM;
|
acc ^= ACC_ENUM;
|
||||||
}
|
}
|
||||||
if (acc == access) {
|
if (acc == access)
|
||||||
return s;
|
return s;
|
||||||
} else {
|
return "0x" + Integer.toHexString(access) + " ";
|
||||||
return "0x" + Integer.toHexString(access) + " ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -544,8 +542,7 @@ public class ClassUtil {
|
|||||||
DecompilationInterface di = diMap.get(o.getClass());
|
DecompilationInterface di = diMap.get(o.getClass());
|
||||||
if (di != null)
|
if (di != null)
|
||||||
return di.apply(o, desc, escapeSpaces, hs);
|
return di.apply(o, desc, escapeSpaces, hs);
|
||||||
else
|
return o.toString();
|
||||||
return o.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDecompiledValue(Object o, String desc, HugeStrings hs) {
|
public static String getDecompiledValue(Object o, String desc, HugeStrings hs) {
|
||||||
|
|||||||
@@ -84,11 +84,9 @@ public class UnicodeUtils {
|
|||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
}
|
||||||
if (stage != 0) {
|
if (stage != 0) {
|
||||||
if (unicodeBuffer != 0) {
|
if (unicodeBuffer != 0)
|
||||||
throw new IllegalArgumentException("The unicode at the end is incomplete.");
|
throw new IllegalArgumentException("The unicode at the end is incomplete.");
|
||||||
} else {
|
throw new IllegalArgumentException("'\\' at the end is invalid.");
|
||||||
throw new IllegalArgumentException("'\\' at the end is invalid.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user