From e7bffb85baa41ee6ea7a737df1791620bbc6e9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sat, 23 Mar 2013 10:45:26 +0100 Subject: [PATCH] AS1/2 better deobfuscation --- .../decompiler/flash/SWFInputStream.java | 46 ++++++++++++---- .../jpexs/decompiler/flash/action/Action.java | 54 +++++++++++++------ .../decompiler/flash/action/ActionGraph.java | 18 +++++++ .../flash/action/special/ActionEnd.java | 41 ++++++++++++++ .../flash/action/swf3/ActionGetURL.java | 4 +- .../flash/action/swf3/ActionGoToLabel.java | 4 +- .../flash/action/swf3/ActionSetTarget.java | 4 +- .../flash/action/swf5/ActionConstantPool.java | 2 +- .../flash/action/swf5/ActionEnumerate.java | 6 ++- .../flash/action/swf5/ActionSetMember.java | 2 +- .../flash/action/swf6/ActionEnumerate2.java | 6 ++- .../treemodel/clauses/ClassTreeItem.java | 2 +- .../jpexs/decompiler/flash/graph/Graph.java | 8 ++- 13 files changed, 160 insertions(+), 37 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/action/special/ActionEnd.java diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java index 5aca3283e..4ff2738ec 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -21,6 +21,8 @@ import com.jpexs.decompiler.flash.action.ActionGraphSource; import com.jpexs.decompiler.flash.action.UnknownActionException; import com.jpexs.decompiler.flash.action.parser.ASMParser; import com.jpexs.decompiler.flash.action.parser.ParseException; +import com.jpexs.decompiler.flash.action.special.ActionContainer; +import com.jpexs.decompiler.flash.action.special.ActionEnd; import com.jpexs.decompiler.flash.action.special.ActionNop; import com.jpexs.decompiler.flash.action.swf3.*; import com.jpexs.decompiler.flash.action.swf4.*; @@ -509,7 +511,11 @@ public class SWFInputStream extends InputStream { if (ins instanceof ActionConstantPool) { constantPools.add(new ConstantPool(((ActionConstantPool) ins).constantPool)); } - + + //for..in return + if (((ins instanceof ActionEquals) || (ins instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueTreeItem)) { + stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList())); + } ins.translate(localData, stack, output); if (ins.isExit()) { break; @@ -602,6 +608,17 @@ public class SWFInputStream extends InputStream { } last = a; } + int len=retdups.size(); + for(int i=0;i pools = new ArrayList(); pools = getConstantPool(new ActionGraphSource(ret, version, new HashMap(), new HashMap(), new HashMap()), ip); @@ -639,16 +656,22 @@ public class SWFInputStream extends InputStream { long filePos = rri.getPos(); Scanner sc = new Scanner(System.in); int prevIp = ip; - while ((a = sis.readAction()) != null) { + while ((a = sis.readAction()) != null) { a.setAddress(prevIp, SWF.DEFAULT_VERSION); int info = a.actionLength + 1 + ((a.actionCode > 0x80) ? 2 : 0); - int actual = a.getBytes(sis.version).length; - if (info != actual) { - if (!(a instanceof ActionDefineFunction)) { - if (!(a instanceof ActionDefineFunction2)) { - //throw new RuntimeException("Lengths do not match "+a+" "+info+"<>"+actual); - } + int actual = 0; + if(a instanceof ActionContainer){ + actual=((ActionContainer)a).getHeaderBytes().length; + }else{ + actual=a.getBytes(sis.version).length; + } + if(!(a instanceof ActionContainer)){ + int change=info-(rri.getPos()-ip); + if(change > 0){ + a.afterInsert=new ActionJump(change); } + }else{ + info=rri.getPos()-ip; } if (ip < startIp) { retv = true; @@ -805,10 +828,13 @@ public class SWFInputStream extends InputStream { ret.set(ip + i, a); } + if(a instanceof ActionEnd){ + break; + } if (newip > -1) { ip = newip; } else { - ip = ip + (int) actionLen; + ip = ip + info; //(int) actionLen; } rri.setPos(ip); filePos = rri.getPos(); @@ -1172,7 +1198,7 @@ public class SWFInputStream extends InputStream { { int actionCode = readUI8(); if (actionCode == 0) { - return null; + return new ActionEnd(); } if (actionCode == -1) { return null; diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index da8a7ab9b..4ec38adad 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -52,6 +52,8 @@ import java.util.logging.Logger; public class Action implements GraphSourceItem { public Action beforeInsert; + public Action afterInsert; + public Action replaceWith; public boolean ignored = false; /** * Action type identifier @@ -157,8 +159,20 @@ public class Action implements GraphSourceItem { public static List getActionsAllRefs(List list, int version) { List ret = new ArrayList(); for (Action a : list) { + if (a.replaceWith != null) { + a.replaceWith.setAddress(a.getAddress(), version); + ret.addAll(a.replaceWith.getAllRefs(version)); + } + if (a.beforeInsert != null) { + a.beforeInsert.setAddress(a.getAddress(), version); + ret.addAll(a.beforeInsert.getAllRefs(version)); + } List part = a.getAllRefs(version); ret.addAll(part); + if (a.afterInsert != null) { + a.afterInsert.setAddress(a.getAddress(), version); + ret.addAll(a.afterInsert.getAllRefs(version)); + } } return ret; } @@ -371,7 +385,9 @@ public class Action implements GraphSourceItem { ret += "loc" + Helper.formatAddress(offset) + ":"; } - if (a.ignored) { + if (a.replaceWith != null) { + ret += Highlighting.hilighOffset("", offset) + a.replaceWith.getASMSource(importantOffsets, constantPool, version, hex) + "\r\n"; + } else if (a.ignored) { int len = a.getBytes(version).length; for (int i = 0; i < len; i++) { ret += "Nop\r\n"; @@ -383,6 +399,9 @@ public class Action implements GraphSourceItem { //if (!(a instanceof ActionNop)) { ret += Highlighting.hilighOffset("", offset) + a.getASMSource(importantOffsets, constantPool, version, hex) + (a.ignored ? "; ignored" : "") + "\r\n"; //} + if (a.afterInsert != null) { + ret += a.afterInsert.getASMSource(importantOffsets, constantPool, version, hex) + "\r\n"; + } } offset += a.getBytes(version).length; } @@ -758,14 +777,6 @@ public class Action implements GraphSourceItem { ip++; } - if (stack.size() > 0) { - for (int i = stack.size() - 1; i >= 0; i--) { - if (stack.get(i) instanceof FunctionTreeItem) { - output.add(0, stack.get(i)); - stack.remove(i); - } - } - } //output = checkClass(output); log("Leaving " + start + "-" + end); return output; @@ -809,6 +820,7 @@ public class Action implements GraphSourceItem { GraphTargetItem extendsOp = null; List implementsOp = new ArrayList(); boolean ok = true; + int prevCount = 0; for (GraphTargetItem t : output) { if (t instanceof IfItem) { IfItem it = (IfItem) t; @@ -843,6 +855,14 @@ public class Action implements GraphSourceItem { pos++; } + if (parts.size() <= pos) { + List output2 = new ArrayList(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new ClassTreeItem(className, extendsOp, implementsOp, functions, vars, staticFunctions, staticVars)); + return output2; + } if (parts.get(pos) instanceof StoreRegisterTreeItem) { int instanceReg = -1; if (((StoreRegisterTreeItem) parts.get(pos)).value instanceof GetMemberTreeItem) { @@ -934,7 +954,10 @@ public class Action implements GraphSourceItem { } if (ok) { List output2 = new ArrayList(); - output2.add(new ClassTreeItem(className, extendsOp, implementsOp, functions, vars, staticFunctions, staticVars)); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new ClassTreeItem(className, extendsOp, implementsOp, functions, vars, staticFunctions, staticVars)); return output2; } } else { @@ -965,6 +988,9 @@ public class Action implements GraphSourceItem { } } List output2 = new ArrayList(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } output2.add(new InterfaceTreeItem(sm.objectName, implementsOp)); return output2; } else { @@ -990,16 +1016,14 @@ public class Action implements GraphSourceItem { ok = false; } } else { - ok = false; + prevCount++; + //ok = false; } if (!ok) { break; } } - if (!ok) { - return output; - } - return ret; + return output; } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java index 709dbe6ae..d4c05398d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.action.swf4.Null; import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; import com.jpexs.decompiler.flash.action.treemodel.DirectValueTreeItem; import com.jpexs.decompiler.flash.action.treemodel.EnumerateTreeItem; +import com.jpexs.decompiler.flash.action.treemodel.FunctionTreeItem; import com.jpexs.decompiler.flash.action.treemodel.SetTypeTreeItem; import com.jpexs.decompiler.flash.action.treemodel.StoreRegisterTreeItem; import com.jpexs.decompiler.flash.action.treemodel.clauses.ForInTreeItem; @@ -69,6 +70,23 @@ public class ActionGraph extends Graph { return g.translate(localData); } + @Override + public void finalProcessStack(Stack stack,List output) { + if (stack.size() > 0) { + for (int i = stack.size() - 1; i >= 0; i--) { + //System.err.println(stack.get(i)); + if (stack.get(i) instanceof FunctionTreeItem) { + FunctionTreeItem f=(FunctionTreeItem)stack.remove(i); + if(!output.contains(f)){ + output.add(0, f); + } + } + } + } + } + + + @Override protected void finalProcess(List list, int level) { List ret = Action.checkClass(list); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/special/ActionEnd.java b/trunk/src/com/jpexs/decompiler/flash/action/special/ActionEnd.java new file mode 100644 index 000000000..d0f008f1e --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/action/special/ActionEnd.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010-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.action.special; + +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.graph.GraphTargetItem; +import java.util.HashMap; +import java.util.List; +import java.util.Stack; + +public class ActionEnd extends Action { + + public ActionEnd() { + super(0, 0); + ignored = true; + } + + @Override + public String toString() { + return "End"; + } + + @Override + public void translate(Stack stack, List output, java.util.HashMap regNames, HashMap variables, HashMap functions) { + //output.add(new SimpleActionTreeItem(this, "end()")); + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionGetURL.java b/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionGetURL.java index 6b8ee50b7..f4652be11 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionGetURL.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionGetURL.java @@ -38,8 +38,8 @@ public class ActionGetURL extends Action { public ActionGetURL(int actionLength, SWFInputStream sis, int version) throws IOException { super(0x83, actionLength); - byte data[] = sis.readBytes(actionLength); - sis = new SWFInputStream(new ByteArrayInputStream(data), version); + //byte data[] = sis.readBytes(actionLength); + //sis = new SWFInputStream(new ByteArrayInputStream(data), version); urlString = sis.readString(); targetString = sis.readString(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionGoToLabel.java b/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionGoToLabel.java index d3fc3fe9c..8c22f7693 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionGoToLabel.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionGoToLabel.java @@ -37,8 +37,8 @@ public class ActionGoToLabel extends Action { public ActionGoToLabel(int actionLength, SWFInputStream sis, int version) throws IOException { super(0x8C, actionLength); - byte data[] = sis.readBytes(actionLength); - sis = new SWFInputStream(new ByteArrayInputStream(data), version); + //byte data[] = sis.readBytes(actionLength); + //sis = new SWFInputStream(new ByteArrayInputStream(data), version); label = sis.readString(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionSetTarget.java b/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionSetTarget.java index 9fadc8ca8..33fa9ac1e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionSetTarget.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf3/ActionSetTarget.java @@ -37,8 +37,8 @@ public class ActionSetTarget extends Action { public ActionSetTarget(int actionLength, SWFInputStream sis, int version) throws IOException { super(0x8B, actionLength); - byte data[] = sis.readBytes(actionLength); - sis = new SWFInputStream(new ByteArrayInputStream(data), version); + //byte data[] = sis.readBytes(actionLength); + //sis = new SWFInputStream(new ByteArrayInputStream(data), version); targetName = sis.readString(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionConstantPool.java b/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionConstantPool.java index 9ccd096ce..4037b6473 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionConstantPool.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionConstantPool.java @@ -38,7 +38,7 @@ public class ActionConstantPool extends Action { public ActionConstantPool(int actionLength, SWFInputStream sis, int version) throws IOException { super(0x88, actionLength); - sis = new SWFInputStream(new ByteArrayInputStream(sis.readBytes(actionLength)), version); + //sis = new SWFInputStream(new ByteArrayInputStream(sis.readBytes(actionLength)), version); int count = sis.readUI16(); for (int i = 0; i < count; i++) { constantPool.add(sis.readString()); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java b/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java index 1a575516d..b0f3f9e99 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionEnumerate.java @@ -17,8 +17,11 @@ package com.jpexs.decompiler.flash.action.swf5; import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.swf4.Null; +import com.jpexs.decompiler.flash.action.treemodel.DirectValueTreeItem; import com.jpexs.decompiler.flash.action.treemodel.EnumerateTreeItem; import com.jpexs.decompiler.flash.graph.GraphTargetItem; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Stack; @@ -37,6 +40,7 @@ public class ActionEnumerate extends Action { @Override public void translate(Stack stack, List output, java.util.HashMap regNames, HashMap variables, HashMap functions) { GraphTargetItem object = stack.pop(); - stack.push(new EnumerateTreeItem(this, object)); + stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList())); + stack.push(new EnumerateTreeItem(this, object)); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionSetMember.java b/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionSetMember.java index 3b3b35b9c..5eb4a57a3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionSetMember.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf5/ActionSetMember.java @@ -36,7 +36,7 @@ public class ActionSetMember extends Action { @Override public void translate(Stack stack, List output, java.util.HashMap regNames, HashMap variables, HashMap functions) { - GraphTargetItem value = stack.pop(); + GraphTargetItem value = stack.pop(); GraphTargetItem objectName = stack.pop(); GraphTargetItem object = stack.pop(); output.add(new SetMemberTreeItem(this, object, objectName, value)); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java b/trunk/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java index 3e0a5f7fb..651c213da 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf6/ActionEnumerate2.java @@ -17,8 +17,11 @@ package com.jpexs.decompiler.flash.action.swf6; import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.swf4.Null; +import com.jpexs.decompiler.flash.action.treemodel.DirectValueTreeItem; import com.jpexs.decompiler.flash.action.treemodel.EnumerateTreeItem; import com.jpexs.decompiler.flash.graph.GraphTargetItem; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Stack; @@ -37,6 +40,7 @@ public class ActionEnumerate2 extends Action { @Override public void translate(Stack stack, List output, java.util.HashMap regNames, HashMap variables, HashMap functions) { GraphTargetItem object = stack.pop(); - stack.push(new EnumerateTreeItem(this, object)); + stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList())); + stack.push(new EnumerateTreeItem(this, object)); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/treemodel/clauses/ClassTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/action/treemodel/clauses/ClassTreeItem.java index cc9276bad..2077c2f84 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/treemodel/clauses/ClassTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/treemodel/clauses/ClassTreeItem.java @@ -29,7 +29,7 @@ import java.util.List; public class ClassTreeItem extends TreeItem implements Block { - public List functions; + private List functions; public List staticFunctions; public GraphTargetItem extendsOp; public List implementsOp; diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java index 761a16abc..19794bdfe 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java @@ -290,11 +290,17 @@ public class Graph { for (GraphPart head : heads) { populateParts(head, allParts); } - List ret = printGraph(localData, new Stack(), allParts, null, heads.get(0), null, new ArrayList(), new HashMap>()); + Stack stack = new Stack(); + List ret = printGraph(localData, stack, allParts, null, heads.get(0), null, new ArrayList(), new HashMap>()); + finalProcessStack(stack,ret); finalProcessAll(ret, 0); return ret; } + public void finalProcessStack(Stack stack,List output){ + + } + private void finalProcessAll(List list, int level) { finalProcess(list, level); for (GraphTargetItem item : list) {