diff --git a/BytecodeViewer Beta 1.3.jar b/BytecodeViewer Beta 1.3.jar new file mode 100644 index 00000000..f64f25ac Binary files /dev/null and b/BytecodeViewer Beta 1.3.jar differ diff --git a/libs/byteanalysis-1.0.jar b/libs/byteanalysis-1.0.jar new file mode 100644 index 00000000..af185ccf Binary files /dev/null and b/libs/byteanalysis-1.0.jar differ diff --git a/libs/fernflower2014.jar b/libs/fernflower2014.jar new file mode 100644 index 00000000..c456ff95 Binary files /dev/null and b/libs/fernflower2014.jar differ diff --git a/libs/fernflower_no_output.jar b/libs/fernflower_no_output.jar deleted file mode 100644 index 23d9f664..00000000 Binary files a/libs/fernflower_no_output.jar and /dev/null differ diff --git a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index 45a5b02b..6aa98e90 100644 --- a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -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(); } @@ -223,15 +262,17 @@ public class BytecodeViewer { @SuppressWarnings("deprecation") public static void resetWorkSpace() { JOptionPane pane = new JOptionPane("Are you sure you want to reset the workspace?\n\rIt will also reset your file navigator and search."); - Object[] options = new String[] { "Yes", "No" }; - pane.setOptions(options); - JDialog dialog = pane.createDialog(viewer, "Bytecode Viewer - Reset Workspace"); - dialog.show(); - Object obj = pane.getValue(); - int result = -1; - for (int k = 0; k < options.length; k++) - if (options[k].equals(obj)) - result = k; + Object[] options = new String[] { "Yes", "No" }; + pane.setOptions(options); + JDialog dialog = pane.createDialog(viewer, "Bytecode Viewer - Reset Workspace"); + dialog.show(); + Object obj = pane.getValue(); + int result = -1; + 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) { } } diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/BytecodeDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/BytecodeDecompiler.java deleted file mode 100644 index ac0d7879..00000000 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/BytecodeDecompiler.java +++ /dev/null @@ -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 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 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 mni = cn.methods.iterator(); - while (mni.hasNext()) { - final MethodNode mn = mni.next(); - final String mnm = mn.name; - if (!mnm.equals("")) { - cb.append(Modifier.toString(mn.access) + " "); - } - - if (mnm.equals("")) { - cb.append(class_); - } - else if (mnm.equals("")) { - cb.append("static {"); - if (BytecodeViewer.viewer.debugHelpers.isSelected()) - cb.appendnl(" // "); - else - cb.appendnl(); - } - else { - cb.append(Type.getReturnType(mn.desc).getClassName() + " "); - cb.append(mnm); - } - - TypeAndName[] args = new TypeAndName[0]; - - if (!mnm.equals("")) { - 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; - } - -} diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/ClassNodeDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/ClassNodeDecompiler.java new file mode 100644 index 00000000..01f373ba --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/ClassNodeDecompiler.java @@ -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(), cn).toString(); + } + + @SuppressWarnings("unchecked") + protected static PrefixedStringBuilder decompileClassNode(PrefixedStringBuilder sb, ArrayList decompiledClasses, ClassNode cn) { + ArrayList unableToDecompile = new ArrayList(); + 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)cn.fields) { + sb.append(BytecodeViewer.nl+" "); + FieldNodeDecompiler.decompile(sb, fn); + } + if (cn.fields.size() > 0) { + sb.append(BytecodeViewer.nl); + } + for (MethodNode mn : (List)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 tokens = new ArrayList(); + 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(); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/ClassStringBuilder.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/ClassStringBuilder.java deleted file mode 100644 index 59226882..00000000 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/ClassStringBuilder.java +++ /dev/null @@ -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; - } - } -} diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/FieldNodeDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/FieldNodeDecompiler.java new file mode 100644 index 00000000..c158bcd7 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/FieldNodeDecompiler.java @@ -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 tokens = new ArrayList(); + 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(); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionPattern.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionPattern.java new file mode 100644 index 00000000..10d4e4a7 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionPattern.java @@ -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())); + } + } + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionPrinter.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionPrinter.java new file mode 100644 index 00000000..7722e2fc --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionPrinter.java @@ -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 matchedInsns; + protected Map labels; + + public InstructionPrinter(MethodNode m, TypeAndName[] args) { + this.args = args; + mNode = m; + labels = new HashMap(); + // matchedInsns = new ArrayList(); // ingnored because match = false + match = false; + } + + public InstructionPrinter(MethodNode m, InstructionPattern pattern, TypeAndName[] args) { + this.args = args; + mNode = m; + labels = new HashMap(); + 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 createPrint() { + ArrayList info = new ArrayList(); + 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 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(); + } + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionSearcher.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionSearcher.java new file mode 100644 index 00000000..cca91d84 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/InstructionSearcher.java @@ -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 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(); + } + + 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 getMatches() { + return matches; + } + + public int size() { + return matches.size(); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/MethodNodeDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/MethodNodeDecompiler.java new file mode 100644 index 00000000..8be0058f --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/MethodNodeDecompiler.java @@ -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("")) { + sb.append(class_); + } else if (m.name.equals("")) { + } else { + sb.append(m.name); + } + + TypeAndName[] args = new TypeAndName[0]; + + if (!m.name.equals("")) { + 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 + 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("")) + sb.append(" // "); + else if(m.name.equals("")) + sb.append(" // "); + } + + 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 tokens = new ArrayList(); + 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(); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/PrefixedStringBuilder.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/PrefixedStringBuilder.java new file mode 100644 index 00000000..5d0b7b22 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/PrefixedStringBuilder.java @@ -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(); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/TypeAndName.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/TypeAndName.java index bdf553e2..f8c127bf 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/TypeAndName.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/TypeAndName.java @@ -11,4 +11,4 @@ import org.objectweb.asm.Type; public class TypeAndName { public Type type = null; public String name = null; -} +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/java/CFRDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/java/CFRDecompiler.java index 3294042b..65502df1 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/java/CFRDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/java/CFRDecompiler.java @@ -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."); } diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/java/FernFlowerDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/java/FernFlowerDecompiler.java index d2e06d67..ab73c65c 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/java/FernFlowerDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/java/FernFlowerDecompiler.java @@ -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(); diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/java/JavaDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/java/JavaDecompiler.java index c8123a6c..4994e0ab 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/java/JavaDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/java/JavaDecompiler.java @@ -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); diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/java/ProcyonDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/java/ProcyonDecompiler.java index 963b7ea5..e1157c7e 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/java/ProcyonDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/java/ProcyonDecompiler.java @@ -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."); } diff --git a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java index f563c469..d1d835b7 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java @@ -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); } }); diff --git a/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java b/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java index cbd6a156..ffb411a1 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java @@ -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 rfComps = new ArrayList(); @@ -105,7 +107,68 @@ 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) { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); @@ -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() { + 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(); diff --git a/src/the/bytecode/club/bytecodeviewer/gui/PaneUpdaterThread.java b/src/the/bytecode/club/bytecodeviewer/gui/PaneUpdaterThread.java index f81a01af..08ca7be2 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/PaneUpdaterThread.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/PaneUpdaterThread.java @@ -1,22 +1,13 @@ 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 * */ 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(); diff --git a/src/the/bytecode/club/bytecodeviewer/plugins/AllatoriStringDecrypter.java b/src/the/bytecode/club/bytecodeviewer/plugins/AllatoriStringDecrypter.java index a83147bb..6a3cd954 100644 --- a/src/the/bytecode/club/bytecodeviewer/plugins/AllatoriStringDecrypter.java +++ b/src/the/bytecode/club/bytecodeviewer/plugins/AllatoriStringDecrypter.java @@ -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."); } } diff --git a/src/the/bytecode/club/bytecodeviewer/plugins/MaliciousCodeScanner.java b/src/the/bytecode/club/bytecodeviewer/plugins/MaliciousCodeScanner.java index 57e7525a..23b95ab9 100644 --- a/src/the/bytecode/club/bytecodeviewer/plugins/MaliciousCodeScanner.java +++ b/src/the/bytecode/club/bytecodeviewer/plugins/MaliciousCodeScanner.java @@ -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 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); } diff --git a/src/the/bytecode/club/bytecodeviewer/plugins/ReplaceStrings.java b/src/the/bytecode/club/bytecodeviewer/plugins/ReplaceStrings.java index 9d117404..dc633bcd 100644 --- a/src/the/bytecode/club/bytecodeviewer/plugins/ReplaceStrings.java +++ b/src/the/bytecode/club/bytecodeviewer/plugins/ReplaceStrings.java @@ -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 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); } diff --git a/src/the/bytecode/club/bytecodeviewer/plugins/ShowAllStrings.java b/src/the/bytecode/club/bytecodeviewer/plugins/ShowAllStrings.java index 1f70c0be..126abb52 100644 --- a/src/the/bytecode/club/bytecodeviewer/plugins/ShowAllStrings.java +++ b/src/the/bytecode/club/bytecodeviewer/plugins/ShowAllStrings.java @@ -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 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); } diff --git a/src/the/bytecode/club/bytecodeviewer/plugins/ShowMainMethods.java b/src/the/bytecode/club/bytecodeviewer/plugins/ShowMainMethods.java index a0f7010b..18f8e02d 100644 --- a/src/the/bytecode/club/bytecodeviewer/plugins/ShowMainMethods.java +++ b/src/the/bytecode/club/bytecodeviewer/plugins/ShowMainMethods.java @@ -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 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); } diff --git a/src/the/bytecode/club/bytecodeviewer/plugins/ZKMStringDecrypter.java b/src/the/bytecode/club/bytecodeviewer/plugins/ZKMStringDecrypter.java index 180d3d65..5042332a 100644 --- a/src/the/bytecode/club/bytecodeviewer/plugins/ZKMStringDecrypter.java +++ b/src/the/bytecode/club/bytecodeviewer/plugins/ZKMStringDecrypter.java @@ -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."); } }