diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java index 2b43b0efc..2b38e794a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -16,8 +16,9 @@ */ package com.jpexs.decompiler.flash; -import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.action.Action; +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.ActionNop; @@ -27,6 +28,7 @@ import com.jpexs.decompiler.flash.action.swf5.*; import com.jpexs.decompiler.flash.action.swf6.*; import com.jpexs.decompiler.flash.action.swf7.*; import com.jpexs.decompiler.flash.action.treemodel.ConstantPool; +import com.jpexs.decompiler.flash.graph.GraphSourceItem; import com.jpexs.decompiler.flash.graph.GraphSourceItemPos; import com.jpexs.decompiler.flash.graph.GraphTargetItem; import com.jpexs.decompiler.flash.helpers.Helper; @@ -76,6 +78,7 @@ public class SWFInputStream extends InputStream { private long percentMax; private List buffered = new ArrayList(); private ByteArrayOutputStream buffer; + private static boolean DEOBFUSCATION_ALL_CODE_IN_PREVIOUS_TAG = true; public int getBufferLength() { return buffer.size(); @@ -490,6 +493,68 @@ public class SWFInputStream extends InputStream { return readActionList(rri, version, 0); } + private static void getConstantPool(List localData, Stack stack, List output, ActionGraphSource code, int ip, int lastIp, List constantPools, List visited) { + boolean debugMode = false; + while ((ip > -1) && ip < code.size()) { + /*if (visited.contains(ip)) { + break; + }*/ + visited.add(ip); + lastIp = ip; + GraphSourceItem ins = code.get(ip); + if (debugMode) { + System.out.println("Visit " + ip + ": " + ins + " stack:" + Highlighting.stripHilights(stack.toString())); + } + if (ins instanceof ActionConstantPool) { + constantPools.add(new ConstantPool(((ActionConstantPool) ins).constantPool)); + } + + ins.translate(localData, stack, output); + if (ins.isExit()) { + break; + } + + if (ins.isBranch() || ins.isJump()) { + + if (ins instanceof ActionIf && !stack.isEmpty() && (stack.peek().isCompileTime())) { + boolean condition = stack.peek().toBoolean(); + if (debugMode) { + if (condition) { + System.out.println("JUMP"); + } else { + System.out.println("SKIP"); + } + } + stack.pop(); + getConstantPool(localData, stack, output, code, condition ? (code.adr2pos(((ActionIf) ins).getAddress() + ((ActionIf) ins).getBytes(code.version).length + ((ActionIf) ins).offset)) : ip + 1, ip, constantPools, visited); + } else { + List branches = ins.getBranches(code); + for (int b : branches) { + if (b >= 0) { + getConstantPool(localData, stack, output, code, b, ip, constantPools, visited); + } else { + if (debugMode) { + System.out.println("Negative branch:" + b); + } + } + } + } + break; + } + ip++; + }; + if (ip < 0) { + System.out.println("Visited Negative: " + ip); + } + } + + public static List getConstantPool(ActionGraphSource code, int addr) { + List ret = new ArrayList(); + List localData = Helper.toList(new HashMap(), new HashMap(), new HashMap()); + getConstantPool(localData, new Stack(), new ArrayList(), code, code.adr2pos(addr), 0, ret, new ArrayList()); + return ret; + } + /** * Reads list of actions from the stream. Reading ends with ActionEndFlag(=0) * or end of the stream. @@ -508,14 +573,14 @@ public class SWFInputStream extends InputStream { SWFInputStream sis = new SWFInputStream(rri, version); boolean goesPrev = false; + int method = 1; try { goesPrev = readActionListAtPos(false, localData, stack, cpool, sis, rri, ip, retdups, ip); } catch (Exception ex) { + method = 2; goesPrev = readActionListAtPos(true, localData, stack, cpool, sis, rri, ip, retdups, ip); } if (goesPrev) { - retdups.add(0, new ActionJump(ip)); - } else { for (int i = 0; i < ip; i++) { retdups.remove(0); @@ -529,8 +594,22 @@ public class SWFInputStream extends InputStream { } last = a; } + + List pools = getConstantPool(new ActionGraphSource(ret, version, new HashMap(), new HashMap(), new HashMap()), ip); + + if (pools.size() == 1) { + Action.setConstantPool(ret, pools.get(0)); + } + if (goesPrev && (!DEOBFUSCATION_ALL_CODE_IN_PREVIOUS_TAG)) { + ActionJump aj = new ActionJump(ip); + int skip = aj.getBytes(version).length; + for (Action a : ret) { + a.setAddress(a.getAddress() + skip, version); + } + ret.add(0, aj); + } String s = null; - Action.setConstantPool(ret, cpool); + //Action.setConstantPool(ret, cpool); try { s = Highlighting.stripHilights(Action.actionsToString(ret, null, version)); @@ -540,7 +619,6 @@ public class SWFInputStream extends InputStream { } return ret; } - public static List dobranch = new ArrayList(); private static boolean readActionListAtPos(boolean enableVariables, List localData, Stack stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List ret, int startIp) throws IOException { boolean debugMode = false; @@ -568,7 +646,7 @@ public class SWFInputStream extends InputStream { } if (debugMode) { //if(a instanceof ActionIf){ - System.out.println(" rripos: " + rri.getPos() + " rricount:" + rri.getCount() + " ip: " + (ip - startIp) + " action(len " + a.actionLength + "): " + a + " stack:" + Highlighting.stripHilights(stack.toString()) + " " + Helper.byteArrToString(a.getBytes(SWF.DEFAULT_VERSION))); + System.out.println(" ip: " + (ip - startIp) + " action(len " + a.actionLength + "): " + a + " stack:" + Highlighting.stripHilights(stack.toString()) + " " + Helper.byteArrToString(a.getBytes(SWF.DEFAULT_VERSION))); //} } /*if(a instanceof ActionConstantPool){ @@ -577,16 +655,19 @@ public class SWFInputStream extends InputStream { if (a instanceof ActionPush) { if (cpool != null) { ((ActionPush) a).constantPool = cpool.constants; + cpool.count++; } } if (a instanceof ActionDefineFunction) { if (cpool != null) { ((ActionDefineFunction) a).setConstantPool(cpool.constants); + cpool.count++; } } if (a instanceof ActionDefineFunction2) { if (cpool != null) { ((ActionDefineFunction2) a).setConstantPool(cpool.constants); + cpool.count++; } } long newFilePos = rri.getPos(); @@ -602,7 +683,7 @@ public class SWFInputStream extends InputStream { if (cpool == null) { cpool = new ConstantPool(); } - cpool.constants = ((ActionConstantPool) a).constantPool; + cpool.setNew(((ActionConstantPool) a).constantPool); } Action beforeInsert = null; ActionIf aif = null; @@ -670,6 +751,9 @@ public class SWFInputStream extends InputStream { } } else { + if (debugMode) { + System.out.println("goaif"); + } //throw new RuntimeException("goaif"); goaif = true; } @@ -722,8 +806,11 @@ public class SWFInputStream extends InputStream { } private static void ensureCapacity(List ret, int index) { + int pos = ret.size(); while (ret.size() <= index) { - ret.add(new ActionNop()); + Action a = new ActionNop(); + a.setAddress(pos++, SWF.DEFAULT_VERSION); + ret.add(a); } } @@ -1283,8 +1370,8 @@ public class SWFInputStream extends InputStream { if (actionLength > 0) { skip(actionLength); } - //throw new UnknownActionException(actionCode); - return new Action(actionCode, actionLength); + throw new UnknownActionException(actionCode); + //return new Action(actionCode, actionLength); } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index ee0f3f8c5..af0a6756d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -983,10 +983,10 @@ public class Action implements GraphSourceItem { } return ret; } - - public static void setConstantPool(List actions,ConstantPool cpool){ - for(Action a:actions){ - if (a instanceof ActionPush) { + + public static void setConstantPool(List actions, ConstantPool cpool) { + for (Action a : actions) { + if (a instanceof ActionPush) { if (cpool != null) { ((ActionPush) a).constantPool = cpool.constants; } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java index e8ff27898..8005a2634 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java @@ -49,11 +49,27 @@ public class ActionGraphSource extends GraphSource { @Override public int adr2pos(long adr) { - return Action.adr2ip(actions, adr, version); + int pos = 0; + long lastAddr = 0; + for (Action a : actions) { + lastAddr = a.getAddress(); + if (lastAddr == adr) { + return pos; + } + + pos++; + } + if (adr > lastAddr) { + return actions.size(); + } + if (adr == 0) { + return 0; + } + return -1; } @Override public long pos2adr(int pos) { - return Action.ip2adr(actions, pos, version); + return actions.get(pos).getAddress();//Action.ip2adr(actions, pos, version); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/gui/ActionPanel.java b/trunk/src/com/jpexs/decompiler/flash/action/gui/ActionPanel.java index 384acdb51..a159625d6 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/gui/ActionPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/gui/ActionPanel.java @@ -73,6 +73,10 @@ public class ActionPanel extends JPanel implements ActionListener { (new Thread() { @Override public void run() { + editor.setText("; Disassembling..."); + if (Main.DO_DECOMPILE) { + decompiledEditor.setText("//Decompiling..."); + } lastDisasm = asm.getASMSource(SWF.DEFAULT_VERSION); disassembledHilights = Highlighting.getInstrHighlights(lastDisasm); lastDisasm = Highlighting.stripHilights(lastDisasm); @@ -81,7 +85,6 @@ public class ActionPanel extends JPanel implements ActionListener { List as = asm.getActions(SWF.DEFAULT_VERSION); lastCode = as; com.jpexs.decompiler.flash.action.Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION); - decompiledEditor.setText("//Decompiling..."); String s = com.jpexs.decompiler.flash.action.Action.actionsToSource(as, SWF.DEFAULT_VERSION); decompiledHilights = Highlighting.getInstrHighlights(s); decompiledEditor.setText(Highlighting.stripHilights(s)); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionGetVariable.java b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionGetVariable.java index 8752ffc3c..ee5674675 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionGetVariable.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionGetVariable.java @@ -40,7 +40,7 @@ public class ActionGetVariable extends Action { GraphTargetItem name = stack.pop(); GraphTargetItem computedVal = variables.get(Highlighting.stripHilights(name.toStringNoQuotes())); GetVariableTreeItem gvt = new GetVariableTreeItem(this, name); - gvt.computedValue = computedVal; + gvt.setComputedValue(computedVal); stack.push(gvt); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java index 62ee1cf97..06f036734 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java @@ -214,7 +214,7 @@ public class ActionPush extends Action { for (Object o : values) { if (o instanceof ConstantIndex) { if ((constantPool == null) || (((ConstantIndex) o).index >= constantPool.size())) { - o = "CONSTANT"+((ConstantIndex) o).index; + o = "CONSTANT" + ((ConstantIndex) o).index; } else { o = constantPool.get(((ConstantIndex) o).index); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/treemodel/ConstantPool.java b/trunk/src/com/jpexs/decompiler/flash/action/treemodel/ConstantPool.java index 894a83ac4..971c60e6d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/treemodel/ConstantPool.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/treemodel/ConstantPool.java @@ -21,5 +21,44 @@ import java.util.List; public class ConstantPool { + public List> archive = new ArrayList>(); + public List archiveCounts = new ArrayList(); public List constants = new ArrayList(); + public int count; + + public ConstantPool() { + } + + public ConstantPool(List constants) { + this.constants = constants; + } + + public void setNew(List constants) { + archive.add(this.constants); + this.constants = constants; + archiveCounts.add(count); + count = 0; + } + + @Override + public String toString() { + return "" + count + "x " + constants.toString(); + } + + public boolean isEmpty() { + return constants.isEmpty(); + } + + public void getLastUsed() { + if (count > 0) { + return; + } + for (int i = archive.size() - 1; i >= 0; i--) { + if (archiveCounts.get(i) > 0) { + count = archiveCounts.get(i); + constants = archive.get(i); + break; + } + } + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/treemodel/GetVariableTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/action/treemodel/GetVariableTreeItem.java index 4b053561c..ac5f3e334 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/treemodel/GetVariableTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/treemodel/GetVariableTreeItem.java @@ -23,7 +23,11 @@ import java.util.List; public class GetVariableTreeItem extends TreeItem { public GraphTargetItem name; - public GraphTargetItem computedValue; + private GraphTargetItem computedValue; + private double computedNumber = 0; + private boolean computedBool = false; + private boolean computedCompiletime = false; + private boolean computedVariableComputed = false; public GetVariableTreeItem(GraphSourceItem instruction, GraphTargetItem value) { super(instruction, PRECEDENCE_PRIMARY); @@ -32,6 +36,9 @@ public class GetVariableTreeItem extends TreeItem { @Override public String toString(ConstantPool constants) { + if (computedValue == null) { + //return "null"; + } //return ""+computedValue.toNumber(); return stripQuotes(name); } @@ -53,7 +60,7 @@ public class GetVariableTreeItem extends TreeItem { if (computedValue == null) { return false; } - return computedValue.isCompileTime(); + return computedCompiletime; } @Override @@ -61,7 +68,7 @@ public class GetVariableTreeItem extends TreeItem { if (computedValue == null) { return false; } - return computedValue.toBoolean(); + return computedBool; } @Override @@ -69,6 +76,16 @@ public class GetVariableTreeItem extends TreeItem { if (computedValue == null) { return 0; } - return computedValue.toNumber(); + return computedNumber; + } + + public void setComputedValue(GraphTargetItem computedValue) { + this.computedValue = computedValue; + if (computedValue != null) { + computedNumber = computedValue.toNumber(); + computedBool = computedValue.toBoolean(); + computedCompiletime = computedValue.isCompileTime(); + computedVariableComputed = computedValue.isVariableComputed(); + } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java index 1869c7f75..f2ebb3a05 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java @@ -16,7 +16,6 @@ */ package com.jpexs.decompiler.flash.graph; -import com.jpexs.decompiler.flash.action.treemodel.DirectValueTreeItem; import com.jpexs.decompiler.flash.helpers.Highlighting; import java.util.ArrayList; import java.util.HashMap; @@ -461,14 +460,14 @@ public class Graph { } } if (part.nextParts.size() == 2) { - if(part.nextParts.get(0)==part.nextParts.get(1)){ - if(!stack.isEmpty()) { + if (part.nextParts.get(0) == part.nextParts.get(1)) { + if (!stack.isEmpty()) { stack.pop(); } part.nextParts.remove(0); } } - + if (part.nextParts.size() == 2) { if ((stack.size() >= 2) && (stack.get(stack.size() - 1) instanceof NotItem) && (((NotItem) (stack.get(stack.size() - 1))).getOriginal() == stack.get(stack.size() - 2))) { @@ -1086,6 +1085,10 @@ public class Graph { expr = stack.pop(); } loopBody.addAll(0, output); + if (part.nextParts.size() == 1) { + loopBody.addAll(printGraph(localData, stack, allParts, part, part.nextParts.get(0), stopPart, loops, forFinalCommands)); + } + checkContinueAtTheEnd(loopBody, currentLoop); List addIf = new ArrayList(); @@ -1111,11 +1114,7 @@ public class Graph { next = part.nextParts.get(reversed ? 0 : 1); } if (doWhile) { - if (part.nextParts.size() == 1) { - next = part.nextParts.get(0); - } else { - next = null; - } + next = null; } if (next != null) { GraphTargetItem ti = checkLoop(next, stopPart, loops); @@ -1341,7 +1340,7 @@ public class Graph { } else if (ins.isBranch()) { part.end = ip; allBlocks.add(part); - List branches = ins.getBranches(code); + List branches = ins.getBranches(code); for (int i = 0; i < branches.size(); i++) { part.nextParts.add(g = makeGraph(part, path + i, code, branches.get(i), ip, allBlocks, refs, visited2)); g.refs.add(part);