From 8b29ca20ffcbae3ee2575dfba0cf1287581b2f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Thu, 18 Apr 2013 21:17:54 +0200 Subject: [PATCH] AS3: better deobfuscation --- .../decompiler/flash/abc/avm2/AVM2Code.java | 49 ++++++++++++------- .../instructions/localregs/DecLocalIIns.java | 7 ++- .../instructions/localregs/DecLocalIns.java | 7 ++- .../instructions/localregs/IncLocalIIns.java | 7 ++- .../instructions/localregs/IncLocalIns.java | 7 ++- .../localregs/SetLocalTypeIns.java | 7 ++- .../treemodel/NotCompileTimeTreeItem.java | 43 ++++++++++++++++ .../decompiler/flash/abc/gui/DetailPanel.java | 2 +- 8 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/NotCompileTimeTreeItem.java diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 27bcf2fcb..4b163f739 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -2411,27 +2411,32 @@ public class AVM2Code implements Serializable { public boolean skipUsed = false; } - private static int removeTraps(boolean secondPass, boolean useVisited, List localData, Stack stack, List output, AVM2GraphSource code, int ip, int lastIp, List visited, HashMap> visitedStates, HashMap decisions) { + private static int removeTraps(boolean secondPass, boolean useVisited, List localData, Stack stack, List output, AVM2GraphSource code, int ip, int lastIp, HashMap visited, HashMap> visitedStates, HashMap decisions) { boolean debugMode = false; int ret = 0; iploop: while ((ip > -1) && ip < code.size()) { - - - HashMap currentState = (HashMap) localData.get(2); - if (visitedStates.containsKey(ip)) { - HashMap lastState = visitedStates.get(ip); - if (lastState.equals(currentState)) { + if (useVisited) { + if (visited.containsKey(ip)) { break; } - } - visitedStates.put(ip, (HashMap) currentState.clone()); - if (useVisited && visited.contains(ip)) { - break; - } - if (!visited.contains(ip)) { - visited.add(ip); + if (!visited.containsKey(ip)) { + visited.put(ip, 0); + } else { + visited.put(ip, visited.get(ip) + 1); + } + } else { + HashMap currentState = (HashMap) localData.get(2); + + if (visitedStates.containsKey(ip)) { + HashMap lastState = visitedStates.get(ip); + if (lastState.equals(currentState)) { + break; + } + } + visitedStates.put(ip, (HashMap) currentState.clone()); + } lastIp = ip; GraphSourceItem ins = code.get(ip); @@ -2440,7 +2445,7 @@ public class AVM2Code implements Serializable { continue; } if (debugMode) { - System.out.println((useVisited ? "useV " : "") + "Visit " + ip + ": " + ins + " stack:" + Highlighting.stripHilights(stack.toString())); + System.out.println((useVisited ? "useV " : "") + (secondPass ? "secondPass " : "") + "Visit " + ip + ": " + ins + " stack:" + Highlighting.stripHilights(stack.toString())); } AVM2Instruction ains = (AVM2Instruction) ins; if (ains.definition instanceof DupIns) { @@ -2551,6 +2556,15 @@ public class AVM2Code implements Serializable { } else { if (ins.isBranch() && (!ins.isJump())) { stack.pop(); + + Decision dec = new Decision(); + if (decisions.containsKey(ins)) { + dec = decisions.get(ins); + } else { + decisions.put(ins, dec); + } + dec.jumpUsed = true; + dec.skipUsed = true; } for (int b : branches) { @@ -2576,7 +2590,8 @@ public class AVM2Code implements Serializable { public static int removeTraps(List localData, AVM2GraphSource code, int addr) { HashMap decisions = new HashMap(); - removeTraps(false, false, localData, new Stack(), new ArrayList(), code, code.adr2pos(addr), 0, new ArrayList(), new HashMap>(), decisions); - return removeTraps(true, false, localData, new Stack(), new ArrayList(), code, code.adr2pos(addr), 0, new ArrayList(), new HashMap>(), decisions); + removeTraps(false, false, localData, new Stack(), new ArrayList(), code, code.adr2pos(addr), 0, new HashMap(), new HashMap>(), decisions); + localData.set(2, new HashMap()); + return removeTraps(true, true, localData, new Stack(), new ArrayList(), code, code.adr2pos(addr), 0, new HashMap(), new HashMap>(), decisions); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIIns.java index 4fe5d6247..f8267a20e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIIns.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.treemodel.DecLocalTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.IntegerValueTreeItem; +import com.jpexs.decompiler.flash.abc.avm2.treemodel.NotCompileTimeTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.SubtractTreeItem; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.graph.GraphTargetItem; @@ -59,7 +60,11 @@ public class DecLocalIIns extends InstructionDefinition { public void translate(boolean isStatic, int classIndex, java.util.HashMap localRegs, Stack stack, java.util.Stack scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap localRegNames, List fullyQualifiedNames) { int regIndex = ins.operands[0]; output.add(new DecLocalTreeItem(ins, regIndex)); - localRegs.put(regIndex, new SubtractTreeItem(ins, localRegs.get(regIndex), new IntegerValueTreeItem(ins, new Long(1)))); + if (localRegs.containsKey(regIndex)) { + localRegs.put(regIndex, new NotCompileTimeTreeItem(ins)); + } else { + localRegs.put(regIndex, new SubtractTreeItem(ins, localRegs.get(regIndex), new IntegerValueTreeItem(ins, new Long(1)))); + } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIns.java index a7cfff629..d45cdf689 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/DecLocalIns.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.treemodel.DecLocalTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.IntegerValueTreeItem; +import com.jpexs.decompiler.flash.abc.avm2.treemodel.NotCompileTimeTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.SubtractTreeItem; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.graph.GraphTargetItem; @@ -59,6 +60,10 @@ public class DecLocalIns extends InstructionDefinition { public void translate(boolean isStatic, int classIndex, java.util.HashMap localRegs, Stack stack, java.util.Stack scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap localRegNames, List fullyQualifiedNames) { int regIndex = ins.operands[0]; output.add(new DecLocalTreeItem(ins, regIndex)); - localRegs.put(regIndex, new SubtractTreeItem(ins, localRegs.get(regIndex), new IntegerValueTreeItem(ins, new Long(1)))); + if (localRegs.containsKey(regIndex)) { + localRegs.put(regIndex, new NotCompileTimeTreeItem(ins)); + } else { + localRegs.put(regIndex, new SubtractTreeItem(ins, localRegs.get(regIndex), new IntegerValueTreeItem(ins, new Long(1)))); + } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIIns.java index b4d7ff850..99b3fde4e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIIns.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.treemodel.IncLocalTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.IntegerValueTreeItem; +import com.jpexs.decompiler.flash.abc.avm2.treemodel.NotCompileTimeTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.AddTreeItem; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.graph.GraphTargetItem; @@ -39,6 +40,10 @@ public class IncLocalIIns extends InstructionDefinition { public void translate(boolean isStatic, int classIndex, java.util.HashMap localRegs, Stack stack, java.util.Stack scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap localRegNames, List fullyQualifiedNames) { int regIndex = ins.operands[0]; output.add(new IncLocalTreeItem(ins, regIndex)); - localRegs.put(regIndex, new AddTreeItem(ins, localRegs.get(regIndex), new IntegerValueTreeItem(ins, new Long(1)))); + if (localRegs.containsKey(regIndex)) { + localRegs.put(regIndex, new NotCompileTimeTreeItem(ins)); + } else { + localRegs.put(regIndex, new AddTreeItem(ins, localRegs.get(regIndex), new IntegerValueTreeItem(ins, new Long(1)))); + } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIns.java index 81ac04460..542ddd131 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/IncLocalIns.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.treemodel.IncLocalTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.IntegerValueTreeItem; +import com.jpexs.decompiler.flash.abc.avm2.treemodel.NotCompileTimeTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.operations.AddTreeItem; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.graph.GraphTargetItem; @@ -39,6 +40,10 @@ public class IncLocalIns extends InstructionDefinition { public void translate(boolean isStatic, int classIndex, java.util.HashMap localRegs, Stack stack, java.util.Stack scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap localRegNames, List fullyQualifiedNames) { int regIndex = ins.operands[0]; output.add(new IncLocalTreeItem(ins, regIndex)); - localRegs.put(regIndex, new AddTreeItem(ins, localRegs.get(regIndex), new IntegerValueTreeItem(ins, new Long(1)))); + if (localRegs.containsKey(regIndex)) { + localRegs.put(regIndex, new NotCompileTimeTreeItem(ins)); + } else { + localRegs.put(regIndex, new AddTreeItem(ins, localRegs.get(regIndex), new IntegerValueTreeItem(ins, new Long(1)))); + } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java index 05b51f1ad..4dfdcb269 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.treemodel.FindPropertyTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.IncrementTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.LocalRegTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.NewActivationTreeItem; +import com.jpexs.decompiler.flash.abc.avm2.treemodel.NotCompileTimeTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.PostDecrementTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.PostIncrementTreeItem; import com.jpexs.decompiler.flash.abc.avm2.treemodel.SetLocalTreeItem; @@ -48,7 +49,11 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S public void translate(boolean isStatic, int classIndex, java.util.HashMap localRegs, Stack stack, java.util.Stack scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap localRegNames, List fullyQualifiedNames) { int regId = getRegisterId(ins); GraphTargetItem value = (GraphTargetItem) stack.pop(); - localRegs.put(regId, value); + if (localRegs.containsKey(regId)) { + localRegs.put(regId, new NotCompileTimeTreeItem(ins)); + } else { + localRegs.put(regId, value); + } if (value instanceof NewActivationTreeItem) { return; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/NotCompileTimeTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/NotCompileTimeTreeItem.java new file mode 100644 index 000000000..c78ecca19 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/treemodel/NotCompileTimeTreeItem.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.abc.avm2.treemodel; + +import com.jpexs.decompiler.flash.abc.avm2.ConstantPool; +import com.jpexs.decompiler.flash.graph.GraphSourceItem; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class NotCompileTimeTreeItem extends TreeItem { + + public NotCompileTimeTreeItem(GraphSourceItem instruction) { + super(instruction, NOPRECEDENCE); + } + + @Override + public String toString(ConstantPool constants, HashMap localRegNames, List fullyQualifiedNames) { + return ""; + } + + @Override + public boolean isCompileTime() { + return false; + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/gui/DetailPanel.java b/trunk/src/com/jpexs/decompiler/flash/abc/gui/DetailPanel.java index 43084b219..8c09cba8a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/gui/DetailPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/gui/DetailPanel.java @@ -77,7 +77,7 @@ public class DetailPanel extends JPanel implements ActionListener { editButton.setMargin(new Insets(3, 3, 3, 10)); saveButton.setMargin(new Insets(3, 3, 3, 10)); cancelButton.setMargin(new Insets(3, 3, 3, 10)); - + buttonsPanel = new JPanel(); buttonsPanel.setLayout(new FlowLayout()); saveButton.setActionCommand("SAVEDETAIL");