5 Commits
Author SHA1 Message Date
SuspiciousActivity d1710ea6a5 Better frames 2020-11-29 00:38:20 +01:00
SuspiciousActivity ad55d6793c Fixed number obfuscator 2020-11-27 11:06:26 +01:00
SuspiciousActivity ac247a89ca Fixed number deobfuscator 2020-11-27 01:01:30 +01:00
SuspiciousActivity b5e4847be5 Added number deobfuscator 2020-11-27 00:07:03 +01:00
SuspiciousActivity 30c9c81d38 Fixed crash 2020-11-26 17:07:36 +01:00
5 changed files with 944 additions and 261 deletions

No files matched your search

+73 -106
View File
@@ -674,118 +674,41 @@ public class Assembler {
labels.put(ln, labelNr); labels.put(ln, labelNr);
return new LineNumberNode(Integer.parseInt(s.split(" ")[0]), ln); return new LineNumberNode(Integer.parseInt(s.split(" ")[0]), ln);
} else if (s.startsWith("// frame ")) { } else if (s.startsWith("// frame ")) {
String str1 = s.substring(7); String str1 = s.substring(9);
String str = str1.substring(str1.indexOf(' ', 3) + 1); String[] split = str1.split(" ", 2);
Object[] local;
Object[] stack;
ArrayList<Object> arr = new ArrayList<>();
if (str.startsWith("l:null")) {
local = new Object[0];
} else {
String l = str.substring(3, str.indexOf("s:") - 2);
if (l.isEmpty()) {
local = new Object[0];
} else {
for (String asd : l.split(", ")) {
if (!asd.startsWith("(")) {
int frameType = ClassUtil.getFrameTypeByName(asd);
if (frameType != -1)
arr.add(new Integer(frameType));
else
arr.add(UnicodeUtils.unescape(hsr, asd.substring(1, asd.length() - 1)));
} else {
if (asd.startsWith("(label) ")) {
int labelNr = Integer.parseInt(asd.split(" ")[1]);
boolean found = false;
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
if (entry.getValue() == labelNr) {
arr.add(entry.getKey());
found = true;
}
}
if (!found) {
LabelNode ln = new LabelNode(new Label());
labels.put(ln, labelNr);
arr.add(ln);
}
} else {
arr.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
}
}
}
local = new Object[arr.size()];
int c = 0;
for (Object o : arr) {
local[c] = o;
c++;
}
}
}
arr.clear();
if (str.endsWith("s:null")) {
stack = new Object[0];
} else {
String st = str.substring(str.indexOf("s:") + 3, str.length() - 1);
if (st.isEmpty()) {
stack = new Object[0];
} else {
for (String asd : st.split(", ")) {
if (!asd.startsWith("(")) {
int frameType = ClassUtil.getFrameTypeByName(asd);
if (frameType != -1)
arr.add(new Integer(frameType));
else
arr.add(UnicodeUtils.unescape(hsr, asd.substring(1, asd.length() - 1)));
} else {
if (asd.startsWith("(label) ")) {
int labelNr = Integer.parseInt(asd.split(" ")[1]);
boolean found = false;
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
if (entry.getValue() == labelNr) {
arr.add(entry.getKey());
found = true;
}
}
if (!found) {
LabelNode ln = new LabelNode(new Label());
labels.put(ln, labelNr);
arr.add(ln);
}
} else {
arr.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
}
}
}
stack = new Object[arr.size()];
int c = 0;
for (Object o : arr) {
stack[c] = o;
c++;
}
}
}
int type = 0; int type = 0;
switch (str1.substring(str1.indexOf(' ', 1) + 1, str1.indexOf(' ', 3))) { Object[] local = null;
case "NEW": Object[] stack = null;
type = Opcodes.F_NEW; int localLen = 0;
break; int stackLen = 0;
case "FULL": switch (split[0].toUpperCase()) {
type = Opcodes.F_FULL;
break;
case "APPEND":
type = Opcodes.F_APPEND;
break;
case "CHOP":
type = Opcodes.F_CHOP;
break;
case "SAME": case "SAME":
type = Opcodes.F_SAME; type = Opcodes.F_SAME;
break; break;
case "SAME1": case "SAME1":
type = Opcodes.F_SAME1; type = Opcodes.F_SAME1;
stack = parseFrameList(hsr, split[1], labels);
stackLen = stack.length;
break;
case "CHOP":
type = Opcodes.F_CHOP;
localLen = Integer.parseInt(split[1]);
break;
case "APPEND":
type = Opcodes.F_APPEND;
local = parseFrameList(hsr, split[1], labels);
localLen = local.length;
break;
case "FULL":
type = Opcodes.F_FULL;
split = split[1].split("\\] \\[", 2);
local = parseFrameList(hsr, split[0] + "]", labels);
localLen = local.length;
stack = parseFrameList(hsr, "[" + split[1], labels);
stackLen = stack.length;
break; break;
} }
return new FrameNode(type, local.length, local, stack.length, stack); return new FrameNode(type, localLen, local, stackLen, stack);
} else { } else {
String[] split = s.split(" "); String[] split = s.split(" ");
String command = split[0]; String command = split[0];
@@ -823,10 +746,10 @@ public class Assembler {
case "dconst_1": case "dconst_1":
return new InsnNode(15); return new InsnNode(15);
case "bipush": { case "bipush": {
return new IntInsnNode(16, Integer.parseInt(split[1])); return new IntInsnNode(16, (byte) Integer.parseInt(split[1]));
} }
case "sipush": { case "sipush": {
return new IntInsnNode(17, Integer.parseInt(split[1])); return new IntInsnNode(17, (short) Integer.parseInt(split[1]));
} }
case "ldc": { case "ldc": {
String str = consolidateStrings(split, 1); String str = consolidateStrings(split, 1);
@@ -1633,4 +1556,48 @@ public class Assembler {
} }
} }
} }
private static Object[] parseFrameList(HugeStringsRev hsr, String str, HashMap<LabelNode, Integer> labels) {
ArrayList<Object> list = new ArrayList<>();
String l = str.substring(1, str.length() - 1);
if (l.isEmpty()) {
return new Object[0];
} else {
for (String asd : l.split(", ")) {
if (!asd.startsWith("(")) {
int frameType = ClassUtil.getFrameTypeByName(asd);
if (frameType != -1)
list.add(new Integer(frameType));
else
list.add(UnicodeUtils.unescape(hsr, asd.substring(1, asd.length() - 1)));
} else {
if (asd.startsWith("(label) ")) {
int labelNr = Integer.parseInt(asd.split(" ")[1]);
boolean found = false;
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
if (entry.getValue() == labelNr) {
list.add(entry.getKey());
found = true;
}
}
if (!found) {
LabelNode ln = new LabelNode(new Label());
labels.put(ln, labelNr);
list.add(ln);
}
} else {
list.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
}
}
}
Object[] arr = new Object[list.size()];
int c = 0;
for (Object o : list) {
arr[c] = o;
c++;
}
return arr;
}
}
} }
+152 -153
View File
@@ -1,5 +1,22 @@
package me.ByteEdit.edit; package me.ByteEdit.edit;
import static org.objectweb.asm.tree.AbstractInsnNode.FIELD_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.FRAME;
import static org.objectweb.asm.tree.AbstractInsnNode.IINC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INT_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INVOKE_DYNAMIC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LABEL;
import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LINE;
import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.MULTIANEWARRAY_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TYPE_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.VAR_INSN;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@@ -24,7 +41,7 @@ import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.FrameNode; import org.objectweb.asm.tree.FrameNode;
import org.objectweb.asm.tree.IincInsnNode; import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.InnerClassNode; import org.objectweb.asm.tree.InnerClassNode;
import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.IntInsnNode; import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode; import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.JumpInsnNode;
@@ -419,9 +436,18 @@ public class Disassembler {
HashMap<Label, Integer> labels = new HashMap<Label, Integer>(); HashMap<Label, Integer> labels = new HashMap<Label, Integer>();
String localVarTable; String localVarTable;
String tryCatchTable; String tryCatchTable;
for (AbstractInsnNode n : mn.instructions.toArray()) {
InsnList insnList = mn.instructions;
boolean deobfNumbers = Main.INSTANCE.mntmNumbers.isSelected();
ArrayList<Label> labelsReversed = deobfNumbers ? new ArrayList<>() : null;
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
if (n instanceof LabelNode) { if (n instanceof LabelNode) {
labels.put(((LabelNode) n).getLabel(), labels.size() + 1); int id = labels.size() + 1;
if (deobfNumbers)
labelsReversed.add(((LabelNode) n).getLabel());
labels.put(((LabelNode) n).getLabel(), id);
} }
} }
if (mn.localVariables != null && !mn.localVariables.isEmpty()) { if (mn.localVariables != null && !mn.localVariables.isEmpty()) {
@@ -449,110 +475,62 @@ public class Disassembler {
tryCatchTable = ctx.finish(); tryCatchTable = ctx.finish();
} else } else
tryCatchTable = ""; tryCatchTable = "";
AbstractInsnNode[] insns = mn.instructions.toArray();
StringContext ctx = new StringContext(insns.length); if (deobfNumbers) {
for (AbstractInsnNode n : insns) { StackBasedCalculator calc = new StackBasedCalculator(insnList);
calc.run();
insnList = calc.get();
int i = 0;
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
if (n instanceof LabelNode) {
((LabelNode) n).setLabel(labelsReversed.get(i++));
}
}
}
StringContext ctx = new StringContext(insnList.size());
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
ctx.next(disassembleInstruction(n, labels, hs)); ctx.next(disassembleInstruction(n, labels, hs));
} }
return new String[] { ctx.finish(), localVarTable, tryCatchTable }; return new String[] { ctx.finish(), localVarTable, tryCatchTable };
} }
public static final HashMap<Class, InstructionInterface> iiMap = new HashMap<>(); public static String disassembleInstruction(AbstractInsnNode n, HashMap<Label, Integer> labels, HugeStrings hs) {
switch (n.getType()) {
static { case INSN: {
iiMap.put(FieldInsnNode.class, (n, labels, hs) -> { return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + "\n";
}
case INT_INSN: {
IntInsnNode node = (IntInsnNode) n;
if (n.getOpcode() == Opcodes.NEWARRAY) {
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
+ ClassUtil.getArrayTypeByID(node.operand) + "\n";
} else {
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n";
}
}
case VAR_INSN: {
VarInsnNode node = (VarInsnNode) n;
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + "\n";
}
case TYPE_INSN: {
TypeInsnNode node = (TypeInsnNode) n;
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + "\n";
}
case FIELD_INSN: {
FieldInsnNode node = (FieldInsnNode) n; FieldInsnNode node = (FieldInsnNode) n;
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner) + UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner)
+ "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n"; + "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n";
});
iiMap.put(LabelNode.class, (n, labels, hs) -> {
LabelNode node = (LabelNode) n;
return "\t\t// label " + labels.get(node.getLabel()) + "\n";
});
iiMap.put(FrameNode.class, (n, labels, hs) -> {
FrameNode node = (FrameNode) n;
String type = "";
switch (node.type) {
case Opcodes.F_NEW:
type = "NEW";
break;
case Opcodes.F_FULL:
type = "FULL";
break;
case Opcodes.F_APPEND:
type = "APPEND";
break;
case Opcodes.F_CHOP:
type = "CHOP";
break;
case Opcodes.F_SAME:
type = "SAME";
break;
case Opcodes.F_SAME1:
type = "SAME1";
break;
} }
String s = "\t\t// frame " + type + " l:"; case METHOD_INSN: {
ArrayList<String> arr = new ArrayList<>(); MethodInsnNode node = (MethodInsnNode) n;
if (node.local != null) { return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
for (Object o : node.local) { + UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner)
if (o == null) { + "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n";
arr.add(null);
} else {
if (o instanceof String) {
arr.add("\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"");
} else if (o instanceof LabelNode) {
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
} else if (o instanceof Integer) {
String frameType = ClassUtil.getFrameTypeByID(((Integer) o).intValue());
if (frameType != null)
arr.add(frameType);
else
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
} else {
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
} }
} case INVOKE_DYNAMIC_INSN: {
}
s += arr.toString();
} else {
s += "null";
}
arr.clear();
s += " s:";
if (node.stack != null) {
for (Object o : node.stack) {
if (o == null) {
arr.add(null);
} else {
if (o instanceof String) {
arr.add("\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"");
} else if (o instanceof LabelNode) {
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
} else if (o instanceof Integer) {
String frameType = ClassUtil.getFrameTypeByID(((Integer) o).intValue());
if (frameType != null)
arr.add(frameType);
else
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
} else {
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
}
}
}
s += arr.toString();
} else {
s += "null";
}
s += "\n";
return s;
});
iiMap.put(LineNumberNode.class, (n, labels, hs) -> {
LineNumberNode node = (LineNumberNode) n;
return "\t\t// line " + node.line + " " + labels.get(node.start.getLabel()) + "\n";
});
iiMap.put(InvokeDynamicInsnNode.class, (n, labels, hs) -> {
InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) n; InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) n;
String s = "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " [\n\t\t\tname: " String s = "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " [\n\t\t\tname: "
+ UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n\t\t\tdesc: " + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n\t\t\tdesc: "
@@ -588,24 +566,17 @@ public class Disassembler {
} }
s += "\t\t\t]\n\t\t]\n"; s += "\t\t\t]\n\t\t]\n";
return s; return s;
}); }
iiMap.put(MethodInsnNode.class, (n, labels, hs) -> { case JUMP_INSN: {
MethodInsnNode node = (MethodInsnNode) n; JumpInsnNode node = (JumpInsnNode) n;
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + labels.get(node.label.getLabel())
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner) + "\n";
+ "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n"; }
}); case LABEL: {
iiMap.put(TypeInsnNode.class, (n, labels, hs) -> { LabelNode node = (LabelNode) n;
TypeInsnNode node = (TypeInsnNode) n; return "\t\t// label " + labels.get(node.getLabel()) + "\n";
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " }
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + "\n"; case LDC_INSN: {
});
iiMap.put(MultiANewArrayInsnNode.class, (n, labels, hs) -> {
MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) n;
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + node.dims + "\n";
});
iiMap.put(LdcInsnNode.class, (n, labels, hs) -> {
LdcInsnNode node = (LdcInsnNode) n; LdcInsnNode node = (LdcInsnNode) n;
if (node.cst instanceof Type) { if (node.cst instanceof Type) {
Type type = (Type) node.cst; Type type = (Type) node.cst;
@@ -628,30 +599,12 @@ public class Disassembler {
} }
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + decomp + "\n"; return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + decomp + "\n";
} }
});
iiMap.put(VarInsnNode.class, (n, labels, hs) -> {
VarInsnNode node = (VarInsnNode) n;
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + "\n";
});
iiMap.put(InsnNode.class, (n, labels, hs) -> {
InsnNode node = (InsnNode) n;
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + "\n";
});
iiMap.put(IntInsnNode.class, (n, labels, hs) -> {
IntInsnNode node = (IntInsnNode) n;
if (n.getOpcode() == Opcodes.NEWARRAY) {
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
+ ClassUtil.getArrayTypeByID(node.operand) + "\n";
} else {
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n";
} }
}); case IINC_INSN: {
iiMap.put(JumpInsnNode.class, (n, labels, hs) -> { IincInsnNode node = (IincInsnNode) n;
JumpInsnNode node = (JumpInsnNode) n; return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + " " + node.incr + "\n";
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + labels.get(node.label.getLabel()) }
+ "\n"; case TABLESWITCH_INSN: {
});
iiMap.put(TableSwitchInsnNode.class, (n, labels, hs) -> {
TableSwitchInsnNode node = (TableSwitchInsnNode) n; TableSwitchInsnNode node = (TableSwitchInsnNode) n;
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tmin: " + node.min String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tmin: " + node.min
+ "\n\t\t\tmax: " + node.max + "\n\t\t\tdefault: " + labels.get(node.dflt.getLabel()) + "\n\t\t\tmax: " + node.max + "\n\t\t\tdefault: " + labels.get(node.dflt.getLabel())
@@ -661,8 +614,8 @@ public class Disassembler {
} }
s += "\t\t\t]\n\t\t]\n"; s += "\t\t\t]\n\t\t]\n";
return s; return s;
}); }
iiMap.put(LookupSwitchInsnNode.class, (n, labels, hs) -> { case LOOKUPSWITCH_INSN: {
LookupSwitchInsnNode node = (LookupSwitchInsnNode) n; LookupSwitchInsnNode node = (LookupSwitchInsnNode) n;
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tdefault: " String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tdefault: "
+ labels.get(node.dflt.getLabel()) + "\n\t\t\tkeys: [\n"; + labels.get(node.dflt.getLabel()) + "\n\t\t\tkeys: [\n";
@@ -675,24 +628,70 @@ public class Disassembler {
} }
s += "\t\t\t]\n\t\t]\n"; s += "\t\t\t]\n\t\t]\n";
return s; return s;
});
iiMap.put(IincInsnNode.class, (n, labels, hs) -> {
IincInsnNode node = (IincInsnNode) n;
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + " " + node.incr + "\n";
});
} }
case MULTIANEWARRAY_INSN: {
static interface InstructionInterface { MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) n;
String apply(AbstractInsnNode n, HashMap<Label, Integer> labels, HugeStrings hs); return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + node.dims + "\n";
} }
case FRAME: {
public static String disassembleInstruction(AbstractInsnNode n, HashMap<Label, Integer> labels, HugeStrings hs) { FrameNode node = (FrameNode) n;
InstructionInterface ii = iiMap.get(n.getClass()); String out = "";
if (ii != null) switch (node.type) {
return ii.apply(n, labels, hs); case Opcodes.F_SAME:
else out = "SAME";
break;
case Opcodes.F_SAME1:
out = "SAME1 " + getFrameArray(hs, node.stack, labels);
break;
case Opcodes.F_CHOP:
out = "CHOP " + Integer.toString(node.local.size());
break;
case Opcodes.F_APPEND:
out = "APPEND " + getFrameArray(hs, node.local, labels);
break;
case Opcodes.F_FULL:
out = "FULL " + getFrameArray(hs, node.local, labels) + " " + getFrameArray(hs, node.stack, labels);
break;
}
return "\t\t// frame " + out + "\n";
}
case LINE: {
LineNumberNode node = (LineNumberNode) n;
return "\t\t// line " + node.line + " " + labels.get(node.start.getLabel()) + "\n";
}
default: {
return "\t\tNOT HANDLED! " + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " return "\t\tNOT HANDLED! " + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
+ n.getClass().getSimpleName() + "\n"; + n.getClass().getSimpleName() + "\n";
} }
}
}
private static String getFrameArray(HugeStrings hs, List<Object> list, HashMap<Label, Integer> labels) {
ArrayList<String> arr = new ArrayList<>();
if (list != null) {
for (Object o : list) {
if (o == null) {
arr.add(null);
} else {
if (o instanceof String) {
arr.add("\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"");
} else if (o instanceof LabelNode) {
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
} else if (o instanceof Integer) {
String frameType = ClassUtil.getFrameTypeByID(((Integer) o).intValue());
if (frameType != null)
arr.add(frameType);
else
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
} else {
arr.add("(" + o.getClass().getName().replace(".", "/") + ") " + o);
}
}
}
return arr.toString();
}
return "null";
}
} }
@@ -0,0 +1,689 @@
package me.ByteEdit.edit;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Stack;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LdcInsnNode;
public class StackBasedCalculator implements Opcodes, Runnable {
private final InsnList insns;
private final Stack<Number> stack = new Stack<>();
private AbstractInsnNode start;
private int startIdx = -1;
private boolean isAtEnd = false;
public StackBasedCalculator(InsnList insns) {
this.insns = new InsnList();
HashMap<LabelNode, LabelNode> labelMap = new HashMap<>();
for (AbstractInsnNode node = insns.getFirst(); node != null; node = node.getNext()) {
if (node.getType() == AbstractInsnNode.LABEL) {
labelMap.put((LabelNode) node, new LabelNode());
}
}
for (AbstractInsnNode node = insns.getFirst(); node != null; node = node.getNext()) {
this.insns.add(node.clone(labelMap));
}
}
public InsnList get() {
return insns;
}
@Override
public void run() {
while (!isAtEnd) {
out: {
AbstractInsnNode[] arr = insns.toArray();
for (int i = startIdx == -1 ? 0 : startIdx; i < arr.length; i++) {
if (!handle(arr[i]))
break out;
}
isAtEnd = true;
}
}
}
private boolean handle(AbstractInsnNode node) {
try {
switch (node.getOpcode()) {
case ICONST_0:
stack.push(Integer.valueOf(0));
if (start == null)
start = node;
break;
case ICONST_1:
stack.push(Integer.valueOf(1));
if (start == null)
start = node;
break;
case ICONST_2:
stack.push(Integer.valueOf(2));
if (start == null)
start = node;
break;
case ICONST_3:
stack.push(Integer.valueOf(3));
if (start == null)
start = node;
break;
case ICONST_4:
stack.push(Integer.valueOf(4));
if (start == null)
start = node;
break;
case ICONST_5:
stack.push(Integer.valueOf(5));
if (start == null)
start = node;
break;
case ICONST_M1:
stack.push(Integer.valueOf(-1));
if (start == null)
start = node;
break;
case DCONST_0:
stack.push(Double.valueOf(0));
if (start == null)
start = node;
break;
case DCONST_1:
stack.push(Double.valueOf(1));
if (start == null)
start = node;
break;
case FCONST_0:
stack.push(Float.valueOf(0));
if (start == null)
start = node;
break;
case FCONST_1:
stack.push(Float.valueOf(1));
if (start == null)
start = node;
break;
case FCONST_2:
stack.push(Float.valueOf(2));
if (start == null)
start = node;
break;
case LCONST_0:
stack.push(Long.valueOf(0));
if (start == null)
start = node;
break;
case LCONST_1:
stack.push(Long.valueOf(1));
if (start == null)
start = node;
break;
case BIPUSH:
case SIPUSH:
stack.push(((IntInsnNode) node).operand);
if (start == null)
start = node;
break;
case D2F:
stack.push(((Double) stack.pop()).floatValue());
change(node);
return false;
case D2I:
stack.push(((Double) stack.pop()).intValue());
change(node);
return false;
case D2L:
stack.push(((Double) stack.pop()).longValue());
change(node);
return false;
case F2D:
stack.push(((Float) stack.pop()).doubleValue());
change(node);
return false;
case F2I:
stack.push(((Float) stack.pop()).intValue());
change(node);
return false;
case F2L:
stack.push(((Float) stack.pop()).longValue());
change(node);
return false;
case L2D:
stack.push(((Long) stack.pop()).doubleValue());
change(node);
return false;
case L2F:
stack.push(((Long) stack.pop()).floatValue());
change(node);
return false;
case L2I:
stack.push(((Long) stack.pop()).intValue());
change(node);
return false;
case I2B:
error(node);
return true;
case I2C:
error(node);
return true;
case I2D:
stack.push(((Integer) stack.pop()).doubleValue());
change(node);
return false;
case I2F:
stack.push(((Integer) stack.pop()).floatValue());
change(node);
return false;
case I2L:
stack.push(((Integer) stack.pop()).longValue());
change(node);
return false;
case I2S:
error(node);
return true;
case NOP:
break;
case LDC:
LdcInsnNode ldc = (LdcInsnNode) node;
if (ldc.cst instanceof Number) {
stack.push((Number) ldc.cst);
if (start == null)
start = node;
} else {
error(node);
return true;
}
break;
// long
case LADD: {
long top = ((Long) stack.pop()).longValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom + top);
change(node);
return false;
}
case LSUB: {
long top = ((Long) stack.pop()).longValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom - top);
change(node);
return false;
}
case LMUL: {
long top = ((Long) stack.pop()).longValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom * top);
change(node);
return false;
}
case LDIV: {
long top = ((Long) stack.pop()).longValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom / top);
change(node);
return false;
}
case LREM: {
long top = ((Long) stack.pop()).longValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom % top);
change(node);
return false;
}
case LNEG: {
long top = ((Long) stack.pop()).longValue();
stack.push(-top);
change(node);
return false;
}
case LAND: {
long top = ((Long) stack.pop()).longValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom & top);
change(node);
return false;
}
case LOR: {
long top = ((Long) stack.pop()).longValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom | top);
change(node);
return false;
}
case LXOR: {
long top = ((Long) stack.pop()).longValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom ^ top);
change(node);
return false;
}
case LSHR: {
int top = ((Integer) stack.pop()).intValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom >> top);
change(node);
return false;
}
case LSHL: {
int top = ((Integer) stack.pop()).intValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom << top);
change(node);
return false;
}
case LUSHR: {
int top = ((Integer) stack.pop()).intValue();
long bottom = ((Long) stack.pop()).longValue();
stack.push(bottom >>> top);
change(node);
return false;
}
// int
case IADD: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom + top);
change(node);
return false;
}
case ISUB: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom - top);
change(node);
return false;
}
case IMUL: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom * top);
change(node);
return false;
}
case IDIV: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom / top);
change(node);
return false;
}
case IREM: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom % top);
change(node);
return false;
}
case INEG: {
int top = ((Integer) stack.pop()).intValue();
stack.push(-top);
change(node);
return false;
}
case IAND: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom & top);
change(node);
return false;
}
case IOR: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom | top);
change(node);
return false;
}
case IXOR: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom ^ top);
change(node);
return false;
}
case ISHR: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom >> top);
change(node);
return false;
}
case ISHL: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom << top);
change(node);
return false;
}
case IUSHR: {
int top = ((Integer) stack.pop()).intValue();
int bottom = ((Integer) stack.pop()).intValue();
stack.push(bottom >>> top);
change(node);
return false;
}
// double
case DADD: {
double top = ((Double) stack.pop()).doubleValue();
double bottom = ((Double) stack.pop()).doubleValue();
stack.push(bottom + top);
change(node);
return false;
}
case DSUB: {
double top = ((Double) stack.pop()).doubleValue();
double bottom = ((Double) stack.pop()).doubleValue();
stack.push(bottom - top);
change(node);
return false;
}
case DMUL: {
double top = ((Double) stack.pop()).doubleValue();
double bottom = ((Double) stack.pop()).doubleValue();
stack.push(bottom * top);
change(node);
return false;
}
case DDIV: {
double top = ((Double) stack.pop()).doubleValue();
double bottom = ((Double) stack.pop()).doubleValue();
stack.push(bottom / top);
change(node);
return false;
}
case DREM: {
double top = ((Double) stack.pop()).doubleValue();
double bottom = ((Double) stack.pop()).doubleValue();
stack.push(bottom % top);
change(node);
return false;
}
case DNEG: {
double top = ((Double) stack.pop()).doubleValue();
stack.push(-top);
change(node);
return false;
}
// float
case FADD: {
float top = ((Float) stack.pop()).floatValue();
float bottom = ((Float) stack.pop()).floatValue();
stack.push(bottom + top);
change(node);
return false;
}
case FSUB: {
float top = ((Float) stack.pop()).floatValue();
float bottom = ((Float) stack.pop()).floatValue();
stack.push(bottom - top);
change(node);
return false;
}
case FMUL: {
float top = ((Float) stack.pop()).floatValue();
float bottom = ((Float) stack.pop()).floatValue();
stack.push(bottom * top);
change(node);
return false;
}
case FDIV: {
float top = ((Float) stack.pop()).floatValue();
float bottom = ((Float) stack.pop()).floatValue();
stack.push(bottom / top);
change(node);
return false;
}
case FREM: {
float top = ((Float) stack.pop()).floatValue();
float bottom = ((Float) stack.pop()).floatValue();
stack.push(bottom % top);
change(node);
return false;
}
case FNEG: {
float top = ((Float) stack.pop()).floatValue();
stack.push(-top);
change(node);
return false;
}
// dup
case DUP: {
Number num = stack.pop();
if (num instanceof Double || num instanceof Long) {
error(node);
return true;
}
stack.push(num);
stack.push(num);
change(node);
return false;
}
case DUP_X1: {
Number top = stack.pop();
Number bottom = stack.pop();
if (bottom instanceof Double || bottom instanceof Long || top instanceof Double
|| top instanceof Long) {
error(node);
return true;
}
stack.push(top);
stack.push(bottom);
stack.push(top);
change(node);
return false;
}
case DUP_X2: {
Number top = stack.pop();
Number bottom = stack.pop();
if (top instanceof Double || top instanceof Long) {
error(node);
return true;
}
Number bottom2 = null;
if (!(bottom instanceof Double || bottom instanceof Long)) {
bottom2 = stack.pop();
if (bottom instanceof Double || bottom instanceof Long) {
error(node);
return true;
}
}
stack.push(top);
if (bottom2 != null)
stack.push(bottom2);
stack.push(bottom);
stack.push(top);
change(node);
return false;
}
case DUP2: {
Number top = stack.pop();
Number bottom = null;
if (!(top instanceof Double || top instanceof Long)) {
bottom = stack.pop();
if (bottom instanceof Double || bottom instanceof Long) {
error(node);
return true;
}
}
if (bottom != null)
stack.push(bottom);
stack.push(top);
if (bottom != null)
stack.push(bottom);
stack.push(top);
change(node);
return false;
}
case DUP2_X1: {
Number top = stack.pop();
Number bottom = null;
if (!(top instanceof Double || top instanceof Long)) {
bottom = stack.pop();
if (bottom instanceof Double || bottom instanceof Long) {
error(node);
return true;
}
}
Number bottom2 = stack.pop();
if (bottom != null)
stack.push(bottom);
stack.push(top);
stack.push(bottom2);
if (bottom != null)
stack.push(bottom);
stack.push(top);
change(node);
return false;
}
case DUP2_X2: {
Number top = stack.pop();
Number bottom = null;
if (!(top instanceof Double || top instanceof Long)) {
bottom = stack.pop();
if (bottom instanceof Double || bottom instanceof Long) {
error(node);
return true;
}
}
Number top2 = stack.pop();
Number bottom2 = null;
if (!(top2 instanceof Double || top2 instanceof Long)) {
bottom2 = stack.pop();
if (bottom2 instanceof Double || bottom2 instanceof Long) {
error(node);
return true;
}
}
if (bottom != null)
stack.push(bottom);
stack.push(top);
if (bottom2 != null)
stack.push(bottom2);
stack.push(top2);
if (bottom != null)
stack.push(bottom);
stack.push(top);
change(node);
return false;
}
// stack
case POP:
stack.pop();
change(node);
return false;
case POP2:
stack.pop();
stack.pop();
change(node);
return false;
case SWAP: {
Number top = stack.pop();
Number bottom = stack.pop();
if (bottom instanceof Double || bottom instanceof Long || top instanceof Double
|| top instanceof Long) {
error(node);
return true;
}
stack.push(top);
stack.push(bottom);
change(node);
return false;
}
default:
error(node);
return true;
}
} catch (ClassCastException | EmptyStackException ex) {
error(node);
return true;
}
return true;
}
private void error(AbstractInsnNode node) {
change(node.getPrevious());
stack.clear();
start = null;
}
private void change(AbstractInsnNode node) {
if (start == null)
return;
int idx = insns.indexOf(start);
startIdx = idx;
int idx2 = insns.indexOf(node);
if (idx != idx2) {
for (int i = 0; i <= idx2 - idx; i++) {
insns.remove(insns.get(idx));
}
while (!stack.isEmpty()) {
addNode(idx, stack.pop());
}
}
stack.clear();
start = null;
}
private void addNode(int idx, Number n) {
if (n instanceof Double) {
double val = n.doubleValue();
if (val == 0.0)
insns.insertBefore(insns.get(idx), new InsnNode(DCONST_0));
else if (val == 1.0)
insns.insertBefore(insns.get(idx), new InsnNode(DCONST_1));
else
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
} else if (n instanceof Float) {
float val = n.floatValue();
if (val == 0.0f)
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_0));
else if (val == 1.0f)
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_1));
else if (val == 2.0f)
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_2));
else
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
} else if (n instanceof Long) {
long val = n.longValue();
if (val == 0l)
insns.insertBefore(insns.get(idx), new InsnNode(LCONST_0));
else if (val == 1l)
insns.insertBefore(insns.get(idx), new InsnNode(LCONST_1));
else
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
} else if (n instanceof Integer) {
int val = n.intValue();
if (val == 0)
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_0));
else if (val == 1)
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_1));
else if (val == 2)
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_2));
else if (val == 3)
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_3));
else if (val == 4)
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_4));
else if (val == 5)
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_5));
else if (val == -1)
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_M1));
else if (val == (byte) val)
insns.insertBefore(insns.get(idx), new IntInsnNode(BIPUSH, (byte) val));
else if (val == (short) val)
insns.insertBefore(insns.get(idx), new IntInsnNode(SIPUSH, (short) val));
else
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
} else {
throw new RuntimeException("Unexpected number: " + n);
}
}
}
+20 -2
View File
@@ -148,6 +148,8 @@ public class Main extends JFrame {
private JMenuItem rdbtnmntm5000; private JMenuItem rdbtnmntm5000;
private JMenuItem rdbtnmntm10000; private JMenuItem rdbtnmntm10000;
public JCheckBoxMenuItem mntmMultithreaded; public JCheckBoxMenuItem mntmMultithreaded;
private JMenu mnDeobfuscation;
public JCheckBoxMenuItem mntmNumbers;
public static final Object treeLock = new Object(); public static final Object treeLock = new Object();
@@ -229,7 +231,17 @@ public class Main extends JFrame {
"// #Max: l:0 s:0\n\t// #TryCatch:\n\t// #LocalVars:\n\tpublic static method ()V {\n\t\treturn\n\t}", "// #Max: l:0 s:0\n\t// #TryCatch:\n\t// #LocalVars:\n\tpublic static method ()V {\n\t\treturn\n\t}",
null, "<html><b><u>method</u></b><br>Creates an example method</html>")); null, "<html><b><u>method</u></b><br>Creates an example method</html>"));
provider.addCompletion(new ShorthandCompletion(provider, "frame", "frame FULL l:[] s:[]", null, provider.addCompletion(new ShorthandCompletion(provider, "frame", "frame FULL l:[] s:[]", null,
"<html><b><u>frame</u></b><br>Creates a stack map frame</html>")); "<html><b><u>frame</u></b><br>Creates a stack map frame<br><br><b>Possible frames:</b><br><ul><li><code>SAME: same locals, empty stack</code></li><li><code>SAME1: same locals, stack has 1 entry</code></li><li><code>CHOP: same locals - k, empty stack</code></li><li><code>APPEND: same locals + k, empty stack</code></li><li><code>FULL: define locals, define stack</code></li></ul></html>"));
provider.addCompletion(new BasicCompletion(provider, "SAME", null,
"<html><b><u>Frames:</u></b><br><code>SAME</code><br><br><u>Locals:</u> same as previous<br><u>Stack:</u> empty</html>"));
provider.addCompletion(new BasicCompletion(provider, "SAME1", null,
"<html><b><u>Frames:</u></b><br><code>SAME1 [(type)]</code><br><br><u>Locals:</u> same as previous<br><u>Stack:</u> 1 entry</html>"));
provider.addCompletion(new BasicCompletion(provider, "CHOP", null,
"<html><b><u>Frames:</u></b><br><code>CHOP (int:k)</code><br><br><u>Locals:</u> removes the top <i>k</i> elements<br><u>Stack:</u> empty</html>"));
provider.addCompletion(new BasicCompletion(provider, "APPEND", null,
"<html><b><u>Frames:</u></b><br><code>APPEND [(type), (type), ...]</code><br><br><u>Locals:</u> adds the elements to the top<br><u>Stack:</u> empty</html>"));
provider.addCompletion(new BasicCompletion(provider, "FULL", null,
"<html><b><u>Frames:</u></b><br><code>FULL [(type), (type), ...] [(type), (type), ...]</code><br><i>first locals, then stack</i><br><br><u>Locals:</u> sets the elements<br><u>Stack:</u> sets the elements</html>"));
return provider; return provider;
} }
@@ -416,6 +428,12 @@ public class Main extends JFrame {
group.add(rdbtnmntm5000); group.add(rdbtnmntm5000);
group.add(rdbtnmntm10000); group.add(rdbtnmntm10000);
mnDeobfuscation = new JMenu("Deobfuscation");
menuBar.add(mnDeobfuscation);
mntmNumbers = new JCheckBoxMenuItem("Numbers");
mnDeobfuscation.add(mntmNumbers);
contentPane = new JPanel(); contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane); setContentPane(contentPane);
@@ -672,7 +690,7 @@ public class Main extends JFrame {
len += asm.length(); len += asm.length();
} }
} }
} catch (BadLocationException e1) { } catch (Exception e1) {
} }
return null; return null;
} }
@@ -403,6 +403,9 @@ public class TokenImpl implements Token {
int last = getOffset(); int last = getOffset();
FontMetrics fm = null; FontMetrics fm = null;
while (token != null && token.isPaintable()) { while (token != null && token.isPaintable()) {
if (token.textCount > 10000) {
return getOffset() + (int) (x / 7);
}
fm = textArea.getFontMetricsForTokenType(token.getType()); fm = textArea.getFontMetricsForTokenType(token.getType());
char[] text = token.text; char[] text = token.text;
int start = token.textOffset; int start = token.textOffset;
@@ -786,6 +789,13 @@ public class TokenImpl implements Token {
this.type = type; this.type = type;
} }
public void reset() {
text = null;
offset = -1;
type = Token.NULL;
nextToken = null;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */