From 96cb81a8ac90a2f9b8eada03759811c41c3c5b38 Mon Sep 17 00:00:00 2001 From: SuspiciousActivity <38253929+SuspiciousActivity@users.noreply.github.com> Date: Sat, 21 Apr 2018 12:48:54 +0200 Subject: [PATCH] Added Inner/OuterClass support and TryCatchBlocks --- src/me/ByteEdit/main/Assembler.java | 73 +++++++++++++++++++------- src/me/ByteEdit/main/Disassembler.java | 39 ++++++++------ src/me/ByteEdit/main/Main.java | 5 +- 3 files changed, 79 insertions(+), 38 deletions(-) diff --git a/src/me/ByteEdit/main/Assembler.java b/src/me/ByteEdit/main/Assembler.java index b424c69..f8b52a8 100644 --- a/src/me/ByteEdit/main/Assembler.java +++ b/src/me/ByteEdit/main/Assembler.java @@ -22,6 +22,7 @@ import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.FrameNode; import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InnerClassNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.IntInsnNode; @@ -36,6 +37,7 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MultiANewArrayInsnNode; import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TryCatchBlockNode; import org.objectweb.asm.tree.TypeInsnNode; import org.objectweb.asm.tree.VarInsnNode; @@ -58,7 +60,19 @@ public class Assembler { clazz.version = Integer.parseInt(s.substring(12)); - while (!(s = read.readLine()).startsWith("// #SourceFile: ")) { + while ((s = read.readLine()).startsWith("// ")) { + if (s.startsWith("// #OuterClass: ")) { + clazz.outerClass = s.substring(16).equals("null") ? null : s.substring(16); + } else if (s.equals("// #InnerClasses:")) { + clazz.innerClasses = new ArrayList<>(); + } else { + String split[] = s.split(" "); + clazz.innerClasses.add(new InnerClassNode(split[1], split[2].equals("null") ? null : split[2], + split[3].equals("null") ? null : split[3], Integer.parseInt(split[4]))); + } + } + + { s = s.substring(0, s.length() - 2); if (s.contains(" implements ")) { String interfaces = s.substring(s.indexOf(" implements ") + 12); @@ -108,9 +122,10 @@ public class Assembler { clazz.access ^= ClassUtil.ACC_ABSTRACT; } } - } + s = read.readLine(); + clazz.sourceFile = s.substring(16).equals("null") ? null : s.substring(16); while (!(s = read.readLine()).equals("// #Fields")) { @@ -208,20 +223,16 @@ public class Assembler { } } - HashMap> classLabelMap; - if ((classLabelMap = Main.labels.get(clazz.name)) == null) { - classLabelMap = new HashMap>(); - Main.labels.put(clazz.name, classLabelMap); - } else { - classLabelMap.clear(); - } - HashMap methodLabelMap = null; + HashMap methodLabelMap = new HashMap(); annotationsForNext.clear(); MethodNode node = null; String temp = ""; ArrayList localVarsToParse = new ArrayList<>(); + ArrayList tryCatchBlocksToParse = new ArrayList<>(); + + int stage = 0; while ((s = read.readLine()) != null) { if (s.trim().isEmpty() || s.equals("}")) @@ -240,10 +251,19 @@ public class Assembler { node.maxLocals = Integer.parseInt(s.split(" ")[0]); node.maxStack = Integer.parseInt(s.split(" ")[1].substring(2)); localVarsToParse.clear(); + tryCatchBlocksToParse.clear(); + stage = 0; + } else if (s.equals("// #TryCatch:")) { + stage = 1; } else if (s.equals("// #LocalVars:")) { - } else if (s.startsWith("// ")) { // LocalVars + stage = 2; + } else if (s.startsWith("// ")) { s = s.substring(3); - localVarsToParse.add(s); + if (stage == 1) { + tryCatchBlocksToParse.add(s); + } else if (stage == 2) { + localVarsToParse.add(s); + } } else if (s.equals("}")) { if (!annotationsForNext.isEmpty()) { if (node.visibleAnnotations == null) { @@ -272,6 +292,28 @@ public class Assembler { node.localVariables.add(new LocalVariableNode(sp[0], sp[1].substring(1, sp[1].length() - 2), null, _start, _end, Integer.parseInt(sp[2].substring(0, sp[2].length() - 2)))); } + + for (String st : tryCatchBlocksToParse) { + String[] sp = st.split(" "); + int start = Integer.parseInt(sp[1].substring(2)); + int end = Integer.parseInt(sp[2].substring(2)); + int handler = Integer.parseInt(sp[3].substring(2)); + LabelNode _start = null; + LabelNode _end = null; + LabelNode _handler = null; + for (Entry entry : methodLabelMap.entrySet()) { + if (entry.getValue() == start) { + _start = new LabelNode(entry.getKey()); + } + if (entry.getValue() == end) { + _end = new LabelNode(entry.getKey()); + } + if (entry.getValue() == handler) { + _handler = new LabelNode(entry.getKey()); + } + } + node.tryCatchBlocks.add(new TryCatchBlockNode(_start, _end, _handler, sp[0])); + } clazz.methods.add(node); } else if (!s.startsWith("\t")) { s = s.substring(0, s.length() - 2); @@ -338,12 +380,7 @@ public class Assembler { } } node.access = access; - if ((methodLabelMap = classLabelMap.get(node.name + "|" + node.desc)) == null) { - methodLabelMap = new HashMap(); - classLabelMap.put(node.name + "|" + node.desc, methodLabelMap); - } else { - methodLabelMap.clear(); - } + methodLabelMap.clear(); } else { s = s.substring(1); if (!temp.isEmpty()) { diff --git a/src/me/ByteEdit/main/Disassembler.java b/src/me/ByteEdit/main/Disassembler.java index 034e7e2..07bb149 100644 --- a/src/me/ByteEdit/main/Disassembler.java +++ b/src/me/ByteEdit/main/Disassembler.java @@ -16,6 +16,7 @@ import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.FrameNode; import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InnerClassNode; import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.IntInsnNode; import org.objectweb.asm.tree.InvokeDynamicInsnNode; @@ -29,6 +30,7 @@ import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MultiANewArrayInsnNode; import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TryCatchBlockNode; import org.objectweb.asm.tree.TypeInsnNode; import org.objectweb.asm.tree.VarInsnNode; @@ -39,13 +41,6 @@ public class Disassembler { return "ClassNode is null! This is not a valid java class file!"; } try { - HashMap> classLabelMap; - if ((classLabelMap = Main.labels.get(classNode.name)) == null) { - classLabelMap = new HashMap>(); - Main.labels.put(classNode.name, classLabelMap); - } else { - classLabelMap.clear(); - } String s = ""; s += "// #Annotations\n"; if (classNode.visibleAnnotations != null && !classNode.visibleAnnotations.isEmpty()) { @@ -104,6 +99,13 @@ public class Disassembler { } } s += "// #Class v:" + classNode.version + "\n"; + s += "// #OuterClass: " + classNode.outerClass + "\n"; + s += "// #InnerClasses:\n"; + if (classNode.innerClasses != null) { + for (InnerClassNode icn : classNode.innerClasses) { + s += "// " + icn.name + " " + icn.outerName + " " + icn.innerName + " " + icn.access + "\n"; + } + } s += ClassUtil.getAccessFlagsClass(classNode.access) + classNode.name + " "; s += "extends " + classNode.superName + " "; if (classNode.interfaces != null && !classNode.interfaces.isEmpty()) { @@ -188,14 +190,10 @@ public class Disassembler { for (MethodNode mn : classNode.methods) { try { - HashMap methodLabelMap; - if ((methodLabelMap = classLabelMap.get(mn.name + "|" + mn.desc)) == null) { - methodLabelMap = new HashMap(); - classLabelMap.put(mn.name + "|" + mn.desc, methodLabelMap); - } s += "\t// #Max: l:" + mn.maxLocals + " s:" + mn.maxStack + "\n"; - String[] dis = disassembleMethod(classNode.name, mn, methodLabelMap); + String[] dis = disassembleMethod(classNode.name, mn); + s += dis[2]; s += dis[1]; if (mn.visibleAnnotations != null && !mn.visibleAnnotations.isEmpty()) { @@ -286,19 +284,28 @@ public class Disassembler { } } - private static String[] disassembleMethod(String className, MethodNode mn, HashMap labels) { + private static String[] disassembleMethod(String className, MethodNode mn) { + HashMap labels = new HashMap(); String s = ""; String localVarTable = "\t// #LocalVars:\n"; + String tryCatchTable = "\t// #TryCatch:\n"; for (AbstractInsnNode n : mn.instructions.toArray()) { if (n instanceof LabelNode) { labels.put(((LabelNode) n).getLabel(), labels.size() + 1); } } - if (mn.localVariables != null) + if (mn.localVariables != null) { for (LocalVariableNode lvn : mn.localVariables) { localVarTable += "\t// " + lvn.name + ": " + lvn.desc + " i:" + lvn.index + " s:" + labels.get(lvn.start.getLabel()) + " e:" + labels.get(lvn.end.getLabel()) + "\n"; } + } + if (mn.tryCatchBlocks != null) { + for (TryCatchBlockNode tcbn : mn.tryCatchBlocks) { + tryCatchTable += "\t// " + tcbn.type + " s:" + labels.get(tcbn.start.getLabel()) + " e:" + + labels.get(tcbn.end.getLabel()) + " h:" + labels.get(tcbn.handler.getLabel()) + "\n"; + } + } for (AbstractInsnNode n : mn.instructions.toArray()) { switch (n.getClass().getSimpleName()) { case "FieldInsnNode": { @@ -520,7 +527,7 @@ public class Disassembler { break; } } - return new String[] { s, localVarTable }; + return new String[] { s, localVarTable, tryCatchTable }; } } \ No newline at end of file diff --git a/src/me/ByteEdit/main/Main.java b/src/me/ByteEdit/main/Main.java index 647e035..b59d199 100644 --- a/src/me/ByteEdit/main/Main.java +++ b/src/me/ByteEdit/main/Main.java @@ -64,6 +64,7 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.MethodNode; public class Main extends JFrame { @@ -79,8 +80,6 @@ public class Main extends JFrame { public static RSyntaxTextArea textArea; public static SearchBox searchBox; - // Class, Method, LabelMap - public static HashMap>> labels = new HashMap<>(); /** * Launch the application. @@ -237,7 +236,6 @@ public class Main extends JFrame { public void keyReleased(KeyEvent e) { if (e.getKeyCode() == 116 && jarFile != null) { try { - labels.clear(); isChangingFile = true; try { tree.setModel(new ArchiveTreeModel(new JarFile(jarFile))); @@ -321,7 +319,6 @@ public class Main extends JFrame { final File file = files.get(0); if (file.getName().endsWith(".jar")) { - labels.clear(); jarFile = file; isChangingFile = true; try {