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 7ce5fe1b5..2e0e3b905 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1416,7 +1416,12 @@ public class AVM2Code implements Serializable { if (ex2 instanceof OutOfMemoryError) { System.gc(); } - return writer.append("/*\r\n * Decompilation error\r\n * Code may be obfuscated\r\n * Error type: " + ex2.getClass().getSimpleName() + "\r\n */\r\nthrow new IllegalOperationError(\"Not decompiled due to error\");\r\n"); + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * Decompilation error").newLine(); + writer.appendNoHilight(" * Code may be obfuscated").newLine(); + writer.appendNoHilight(" * Error type: " + ex2.getClass().getSimpleName()).newLine(); + writer.appendNoHilight(" */").newLine(); + return writer.appendNoHilight("throw new IllegalOperationError(\"Not decompiled due to error\");").newLine(); } if (initTraits != null) { for (int i = 0; i < list.size(); i++) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java index 26afc902f..b2fed18f1 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java @@ -39,7 +39,7 @@ public class CallSuperAVM2Item extends AVM2Item { @Override protected HilightedTextWriter appendTo(HilightedTextWriter writer, LocalData localData) { - if (!receiver.toString(localData).equals("this")) { + if (!receiver.toString().equals("this")) { receiver.toString(writer, localData); writer.append("."); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructSuperAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructSuperAVM2Item.java index 9f2af88b9..9e4b843cd 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructSuperAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructSuperAVM2Item.java @@ -35,7 +35,7 @@ public class ConstructSuperAVM2Item extends AVM2Item { @Override protected HilightedTextWriter appendTo(HilightedTextWriter writer, LocalData localData) { - if (!object.toString(localData).equals("this")) { + if (!object.toString().equals("this")) { object.toString(writer, localData); writer.append("."); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/GetSuperAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/GetSuperAVM2Item.java index b2b1a5aa4..6a3116871 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/GetSuperAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/GetSuperAVM2Item.java @@ -34,7 +34,7 @@ public class GetSuperAVM2Item extends AVM2Item { @Override protected HilightedTextWriter appendTo(HilightedTextWriter writer, LocalData localData) { - if (!object.toString(localData).equals("this")) { + if (!object.toString().equals("this")) { object.toString(writer, localData); writer.append("."); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSuperAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSuperAVM2Item.java index 600d2e814..5ef62d46f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSuperAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSuperAVM2Item.java @@ -42,7 +42,7 @@ public class SetSuperAVM2Item extends AVM2Item { @Override protected HilightedTextWriter appendTo(HilightedTextWriter writer, LocalData localData) { - if (!object.toString(localData).equals("this")) { + if (!object.toString().equals("this")) { object.toString(writer, localData); writer.append("."); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/ThisAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/ThisAVM2Item.java index c3eb1a1d8..320347bd3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/ThisAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/ThisAVM2Item.java @@ -29,6 +29,11 @@ public class ThisAVM2Item extends AVM2Item { this.className = className; } + @Override + public String toString() { + return "this"; + } + @Override protected HilightedTextWriter appendTo(HilightedTextWriter writer, LocalData localData) { return writer.append("this"); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 0a2e25605..7a820178f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -151,7 +151,8 @@ public class MethodBody implements Cloneable, Serializable { writer.appendNoHilight("/*").newLine(); writer.appendNoHilight(" * Decompilation error").newLine(); writer.appendNoHilight(" * Timeout (" + Helper.formatTimeToText(timeout) + ") was reached").newLine(); - writer.appendNoHilight(" */"); + writer.appendNoHilight(" */").newLine(); + writer.appendNoHilight("throw new IllegalOperationError(\"Not decompiled due to timeout\");").newLine(); } writer.unindent(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index 8d8d42154..ef355e3e2 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -43,6 +43,7 @@ import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser; import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionNop; import com.jpexs.decompiler.flash.action.swf4.*; import com.jpexs.decompiler.flash.action.swf5.*; import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; @@ -754,7 +755,8 @@ public class Action implements GraphSourceItem { writer.appendNoHilight("/*").newLine(); writer.appendNoHilight(" * Decompilation error").newLine(); writer.appendNoHilight(" * Timeout (" + Helper.formatTimeToText(timeout) + ") was reached").newLine(); - writer.appendNoHilight(" */"); + writer.appendNoHilight(" */").newLine(); + writer.appendNoHilight("throw new IllegalOperationError(\"Not decompiled due to timeout\");").newLine(); } catch (Exception | OutOfMemoryError | StackOverflowError ex2) { Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex2); if (ex2 instanceof OutOfMemoryError) { @@ -765,7 +767,8 @@ public class Action implements GraphSourceItem { writer.appendNoHilight(" * Decompilation error").newLine(); writer.appendNoHilight(" * Code may be obfuscated").newLine(); writer.appendNoHilight(" * Error type: " + ex2.getClass().getSimpleName()).newLine(); - writer.appendNoHilight(" */"); + writer.appendNoHilight(" */").newLine(); + return writer.appendNoHilight("throw new IllegalOperationError(\"Not decompiled due to error\");").newLine(); } return writer; } @@ -1224,7 +1227,7 @@ public class Action implements GraphSourceItem { List ret = actions; if (true) { //return ret; - } + } String s = null; try { HilightedTextWriter writer = new HilightedTextWriter(false); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java index d7df4fe58..f7f9afb3f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -43,7 +43,6 @@ import com.jpexs.decompiler.graph.NotCompileTimeItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.Helper; import com.jpexs.helpers.ReReadableInputStream; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -150,7 +149,7 @@ public class ActionListReader { updateActionLengths(actions, version); if (deobfuscate) { - actions = deobfuscateActionList(listeners, containerSWFOffset, actions, version, 0, path); + actions = deobfuscateActionList(listeners, containerSWFOffset, actions, version, ip, path); updateActionLengths(actions, version); removeZeroJumps(actions, version); } @@ -172,9 +171,12 @@ public class ActionListReader { * @throws IOException */ public static List deobfuscateActionList(List listeners, long containerSWFOffset, List actions, int version, int ip, String path) throws IOException { - byte[] data = Action.actionsToBytes(actions, true, version); - ReReadableInputStream rri = new ReReadableInputStream(new ByteArrayInputStream(data)); - int endIp = data.length; + if (actions.isEmpty()) { + return actions; + } + + Action lastAction = actions.get(actions.size() - 1); + int endIp = (int) lastAction.getAddress(); List retdups = new ArrayList<>(); for (int i = 0; i < endIp; i++) { @@ -182,14 +184,21 @@ public class ActionListReader { a.setAddress(i, version); retdups.add(a); } + List actionMap = new ArrayList<>(endIp); + for (int i = 0; i <= endIp; i++) { + actionMap.add(null); + } + for (Action a : actions) { + actionMap.set((int) a.getAddress(), a); + } + ConstantPool cpool = new ConstantPool(); Stack stack = new Stack<>(); List localData = Helper.toList(new HashMap(), new HashMap(), new HashMap()); - SWFInputStream sis = new SWFInputStream(rri, version); - deobfustaceActionListAtPosRecursive(listeners, new ArrayList(), new HashMap>(), containerSWFOffset, localData, stack, cpool, sis, rri, ip, retdups, ip, endIp, path, new HashMap(), false, new HashMap>(), version); + deobfustaceActionListAtPosRecursive(listeners, new ArrayList(), new HashMap>(), containerSWFOffset, localData, stack, cpool, actionMap, ip, ip, retdups, ip, endIp, path, new HashMap(), false, new HashMap>(), version); if (!retdups.isEmpty()) { for (int i = 0; i < ip; i++) { @@ -442,8 +451,9 @@ public class ActionListReader { if (a instanceof ActionJump) { ActionJump aJump = (ActionJump)a; if (aJump.getJumpOffset() == 0) { - removeAction(actions, i, version); - i--; + if (removeAction(actions, i, version, false)) { + i--; + } } } } @@ -454,10 +464,10 @@ public class ActionListReader { * @param actions * @param index */ - private static void removeAction(List actions, int index, int version) { + public static boolean removeAction(List actions, int index, int version, boolean removeWhenLast) { if (index < 0 || actions.size() <= index) { - return; + return false; } long startIp = actions.get(0).getAddress(); @@ -486,6 +496,9 @@ public class ActionListReader { List lastActions = containerLastActions.get(a); for (int i = 0; i < lastActions.size(); i++) { if (lastActions.get(i) == actionToRemove) { + if (!removeWhenLast) { + return false; + } lastActions.set(i, prevAction); } } @@ -510,6 +523,8 @@ public class ActionListReader { updateActionStores(actions, jumps); updateContainerSizes(actions, containerLastActions); updateActionLengths(actions, version); + + return true; } @SuppressWarnings("unchecked") @@ -629,18 +644,18 @@ public class ActionListReader { } @SuppressWarnings("unchecked") - private static void deobfustaceActionListAtPosRecursive(List listeners, List output, HashMap> containers, long containerSWFOffset, List localData, Stack stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List ret, int startIp, int endip, String path, Map visited, boolean indeterminate, Map> decisionStates, int version) throws IOException { + private static void deobfustaceActionListAtPosRecursive(List listeners, List output, HashMap> containers, long containerSWFOffset, List localData, Stack stack, ConstantPool cpool, List actions, int pos, int ip, List ret, int startIp, int endip, String path, Map visited, boolean indeterminate, Map> decisionStates, int version) throws IOException { boolean debugMode = false; boolean decideBranch = false; boolean deobfuscate = Configuration.getConfig("autoDeobfuscate", true); - rri.setPos(ip); + pos = ip; Action a; - long filePos = rri.getPos(); Scanner sc = new Scanner(System.in, "utf-8"); - int prevIp = ip; loopip: - while (((endip == -1) || (endip > ip)) && (a = sis.readAction(rri, cpool)) != null) { + while (((endip == -1) || (endip > ip)) && (a = actions.get(pos)) != null) { + int actionLen = getTotalActionLength(a); + pos += actionLen; if (!visited.containsKey(ip)) { visited.put(ip, 0); } @@ -648,13 +663,12 @@ public class ActionListReader { curVisited++; visited.put(ip, curVisited); for (int i = 0; i < listeners.size(); i++) { - listeners.get(i).progress("Deobfuscating", rri.getCount(), rri.length()); + listeners.get(i).progress("Deobfuscating", pos, actions.size()); } if ((ip < ret.size()) && (!(ret.get(ip) instanceof ActionNop))) { a = ret.get(ip); } a.containerSWFOffset = containerSWFOffset; - a.setAddress(prevIp, version, false); int info = a.actionLength + 1 + ((a.actionCode >= 0x80) ? 2 : 0); if (a instanceof ActionPush) { @@ -685,8 +699,6 @@ public class ActionListReader { } System.err.println(add); } - long newFilePos = rri.getPos(); - long actionLen = newFilePos - filePos; int newip = -1; @@ -713,15 +725,15 @@ public class ActionListReader { if (deobfuscate) { top = stack.pop(); } - int nip = (int) rri.getPos() + aif.getJumpOffset(); + int nip = pos + aif.getJumpOffset(); if (decideBranch) { System.out.print("newip " + nip + ", "); System.out.print("Action: jump(j),ignore(i),compute(c)?"); String next = sc.next(); if (next.equals("j")) { - newip = (int) rri.getPos() + aif.getJumpOffset(); - rri.setPos(newip); + newip = pos + aif.getJumpOffset(); + pos = newip; } else if (next.equals("i")) { } else if (next.equals("c")) { @@ -733,7 +745,7 @@ public class ActionListReader { System.err.print("is compiletime -> "); } if (EcmaScript.toBoolean(top.getResult())) { - newip = (int) rri.getPos() + aif.getJumpOffset(); + newip = pos + aif.getJumpOffset(); aif.jumpUsed = true; if (aif.ignoreUsed) { aif.compileTime = false; @@ -757,7 +769,7 @@ public class ActionListReader { goaif = true; } } else if (a instanceof ActionJump) { - newip = (int) rri.getPos() + ((ActionJump) a).getJumpOffset(); + newip = pos + ((ActionJump) a).getJumpOffset(); } else if (!(a instanceof GraphSourceItemContainer)) { if (deobfuscate) { //return in for..in, TODO:Handle this better way @@ -816,7 +828,7 @@ public class ActionListReader { } else { localData2 = localData; } - deobfustaceActionListAtPosRecursive(listeners, output2, containers, containerSWFOffset, localData2, new Stack(), cpool, sis, rri, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version); + deobfustaceActionListAtPosRecursive(listeners, output2, containers, containerSWFOffset, localData2, new Stack(), cpool, actions, pos, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version); output2s.add(output2); endAddr += size; } @@ -824,9 +836,7 @@ public class ActionListReader { cnt.translateContainer(output2s, stack, output, (HashMap) localData.get(0), (HashMap) localData.get(1), (HashMap) localData.get(2)); } ip = (int) endAddr; - prevIp = ip; - rri.setPos(ip); - filePos = rri.getPos(); + pos = ip; continue; } } @@ -839,8 +849,7 @@ public class ActionListReader { } else { ip = ip + info; } - rri.setPos(ip); - filePos = rri.getPos(); + pos = ip; if (goaif) { aif.ignoreUsed = true; aif.jumpUsed = true; @@ -871,8 +880,8 @@ public class ActionListReader { if ((!stateChanged) && curVisited > 1) { List branches = new ArrayList<>(); - branches.add((int) rri.getPos() + aif.getJumpOffset()); - branches.add((int) rri.getPos()); + branches.add(pos + aif.getJumpOffset()); + branches.add(pos); for (int br : branches) { int visc = 0; if (visited.containsKey(br)) { @@ -880,28 +889,23 @@ public class ActionListReader { } if (visc == 0) {// substack = (Stack) stack.clone(); - deobfustaceActionListAtPosRecursive(listeners, output, containers, containerSWFOffset, prepareLocalBranch(localData), substack, cpool, sis, rri, (int) rri.getPos() + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version); - rri.setPos(oldPos); + deobfustaceActionListAtPosRecursive(listeners, output, containers, containerSWFOffset, prepareLocalBranch(localData), substack, cpool, actions, pos, pos + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version); } - prevIp = ip; if (a.isExit()) { break; } } for (DisassemblyListener listener : listeners) { - listener.progress("Deobfuscating", rri.getCount(), rri.length()); + listener.progress("Deobfuscating", pos, actions.size()); } }