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:
Kalen Kinloch 2014-10-29 19:02:29 -07:00
parent 069246a297
commit 30dc40a095

AI 샘플 코드 생성 중입니다

Loading...
28 changed files with 1422 additions and 579 deletions

BIN
BytecodeViewer Beta 1.3.jar Normal file

Binary file not shown.

BIN
libs/byteanalysis-1.0.jar Normal file

Binary file not shown.

BIN
libs/fernflower2014.jar Normal file

Binary file not shown.

Binary file not shown.

View File

@ -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) {
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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()));
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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.");
}

View File

@ -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();

View File

@ -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);

View File

@ -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.");
}

View File

@ -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);
}
});

View File

@ -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();

View File

@ -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

View File

@ -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.");
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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.");
}
}