From f843082a976c098844dce46c211a41bdef76db71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Mon, 25 Mar 2013 20:50:06 +0100 Subject: [PATCH] AS3 fixed deobfuscation causing incorrect decompilation in some cases alse Issue #47 --- .../decompiler/flash/abc/avm2/AVM2Code.java | 19 +++++-- .../flash/abc/avm2/graph/AVM2Graph.java | 13 +++++ .../construction/NewFunctionIns.java | 6 +++ .../abc/avm2/instructions/stack/DupIns.java | 3 ++ .../abc/avm2/instructions/stack/SwapIns.java | 4 +- .../flash/abc/types/traits/Trait.java | 1 + .../types/traits/TraitMethodGetterSetter.java | 3 ++ .../jpexs/decompiler/flash/graph/Graph.java | 51 +++++-------------- .../flash/graph/GraphTargetItem.java | 2 +- 9 files changed, 59 insertions(+), 43 deletions(-) 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 a2d8fff66..26defdd11 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1173,7 +1173,17 @@ public class AVM2Code implements Serializable { } visited[ip] = true; AVM2Instruction ins = code.get(ip); - + if(debugMode){ + System.out.println("translating ip "+ip+" ins "+ins.toString()+" stack:"+Highlighting.stripHilights(stack.toString())+" scopeStack:"+Highlighting.stripHilights(scopeStack.toString())); + } + if(ins.definition instanceof NewFunctionIns){ + if(ip+1<=end){ + if(code.get(ip+1).definition instanceof PopIns){ + ip+=2; + continue; + } + } + } if ((ip + 8 < code.size())) { //return in finally clause if (ins.definition instanceof SetLocalTypeIns) { if (code.get(ip + 1).definition instanceof PushByteIns) { @@ -2417,7 +2427,8 @@ public class AVM2Code implements Serializable { if (ins.isBranch() || ins.isJump()) { List branches = ins.getBranches(code); - if (ins.isBranch() && !stack.isEmpty() && (stack.peek().isCompileTime())) { + if ((ins instanceof AVM2Instruction)&&((AVM2Instruction)ins).definition instanceof IfTypeIns + && (!(((AVM2Instruction)ins).definition instanceof JumpIns)) && (!stack.isEmpty()) && (stack.peek().isCompileTime())) { boolean condition = stack.peek().toBoolean(); if (debugMode) { if (condition) { @@ -2433,7 +2444,9 @@ public class AVM2Code implements Serializable { } GraphTargetItem tar = stack.pop(); for (GraphSourceItemPos pos : tar.getNeededSources()) { - pos.item.setIgnored(true); + if(pos.item!=ins){ + pos.item.setIgnored(true); + } } ret += removeTraps(localData, stack, output, code, condition ? branches.get(0) : branches.get(1), ip, visited); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 400c6abd0..4e593ab9a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -1556,4 +1556,17 @@ public class AVM2Graph extends Graph { } return true; } + + @Override + public List prepareBranchLocalData(List localData) { + List ret=new ArrayList(); + ret.addAll(localData); + Stack scopeStack=(Stack)ret.get(DATA_SCOPESTACK); + Stack copyScopeStack=new Stack(); + copyScopeStack.addAll(scopeStack); + ret.set(DATA_SCOPESTACK, copyScopeStack); + return ret; + } + + } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewFunctionIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewFunctionIns.java index d4c854f28..a791e5e4f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewFunctionIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewFunctionIns.java @@ -29,6 +29,8 @@ import com.jpexs.decompiler.flash.helpers.Highlighting; import java.util.HashMap; import java.util.List; import java.util.Stack; +import java.util.logging.Level; +import java.util.logging.Logger; public class NewFunctionIns extends InstructionDefinition { @@ -43,7 +45,11 @@ public class NewFunctionIns extends InstructionDefinition { String bodyStr = ""; String paramStr = ""; if (mybody != null) { + try{ bodyStr = Highlighting.hilighMethodEnd() + mybody.toString("", false, isStatic, classIndex, abc, constants, method_info, new Stack()/*scopeStack*/, false, true, fullyQualifiedNames, null) + Highlighting.hilighMethodBegin(body.method_info); + }catch(Exception ex){ + Logger.getLogger(NewFunctionIns.class.getName()).log(Level.SEVERE, "error during newfunction", ex); + } paramStr = method_info[methodIndex].getParamStr(constants, mybody, abc, fullyQualifiedNames); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/DupIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/DupIns.java index 46ad5a976..1926ff754 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/DupIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/DupIns.java @@ -22,6 +22,8 @@ import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.graph.GraphSourceItem; +import com.jpexs.decompiler.flash.graph.GraphSourceItemPos; import com.jpexs.decompiler.flash.graph.GraphTargetItem; import java.util.HashMap; import java.util.List; @@ -45,6 +47,7 @@ public class DupIns extends InstructionDefinition { GraphTargetItem v = stack.pop(); stack.push(v); stack.push(v); + v.moreSrc.add(new GraphSourceItemPos(ins, 0)); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/SwapIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/SwapIns.java index 380308c3c..bf640f2df 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/SwapIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/SwapIns.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.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.graph.GraphSourceItemPos; import com.jpexs.decompiler.flash.graph.GraphTargetItem; import java.util.HashMap; import java.util.List; @@ -49,7 +50,8 @@ public class SwapIns extends InstructionDefinition { GraphTargetItem o2 = stack.pop(); stack.push(o1); stack.push(o2); - + o1.moreSrc.add(new GraphSourceItemPos(ins, 0)); + o2.moreSrc.add(new GraphSourceItemPos(ins, 0)); } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 253ea0aa0..7cadb1df5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -26,6 +26,7 @@ import java.util.List; public abstract class Trait implements Serializable { + public boolean debugMode = false; public int name_index; public int kindType; public int kindFlags; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index c338eb819..120b94849 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -54,6 +54,9 @@ public class TraitMethodGetterSetter extends Trait { @Override public String convert(String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List fullyQualifiedNames) { + if(debugMode){ + System.out.println("Decompiling "+path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames)); + } String header = convertHeader(path, abcTags, abc, isStatic, pcode, classIndex, highlight, fullyQualifiedNames); String bodyStr = ""; diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java index 97c44574d..4724e99b1 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Stack; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -440,6 +442,7 @@ public class Graph { try { output.addAll(code.translatePart(localData, stack, start, end)); } catch (Exception ex) { + Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "error during printgraph", ex); //ex.printStackTrace(); return ret; } @@ -976,7 +979,7 @@ public class Graph { if (debugMode) { System.err.println("ONTRUE: (inside " + part + ")"); } - onTrue = printGraph(localData, trueStack, allParts, part, part.nextParts.get(1), next == null ? stopPart : next, loops, forFinalCommands); + onTrue = printGraph(prepareBranchLocalData(localData), trueStack, allParts, part, part.nextParts.get(1), next == null ? stopPart : next, loops, forFinalCommands); if (debugMode) { System.err.println("/ONTRUE (inside " + part + ")"); } @@ -988,7 +991,7 @@ public class Graph { if (debugMode) { System.err.println("ONFALSE: (inside " + part + ")"); } - onFalse = (((next == part.nextParts.get(0)) || (part.nextParts.get(0).path.equals(part.path) || part.nextParts.get(0).path.length() < part.path.length())) ? new ArrayList() : printGraph(localData, falseStack, allParts, part, part.nextParts.get(0), next == null ? stopPart : next, loops, forFinalCommands)); + onFalse = (((next == part.nextParts.get(0)) || (part.nextParts.get(0).path.equals(part.path) || part.nextParts.get(0).path.length() < part.path.length())) ? new ArrayList() : printGraph(prepareBranchLocalData(localData), falseStack, allParts, part, part.nextParts.get(0), next == null ? stopPart : next, loops, forFinalCommands)); if (debugMode) { System.err.println("/ONFALSE (inside " + part + ")"); } @@ -1048,47 +1051,15 @@ public class Graph { if ((loopBodyStart != null) && ((ti = checkLoop(loopBodyStart, stopPart, loops)) != null)) { loopBody.add(ti); } else { - if (!(doWhile && (loopBodyStart == null))) { - loopBody = printGraph(localData, stack, allParts, part, loopBodyStart != null ? loopBodyStart : part.nextParts.get(reversed ? 1 : 0), stopPart, loops, forFinalCommands); - + if (!(doWhile && (loopBodyStart == null))) { + loopBody = printGraph(prepareBranchLocalData(localData), stack, allParts, part, loopBodyStart != null ? loopBodyStart : part.nextParts.get(reversed ? 1 : 0), stopPart, loops, forFinalCommands); } } checkContinueAtTheEnd(loopBody, currentLoop); finalCommands = forFinalCommands.get(currentLoop); if (!finalCommands.isEmpty()) { ret.add(new ForTreeItem(null, currentLoop, new ArrayList(), expr, finalCommands, loopBody)); - } /*else if ((expr instanceof HasNextTreeItem) && ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister() instanceof FilteredCheckTreeItem) { - TreeItem gti = ((HasNextTreeItem) expr).collection.getNotCoerced().getThroughRegister(); - boolean found = false; - if ((loopBody.size() == 3) || (loopBody.size() == 4)) { - TreeItem ft = loopBody.get(0); - if (ft instanceof WithTreeItem) { - ft = loopBody.get(1); - if (ft instanceof IfItem) { - IfItem ift = (IfItem) ft; - if (ift.onTrue.size() > 0) { - ft = ift.onTrue.get(0); - if (ft instanceof SetPropertyTreeItem) { - SetPropertyTreeItem spt = (SetPropertyTreeItem) ft; - if (spt.object instanceof LocalRegTreeItem) { - int regIndex = ((LocalRegTreeItem) spt.object).regIndex; - HasNextTreeItem iti = (HasNextTreeItem) expr; - localRegs.put(regIndex, new FilterTreeItem(null, iti.collection.getThroughRegister(), ift.expression)); - } - } - } - } - } - } - } else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextValueTreeItem)) { - TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject(); - loopBody.remove(0); - ret.add(new ForEachInTreeItem(null, currentLoop.id, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody)); - } else if ((expr instanceof HasNextTreeItem) && (!loopBody.isEmpty()) && (loopBody.get(0) instanceof SetTypeTreeItem) && (((SetTypeTreeItem) loopBody.get(0)).getValue().getNotCoerced() instanceof NextNameTreeItem)) { - TreeItem obj = ((SetTypeTreeItem) loopBody.get(0)).getObject(); - loopBody.remove(0); - ret.add(new ForInTreeItem(null, currentLoop.id, part.start, new InTreeItem(expr.instruction, obj, ((HasNextTreeItem) expr).collection), loopBody)); - }*/ else { + } else { if (doWhile) { if (stack.isEmpty() || (part.nextParts.size() == 1)) { expr = new TrueItem(null); @@ -1097,7 +1068,7 @@ public class Graph { } loopBody.addAll(0, output); if (part.nextParts.size() == 1) { - loopBody.addAll(printGraph(localData, stack, allParts, part, part.nextParts.get(0), stopPart, loops, forFinalCommands)); + loopBody.addAll(printGraph(prepareBranchLocalData(localData), stack, allParts, part, part.nextParts.get(0), stopPart, loops, forFinalCommands)); } checkContinueAtTheEnd(loopBody, currentLoop); @@ -1509,4 +1480,8 @@ public class Graph { } return ret.toString(); } + + public List prepareBranchLocalData(List localData){ + return localData; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/GraphTargetItem.java b/trunk/src/com/jpexs/decompiler/flash/graph/GraphTargetItem.java index f62ddd6d7..9a7930d53 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/GraphTargetItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/GraphTargetItem.java @@ -69,7 +69,7 @@ public abstract class GraphTargetItem { @Override public String toString() { - return toString(new ArrayList()); + return this.getClass().getName(); } public abstract String toString(List localData);