1.3 released
10/22/2014 - Imported Bibl's Bytecode Decompiler from CFIDE. 10/22/2014 - Did some changes to the Bytecode Decompiler. 10/23/2014 - Added CFR settings. 10/23/2014 - Updated FernFlower to Intellij's Open Sourced version of FernFlower. 10/24/2014 - Fixed FernFlower save Java files as zip. 10/29/2014 - Added version checker. 10/29/2014 - Added Procyon settings. 10/29/2014 - When saving as jars or zips, it'll automatically append the file extension if it's not added. 10/29/2014 - All the built in plugins no longer set the cursor to busy. 10/29/2014 - Tried to fix the issue with JSyntaxPane by making it create the object in a background thread, it still freezes the UI. Changes kept for later implementation of another syntax highlighter. 10/29/2014 - Sped up start up time
This commit is contained in:
parent
069246a297
commit
30dc40a095
BIN
BytecodeViewer Beta 1.3.jar
Normal file
BIN
BytecodeViewer Beta 1.3.jar
Normal file
Binary file not shown.
BIN
libs/byteanalysis-1.0.jar
Normal file
BIN
libs/byteanalysis-1.0.jar
Normal file
Binary file not shown.
BIN
libs/fernflower2014.jar
Normal file
BIN
libs/fernflower2014.jar
Normal file
Binary file not shown.
Binary file not shown.
|
@ -2,9 +2,12 @@ package the.bytecode.club.bytecodeviewer;
|
|||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
@ -44,9 +47,10 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager;
|
|||
* class loaded in the file system to the execute function, this allows the user to handle it
|
||||
* completely using ASM.
|
||||
*
|
||||
* Bytecode Decompiler, File Navigation Pane, Search Pane and Work Pane based off of J-RET by WaterWolf - https://github.com/Waterwolf/Java-ReverseEngineeringTool
|
||||
* File Navigation Pane, Search Pane and Work Pane based off of J-RET by WaterWolf - https://github.com/Waterwolf/Java-ReverseEngineeringTool
|
||||
* HexViewer pane based off of Re-Java's by Sami Koivu - http://rejava.sourceforge.net/
|
||||
* Java Decompiler is a modified version of FernFlower
|
||||
* Java Decompiler is a modified version of FernFlower, Procyon and CFR.
|
||||
* Bytecode Decompiler base & ByteAnalysis lib by Bibl. -
|
||||
*
|
||||
* TODO:
|
||||
* Fix the fucking import jar method cause it's a bitch on memory (at the.bytecode.club.bytecodeviewer.JarUtils.getNode(JarUtils.java:83))
|
||||
|
@ -56,6 +60,8 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager;
|
|||
* Middle mouse click should close tabs
|
||||
* http://i.imgur.com/yHaai9D.png
|
||||
*
|
||||
*
|
||||
* ----Beta 1.0-----:
|
||||
* 10/4/2014 - Designed a POC GUI, still needs a lot of work.
|
||||
* 10/4/2014 - Started importing J-RET's backend.
|
||||
* 10/5/2014 - Finished importing J-RET's backend.
|
||||
|
@ -114,9 +120,23 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager;
|
|||
* 10/16/2014 - Now if you try search with an empty string, it won't search.
|
||||
* 10/16/2014 - Added Replace Strings plugin.
|
||||
* 10/16/2014 - Added a loading icon that displays whenever a background task is being executed.
|
||||
* ----Beta 1.1-----:
|
||||
* 10/19/2014 - Fixed harcoded \\.
|
||||
* ----Beta 1.2-----:
|
||||
* 10/19/2014 - Started importing Procyon and CFR decompilers.
|
||||
* 10/19/2014 - Partially finished importing Procyon and CFR, just need to finish export java files as zip.
|
||||
* ----Beta 1.3-----:
|
||||
* 10/22/2014 - Imported Bibl's Bytecode Decompiler from CFIDE.
|
||||
* 10/22/2014 - Did some changes to the Bytecode Decompiler.
|
||||
* 10/23/2014 - Added CFR settings.
|
||||
* 10/23/2014 - Updated FernFlower to Intellij's Open Sourced version of FernFlower.
|
||||
* 10/24/2014 - Fixed FernFlower save Java files as zip.
|
||||
* 10/29/2014 - Added version checker.
|
||||
* 10/29/2014 - Added Procyon settings.
|
||||
* 10/29/2014 - When saving as jars or zips, it'll automatically append the file extension if it's not added.
|
||||
* 10/29/2014 - All the built in plugins no longer set the cursor to busy.
|
||||
* 10/29/2014 - Tried to fix the issue with JSyntaxPane by making it create the object in a background thread, it still freezes the UI. Changes kept for later implementation of another syntax highlighter.
|
||||
* 10/29/2014 - Sped up start up time.
|
||||
*
|
||||
* @author Konloch
|
||||
*
|
||||
|
@ -135,6 +155,7 @@ public class BytecodeViewer {
|
|||
public static String tempDirectory = "bcv_temp";
|
||||
public static String fs = System.getProperty("file.separator");
|
||||
public static String nl = System.getProperty("line.separator");
|
||||
public static String version = "Beta 1.3";
|
||||
|
||||
public static void main(String[] args) {
|
||||
cleanup();
|
||||
|
@ -144,14 +165,32 @@ public class BytecodeViewer {
|
|||
cleanup();
|
||||
}
|
||||
});
|
||||
Thread versionChecker = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL("https://raw.githubusercontent.com/Konloch/bytecode-viewer/master/VERSION").openConnection();
|
||||
connection.setUseCaches(false);
|
||||
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String version = reader.readLine();
|
||||
reader.close();
|
||||
if(!BytecodeViewer.version.equals(version))
|
||||
showMessage("You're running an outdated version of Bytecode Viewer, current version: " + BytecodeViewer.version + ", latest version: " + version);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
versionChecker.start();
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
viewer = new MainViewerGUI();
|
||||
viewer.setVisible(true);
|
||||
resetRecentFilesMenu();
|
||||
viewer.setVisible(true);
|
||||
}
|
||||
|
||||
public static ClassNode getClassNode(String name) {
|
||||
|
@ -180,7 +219,7 @@ public class BytecodeViewer {
|
|||
if (fn.endsWith(".jar")) {
|
||||
try {
|
||||
JarUtils.put(f, BytecodeViewer.loadedClasses);
|
||||
} catch (final IOException e) {
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
@ -232,6 +271,8 @@ public class BytecodeViewer {
|
|||
for (int k = 0; k < options.length; k++)
|
||||
if (options[k].equals(obj))
|
||||
result = k;
|
||||
|
||||
|
||||
if(result == 0) {
|
||||
loadedResources.clear();
|
||||
loadedClasses.clear();
|
||||
|
@ -318,16 +359,14 @@ public class BytecodeViewer {
|
|||
public static void cleanup() {
|
||||
tempF = new File(tempDirectory);
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
FileUtils.deleteDirectory(tempF);
|
||||
Thread.sleep(100);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
while(!tempF.exists()) { //keep making dirs
|
||||
try {
|
||||
tempF.mkdir();
|
||||
Thread.sleep(100);
|
||||
Thread.sleep(1);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,381 +0,0 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.IincInsnNode;
|
||||
import org.objectweb.asm.tree.IntInsnNode;
|
||||
import org.objectweb.asm.tree.JumpInsnNode;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TryCatchBlockNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.searching.commons.InstructionSearcher;
|
||||
|
||||
/**
|
||||
* A Bytecode decompiler
|
||||
*
|
||||
* @author Konloch
|
||||
* @author WaterWolf
|
||||
*
|
||||
*/
|
||||
|
||||
public class BytecodeDecompiler {
|
||||
|
||||
public static String[] opcodeStrings;
|
||||
public static String[] typeStrings;
|
||||
|
||||
static {
|
||||
opcodeStrings = new String[256];
|
||||
for (final Field f : Opcodes.class.getFields()) {
|
||||
try {
|
||||
final Object oo = f.get(null);
|
||||
if (oo instanceof Integer) {
|
||||
final int oi = ((Integer)oo);
|
||||
if (oi < 256 && oi >= 0) {
|
||||
opcodeStrings[oi] = f.getName().toLowerCase();
|
||||
}
|
||||
}
|
||||
} catch (final IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (final IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
typeStrings = new String[100];
|
||||
for (final Field f : AbstractInsnNode.class.getFields()) {
|
||||
if (!(f.getName().endsWith("_INSN"))) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
final Object oo = f.get(null);
|
||||
if (oo instanceof Integer) {
|
||||
final int oi = ((Integer)oo);
|
||||
if (oi < 256 && oi >= 0) {
|
||||
typeStrings[oi] = f.getName().toLowerCase();
|
||||
}
|
||||
}
|
||||
} catch (final IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (final IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public String decompileClassNode(final ClassNode cn) {
|
||||
final StringBuilder classBuilder = new StringBuilder();
|
||||
final ClassStringBuilder cb = new ClassStringBuilder(classBuilder);
|
||||
|
||||
final String cnm = cn.name;
|
||||
String package_ = null;
|
||||
String class_ = null;
|
||||
if (cnm.contains("/")) {
|
||||
package_ = cnm.substring(0, cnm.lastIndexOf("/"));
|
||||
class_ = cnm.substring(cnm.lastIndexOf("/")+1);
|
||||
}
|
||||
else {
|
||||
class_ = cnm;
|
||||
}
|
||||
|
||||
if (package_ != null) {
|
||||
cb.appendnl("package " + package_ + ";", 2);
|
||||
}
|
||||
|
||||
cb.append(Modifier.toString(cn.access) + " class " + class_ + " ");
|
||||
|
||||
if (cn.superName != null) {
|
||||
cb.append("extends " + cn.superName + " ");
|
||||
}
|
||||
if (cn.interfaces.size() > 0) {
|
||||
cb.append("implements ");
|
||||
final Iterator<String> sit = cn.interfaces.iterator();
|
||||
while (sit.hasNext()) {
|
||||
final String s = sit.next();
|
||||
cb.append(s);
|
||||
if (sit.hasNext()) {
|
||||
cb.append(", ");
|
||||
} else {
|
||||
cb.append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cb.appendnl("{");
|
||||
cb.increase();
|
||||
cb.appendnl();
|
||||
|
||||
final Iterator<FieldNode> fni = cn.fields.iterator();
|
||||
|
||||
while (fni.hasNext()) {
|
||||
final FieldNode fn = fni.next();
|
||||
|
||||
cb.appendnl(Modifier.toString(fn.access) + " " + Type.getType(fn.desc).getClassName() + " " + fn.name + ";");
|
||||
|
||||
}
|
||||
|
||||
cb.appendnl();
|
||||
|
||||
final Iterator<MethodNode> mni = cn.methods.iterator();
|
||||
while (mni.hasNext()) {
|
||||
final MethodNode mn = mni.next();
|
||||
final String mnm = mn.name;
|
||||
if (!mnm.equals("<clinit>")) {
|
||||
cb.append(Modifier.toString(mn.access) + " ");
|
||||
}
|
||||
|
||||
if (mnm.equals("<init>")) {
|
||||
cb.append(class_);
|
||||
}
|
||||
else if (mnm.equals("<clinit>")) {
|
||||
cb.append("static {");
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected())
|
||||
cb.appendnl(" // <clinit>");
|
||||
else
|
||||
cb.appendnl();
|
||||
}
|
||||
else {
|
||||
cb.append(Type.getReturnType(mn.desc).getClassName() + " ");
|
||||
cb.append(mnm);
|
||||
}
|
||||
|
||||
TypeAndName[] args = new TypeAndName[0];
|
||||
|
||||
if (!mnm.equals("<clinit>")) {
|
||||
cb.append("(");
|
||||
|
||||
// TODO desc
|
||||
final Type[] argTypes = Type.getArgumentTypes(mn.desc);
|
||||
args = new TypeAndName[argTypes.length];
|
||||
|
||||
for (int i = 0;i < argTypes.length; i++) {
|
||||
final Type type = argTypes[i];
|
||||
|
||||
final TypeAndName tan = new TypeAndName();
|
||||
final String argName = "arg" + i;
|
||||
|
||||
tan.name = argName;
|
||||
tan.type = type;
|
||||
|
||||
args[i] = tan;
|
||||
|
||||
cb.append(type.getClassName() + " " + argName + (i < argTypes.length-1 ? ", " : ""));
|
||||
}
|
||||
|
||||
cb.appendnl(") {");
|
||||
}
|
||||
|
||||
cb.increase();
|
||||
|
||||
try {
|
||||
decompileMethod(cb, args, mn, cn);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
cb.decrease();
|
||||
cb.appendnl("}");
|
||||
cb.appendnl();
|
||||
}
|
||||
|
||||
cb.decrease();
|
||||
cb.appendnl("}");
|
||||
|
||||
|
||||
return classBuilder.toString();
|
||||
}
|
||||
|
||||
public void decompileMethod(final ClassStringBuilder builder, final TypeAndName[] args, final MethodNode mn, final ClassNode parent) throws UnsupportedEncodingException {
|
||||
final InstructionSearcher is = new InstructionSearcher(mn);
|
||||
//AbstractInsnNode next = is.getCurrent();
|
||||
|
||||
for(Object e : mn.tryCatchBlocks.toArray()) {
|
||||
TryCatchBlockNode t = (TryCatchBlockNode)e;
|
||||
String type = t.type;
|
||||
LabelNode start = t.start;
|
||||
LabelNode end = t.end;
|
||||
LabelNode handler = t.handler;
|
||||
builder.appendnl("trycatch block L" + start.hashCode() + " to L" + end.hashCode() + " handled by L" + handler.hashCode() + " exception type: " + type);
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for(AbstractInsnNode next : mn.instructions.toArray()) {
|
||||
|
||||
if (next.getOpcode() == -1) {
|
||||
|
||||
if(next instanceof LabelNode) {
|
||||
LabelNode l = (LabelNode)next;
|
||||
builder.appendnl(index++ + ". L" +l.hashCode());
|
||||
} else {
|
||||
builder.appendnl(index++ + ". nop //actually an unimplement opcode, please contact Konloch"); //lets just set it as nop for now.
|
||||
}
|
||||
//next = is.getNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.append(index++ + ". " + opcodeStrings[next.getOpcode()] + " ");
|
||||
|
||||
if (next instanceof FieldInsnNode) {
|
||||
final FieldInsnNode fin = (FieldInsnNode) next;
|
||||
builder.append(fin.owner + " " + fin.name + " " + fin.desc);
|
||||
}
|
||||
else if (next instanceof MethodInsnNode) {
|
||||
final MethodInsnNode min = (MethodInsnNode) next;
|
||||
builder.append(min.owner + " " + min.name + " " + min.desc);
|
||||
}
|
||||
else if (next instanceof VarInsnNode) {
|
||||
final VarInsnNode vin = (VarInsnNode) next;
|
||||
builder.append(vin.var);
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected()) {
|
||||
if (vin.var == 0 && !Modifier.isStatic(mn.access)) {
|
||||
builder.append(" // reference to self");
|
||||
}
|
||||
else {
|
||||
final int refIndex = vin.var - (Modifier.isStatic(mn.access) ? 0 : 1);
|
||||
if (refIndex >= 0 && refIndex < args.length-1) {
|
||||
builder.append(" // reference to " + args[refIndex].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (next instanceof IntInsnNode) {
|
||||
final IntInsnNode iin = (IntInsnNode) next;
|
||||
builder.append(iin.operand);
|
||||
}
|
||||
else if (next instanceof JumpInsnNode) {
|
||||
final JumpInsnNode jin = (JumpInsnNode) next;
|
||||
builder.append(is.computePosition(jin.label));
|
||||
switch (next.getOpcode()) {
|
||||
case Opcodes.IF_ICMPLT:
|
||||
builder.append(" // if val1 less than val2 jump");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (next instanceof LdcInsnNode) {
|
||||
final LdcInsnNode lin = (LdcInsnNode) next;
|
||||
if(lin.cst instanceof String) {
|
||||
String s = ((String)lin.cst).replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r").replaceAll("\\\"", "\\\\\"");
|
||||
if(BytecodeViewer.viewer.chckbxmntmNewCheckItem.isSelected())
|
||||
builder.append("\"" + StringEscapeUtils.escapeJava(s) + "\"");
|
||||
else
|
||||
builder.append("\"" + s + "\"");
|
||||
} else {
|
||||
String s = lin.cst.toString().replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r").replaceAll("\\\"", "\\\\\"");
|
||||
if(BytecodeViewer.viewer.chckbxmntmNewCheckItem.isSelected())
|
||||
builder.append("\"" + StringEscapeUtils.escapeJava(s) + "\"");
|
||||
else
|
||||
builder.append("\"" + s + "\"");
|
||||
}
|
||||
}
|
||||
else if (next instanceof IincInsnNode) {
|
||||
final IincInsnNode iin = (IincInsnNode) next;
|
||||
builder.append("var " + iin.var + " by " + iin.incr);
|
||||
}
|
||||
else if (next instanceof TypeInsnNode) {
|
||||
final TypeInsnNode tin = (TypeInsnNode) next;
|
||||
builder.append(tin.desc);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
switch (next.getOpcode()) {
|
||||
case Opcodes.IF_ICMPLT:
|
||||
buffer.append(" // ");
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (BytecodeViewer.viewer.debugInstructions.isSelected()) {
|
||||
builder.append(" // " + typeStrings[next.getType()] + " ");
|
||||
}
|
||||
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected() &&
|
||||
next instanceof JumpInsnNode)
|
||||
{
|
||||
final JumpInsnNode jin = (JumpInsnNode) next;
|
||||
builder.append(" // line " + is.computePosition(jin.label) + " is " + printInstruction(is.computePosition(jin.label), mn, is).trim());
|
||||
}
|
||||
|
||||
builder.appendnl();
|
||||
}
|
||||
}
|
||||
|
||||
public static String printInstruction(int line, MethodNode mn, InstructionSearcher is) {
|
||||
for(int i = 0; i < mn.instructions.size(); i++) {
|
||||
AbstractInsnNode next = mn.instructions.get(i);
|
||||
if(line == i)
|
||||
if(next.getOpcode() != -1) {
|
||||
return beatifyAbstractInsnNode(next, is);
|
||||
}
|
||||
}
|
||||
return "Unable to find, please contact konloch.";
|
||||
}
|
||||
|
||||
public static String beatifyAbstractInsnNode(AbstractInsnNode next, InstructionSearcher is) {
|
||||
String insn = "";
|
||||
|
||||
if(next.getOpcode() != -1)
|
||||
insn =opcodeStrings[next.getOpcode()] + " ";
|
||||
else if(next instanceof LabelNode) {
|
||||
LabelNode l = (LabelNode)next;
|
||||
insn = "L" +l.hashCode();
|
||||
}
|
||||
|
||||
if (next instanceof FieldInsnNode) {
|
||||
final FieldInsnNode fin = (FieldInsnNode) next;
|
||||
insn += fin.owner + " " + fin.name + " " + fin.desc;
|
||||
}
|
||||
else if (next instanceof MethodInsnNode) {
|
||||
final MethodInsnNode min = (MethodInsnNode) next;
|
||||
insn += min.owner + " " + min.name + " " + min.desc;
|
||||
}
|
||||
else if (next instanceof VarInsnNode) {
|
||||
final VarInsnNode vin = (VarInsnNode) next;
|
||||
insn += vin.var;
|
||||
}
|
||||
else if (next instanceof IntInsnNode) {
|
||||
final IntInsnNode iin = (IntInsnNode) next;
|
||||
insn += iin.operand;
|
||||
}
|
||||
else if (next instanceof JumpInsnNode) {
|
||||
final JumpInsnNode jin = (JumpInsnNode) next;
|
||||
insn += is.computePosition(jin.label);
|
||||
}
|
||||
else if (next instanceof LdcInsnNode) {
|
||||
final LdcInsnNode lin = (LdcInsnNode) next;
|
||||
if(lin.cst instanceof String)
|
||||
insn += "\"" + ((String) lin.cst).replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r") + "\"";
|
||||
else
|
||||
insn += "\"" + lin.cst + "\"";
|
||||
}
|
||||
else if (next instanceof IincInsnNode) {
|
||||
final IincInsnNode iin = (IincInsnNode) next;
|
||||
insn += "var " + iin.var + " by " + iin.incr;
|
||||
}
|
||||
else if (next instanceof TypeInsnNode) {
|
||||
final TypeInsnNode tin = (TypeInsnNode) next;
|
||||
insn += tin.desc;
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.InnerClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konloch
|
||||
* @author Bibl
|
||||
*
|
||||
*/
|
||||
|
||||
public class ClassNodeDecompiler {
|
||||
|
||||
public static String decompile(ClassNode cn) {
|
||||
return decompileClassNode(new PrefixedStringBuilder(), new ArrayList<String>(), cn).toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static PrefixedStringBuilder decompileClassNode(PrefixedStringBuilder sb, ArrayList<String> decompiledClasses, ClassNode cn) {
|
||||
ArrayList<String> unableToDecompile = new ArrayList<String>();
|
||||
decompiledClasses.add(cn.name);
|
||||
sb.append(getAccessString(cn.access));
|
||||
sb.append(" ");
|
||||
sb.append(cn.name);
|
||||
if (cn.superName != null && !cn.superName.equals("java/lang/Object")) {
|
||||
sb.append(" extends " + cn.superName);
|
||||
}
|
||||
|
||||
int amountOfInterfaces = cn.interfaces.size();
|
||||
if (amountOfInterfaces > 0) {
|
||||
sb.append(" implements ");
|
||||
sb.append(cn.interfaces.get(0));
|
||||
if (amountOfInterfaces > 1) {
|
||||
// sb.append(",");
|
||||
}
|
||||
for (int i = 1; i < amountOfInterfaces; i++) {
|
||||
sb.append(", ");
|
||||
sb.append(cn.interfaces.get(i));
|
||||
}
|
||||
}
|
||||
sb.append(" {"+BytecodeViewer.nl);
|
||||
for (FieldNode fn : (List<FieldNode>)cn.fields) {
|
||||
sb.append(BytecodeViewer.nl+" ");
|
||||
FieldNodeDecompiler.decompile(sb, fn);
|
||||
}
|
||||
if (cn.fields.size() > 0) {
|
||||
sb.append(BytecodeViewer.nl);
|
||||
}
|
||||
for (MethodNode mn : (List<MethodNode>)cn.methods) {
|
||||
sb.append(BytecodeViewer.nl);
|
||||
MethodNodeDecompiler.decompile(sb, mn, cn);
|
||||
}
|
||||
|
||||
for (Object o : cn.innerClasses) {
|
||||
InnerClassNode innerClassNode = (InnerClassNode) o;
|
||||
String innerClassName = innerClassNode.name;
|
||||
if ((innerClassName != null) && !decompiledClasses.contains(innerClassName)) {
|
||||
decompiledClasses.add(innerClassName);
|
||||
ClassNode cn1 = BytecodeViewer.getClassNode(innerClassName);
|
||||
if (cn1 != null) {
|
||||
sb.appendPrefix(" ");
|
||||
sb.append(BytecodeViewer.nl+BytecodeViewer.nl);
|
||||
sb = decompileClassNode(sb, decompiledClasses, cn1);
|
||||
sb.trimPrefix(5);
|
||||
sb.append(BytecodeViewer.nl);
|
||||
} else {
|
||||
unableToDecompile.add(innerClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!unableToDecompile.isEmpty()) {
|
||||
sb.append("//the following inner classes couldn't be decompiled: ");
|
||||
for(String s : unableToDecompile)
|
||||
sb.append(s + " ");
|
||||
sb.append(BytecodeViewer.nl);
|
||||
}
|
||||
|
||||
sb.append("}");
|
||||
// System.out.println("Wrote end for " + cn.name + " with prefix length: " + sb.prefix.length());
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static String getAccessString(int access) {
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
if ((access & Opcodes.ACC_PUBLIC) != 0)
|
||||
tokens.add("public");
|
||||
if ((access & Opcodes.ACC_PRIVATE) != 0)
|
||||
tokens.add("private");
|
||||
if ((access & Opcodes.ACC_PROTECTED) != 0)
|
||||
tokens.add("protected");
|
||||
if ((access & Opcodes.ACC_FINAL) != 0)
|
||||
tokens.add("final");
|
||||
if ((access & Opcodes.ACC_SYNTHETIC) != 0)
|
||||
tokens.add("synthetic");
|
||||
// if ((access & Opcodes.ACC_SUPER) != 0)
|
||||
// tokens.add("super"); implied by invokespecial insn
|
||||
if ((access & Opcodes.ACC_ABSTRACT) != 0)
|
||||
tokens.add("abstract");
|
||||
if ((access & Opcodes.ACC_INTERFACE) != 0)
|
||||
tokens.add("interface");
|
||||
if ((access & Opcodes.ACC_ENUM) != 0)
|
||||
tokens.add("enum");
|
||||
if ((access & Opcodes.ACC_ANNOTATION) != 0)
|
||||
tokens.add("annotation");
|
||||
if (!tokens.contains("interface") && !tokens.contains("enum") && !tokens.contains("annotation"))
|
||||
tokens.add("class");
|
||||
if (tokens.size() == 0)
|
||||
return "[Error parsing]";
|
||||
|
||||
// hackery delimeters
|
||||
StringBuilder sb = new StringBuilder(tokens.get(0));
|
||||
for (int i = 1; i < tokens.size(); i++) {
|
||||
sb.append(" ");
|
||||
sb.append(tokens.get(i));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
/**
|
||||
* The buffer where decompiler classes output generated source
|
||||
*
|
||||
* @author Waterwolf
|
||||
*
|
||||
*/
|
||||
public class ClassStringBuilder {
|
||||
private final StringBuilder builder;
|
||||
public final IndentationLevel iLevel;
|
||||
private static final String nl = System.getProperty("line.separator");
|
||||
private static final int TAB_SPACES = 4;
|
||||
private boolean isNewline = true;
|
||||
|
||||
public ClassStringBuilder(final StringBuilder builder) {
|
||||
this.builder = builder;
|
||||
this.iLevel = new IndentationLevel();
|
||||
}
|
||||
|
||||
public void append(final Object obj) {
|
||||
if (isNewline) {
|
||||
for (int i = 0;i < TAB_SPACES*iLevel.indentation; i++) {
|
||||
builder.append(" ");
|
||||
}
|
||||
}
|
||||
builder.append(obj);
|
||||
isNewline = false;
|
||||
}
|
||||
|
||||
public void appendnl(final String s) {
|
||||
appendnl(s, 1);
|
||||
}
|
||||
|
||||
public void appendnl() {
|
||||
appendnl("", 1);
|
||||
}
|
||||
|
||||
public void appendnl(final String s, final int nlAmount) {
|
||||
append(s);
|
||||
for (int i = 0;i < nlAmount; i++) {
|
||||
builder.append(nl);
|
||||
}
|
||||
if (nlAmount > 0) {
|
||||
isNewline = true;
|
||||
}
|
||||
}
|
||||
|
||||
public int increase() {
|
||||
return iLevel.increase();
|
||||
}
|
||||
|
||||
public int decrease() {
|
||||
return iLevel.decrease();
|
||||
}
|
||||
|
||||
public int get() {
|
||||
return iLevel.get();
|
||||
}
|
||||
|
||||
public static class IndentationLevel {
|
||||
private int indentation = 0;
|
||||
|
||||
public int increase() {
|
||||
return ++indentation;
|
||||
}
|
||||
|
||||
public int decrease() {
|
||||
return --indentation;
|
||||
}
|
||||
|
||||
public int get() {
|
||||
return indentation;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konloch
|
||||
* @author Bibl
|
||||
*
|
||||
*/
|
||||
|
||||
public class FieldNodeDecompiler {
|
||||
|
||||
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb, FieldNode f) {
|
||||
String s = getAccessString(f.access);
|
||||
sb.append(s);
|
||||
if (s.length() > 0)
|
||||
sb.append(" ");
|
||||
sb.append(Type.getType(f.desc).getClassName());
|
||||
sb.append(" ");
|
||||
sb.append(f.name);
|
||||
if (f.value != null) {
|
||||
sb.append(" = ");
|
||||
if (f.value instanceof String) {
|
||||
sb.append("\"");
|
||||
sb.append(f.value);
|
||||
sb.append("\"");
|
||||
} else {
|
||||
sb.append(f.value);
|
||||
sb.append(" (");
|
||||
sb.append(f.value.getClass().getCanonicalName());
|
||||
sb.append(")");
|
||||
}
|
||||
}
|
||||
sb.append(";");
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static String getAccessString(int access) {
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
if ((access & Opcodes.ACC_PUBLIC) != 0)
|
||||
tokens.add("public");
|
||||
if ((access & Opcodes.ACC_PRIVATE) != 0)
|
||||
tokens.add("private");
|
||||
if ((access & Opcodes.ACC_PROTECTED) != 0)
|
||||
tokens.add("protected");
|
||||
if ((access & Opcodes.ACC_SYNTHETIC) != 0)
|
||||
tokens.add("synthetic");
|
||||
if ((access & Opcodes.ACC_STATIC) != 0)
|
||||
tokens.add("static");
|
||||
if ((access & Opcodes.ACC_FINAL) != 0)
|
||||
tokens.add("final");
|
||||
if ((access & Opcodes.ACC_TRANSIENT) != 0)
|
||||
tokens.add("transient");
|
||||
if ((access & Opcodes.ACC_VOLATILE) != 0)
|
||||
tokens.add("volatile");
|
||||
if (tokens.size() == 0)
|
||||
return "";
|
||||
// hackery delimeters
|
||||
StringBuilder sb = new StringBuilder(tokens.get(0));
|
||||
for (int i = 1; i < tokens.size(); i++) {
|
||||
sb.append(" ");
|
||||
sb.append(tokens.get(i));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.IincInsnNode;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.JumpInsnNode;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MultiANewArrayInsnNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import eu.bibl.banalysis.filter.InstructionFilter;
|
||||
import eu.bibl.banalysis.filter.OpcodeFilter;
|
||||
import eu.bibl.banalysis.filter.insn.FieldInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.IincInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.InsnInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.JumpInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.LdcInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.MethodInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.MultiANewArrayInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.TypeInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.VarInstructionFilter;
|
||||
|
||||
/**
|
||||
* Pattern filter holder and stepper.
|
||||
* @author Bibl
|
||||
*
|
||||
*/
|
||||
public class InstructionPattern implements Opcodes {
|
||||
|
||||
/** Last instruction-match position pointer **/
|
||||
protected int pointer;
|
||||
/** Filters/patterns/search criteria. **/
|
||||
protected InstructionFilter[] filters;
|
||||
/** Last match found cache. **/
|
||||
protected AbstractInsnNode[] lastMatch;
|
||||
|
||||
/**
|
||||
* Construct a new pattern from the specified instructions.
|
||||
* @param insns {@link AbstractInsnNode} pattern array.
|
||||
*/
|
||||
public InstructionPattern(AbstractInsnNode[] insns) {
|
||||
filters = translate(insns);
|
||||
lastMatch = new AbstractInsnNode[insns.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new pattern from the specified opcode.
|
||||
* @param opcodes Opcodes to convert to {@link OpcodeFilter}s.
|
||||
*/
|
||||
public InstructionPattern(int[] opcodes) {
|
||||
filters = new InstructionFilter[opcodes.length];
|
||||
lastMatch = new AbstractInsnNode[opcodes.length];
|
||||
for(int i = 0; i < opcodes.length; i++) {
|
||||
filters[i] = new OpcodeFilter(opcodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an absolute pattern from user-defined filters.
|
||||
* @param filters User-defined {@link InstructionFilter}s.
|
||||
*/
|
||||
public InstructionPattern(InstructionFilter[] filters) {
|
||||
this.filters = filters;
|
||||
lastMatch = new AbstractInsnNode[filters.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Steps through the instruction list checking if the current instruction ended a successful pattern-match sequence.
|
||||
* @param ain {@link AbstractInsnNode} to check.
|
||||
* @return True if this instruction successfully completed the pattern.
|
||||
*/
|
||||
public boolean accept(AbstractInsnNode ain) {
|
||||
if (pointer >= filters.length)
|
||||
reset();
|
||||
|
||||
InstructionFilter filter = filters[pointer];
|
||||
if (filter.accept(ain)) {
|
||||
lastMatch[pointer] = ain;
|
||||
if (pointer >= (filters.length - 1)) {
|
||||
return true;
|
||||
}
|
||||
pointer++;
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Last pattern sequence match equivilent from the inputted {@link AbstractInsnNode}s.
|
||||
*/
|
||||
public AbstractInsnNode[] getLastMatch() {
|
||||
return lastMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the instruction pointer and clears the last match cache data.
|
||||
*/
|
||||
public void resetMatch() {
|
||||
reset();
|
||||
AbstractInsnNode[] match = lastMatch;
|
||||
lastMatch = new AbstractInsnNode[match.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current instruction pointer to 0 (start of pattern).
|
||||
*/
|
||||
public void reset() {
|
||||
pointer = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array of {@link AbstractInsnNode}s to their {@link InstructionFilter} counterparts.
|
||||
* @param ains {@link AbstractInsnNode}s to convert.
|
||||
* @return Array of {@link InstructionFilter}s.
|
||||
*/
|
||||
public static InstructionFilter[] translate(AbstractInsnNode[] ains) {
|
||||
InstructionFilter[] filters = new InstructionFilter[ains.length];
|
||||
for(int i = 0; i < ains.length; i++) {
|
||||
filters[i] = translate(ains[i]);
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a single {@link AbstractInsnNode} to an {@link InstructionFilter}.
|
||||
* @param ain Instruction to convert.
|
||||
* @return A filter an an equivilent to the inputted instruction.
|
||||
*/
|
||||
public static InstructionFilter translate(AbstractInsnNode ain) {
|
||||
if (ain instanceof LdcInsnNode) {
|
||||
return new LdcInstructionFilter(((LdcInsnNode) ain).cst);
|
||||
} else if (ain instanceof TypeInsnNode) {
|
||||
return new TypeInstructionFilter(ain.getOpcode(), ((TypeInsnNode) ain).desc);
|
||||
} else if (ain instanceof FieldInsnNode) {
|
||||
return new FieldInstructionFilter(ain.getOpcode(), ((FieldInsnNode) ain).owner, ((FieldInsnNode) ain).name, ((FieldInsnNode) ain).desc);
|
||||
} else if (ain instanceof MethodInsnNode) {
|
||||
return new MethodInstructionFilter(ain.getOpcode(), ((MethodInsnNode) ain).owner, ((MethodInsnNode) ain).name, ((MethodInsnNode) ain).desc);
|
||||
} else if (ain instanceof VarInsnNode) {
|
||||
return new VarInstructionFilter(ain.getOpcode(), ((VarInsnNode) ain).var);
|
||||
} else if (ain instanceof InsnNode) {
|
||||
return new InsnInstructionFilter(ain.getOpcode());
|
||||
} else if (ain instanceof IincInsnNode) {
|
||||
return new IincInstructionFilter(((IincInsnNode) ain).incr, ((IincInsnNode) ain).var);
|
||||
} else if (ain instanceof JumpInsnNode) {
|
||||
return new JumpInstructionFilter(ain.getOpcode());
|
||||
} else if (ain instanceof LabelNode) {
|
||||
return InstructionFilter.ACCEPT_ALL; // TODO: Cache labels and check. // TODO: That's a fucking stupid idea.
|
||||
} else if (ain instanceof MultiANewArrayInsnNode) {
|
||||
return new MultiANewArrayInstructionFilter(((MultiANewArrayInsnNode) ain).desc, ((MultiANewArrayInsnNode) ain).dims);
|
||||
} else {
|
||||
return InstructionFilter.ACCEPT_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
AbstractInsnNode[] ains = new AbstractInsnNode[] {
|
||||
new LdcInsnNode("ldc"),
|
||||
new VarInsnNode(ASTORE, 0),
|
||||
new LdcInsnNode("ldc") };
|
||||
InstructionPattern pattern = new InstructionPattern(new AbstractInsnNode[] {
|
||||
new LdcInsnNode("ldc"),
|
||||
new VarInsnNode(-1, -1) });
|
||||
for(AbstractInsnNode ain : ains) {
|
||||
if (pattern.accept(ain)) {
|
||||
System.out.println(Arrays.toString(pattern.getLastMatch()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.FrameNode;
|
||||
import org.objectweb.asm.tree.IincInsnNode;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.IntInsnNode;
|
||||
import org.objectweb.asm.tree.JumpInsnNode;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.LineNumberNode;
|
||||
import org.objectweb.asm.tree.LookupSwitchInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TableSwitchInsnNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.bytecode.TypeAndName;
|
||||
import eu.bibl.banalysis.asm.desc.OpcodeInfo;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konloch
|
||||
* @author Bibl
|
||||
*
|
||||
*/
|
||||
public class InstructionPrinter {
|
||||
|
||||
/** The MethodNode to print **/
|
||||
protected MethodNode mNode;
|
||||
private TypeAndName[] args;
|
||||
|
||||
protected int[] pattern;
|
||||
protected boolean match;
|
||||
protected InstructionSearcher searcher;
|
||||
|
||||
protected List<AbstractInsnNode> matchedInsns;
|
||||
protected Map<LabelNode, Integer> labels;
|
||||
|
||||
public InstructionPrinter(MethodNode m, TypeAndName[] args) {
|
||||
this.args = args;
|
||||
mNode = m;
|
||||
labels = new HashMap<LabelNode, Integer>();
|
||||
// matchedInsns = new ArrayList<AbstractInsnNode>(); // ingnored because match = false
|
||||
match = false;
|
||||
}
|
||||
|
||||
public InstructionPrinter(MethodNode m, InstructionPattern pattern, TypeAndName[] args) {
|
||||
this.args = args;
|
||||
mNode = m;
|
||||
labels = new HashMap<LabelNode, Integer>();
|
||||
searcher = new InstructionSearcher(m.instructions, pattern);
|
||||
match = searcher.search();
|
||||
if (match) {
|
||||
for(AbstractInsnNode[] ains : searcher.getMatches()) {
|
||||
for(AbstractInsnNode ain : ains) {
|
||||
matchedInsns.add(ain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the print
|
||||
* @return The print as an ArrayList
|
||||
*/
|
||||
public ArrayList<String> createPrint() {
|
||||
ArrayList<String> info = new ArrayList<String>();
|
||||
ListIterator<?> it = mNode.instructions.iterator();
|
||||
while (it.hasNext()) {
|
||||
AbstractInsnNode ain = (AbstractInsnNode) it.next();
|
||||
String line = "";
|
||||
if (ain instanceof VarInsnNode) {
|
||||
line = printVarInsnNode((VarInsnNode) ain, it);
|
||||
} else if (ain instanceof IntInsnNode) {
|
||||
line = printIntInsnNode((IntInsnNode) ain, it);
|
||||
} else if (ain instanceof FieldInsnNode) {
|
||||
line = printFieldInsnNode((FieldInsnNode) ain, it);
|
||||
} else if (ain instanceof MethodInsnNode) {
|
||||
line = printMethodInsnNode((MethodInsnNode) ain, it);
|
||||
} else if (ain instanceof LdcInsnNode) {
|
||||
line = printLdcInsnNode((LdcInsnNode) ain, it);
|
||||
} else if (ain instanceof InsnNode) {
|
||||
line = printInsnNode((InsnNode) ain, it);
|
||||
} else if (ain instanceof JumpInsnNode) {
|
||||
line = printJumpInsnNode((JumpInsnNode) ain, it);
|
||||
} else if (ain instanceof LineNumberNode) {
|
||||
line = printLineNumberNode((LineNumberNode) ain, it);
|
||||
} else if (ain instanceof LabelNode) {
|
||||
line = printLabelnode((LabelNode) ain);
|
||||
} else if (ain instanceof TypeInsnNode) {
|
||||
line = printTypeInsnNode((TypeInsnNode) ain);
|
||||
} else if (ain instanceof FrameNode) {
|
||||
line = "";
|
||||
} else if (ain instanceof IincInsnNode) {
|
||||
line = printIincInsnNode((IincInsnNode) ain);
|
||||
} else if (ain instanceof TableSwitchInsnNode) {
|
||||
line = printTableSwitchInsnNode((TableSwitchInsnNode) ain);
|
||||
} else if (ain instanceof LookupSwitchInsnNode) {
|
||||
line = printLookupSwitchInsnNode((LookupSwitchInsnNode) ain);
|
||||
} else {
|
||||
line += "UNADDED OPCODE: " + nameOpcode(ain.getOpcode()) + " " + ain.toString();
|
||||
}
|
||||
if (!line.equals("")) {
|
||||
if (match)
|
||||
if (matchedInsns.contains(ain))
|
||||
line = " -> " + line;
|
||||
|
||||
info.add(line);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
protected String printVarInsnNode(VarInsnNode vin, ListIterator<?> it) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(nameOpcode(vin.getOpcode()));
|
||||
sb.append(vin.var);
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected()) {
|
||||
if (vin.var == 0 && !Modifier.isStatic(mNode.access)) {
|
||||
sb.append(" // reference to self");
|
||||
} else {
|
||||
final int refIndex = vin.var - (Modifier.isStatic(mNode.access) ? 0 : 1);
|
||||
if (refIndex >= 0 && refIndex < args.length-1) {
|
||||
sb.append(" // reference to " + args[refIndex].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String printIntInsnNode(IntInsnNode iin, ListIterator<?> it) {
|
||||
return nameOpcode(iin.getOpcode()) + " " + iin.operand;
|
||||
}
|
||||
|
||||
protected String printFieldInsnNode(FieldInsnNode fin, ListIterator<?> it) {
|
||||
return nameOpcode(fin.getOpcode()) + " " + fin.owner + "." + fin.name + ":" + Type.getType(fin.desc).getClassName();
|
||||
}
|
||||
|
||||
protected String printMethodInsnNode(MethodInsnNode min, ListIterator<?> it) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(nameOpcode(min.getOpcode()) + " " + min.owner + " " + min.name + "(");
|
||||
|
||||
if(Type.getType(min.desc).getClassName() == null ||
|
||||
Type.getType(min.desc).getClassName().equalsIgnoreCase("null"))
|
||||
{
|
||||
//sb.append(min.desc);
|
||||
} else {
|
||||
sb.append(Type.getType(min.desc).getClassName());
|
||||
}
|
||||
sb.append(");");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String printLdcInsnNode(LdcInsnNode ldc, ListIterator<?> it) {
|
||||
if(BytecodeViewer.viewer.chckbxmntmNewCheckItem.isSelected()) { //ascii only
|
||||
if (ldc.cst instanceof String)
|
||||
return nameOpcode(ldc.getOpcode()) + " \"" + StringEscapeUtils.escapeJava(ldc.cst.toString()) + "\" (" + ldc.cst.getClass().getCanonicalName() + ")";
|
||||
|
||||
return nameOpcode(ldc.getOpcode()) + " " + StringEscapeUtils.escapeJava(ldc.cst.toString()) + " (" + ldc.cst.getClass().getCanonicalName() + ")";
|
||||
|
||||
} else {
|
||||
if (ldc.cst instanceof String)
|
||||
return nameOpcode(ldc.getOpcode()) + " \"" + ((String)ldc.cst).replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r").replaceAll("\\\"", "\\\\\"") + "\" (" + ldc.cst.getClass().getCanonicalName() + ")";
|
||||
|
||||
return nameOpcode(ldc.getOpcode()) + " " + ldc.cst + " (" + ldc.cst.getClass().getCanonicalName() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
protected String printInsnNode(InsnNode in, ListIterator<?> it) {
|
||||
return nameOpcode(in.getOpcode());
|
||||
}
|
||||
|
||||
protected String printJumpInsnNode(JumpInsnNode jin, ListIterator<?> it) {
|
||||
String line = nameOpcode(jin.getOpcode()) + " L" + resolveLabel(jin.label);
|
||||
return line;
|
||||
}
|
||||
|
||||
protected String printLineNumberNode(LineNumberNode lin, ListIterator<?> it) {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected String printLabelnode(LabelNode label) {
|
||||
return "L" + resolveLabel(label);
|
||||
}
|
||||
|
||||
protected String printTypeInsnNode(TypeInsnNode tin) {
|
||||
try {
|
||||
return nameOpcode(tin.getOpcode()) + " " + Type.getType(tin.desc).getClassName();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "//error";
|
||||
}
|
||||
|
||||
protected String printIincInsnNode(IincInsnNode iin) {
|
||||
return nameOpcode(iin.getOpcode()) + " " + iin.var + " " + iin.incr;
|
||||
}
|
||||
|
||||
protected String printTableSwitchInsnNode(TableSwitchInsnNode tin) {
|
||||
String line = nameOpcode(tin.getOpcode()) + " \n";
|
||||
List<?> labels = tin.labels;
|
||||
int count = 0;
|
||||
for (int i = tin.min; i < tin.max; i++) {
|
||||
line += " val: " + i + " -> " + "L" + resolveLabel((LabelNode) labels.get(count++)) + "\n";
|
||||
}
|
||||
line += " default" + " -> L" + resolveLabel(tin.dflt) + "";
|
||||
return line;
|
||||
}
|
||||
|
||||
protected String printLookupSwitchInsnNode(LookupSwitchInsnNode lin) {
|
||||
String line = nameOpcode(lin.getOpcode()) + ": \n";
|
||||
List<?> keys = lin.keys;
|
||||
List<?> labels = lin.labels;
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
int key = (Integer) keys.get(i);
|
||||
LabelNode label = (LabelNode) labels.get(i);
|
||||
line += " val: " + key + " -> " + "L" + resolveLabel(label) + "\n";
|
||||
}
|
||||
line += " default" + " -> L" + resolveLabel(lin.dflt) + "";
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
protected String nameOpcode(int opcode) {
|
||||
return " " + OpcodeInfo.OPCODES.get(opcode).toLowerCase();
|
||||
}
|
||||
|
||||
protected int resolveLabel(LabelNode label) {
|
||||
if (labels.containsKey(label)) {
|
||||
return labels.get(label);
|
||||
} else {
|
||||
int newLabelIndex = labels.size() + 1;
|
||||
labels.put(label, newLabelIndex);
|
||||
return newLabelIndex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the print
|
||||
* @return The print as a string array
|
||||
*/
|
||||
public String[] getLines() {
|
||||
ArrayList<String> lines = createPrint();
|
||||
return lines.toArray(new String[lines.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static method to print
|
||||
* @param lines To print
|
||||
*/
|
||||
public static void consolePrint(String[] lines) {
|
||||
for(String line : lines) {
|
||||
System.out.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveTo(File file, InstructionPrinter printer) {
|
||||
try {
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
|
||||
for(String s : printer.createPrint()) {
|
||||
bw.write(s);
|
||||
bw.newLine();
|
||||
}
|
||||
bw.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.FrameNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.LineNumberNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Bibl
|
||||
*
|
||||
*/
|
||||
|
||||
public class InstructionSearcher implements Opcodes {
|
||||
|
||||
protected InsnList insns;
|
||||
protected InstructionPattern pattern;
|
||||
|
||||
protected List<AbstractInsnNode[]> matches;
|
||||
|
||||
public InstructionSearcher(InsnList insns, int[] opcodes) {
|
||||
this(insns, new InstructionPattern(opcodes));
|
||||
}
|
||||
|
||||
public InstructionSearcher(InsnList insns, AbstractInsnNode[] ains) {
|
||||
this(insns, new InstructionPattern(ains));
|
||||
}
|
||||
|
||||
public InstructionSearcher(InsnList insns, InstructionPattern pattern) {
|
||||
this.insns = insns;
|
||||
this.pattern = pattern;
|
||||
matches = new ArrayList<AbstractInsnNode[]>();
|
||||
}
|
||||
|
||||
public boolean search() {
|
||||
for(AbstractInsnNode ain : insns.toArray()) {
|
||||
if (ain instanceof LineNumberNode || ain instanceof FrameNode)
|
||||
continue;
|
||||
if (pattern.accept(ain)) {
|
||||
matches.add(pattern.getLastMatch());
|
||||
pattern.resetMatch();
|
||||
}
|
||||
}
|
||||
return size() != 0;
|
||||
}
|
||||
|
||||
public List<AbstractInsnNode[]> getMatches() {
|
||||
return matches;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return matches.size();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TryCatchBlockNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.bytecode.TypeAndName;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konloch
|
||||
* @author Bibl
|
||||
*
|
||||
*/
|
||||
|
||||
public class MethodNodeDecompiler {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb, MethodNode m, ClassNode cn) {
|
||||
String package_ = null;
|
||||
String class_ = null;
|
||||
if (cn.name.contains("/")) {
|
||||
package_ = cn.name.substring(0, cn.name.lastIndexOf("/"));
|
||||
class_ = cn.name.substring(cn.name.lastIndexOf("/")+1);
|
||||
} else {
|
||||
class_ = cn.name;
|
||||
}
|
||||
|
||||
String s = getAccessString(m.access);
|
||||
sb.append(" ");
|
||||
sb.append(s);
|
||||
if (s.length() > 0)
|
||||
sb.append(" ");
|
||||
|
||||
System.out.println(m.name);
|
||||
if (m.name.equals("<init>")) {
|
||||
sb.append(class_);
|
||||
} else if (m.name.equals("<clinit>")) {
|
||||
} else {
|
||||
sb.append(m.name);
|
||||
}
|
||||
|
||||
TypeAndName[] args = new TypeAndName[0];
|
||||
|
||||
if (!m.name.equals("<clinit>")) {
|
||||
sb.append("(");
|
||||
|
||||
final Type[] argTypes = Type.getArgumentTypes(m.desc);
|
||||
args = new TypeAndName[argTypes.length];
|
||||
|
||||
for (int i = 0;i < argTypes.length; i++) {
|
||||
final Type type = argTypes[i];
|
||||
|
||||
final TypeAndName tan = new TypeAndName();
|
||||
final String argName = "arg" + i;
|
||||
|
||||
tan.name = argName;
|
||||
tan.type = type;
|
||||
|
||||
args[i] = tan;
|
||||
|
||||
sb.append(type.getClassName() + " " + argName + (i < argTypes.length-1 ? ", " : ""));
|
||||
}
|
||||
|
||||
sb.append(")");
|
||||
}
|
||||
|
||||
int amountOfThrows = m.exceptions.size();
|
||||
if (amountOfThrows > 0) {
|
||||
sb.append(" throws ");
|
||||
sb.append(m.exceptions.get(0));// exceptions is list<string>
|
||||
for (int i = 1; i < amountOfThrows; i++) {
|
||||
sb.append(", ");
|
||||
sb.append(m.exceptions.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (s.contains("abstract")) {
|
||||
sb.append(" {}"+BytecodeViewer.nl);
|
||||
} else {
|
||||
|
||||
sb.append(" {");
|
||||
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected()) {
|
||||
if(m.name.equals("<clinit>"))
|
||||
sb.append(" // <clinit>");
|
||||
else if(m.name.equals("<init>"))
|
||||
sb.append(" // <init>");
|
||||
}
|
||||
|
||||
sb.append(BytecodeViewer.nl);
|
||||
|
||||
InstructionPrinter insnPrinter = new InstructionPrinter(m, args);
|
||||
for (Object o : m.tryCatchBlocks) {
|
||||
TryCatchBlockNode tcbn = (TryCatchBlockNode) o;
|
||||
sb.append(" ");
|
||||
sb.append("TryCatch: L");
|
||||
sb.append(insnPrinter.resolveLabel(tcbn.start));
|
||||
sb.append(" to L");
|
||||
sb.append(insnPrinter.resolveLabel(tcbn.end));
|
||||
sb.append(" handled by L");
|
||||
sb.append(insnPrinter.resolveLabel(tcbn.handler));
|
||||
sb.append(": ");
|
||||
if(tcbn.type != null)
|
||||
sb.append(tcbn.type);
|
||||
else
|
||||
sb.append("Type is null.");
|
||||
sb.append(BytecodeViewer.nl);
|
||||
}
|
||||
for (String insn : insnPrinter.createPrint()) {
|
||||
sb.append(" ");
|
||||
sb.append(insn);
|
||||
sb.append(BytecodeViewer.nl);
|
||||
}
|
||||
sb.append(" }"+BytecodeViewer.nl);
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static String getAccessString(int access) {
|
||||
// public, protected, private, abstract, static,
|
||||
// final, synchronized, native & strictfp are permitted
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
if ((access & Opcodes.ACC_PUBLIC) != 0)
|
||||
tokens.add("public");
|
||||
if ((access & Opcodes.ACC_PRIVATE) != 0)
|
||||
tokens.add("private");
|
||||
if ((access & Opcodes.ACC_PROTECTED) != 0)
|
||||
tokens.add("protected");
|
||||
if ((access & Opcodes.ACC_STATIC) != 0)
|
||||
tokens.add("static");
|
||||
if ((access & Opcodes.ACC_ABSTRACT) != 0)
|
||||
tokens.add("abstract");
|
||||
if ((access & Opcodes.ACC_FINAL) != 0)
|
||||
tokens.add("final");
|
||||
if ((access & Opcodes.ACC_SYNCHRONIZED) != 0)
|
||||
tokens.add("synchronized");
|
||||
if ((access & Opcodes.ACC_NATIVE) != 0)
|
||||
tokens.add("native");
|
||||
if ((access & Opcodes.ACC_STRICT) != 0)
|
||||
tokens.add("strictfp");
|
||||
if ((access & Opcodes.ACC_BRIDGE) != 0)
|
||||
tokens.add("bridge");
|
||||
if ((access & Opcodes.ACC_VARARGS) != 0)
|
||||
tokens.add("varargs");
|
||||
if (tokens.size() == 0)
|
||||
return "";
|
||||
// hackery delimeters
|
||||
StringBuilder sb = new StringBuilder(tokens.get(0));
|
||||
for (int i = 1; i < tokens.size(); i++) {
|
||||
sb.append(" ");
|
||||
sb.append(tokens.get(i));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Bibl
|
||||
*
|
||||
*/
|
||||
|
||||
public class PrefixedStringBuilder {
|
||||
|
||||
protected StringBuilder sb;
|
||||
protected String prefix;
|
||||
|
||||
public PrefixedStringBuilder() {
|
||||
sb = new StringBuilder();
|
||||
}
|
||||
|
||||
public PrefixedStringBuilder append(String s) {
|
||||
sb.append(s);
|
||||
if (s.contains("\n") && (prefix != null) && (prefix.length() > 0))// insert the prefix at every new line, overridable
|
||||
sb.append(prefix);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PrefixedStringBuilder append(Object o) {
|
||||
return append(o.toString());
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public void trimPrefix(int amount) {
|
||||
if (prefix == null)
|
||||
return;
|
||||
if (prefix.length() < amount)
|
||||
return;
|
||||
prefix = prefix.substring(0, prefix.length() - amount);
|
||||
}
|
||||
|
||||
public void appendPrefix(String s) {
|
||||
if (prefix == null)
|
||||
prefix = "";
|
||||
prefix += s;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -11,7 +11,12 @@ import org.objectweb.asm.ClassWriter;
|
|||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.JarUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konloch
|
||||
*
|
||||
*/
|
||||
|
||||
public class CFRDecompiler extends JavaDecompiler {
|
||||
|
||||
|
@ -73,7 +78,93 @@ public class CFRDecompiler extends JavaDecompiler {
|
|||
return new String[] {
|
||||
filePath,
|
||||
"--outputdir",
|
||||
outputPath
|
||||
outputPath,
|
||||
"--decodeenumswitch",
|
||||
String.valueOf(BytecodeViewer.viewer.decodeenumswitch.isSelected()),
|
||||
"--sugarenums",
|
||||
String.valueOf(BytecodeViewer.viewer.sugarenums.isSelected()),
|
||||
"--decodestringswitch",
|
||||
String.valueOf(BytecodeViewer.viewer.decodestringswitch.isSelected()),
|
||||
"--arrayiter",
|
||||
String.valueOf(BytecodeViewer.viewer.arrayiter.isSelected()),
|
||||
"--collectioniter",
|
||||
String.valueOf(BytecodeViewer.viewer.collectioniter.isSelected()),
|
||||
"--innerclasses",
|
||||
String.valueOf(BytecodeViewer.viewer.innerclasses.isSelected()),
|
||||
"--removeboilerplate",
|
||||
String.valueOf(BytecodeViewer.viewer.removeboilerplate.isSelected()),
|
||||
"--removeinnerclasssynthetics",
|
||||
String.valueOf(BytecodeViewer.viewer.removeinnerclasssynthetics.isSelected()),
|
||||
"--decodelambdas",
|
||||
String.valueOf(BytecodeViewer.viewer.decodelambdas.isSelected()),
|
||||
"--hidebridgemethods",
|
||||
String.valueOf(BytecodeViewer.viewer.hidebridgemethods.isSelected()),
|
||||
"--liftconstructorinit",
|
||||
String.valueOf(BytecodeViewer.viewer.liftconstructorinit.isSelected()),
|
||||
"--removedeadmethods",
|
||||
String.valueOf(BytecodeViewer.viewer.removedeadmethods.isSelected()),
|
||||
"--removebadgenerics",
|
||||
String.valueOf(BytecodeViewer.viewer.removebadgenerics.isSelected()),
|
||||
"--sugarasserts",
|
||||
String.valueOf(BytecodeViewer.viewer.sugarasserts.isSelected()),
|
||||
"--sugarboxing",
|
||||
String.valueOf(BytecodeViewer.viewer.sugarboxing.isSelected()),
|
||||
"--showversion",
|
||||
String.valueOf(BytecodeViewer.viewer.showversion.isSelected()),
|
||||
"--decodefinally",
|
||||
String.valueOf(BytecodeViewer.viewer.decodefinally.isSelected()),
|
||||
"--tidymonitors",
|
||||
String.valueOf(BytecodeViewer.viewer.tidymonitors.isSelected()),
|
||||
"--lenient",
|
||||
String.valueOf(BytecodeViewer.viewer.lenient.isSelected()),
|
||||
"--dumpclasspath",
|
||||
String.valueOf(BytecodeViewer.viewer.dumpclasspath.isSelected()),
|
||||
"--comments",
|
||||
String.valueOf(BytecodeViewer.viewer.comments.isSelected()),
|
||||
"--forcetopsort",
|
||||
String.valueOf(BytecodeViewer.viewer.forcetopsort.isSelected()),
|
||||
"--forcetopsortaggress",
|
||||
String.valueOf(BytecodeViewer.viewer.forcetopsortaggress.isSelected()),
|
||||
"--stringbuffer",
|
||||
String.valueOf(BytecodeViewer.viewer.stringbuffer.isSelected()),
|
||||
"--stringbuilder",
|
||||
String.valueOf(BytecodeViewer.viewer.stringbuilder.isSelected()),
|
||||
"--silent",
|
||||
String.valueOf(BytecodeViewer.viewer.silent.isSelected()),
|
||||
"--recover",
|
||||
String.valueOf(BytecodeViewer.viewer.recover.isSelected()),
|
||||
"--eclipse",
|
||||
String.valueOf(BytecodeViewer.viewer.eclipse.isSelected()),
|
||||
"--override",
|
||||
String.valueOf(BytecodeViewer.viewer.override.isSelected()),
|
||||
"--showinferrable",
|
||||
String.valueOf(BytecodeViewer.viewer.showinferrable.isSelected()),
|
||||
"--aexagg",
|
||||
String.valueOf(BytecodeViewer.viewer.aexagg.isSelected()),
|
||||
"--forcecondpropagate",
|
||||
String.valueOf(BytecodeViewer.viewer.forcecondpropagate.isSelected()),
|
||||
"--hideutf",
|
||||
String.valueOf(BytecodeViewer.viewer.hideutf.isSelected()),
|
||||
"--hidelongstrings",
|
||||
String.valueOf(BytecodeViewer.viewer.hidelongstrings.isSelected()),
|
||||
"--commentmonitors",
|
||||
String.valueOf(BytecodeViewer.viewer.commentmonitor.isSelected()),
|
||||
"--allowcorrecting",
|
||||
String.valueOf(BytecodeViewer.viewer.allowcorrecting.isSelected()),
|
||||
"--labelledblocks",
|
||||
String.valueOf(BytecodeViewer.viewer.labelledblocks.isSelected()),
|
||||
"--j14classobj",
|
||||
String.valueOf(BytecodeViewer.viewer.j14classobj.isSelected()),
|
||||
"--hidelangimports",
|
||||
String.valueOf(BytecodeViewer.viewer.hidelangimports.isSelected()),
|
||||
"--recovertypeclash",
|
||||
String.valueOf(BytecodeViewer.viewer.recoverytypeclash.isSelected()),
|
||||
"--recovertypehints",
|
||||
String.valueOf(BytecodeViewer.viewer.recoverytypehints.isSelected()),
|
||||
"--forcereturningifs",
|
||||
String.valueOf(BytecodeViewer.viewer.forceturningifs.isSelected()),
|
||||
"--forloopaggcapture",
|
||||
String.valueOf(BytecodeViewer.viewer.forloopaggcapture.isSelected()),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -98,7 +189,7 @@ public class CFRDecompiler extends JavaDecompiler {
|
|||
for(File f : new File(fuckery).listFiles()) {
|
||||
//put contents into a zipfile
|
||||
}*/
|
||||
BytecodeViewer.showMessage("CFRDecompiler currently doesn't decompile as zip, please wait till 1.3 of Bytecode Viewer.");
|
||||
BytecodeViewer.showMessage("CFRDecompiler currently doesn't decompile as zip, please wait till Beta 1.4 of Bytecode Viewer.");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,12 @@ public class FernFlowerDecompiler extends JavaDecompiler {
|
|||
if(tempZip.exists())
|
||||
tempZip.delete();
|
||||
|
||||
File f = new File(BytecodeViewer.tempDirectory + "./temp/");
|
||||
f.mkdir();
|
||||
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), tempZip.getAbsolutePath());
|
||||
|
||||
de.fernflower.main.decompiler.ConsoleDecompiler.main(new String[] {tempZip.getAbsolutePath(), BytecodeViewer.tempDirectory + "./temp/"});
|
||||
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(new String[] {tempZip.getAbsolutePath(), BytecodeViewer.tempDirectory + "./temp/"});
|
||||
File tempZip2 = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp" + BytecodeViewer.fs +tempZip.getName());
|
||||
if(tempZip2.exists())
|
||||
tempZip2.renameTo(new File(zipName));
|
||||
|
@ -59,7 +62,7 @@ public class FernFlowerDecompiler extends JavaDecompiler {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
de.fernflower.main.decompiler.ConsoleDecompiler.main(generateMainMethod(tempClass.getAbsolutePath(), "."));
|
||||
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(generateMainMethod(tempClass.getAbsolutePath(), "."));
|
||||
|
||||
tempClass.delete();
|
||||
|
||||
|
|
|
@ -4,6 +4,12 @@ import java.io.File;
|
|||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Konloch
|
||||
*
|
||||
*/
|
||||
|
||||
public abstract class JavaDecompiler {
|
||||
|
||||
public abstract String decompileClassNode(ClassNode cn);
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.objectweb.asm.tree.ClassNode;
|
|||
import com.strobel.decompiler.DecompilationOptions;
|
||||
import com.strobel.decompiler.DecompilerSettings;
|
||||
import com.strobel.decompiler.PlainTextOutput;
|
||||
import com.strobel.decompiler.languages.java.JavaFormattingOptions;
|
||||
import com.strobel.assembler.InputTypeLoader;
|
||||
import com.strobel.assembler.metadata.Buffer;
|
||||
import com.strobel.assembler.metadata.ITypeLoader;
|
||||
|
@ -54,6 +55,22 @@ public class ProcyonDecompiler extends JavaDecompiler {
|
|||
|
||||
|
||||
DecompilerSettings settings = new DecompilerSettings();
|
||||
settings.setAlwaysGenerateExceptionVariableForCatchBlocks(BytecodeViewer.viewer.chckbxmntmNewCheckItem_6.isSelected());
|
||||
settings.setExcludeNestedTypes(BytecodeViewer.viewer.chckbxmntmNewCheckItem_11.isSelected());
|
||||
settings.setShowDebugLineNumbers(BytecodeViewer.viewer.chckbxmntmShowDebugLine.isSelected());
|
||||
settings.setIncludeLineNumbersInBytecode(BytecodeViewer.viewer.chckbxmntmNewCheckItem_3.isSelected());
|
||||
settings.setIncludeErrorDiagnostics(BytecodeViewer.viewer.chckbxmntmNewCheckItem_4.isSelected());
|
||||
settings.setShowSyntheticMembers(BytecodeViewer.viewer.chckbxmntmNewCheckItem_7.isSelected());
|
||||
settings.setSimplifyMemberReferences(BytecodeViewer.viewer.chckbxmntmSimplifyMemberReferences.isSelected());
|
||||
settings.setMergeVariables(BytecodeViewer.viewer.mnMergeVariables.isSelected());
|
||||
settings.setForceExplicitTypeArguments(BytecodeViewer.viewer.chckbxmntmNewCheckItem_8.isSelected());
|
||||
settings.setForceExplicitImports(BytecodeViewer.viewer.chckbxmntmNewCheckItem_9.isSelected());
|
||||
settings.setFlattenSwitchBlocks(BytecodeViewer.viewer.chckbxmntmNewCheckItem_10.isSelected());
|
||||
settings.setRetainPointlessSwitches(BytecodeViewer.viewer.chckbxmntmNewCheckItem_2.isSelected());
|
||||
settings.setRetainRedundantCasts(BytecodeViewer.viewer.chckbxmntmNewCheckItem_5.isSelected());
|
||||
settings.setUnicodeOutputEnabled(BytecodeViewer.viewer.chckbxmntmNewCheckItem_1.isSelected());
|
||||
settings.setFormattingOptions(JavaFormattingOptions.createDefault());
|
||||
|
||||
LuytenTypeLoader typeLoader = new LuytenTypeLoader();
|
||||
MetadataSystem metadataSystem = new MetadataSystem(typeLoader);
|
||||
TypeReference type = metadataSystem.lookupType(tempClass.getCanonicalPath());
|
||||
|
@ -120,7 +137,7 @@ public class ProcyonDecompiler extends JavaDecompiler {
|
|||
tempZip.delete();
|
||||
new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp").delete();*/
|
||||
|
||||
BytecodeViewer.showMessage("ProcyonDecompiler currently doesn't decompile as zip, please wait till 1.3 of Bytecode Viewer.");
|
||||
BytecodeViewer.showMessage("ProcyonDecompiler currently doesn't decompile as zip, please wait till Beta 1.4 of Bytecode Viewer.");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.objectweb.asm.tree.ClassNode;
|
|||
import com.jhe.hexed.JHexEditor;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.bytecode.BytecodeDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.bytecode.ClassNodeDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.java.CFRDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.java.FernFlowerDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.java.ProcyonDecompiler;
|
||||
|
@ -94,8 +94,8 @@ public class ClassViewer extends JPanel {
|
|||
ClassNode cn;
|
||||
JSplitPane sp;
|
||||
JSplitPane sp2;
|
||||
JEditorPane bytecode = new JEditorPane(), decomp = new JEditorPane();
|
||||
JScrollPane bcScroll;
|
||||
public JPanel bytePanel = new JPanel(new BorderLayout());
|
||||
public JPanel decompPanel = new JPanel(new BorderLayout());
|
||||
|
||||
public ClassViewer(final String name, final ClassNode cn) {
|
||||
sourcePane = BytecodeViewer.viewer.sourcePane.isSelected();
|
||||
|
@ -108,29 +108,7 @@ public class ClassViewer extends JPanel {
|
|||
this.setName(name);
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
final JPanel dcPanel = new JPanel(new BorderLayout());
|
||||
final JScrollPane dcScroll = new JScrollPane(decomp);
|
||||
if(sourcePane) {
|
||||
dcPanel.add(dcScroll, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
final JPanel bcPanel = new JPanel(new BorderLayout());
|
||||
if(bytecodePane) {
|
||||
bcScroll = new JScrollPane(bytecode);
|
||||
} else {
|
||||
bcScroll = new JScrollPane();
|
||||
}
|
||||
|
||||
bcPanel.add(bcScroll, BorderLayout.CENTER);
|
||||
|
||||
if(bytecodePane && bytecodeSyntax)
|
||||
bytecode.setContentType("text/java");
|
||||
|
||||
|
||||
if(sourcePane && sourcecodeSyntax)
|
||||
decomp.setContentType("text/java");
|
||||
|
||||
this.sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, dcPanel, bcPanel);
|
||||
this.sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, decompPanel, bytePanel);
|
||||
final ClassWriter cw = new ClassWriter(0);
|
||||
cn.accept(cw);
|
||||
JHexEditor hex = new JHexEditor(cw.toByteArray());
|
||||
|
@ -148,8 +126,9 @@ public class ClassViewer extends JPanel {
|
|||
hex.setSize(0, Integer.MAX_VALUE);
|
||||
resetDivider();
|
||||
BytecodeViewer.viewer.setIcon(true);
|
||||
bytecode.setText("Decompiling, please wait..");
|
||||
decomp.setText("Decompiling, please wait..");
|
||||
|
||||
//
|
||||
|
||||
startPaneUpdater();
|
||||
this.addComponentListener(new ComponentAdapter() {
|
||||
public void componentResized(ComponentEvent e) {
|
||||
|
@ -176,18 +155,16 @@ public class ClassViewer extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
final BytecodeDecompiler bc_dc = new BytecodeDecompiler();
|
||||
final FernFlowerDecompiler ff_dc = new FernFlowerDecompiler();
|
||||
final ProcyonDecompiler proc_dc = new ProcyonDecompiler();
|
||||
final CFRDecompiler cfr_dc = new CFRDecompiler();
|
||||
static FernFlowerDecompiler ff_dc = new FernFlowerDecompiler();
|
||||
static ProcyonDecompiler proc_dc = new ProcyonDecompiler();
|
||||
static CFRDecompiler cfr_dc = new CFRDecompiler();
|
||||
PaneUpdaterThread t;
|
||||
public void startPaneUpdater() {
|
||||
t = new PaneUpdaterThread(bytecode, decomp) {
|
||||
t = new PaneUpdaterThread() {
|
||||
String s = "";
|
||||
@Override
|
||||
public void doShit() {
|
||||
|
||||
final String b = bc_dc.decompileClassNode(cn);
|
||||
final String b = ClassNodeDecompiler.decompile(cn);
|
||||
|
||||
if(BytecodeViewer.viewer.decompilerGroup.isSelected(BytecodeViewer.viewer.fernflowerDec.getModel()))
|
||||
s = ff_dc.decompileClassNode(cn);
|
||||
|
@ -198,12 +175,29 @@ public class ClassViewer extends JPanel {
|
|||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
JEditorPane
|
||||
bytecode = new JEditorPane(),
|
||||
decomp = new JEditorPane();
|
||||
JScrollPane
|
||||
bytecodeScroll = new JScrollPane(bytecode),
|
||||
decompScroll = new JScrollPane(decomp);
|
||||
|
||||
if(bytecodePane && BytecodeViewer.viewer.bycSyntax.isSelected())
|
||||
bytecode.setContentType("text/java");
|
||||
if(sourcePane && BytecodeViewer.viewer.srcSyntax.isSelected())
|
||||
decomp.setContentType("text/java");
|
||||
|
||||
if(bytecodePane)
|
||||
p1.setText(b);
|
||||
bytecode.setText(b);
|
||||
if(sourcePane)
|
||||
p2.setText(s);
|
||||
p1.setCaretPosition(0);
|
||||
p2.setCaretPosition(0);
|
||||
decomp.setText(s);
|
||||
|
||||
bytePanel.add(bytecodeScroll);
|
||||
decompPanel.add(decompScroll);
|
||||
|
||||
bytecode.setCaretPosition(0);
|
||||
decomp.setCaretPosition(0);
|
||||
|
||||
BytecodeViewer.viewer.setIcon(false);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.objectweb.asm.tree.ClassNode;
|
|||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.FileChangeNotifier;
|
||||
import the.bytecode.club.bytecodeviewer.JarUtils;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.bytecode.BytecodeDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.java.CFRDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.java.FernFlowerDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.java.ProcyonDecompiler;
|
||||
|
@ -49,9 +48,12 @@ import javax.swing.JRadioButtonMenuItem;
|
|||
|
||||
public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
||||
|
||||
final FernFlowerDecompiler ff_dc = new FernFlowerDecompiler();
|
||||
final ProcyonDecompiler proc_dc = new ProcyonDecompiler();
|
||||
final CFRDecompiler cfr_dc = new CFRDecompiler();
|
||||
|
||||
private static final long serialVersionUID = 1851409230530948543L;
|
||||
public JCheckBoxMenuItem debugHelpers = new JCheckBoxMenuItem("Debug Helpers");
|
||||
public JCheckBoxMenuItem debugInstructions = new JCheckBoxMenuItem("Debug Instructions");
|
||||
private JSplitPane sp1;
|
||||
private JSplitPane sp2;
|
||||
static ArrayList<VisibleComponent> rfComps = new ArrayList<VisibleComponent>();
|
||||
|
@ -105,6 +107,67 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
|||
public final JRadioButtonMenuItem procyonDec = new JRadioButtonMenuItem("Procyon");
|
||||
public final JRadioButtonMenuItem cfrDec = new JRadioButtonMenuItem("CFR");
|
||||
public final ButtonGroup decompilerGroup = new ButtonGroup();
|
||||
private final JMenu mnNewMenu_3 = new JMenu("CFR");
|
||||
private final JMenu mnNewMenu_4 = new JMenu("Procyon");
|
||||
public final JCheckBoxMenuItem decodeenumswitch = new JCheckBoxMenuItem("Decode Enum Switch");
|
||||
public final JCheckBoxMenuItem sugarenums = new JCheckBoxMenuItem("SugarEnums");
|
||||
public final JCheckBoxMenuItem decodestringswitch = new JCheckBoxMenuItem("Decode String Switch");
|
||||
public final JCheckBoxMenuItem arrayiter = new JCheckBoxMenuItem("Arrayiter");
|
||||
public final JCheckBoxMenuItem collectioniter = new JCheckBoxMenuItem("Collectioniter");
|
||||
public final JCheckBoxMenuItem innerclasses = new JCheckBoxMenuItem("Inner Classes");
|
||||
public final JCheckBoxMenuItem removeboilerplate = new JCheckBoxMenuItem("Remove Boiler Plate");
|
||||
public final JCheckBoxMenuItem removeinnerclasssynthetics = new JCheckBoxMenuItem("Remove Inner Class Synthetics");
|
||||
public final JCheckBoxMenuItem decodelambdas = new JCheckBoxMenuItem("Decode Lambdas");
|
||||
public final JCheckBoxMenuItem hidebridgemethods = new JCheckBoxMenuItem("Hide Bridge Methods");
|
||||
public final JCheckBoxMenuItem liftconstructorinit = new JCheckBoxMenuItem("Lift Constructor Init");
|
||||
public final JCheckBoxMenuItem removedeadmethods = new JCheckBoxMenuItem("Remove Dead Methods");
|
||||
public final JCheckBoxMenuItem removebadgenerics = new JCheckBoxMenuItem("Remove Bad Generics");
|
||||
public final JCheckBoxMenuItem sugarasserts = new JCheckBoxMenuItem("Sugar Asserts");
|
||||
public final JCheckBoxMenuItem sugarboxing = new JCheckBoxMenuItem("Sugar Boxing");
|
||||
public final JCheckBoxMenuItem showversion = new JCheckBoxMenuItem("Show Version");
|
||||
public final JCheckBoxMenuItem decodefinally = new JCheckBoxMenuItem("Decode Finally");
|
||||
public final JCheckBoxMenuItem tidymonitors = new JCheckBoxMenuItem("Tidy Monitors");
|
||||
public final JCheckBoxMenuItem lenient = new JCheckBoxMenuItem("Lenient");
|
||||
public final JCheckBoxMenuItem dumpclasspath = new JCheckBoxMenuItem("Dump Classpath");
|
||||
public final JCheckBoxMenuItem comments = new JCheckBoxMenuItem("Comments");
|
||||
public final JCheckBoxMenuItem forcetopsort = new JCheckBoxMenuItem("Force Top Sort");
|
||||
public final JCheckBoxMenuItem forcetopsortaggress = new JCheckBoxMenuItem("Force Top Sort Aggress");
|
||||
public final JCheckBoxMenuItem stringbuffer = new JCheckBoxMenuItem("String Buffer");
|
||||
public final JCheckBoxMenuItem stringbuilder = new JCheckBoxMenuItem("String Builder");
|
||||
public final JCheckBoxMenuItem silent = new JCheckBoxMenuItem("Silent");
|
||||
public final JCheckBoxMenuItem recover = new JCheckBoxMenuItem("Recover");
|
||||
public final JCheckBoxMenuItem eclipse = new JCheckBoxMenuItem("Eclipse");
|
||||
public final JCheckBoxMenuItem override = new JCheckBoxMenuItem("Override");
|
||||
public final JCheckBoxMenuItem showinferrable = new JCheckBoxMenuItem("Show Inferrable");
|
||||
public final JCheckBoxMenuItem aexagg = new JCheckBoxMenuItem("Aexagg");
|
||||
public final JCheckBoxMenuItem forcecondpropagate = new JCheckBoxMenuItem("Force Cond Propagate");
|
||||
public final JCheckBoxMenuItem hideutf = new JCheckBoxMenuItem("Hide UTF");
|
||||
public final JCheckBoxMenuItem hidelongstrings = new JCheckBoxMenuItem("Hide Long Strings");
|
||||
public final JCheckBoxMenuItem commentmonitor = new JCheckBoxMenuItem("Comment Monitors");
|
||||
public final JCheckBoxMenuItem allowcorrecting = new JCheckBoxMenuItem("Allow Correcting");
|
||||
public final JCheckBoxMenuItem labelledblocks = new JCheckBoxMenuItem("Labelled Blocks");
|
||||
public final JCheckBoxMenuItem j14classobj = new JCheckBoxMenuItem("J14ClassOBJ");
|
||||
public final JCheckBoxMenuItem hidelangimports = new JCheckBoxMenuItem("Hide Lang Imports");
|
||||
public final JCheckBoxMenuItem recoverytypeclash = new JCheckBoxMenuItem("Recover Type Clash");
|
||||
public final JCheckBoxMenuItem recoverytypehints = new JCheckBoxMenuItem("Recover Type Hints");
|
||||
public final JCheckBoxMenuItem forceturningifs = new JCheckBoxMenuItem("Force Returning IFs");
|
||||
public final JCheckBoxMenuItem forloopaggcapture = new JCheckBoxMenuItem("For Loop AGG Capture");
|
||||
public final JCheckBoxMenuItem forceexceptionprune = new JCheckBoxMenuItem("Force Exception Prune");
|
||||
public final JCheckBoxMenuItem chckbxmntmShowDebugLine = new JCheckBoxMenuItem("Show Debug Line Numbers");
|
||||
public final JCheckBoxMenuItem chckbxmntmSimplifyMemberReferences = new JCheckBoxMenuItem("Simplify Member References");
|
||||
public final JCheckBoxMenuItem mnMergeVariables = new JCheckBoxMenuItem("Merge Variables");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_1 = new JCheckBoxMenuItem("Unicode Output Enabled");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_2 = new JCheckBoxMenuItem("Retain Pointless Switches");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_3 = new JCheckBoxMenuItem("Include Line Numbers In Bytecode");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_4 = new JCheckBoxMenuItem("Include Error Diagnostics");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_5 = new JCheckBoxMenuItem("Retain Redundant Casts");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_6 = new JCheckBoxMenuItem("Always Generate Exception Variable For Catch Blocks");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_7 = new JCheckBoxMenuItem("Show Synthetic Members");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_8 = new JCheckBoxMenuItem("Force Explicit Type Arguments");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_9 = new JCheckBoxMenuItem("Force Explicit Imports");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_10 = new JCheckBoxMenuItem("Flatten Switch Blocks");
|
||||
public final JCheckBoxMenuItem chckbxmntmNewCheckItem_11 = new JCheckBoxMenuItem("Exclude Nested Types");
|
||||
|
||||
|
||||
public void setC(boolean busy) {
|
||||
if(busy) {
|
||||
|
@ -177,32 +240,21 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
|||
return image;
|
||||
}
|
||||
|
||||
final BytecodeDecompiler bc_dc = new BytecodeDecompiler();
|
||||
final FernFlowerDecompiler ff_dc = new FernFlowerDecompiler();
|
||||
final ProcyonDecompiler proc_dc = new ProcyonDecompiler();
|
||||
final CFRDecompiler cfr_dc = new CFRDecompiler();
|
||||
public MainViewerGUI() {
|
||||
decompilerGroup.add(fernflowerDec);
|
||||
decompilerGroup.add(procyonDec);
|
||||
decompilerGroup.add(cfrDec);
|
||||
decompilerGroup.setSelected(procyonDec.getModel(), true);
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
//fernflower
|
||||
rbr.setSelected(true);
|
||||
rsy.setSelected(false);
|
||||
din.setSelected(true);
|
||||
dc4.setSelected(true);
|
||||
das.setSelected(true);
|
||||
hes.setSelected(true);
|
||||
hdc.setSelected(true);
|
||||
dgs.setSelected(false);
|
||||
ner.setSelected(true);
|
||||
den.setSelected(true);
|
||||
rgn.setSelected(true);
|
||||
bto.setSelected(true);
|
||||
nns.setSelected(true);
|
||||
uto.setSelected(true);
|
||||
udv.setSelected(true);
|
||||
rer.setSelected(true);
|
||||
fdi.setSelected(true);
|
||||
asc.setSelected(false);
|
||||
srcSyntax.setSelected(true);
|
||||
|
@ -210,6 +262,52 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
|||
debugHelpers.setSelected(true);
|
||||
sourcePane.setSelected(true);
|
||||
bytecodePane.setSelected(true);
|
||||
//cfr
|
||||
decodeenumswitch.setSelected(true);
|
||||
sugarenums.setSelected(true);
|
||||
decodestringswitch.setSelected(true);
|
||||
arrayiter.setSelected(true);
|
||||
collectioniter.setSelected(true);
|
||||
innerclasses.setSelected(true);
|
||||
removeboilerplate.setSelected(true);
|
||||
removeinnerclasssynthetics.setSelected(true);
|
||||
decodelambdas.setSelected(true);
|
||||
hidebridgemethods.setSelected(true);
|
||||
liftconstructorinit.setSelected(true);
|
||||
removedeadmethods.setSelected(true);
|
||||
removebadgenerics.setSelected(true);
|
||||
sugarasserts.setSelected(true);
|
||||
sugarboxing.setSelected(true);
|
||||
showversion.setSelected(true);
|
||||
decodefinally.setSelected(true);
|
||||
tidymonitors.setSelected(true);
|
||||
lenient.setSelected(false);
|
||||
dumpclasspath.setSelected(false);
|
||||
comments.setSelected(true);
|
||||
forcetopsort.setSelected(true);
|
||||
forcetopsortaggress.setSelected(true);
|
||||
forceexceptionprune.setSelected(true);
|
||||
stringbuffer.setSelected(false);
|
||||
stringbuilder.setSelected(true);
|
||||
silent.setSelected(true);
|
||||
recover.setSelected(true);
|
||||
eclipse.setSelected(true);
|
||||
override.setSelected(true);
|
||||
showinferrable.setSelected(true);
|
||||
aexagg.setSelected(true);
|
||||
forcecondpropagate.setSelected(true);
|
||||
hideutf.setSelected(true);
|
||||
hidelongstrings.setSelected(false);
|
||||
commentmonitor.setSelected(false);
|
||||
allowcorrecting.setSelected(true);
|
||||
labelledblocks.setSelected(true);
|
||||
j14classobj.setSelected(false);
|
||||
hidelangimports.setSelected(true);
|
||||
recoverytypeclash.setSelected(true);
|
||||
recoverytypehints.setSelected(true);
|
||||
forceturningifs.setSelected(true);
|
||||
forloopaggcapture.setSelected(true);
|
||||
//procyon
|
||||
|
||||
setJMenuBar(menuBar);
|
||||
|
||||
|
@ -273,7 +371,10 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
|||
int returnVal = fc.showSaveDialog(MainViewerGUI.this);
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fc.getSelectedFile();
|
||||
new ExportJar(file.getAbsolutePath()).setVisible(true);
|
||||
String path = file.getAbsolutePath();
|
||||
if(!path.endsWith(".jar"))
|
||||
path = path + ".jar";
|
||||
new ExportJar(path).setVisible(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -290,12 +391,15 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
|||
if (returnVal == JFileChooser.APPROVE_OPTION) {
|
||||
File file = fc.getSelectedFile();
|
||||
BytecodeViewer.viewer.setC(true);
|
||||
String path = file.getAbsolutePath();
|
||||
if(!path.endsWith(".zip"))
|
||||
path = path + ".zip";
|
||||
if(BytecodeViewer.viewer.decompilerGroup.isSelected(BytecodeViewer.viewer.fernflowerDec.getModel()))
|
||||
ff_dc.decompileToZip(file.getAbsolutePath());
|
||||
ff_dc.decompileToZip(path);
|
||||
else if(BytecodeViewer.viewer.decompilerGroup.isSelected(BytecodeViewer.viewer.procyonDec.getModel()))
|
||||
proc_dc.decompileToZip(file.getAbsolutePath());
|
||||
proc_dc.decompileToZip(path);
|
||||
else if(BytecodeViewer.viewer.decompilerGroup.isSelected(BytecodeViewer.viewer.cfrDec.getModel()))
|
||||
cfr_dc.decompileToZip(file.getAbsolutePath());
|
||||
cfr_dc.decompileToZip(path);
|
||||
BytecodeViewer.viewer.setC(false);
|
||||
}
|
||||
}
|
||||
|
@ -342,24 +446,152 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
|||
|
||||
mnNewMenu_2.add(fernflowerDec);
|
||||
|
||||
menuBar.add(mnNewMenu_4);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_6);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_11);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmShowDebugLine);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_3);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_4);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_7);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmSimplifyMemberReferences);
|
||||
|
||||
mnNewMenu_4.add(mnMergeVariables);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_8);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_9);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_10);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_2);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_5);
|
||||
|
||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_1);
|
||||
|
||||
menuBar.add(mnNewMenu_3);
|
||||
|
||||
mnNewMenu_3.add(decodeenumswitch);
|
||||
|
||||
mnNewMenu_3.add(sugarenums);
|
||||
|
||||
mnNewMenu_3.add(decodestringswitch);
|
||||
|
||||
mnNewMenu_3.add(arrayiter);
|
||||
|
||||
mnNewMenu_3.add(collectioniter);
|
||||
|
||||
mnNewMenu_3.add(innerclasses);
|
||||
|
||||
mnNewMenu_3.add(removeboilerplate);
|
||||
|
||||
mnNewMenu_3.add(removeinnerclasssynthetics);
|
||||
|
||||
mnNewMenu_3.add(decodelambdas);
|
||||
|
||||
mnNewMenu_3.add(hidebridgemethods);
|
||||
|
||||
mnNewMenu_3.add(liftconstructorinit);
|
||||
|
||||
mnNewMenu_3.add(removedeadmethods);
|
||||
|
||||
mnNewMenu_3.add(removebadgenerics);
|
||||
|
||||
mnNewMenu_3.add(sugarasserts);
|
||||
|
||||
mnNewMenu_3.add(sugarboxing);
|
||||
|
||||
mnNewMenu_3.add(showversion);
|
||||
|
||||
mnNewMenu_3.add(decodefinally);
|
||||
|
||||
mnNewMenu_3.add(tidymonitors);
|
||||
|
||||
mnNewMenu_3.add(lenient);
|
||||
|
||||
mnNewMenu_3.add(dumpclasspath);
|
||||
|
||||
mnNewMenu_3.add(comments);
|
||||
|
||||
mnNewMenu_3.add(forcetopsort);
|
||||
|
||||
mnNewMenu_3.add(forcetopsortaggress);
|
||||
|
||||
mnNewMenu_3.add(forceexceptionprune);
|
||||
|
||||
mnNewMenu_3.add(stringbuffer);
|
||||
|
||||
mnNewMenu_3.add(stringbuilder);
|
||||
|
||||
mnNewMenu_3.add(silent);
|
||||
|
||||
mnNewMenu_3.add(recover);
|
||||
|
||||
mnNewMenu_3.add(eclipse);
|
||||
|
||||
mnNewMenu_3.add(override);
|
||||
|
||||
mnNewMenu_3.add(showinferrable);
|
||||
|
||||
mnNewMenu_3.add(aexagg);
|
||||
|
||||
mnNewMenu_3.add(forcecondpropagate);
|
||||
|
||||
mnNewMenu_3.add(hideutf);
|
||||
|
||||
mnNewMenu_3.add(hidelongstrings);
|
||||
|
||||
mnNewMenu_3.add(commentmonitor);
|
||||
|
||||
mnNewMenu_3.add(allowcorrecting);
|
||||
|
||||
mnNewMenu_3.add(labelledblocks);
|
||||
|
||||
mnNewMenu_3.add(j14classobj);
|
||||
|
||||
mnNewMenu_3.add(hidelangimports);
|
||||
|
||||
mnNewMenu_3.add(recoverytypeclash);
|
||||
|
||||
mnNewMenu_3.add(recoverytypehints);
|
||||
|
||||
mnNewMenu_3.add(forceturningifs);
|
||||
|
||||
mnNewMenu_3.add(forloopaggcapture);
|
||||
|
||||
JMenu mnDecompilerSettings = new JMenu("FernFlower");
|
||||
menuBar.add(mnDecompilerSettings);
|
||||
dc4.setSelected(true);
|
||||
mnDecompilerSettings.add(dc4);
|
||||
nns.setSelected(true);
|
||||
mnDecompilerSettings.add(nns);
|
||||
ner.setSelected(true);
|
||||
mnDecompilerSettings.add(ner);
|
||||
bto.setSelected(true);
|
||||
mnDecompilerSettings.add(bto);
|
||||
rgn.setSelected(true);
|
||||
mnDecompilerSettings.add(rgn);
|
||||
rer.setSelected(true);
|
||||
mnDecompilerSettings.add(rer);
|
||||
mnDecompilerSettings.add(rbr);
|
||||
mnDecompilerSettings.add(rsy);
|
||||
mnDecompilerSettings.add(din);
|
||||
mnDecompilerSettings.add(dc4);
|
||||
mnDecompilerSettings.add(das);
|
||||
hes.setSelected(true);
|
||||
mnDecompilerSettings.add(hes);
|
||||
hdc.setSelected(true);
|
||||
mnDecompilerSettings.add(hdc);
|
||||
mnDecompilerSettings.add(din);
|
||||
mnDecompilerSettings.add(das);
|
||||
mnDecompilerSettings.add(dgs);
|
||||
mnDecompilerSettings.add(ner);
|
||||
mnDecompilerSettings.add(den);
|
||||
mnDecompilerSettings.add(rgn);
|
||||
mnDecompilerSettings.add(bto);
|
||||
mnDecompilerSettings.add(nns);
|
||||
mnDecompilerSettings.add(uto);
|
||||
mnDecompilerSettings.add(udv);
|
||||
mnDecompilerSettings.add(rer);
|
||||
mnDecompilerSettings.add(fdi);
|
||||
mnDecompilerSettings.add(asc);
|
||||
|
||||
|
@ -368,8 +600,6 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
|||
|
||||
mnBytecodeDecompilerSettings.add(debugHelpers);
|
||||
|
||||
mnBytecodeDecompilerSettings.add(debugInstructions);
|
||||
|
||||
mnBytecodeDecompilerSettings.add(chckbxmntmNewCheckItem);
|
||||
|
||||
menuBar.add(mnNewMenu_1);
|
||||
|
@ -445,7 +675,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
|
|||
});
|
||||
|
||||
setSize(new Dimension(800, 400));
|
||||
setTitle("Bytecode Viewer - http://the.bytecode.club - @Konloch");
|
||||
setTitle("Bytecode Viewer " + BytecodeViewer.version + " - http://the.bytecode.club - @Konloch");
|
||||
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane();
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package the.bytecode.club.bytecodeviewer.gui;
|
||||
|
||||
import javax.swing.JEditorPane;
|
||||
|
||||
/**
|
||||
* Allows us to run a background thread then update the two JEditorPanes
|
||||
* Allows us to run a background thread
|
||||
*
|
||||
* @author Konloch
|
||||
*
|
||||
|
@ -11,13 +9,6 @@ import javax.swing.JEditorPane;
|
|||
|
||||
public abstract class PaneUpdaterThread extends Thread {
|
||||
|
||||
JEditorPane p1;
|
||||
JEditorPane p2;
|
||||
public PaneUpdaterThread(JEditorPane p1, JEditorPane p2) {
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
}
|
||||
|
||||
public abstract void doShit();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,6 +4,8 @@ import java.util.ArrayList;
|
|||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
/**
|
||||
* Coming soon.
|
||||
*
|
||||
|
@ -18,6 +20,7 @@ public class AllatoriStringDecrypter extends Plugin {
|
|||
for(ClassNode classNode : classNodeList) {
|
||||
|
||||
}
|
||||
BytecodeViewer.showMessage("This is a planned feature.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@ import org.objectweb.asm.tree.LdcInsnNode;
|
|||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
/**
|
||||
* The idea/core was based off of J-RET's Malicious Code Searcher
|
||||
* I improved it, and added more stuff to search for.
|
||||
|
@ -47,7 +45,6 @@ public class MaliciousCodeScanner extends Plugin {
|
|||
@Override
|
||||
public void execute(ArrayList<ClassNode> classNodeList) {
|
||||
PluginConsole frame = new PluginConsole("Malicious Code Scanner");
|
||||
BytecodeViewer.viewer.setC(true);
|
||||
for(ClassNode classNode : classNodeList) {
|
||||
for(Object o : classNode.methods.toArray()) {
|
||||
MethodNode m = (MethodNode) o;
|
||||
|
@ -81,7 +78,6 @@ public class MaliciousCodeScanner extends Plugin {
|
|||
}
|
||||
}
|
||||
}
|
||||
BytecodeViewer.viewer.setC(false);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ import org.objectweb.asm.tree.InsnList;
|
|||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
/**
|
||||
* Replaces all string and string[] instances with whatever.
|
||||
*
|
||||
|
@ -35,8 +33,6 @@ public class ReplaceStrings extends Plugin {
|
|||
|
||||
@Override
|
||||
public void execute(ArrayList<ClassNode> classNodeList) {
|
||||
BytecodeViewer.viewer.setC(true);
|
||||
|
||||
if(!className.equals("*")) {
|
||||
for(ClassNode classNode : classNodeList) {
|
||||
if(classNode.name.equals(className))
|
||||
|
@ -47,8 +43,6 @@ public class ReplaceStrings extends Plugin {
|
|||
scanClassNode(classNode);
|
||||
}
|
||||
}
|
||||
|
||||
BytecodeViewer.viewer.setC(false);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ import org.objectweb.asm.tree.InsnList;
|
|||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
/**
|
||||
* Simply shows all the non-empty strings in every single class
|
||||
*
|
||||
|
@ -23,7 +21,6 @@ public class ShowAllStrings extends Plugin {
|
|||
@Override
|
||||
public void execute(ArrayList<ClassNode> classNodeList) {
|
||||
PluginConsole frame = new PluginConsole("Show All Strings");
|
||||
BytecodeViewer.viewer.setC(true);
|
||||
for(ClassNode classNode : classNodeList) {
|
||||
for(Object o : classNode.fields.toArray()) {
|
||||
FieldNode f = (FieldNode) o;
|
||||
|
@ -57,7 +54,6 @@ public class ShowAllStrings extends Plugin {
|
|||
}
|
||||
}
|
||||
}
|
||||
BytecodeViewer.viewer.setC(false);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ import java.util.ArrayList;
|
|||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
/**
|
||||
* Simply shows all classes that have a public static void main(String[])
|
||||
*
|
||||
|
@ -19,7 +17,6 @@ public class ShowMainMethods extends Plugin {
|
|||
@Override
|
||||
public void execute(ArrayList<ClassNode> classNodeList) {
|
||||
PluginConsole frame = new PluginConsole("Show Main Methods");
|
||||
BytecodeViewer.viewer.setC(true);
|
||||
for(ClassNode classNode : classNodeList) {
|
||||
for(Object o : classNode.methods.toArray()) {
|
||||
MethodNode m = (MethodNode) o;
|
||||
|
@ -28,7 +25,6 @@ public class ShowMainMethods extends Plugin {
|
|||
frame.appendText(classNode.name + "." +m.name+""+m.desc);
|
||||
}
|
||||
}
|
||||
BytecodeViewer.viewer.setC(false);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import java.util.ArrayList;
|
|||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
/**
|
||||
* Coming soon.
|
||||
*
|
||||
|
@ -18,6 +20,7 @@ public class ZKMStringDecrypter extends Plugin {
|
|||
for(ClassNode classNode : classNodeList) {
|
||||
|
||||
}
|
||||
BytecodeViewer.showMessage("This is a planned feature.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user