From 171996673730943f91663952b50e22182ac31060 Mon Sep 17 00:00:00 2001 From: honfika Date: Sat, 23 Aug 2014 18:47:55 +0200 Subject: [PATCH] Another AS2 deobfuscation (will be executed before the previous one) --- .../flash/action/ActionListReader.java | 3 + .../ActionDeobfuscator.java | 399 ++++++++++-------- .../ActionDeobfuscatorSimple.java | 196 +++++++++ .../FixItemCounterTranslateStack.java | 55 +++ .../action/swf5/ActionPushDuplicate.java | 3 +- 5 files changed, 471 insertions(+), 185 deletions(-) rename src/com/jpexs/decompiler/flash/action/{ => deobfuscation}/ActionDeobfuscator.java (50%) create mode 100644 src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java create mode 100644 src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java diff --git a/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/src/com/jpexs/decompiler/flash/action/ActionListReader.java index 8b84326f0..9c08ed982 100644 --- a/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -16,9 +16,11 @@ */ package com.jpexs.decompiler.flash.action; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; import com.jpexs.decompiler.flash.AppStrings; import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscatorSimple; import com.jpexs.decompiler.flash.action.model.ConstantPool; import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump; @@ -178,6 +180,7 @@ public class ActionListReader { if (deobfuscate) { try { + new ActionDeobfuscatorSimple().actionListParsed(actions, sis.getSwf()); new ActionDeobfuscator().actionListParsed(actions, sis.getSwf()); /*actions = deobfuscateActionList(listeners, actions, version, 0, path); updateActionLengths(actions, version); diff --git a/src/com/jpexs/decompiler/flash/action/ActionDeobfuscator.java b/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java similarity index 50% rename from src/com/jpexs/decompiler/flash/action/ActionDeobfuscator.java rename to src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java index 96114f594..2b2fc979a 100644 --- a/src/com/jpexs/decompiler/flash/action/ActionDeobfuscator.java +++ b/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscator.java @@ -14,11 +14,15 @@ * 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; +package com.jpexs.decompiler.flash.action.deobfuscation; import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.ActionListReader; +import com.jpexs.decompiler.flash.action.ActionLocalData; import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; import com.jpexs.decompiler.flash.action.model.ReturnActionItem; import com.jpexs.decompiler.flash.action.special.ActionEnd; @@ -35,11 +39,17 @@ import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; +import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; +import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; +import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; import com.jpexs.decompiler.flash.action.swf5.ActionModulo; +import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; import com.jpexs.decompiler.flash.action.swf5.ActionReturn; import com.jpexs.decompiler.flash.ecma.EcmaScript; import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener; @@ -195,204 +205,230 @@ public class ActionDeobfuscator implements SWFDecompilerListener { } for (int i = 0; i < actions.size(); i++) { - try { - ExecutionResult result = new ExecutionResult(); - executeActions(actions, i, actions.size() - 1, result, fakeFunctions); - - if (result.idx != -1) { - int newIstructionCount = result.constantPool != null ? 2 : 1; - newIstructionCount += 2 * result.variables.size(); - - if (newIstructionCount * 2 < result.instructionsProcessed) { - Action target = actions.get(result.idx); - Action prevAction = actions.get(i); + ExecutionResult result = new ExecutionResult(); + executeActions(actions, i, actions.size() - 1, result, fakeFunctions); - if (result.constantPool != null) { - ActionConstantPool constantPool2 = new ActionConstantPool(new ArrayList<>(result.constantPool.constantPool)); - actions.addAction(i++, constantPool2); - prevAction = constantPool2; - } - - for (String variableName : result.variables.keySet()) { - Object value = result.variables.get(variableName); - ActionPush push = new ActionPush(variableName); - push.values.add(value); - push.setAddress(prevAction.getAddress()); - actions.addAction(i++, push); - prevAction = push; - - if (result.defines.contains(variableName)) { - Action defineLocal = new ActionDefineLocal(); - defineLocal.setAddress(prevAction.getAddress()); - actions.addAction(i++, defineLocal); - prevAction = defineLocal; - } else { - Action setVariable = new ActionSetVariable(); - setVariable.setAddress(prevAction.getAddress()); - actions.addAction(i++, setVariable); - prevAction = setVariable; - } - } - - ActionJump jump = new ActionJump(0); - jump.setAddress(prevAction.getAddress()); - jump.setJumpOffset((int) (target.getAddress() - jump.getAddress() - jump.getTotalActionLength())); - actions.addAction(i++, jump); - - //return true; - } + if (result.idx != -1) { + int newIstructionCount = 1; // jump + if (result.constantPool != null) { + newIstructionCount++; + } + if (!result.stack.isEmpty()) { + newIstructionCount++; + } + newIstructionCount += 2 * result.variables.size(); + + if (newIstructionCount * 2 < result.instructionsProcessed) { + Action target = actions.get(result.idx); + Action prevAction = actions.get(i); + + if (result.constantPool != null) { + ActionConstantPool constantPool2 = new ActionConstantPool(new ArrayList<>(result.constantPool.constantPool)); + actions.addAction(i++, constantPool2); + prevAction = constantPool2; + } + + for (String variableName : result.variables.keySet()) { + Object value = result.variables.get(variableName); + ActionPush push = new ActionPush(variableName); + push.values.add(value); + push.setAddress(prevAction.getAddress()); + actions.addAction(i++, push); + prevAction = push; + + if (result.defines.contains(variableName)) { + ActionDefineLocal defineLocal = new ActionDefineLocal(); + defineLocal.setAddress(prevAction.getAddress()); + actions.addAction(i++, defineLocal); + prevAction = defineLocal; + } else { + ActionSetVariable setVariable = new ActionSetVariable(); + setVariable.setAddress(prevAction.getAddress()); + actions.addAction(i++, setVariable); + prevAction = setVariable; + } + } + + if (!result.stack.isEmpty()) { + ActionPush push = new ActionPush(0); + push.values.clear(); + for (GraphTargetItem graphTargetItem : result.stack) { + DirectValueActionItem dv = (DirectValueActionItem) graphTargetItem; + push.values.add(dv.value); + } + push.setAddress(prevAction.getAddress()); + actions.addAction(i++, push); + prevAction = push; + } + + ActionJump jump = new ActionJump(0); + jump.setAddress(prevAction.getAddress()); + jump.setJumpOffset((int) (target.getAddress() - jump.getAddress() - jump.getTotalActionLength())); + actions.addAction(i++, jump); + + return true; } - } catch (EmptyStackException | TranslateException | InterruptedException ex) { } } return false; } - private void executeActions(ActionList actions, int idx, int endIdx, ExecutionResult result, Map fakeFunctions) throws InterruptedException { + private void executeActions(ActionList actions, int idx, int endIdx, ExecutionResult result, Map fakeFunctions) { List output = new ArrayList<>(); ActionLocalData localData = new ActionLocalData(); - TranslateStack stack = new TranslateStack(); + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(); int instructionsProcessed = 0; ActionConstantPool constantPool = null; - while (true) { - if (idx > endIdx) { - break; - } - - Action action = actions.get(idx); - instructionsProcessed++; - - if (instructionsProcessed > executionLimit) { - break; - } - - /*System.out.print(action.getASMSource(actions, new ArrayList(), ScriptExportMode.PCODE)); - for (int j = 0; j < stack.size(); j++) { - System.out.print(" '" + stack.get(j).getResult() + "'"); - } - System.out.println();*/ - - if (action instanceof ActionConstantPool) { - constantPool = (ActionConstantPool) action; - } - - if (action instanceof ActionDefineLocal) { - GraphTargetItem top = stack.pop(); - String variableName = stack.peek().getResult().toString(); - result.defines.add(variableName); - stack.push(top); - } - - if (action instanceof ActionGetVariable) { - String variableName = stack.peek().getResult().toString(); - if (!localData.variables.containsKey(variableName)) { + try { + while (true) { + if (idx > endIdx) { break; } - } - - if (action instanceof ActionCallFunction){ - String functionName = stack.pop().getResult().toString(); - long numArgs = EcmaScript.toUint32(stack.pop().getResult()); - if (numArgs == 0) { - if (fakeFunctions != null && fakeFunctions.containsKey(functionName)) { - stack.push(new DirectValueActionItem(fakeFunctions.get(functionName))); + + Action action = actions.get(idx); + instructionsProcessed++; + + if (instructionsProcessed > executionLimit) { + break; + } + + /*System.out.print(action.getASMSource(actions, new ArrayList(), ScriptExportMode.PCODE)); + for (int j = 0; j < stack.size(); j++) { + System.out.print(" '" + stack.get(j).getResult() + "'"); + } + System.out.println();*/ + + if (action instanceof ActionConstantPool) { + constantPool = (ActionConstantPool) action; + } + + if (action instanceof ActionDefineLocal) { + GraphTargetItem top = stack.pop(); + String variableName = stack.peek().getResult().toString(); + result.defines.add(variableName); + stack.push(top); + } + + if (action instanceof ActionGetVariable) { + String variableName = stack.peek().getResult().toString(); + if (!localData.variables.containsKey(variableName)) { + break; + } + } + + if (action instanceof ActionCallFunction){ + String functionName = stack.pop().getResult().toString(); + long numArgs = EcmaScript.toUint32(stack.pop().getResult()); + if (numArgs == 0) { + if (fakeFunctions != null && fakeFunctions.containsKey(functionName)) { + stack.push(new DirectValueActionItem(fakeFunctions.get(functionName))); + } else { + break; + } } else { break; } } else { + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + } + + if (!(action instanceof ActionPush || + action instanceof ActionPushDuplicate || + action instanceof ActionAdd || + action instanceof ActionAdd2 || + action instanceof ActionSubtract || + action instanceof ActionModulo || + action instanceof ActionMultiply || + action instanceof ActionBitXor || + action instanceof ActionBitAnd || + action instanceof ActionBitOr || + action instanceof ActionBitLShift || + action instanceof ActionBitRShift || + action instanceof ActionDefineLocal || + action instanceof ActionJump || + action instanceof ActionGetVariable || + action instanceof ActionSetVariable || + action instanceof ActionEquals || + action instanceof ActionNot || + action instanceof ActionIf || + action instanceof ActionConstantPool || + action instanceof ActionCallFunction || + action instanceof ActionReturn || + action instanceof ActionEnd)) { break; } - } else { - action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); - } - if (!(action instanceof ActionPush || - action instanceof ActionAdd || - action instanceof ActionAdd2 || - action instanceof ActionSubtract || - action instanceof ActionModulo || - action instanceof ActionMultiply || - action instanceof ActionDefineLocal || - action instanceof ActionJump || - action instanceof ActionGetVariable || - action instanceof ActionSetVariable || - action instanceof ActionEquals || - action instanceof ActionNot || - action instanceof ActionIf || - action instanceof ActionConstantPool || - action instanceof ActionCallFunction || - action instanceof ActionReturn || - action instanceof ActionEnd)) { - break; - } - - if (action instanceof ActionPush) { - ActionPush push = (ActionPush) action; - boolean ok = true; - for (Object value : push.values) { - if (value instanceof ConstantIndex) { - ok = false; + if (action instanceof ActionPush) { + ActionPush push = (ActionPush) action; + boolean ok = true; + for (Object value : push.values) { + if (value instanceof ConstantIndex) { + ok = false; + break; + } + } + if (!ok) { break; } } - if (!ok) { + + /*for (String variable : localData.variables.keySet()) { + System.out.println(Helper.byteArrToString(variable.getBytes())); + }*/ + + idx++; + + if (action instanceof ActionJump) { + ActionJump jump = (ActionJump) action; + long address = jump.getAddress() + jump.getTotalActionLength() + jump.getJumpOffset(); + idx = actions.indexOf(actions.getByAddress(address)); + if (idx == -1) { + throw new TranslateException("Jump target not found: " + address); + } + } + + if (action instanceof ActionIf) { + ActionIf aif = (ActionIf) action; + if (EcmaScript.toBoolean(stack.pop().getResult())) { + System.out.println("if true"); + long address = aif.getAddress() + aif.getTotalActionLength() + aif.getJumpOffset(); + idx = actions.indexOf(actions.getByAddress(address)); + if (idx == -1) { + throw new TranslateException("If target not found: " + address); + } + } + } + + if (action instanceof ActionDefineFunction) { + List lastActions = actions.getContainerLastActions(action); + int lastActionIdx = actions.indexOf(lastActions.get(0)); + idx = lastActionIdx != -1 ? lastActionIdx + 1 : -1; + } + + if (/*localData.variables.size() == 1 && */stack.allItemsFixed() || action instanceof ActionEnd) { + result.idx = idx == actions.size() ? idx - 1 : idx; + result.instructionsProcessed = instructionsProcessed; + result.constantPool = constantPool; + result.variables.clear(); + for (String variableName : localData.variables.keySet()) { + Object value = localData.variables.get(variableName).getResult(); + result.variables.put(variableName, value); + } + result.stack.clear(); + result.stack.addAll(stack); + } + + if (action instanceof ActionReturn) { + if (output.size() > 0) { + ReturnActionItem ret = (ReturnActionItem) output.get(output.size() - 1); + result.resultValue = ret.value.getResult(); + } break; } } - - /*for (String variable : localData.variables.keySet()) { - System.out.println(Helper.byteArrToString(variable.getBytes())); - }*/ - - idx++; - - if (action instanceof ActionJump) { - ActionJump jump = (ActionJump) action; - long address = jump.getAddress() + jump.getTotalActionLength() + jump.getJumpOffset(); - idx = actions.indexOf(actions.getByAddress(address)); - if (idx == -1) { - throw new TranslateException("Jump target not found: " + address); - } - } - - if (action instanceof ActionIf) { - ActionIf aif = (ActionIf) action; - if (EcmaScript.toBoolean(stack.pop().getResult())) { - System.out.println("if true"); - long address = aif.getAddress() + aif.getTotalActionLength() + aif.getJumpOffset(); - idx = actions.indexOf(actions.getByAddress(address)); - if (idx == -1) { - throw new TranslateException("If target not found: " + address); - } - } - } - - if (action instanceof ActionDefineFunction) { - List lastActions = actions.getContainerLastActions(action); - int lastActionIdx = actions.indexOf(lastActions.get(0)); - idx = lastActionIdx != -1 ? lastActionIdx + 1 : -1; - } - - if (/*localData.variables.size() == 1 && */stack.isEmpty() || action instanceof ActionEnd) { - result.idx = idx == actions.size() ? idx - 1 : idx; - result.instructionsProcessed = instructionsProcessed; - result.constantPool = constantPool; - result.variables.clear(); - for (String variableName : localData.variables.keySet()) { - Object value = localData.variables.get(variableName).getResult(); - result.variables.put(variableName, value); - } - } - - if (action instanceof ActionReturn) { - if (output.size() > 0) { - ReturnActionItem ret = (ReturnActionItem) output.get(output.size() - 1); - result.resultValue = ret.value.getResult(); - } - break; - } + } catch (EmptyStackException | TranslateException | InterruptedException ex) { } } @@ -411,19 +447,15 @@ public class ActionDeobfuscator implements SWFDecompilerListener { if (action instanceof ActionDefineFunction) { ActionDefineFunction def = (ActionDefineFunction) action; if(def.paramNames.isEmpty()) { - try { - ExecutionResult result = new ExecutionResult(); - List lastActions = actions.getContainerLastActions(action); - int lastActionIdx = actions.indexOf(lastActions.get(0)); - executeActions(actions, i + 1, lastActionIdx, result, null); - if (result.resultValue != null) { - results.put(def.functionName, result.resultValue); - for (int j = i; j <= lastActionIdx; j++) { - actions.removeAction(i); - } + ExecutionResult result = new ExecutionResult(); + List lastActions = actions.getContainerLastActions(action); + int lastActionIdx = actions.indexOf(lastActions.get(0)); + executeActions(actions, i + 1, lastActionIdx, result, null); + if (result.resultValue != null) { + results.put(def.functionName, result.resultValue); + for (int j = i; j <= lastActionIdx; j++) { + actions.removeAction(i); } - } catch (EmptyStackException | TranslateException | InterruptedException ex) { - Logger.getLogger(ActionDeobfuscator.class.getName()).log(Level.SEVERE, null, ex); } } } @@ -438,6 +470,7 @@ public class ActionDeobfuscator implements SWFDecompilerListener { public ActionConstantPool constantPool; public Map variables = new HashMap<>(); public Set defines = new HashSet<>(); + public TranslateStack stack = new TranslateStack(); public Object resultValue; } } diff --git a/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java b/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java new file mode 100644 index 000000000..23786b7ed --- /dev/null +++ b/src/com/jpexs/decompiler/flash/action/deobfuscation/ActionDeobfuscatorSimple.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2010-2014 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.deobfuscation; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.ActionLocalData; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.swf4.ActionAdd; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; +import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; +import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; +import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; +import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; +import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; +import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; +import com.jpexs.decompiler.flash.action.swf5.ActionModulo; +import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class ActionDeobfuscatorSimple implements SWFDecompilerListener { + + private final int executionLimit = 30000; + + @Override + public void actionListParsed(ActionList actions, SWF swf) { + removeObfuscationIfs(actions); + } + + private boolean removeObfuscationIfs(ActionList actions) { + if (actions.size() == 0) { + return false; + } + + for (int i = 0; i < actions.size(); i++) { + ExecutionResult result = new ExecutionResult(); + executeActions(actions, i, actions.size() - 1, result); + + if (result.idx != -1) { + int newIstructionCount = 1; // jump + if (!result.stack.isEmpty()) { + newIstructionCount++; + } + + if (newIstructionCount * 2 < result.instructionsProcessed) { + Action target = actions.get(result.idx); + Action prevAction = actions.get(i); + + if (!result.stack.isEmpty()) { + ActionPush push = new ActionPush(0); + push.values.clear(); + for (GraphTargetItem graphTargetItem : result.stack) { + DirectValueActionItem dv = (DirectValueActionItem) graphTargetItem; + push.values.add(dv.value); + } + push.setAddress(prevAction.getAddress()); + actions.addAction(i++, push); + prevAction = push; + } + + ActionJump jump = new ActionJump(0); + jump.setAddress(prevAction.getAddress()); + jump.setJumpOffset((int) (target.getAddress() - jump.getAddress() - jump.getTotalActionLength())); + actions.addAction(i++, jump); + } + } + } + + return false; + } + + private void executeActions(ActionList actions, int idx, int endIdx, ExecutionResult result) { + List output = new ArrayList<>(); + ActionLocalData localData = new ActionLocalData(); + FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack(); + int instructionsProcessed = 0; + + try { + while (true) { + if (idx > endIdx) { + break; + } + + Action action = actions.get(idx); + instructionsProcessed++; + + if (instructionsProcessed > executionLimit) { + break; + } + + /*System.out.print(action.getASMSource(actions, new ArrayList(), ScriptExportMode.PCODE)); + for (int j = 0; j < stack.size(); j++) { + System.out.print(" '" + stack.get(j).getResult() + "'"); + } + System.out.println();*/ + + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + + if (!(action instanceof ActionPush || + action instanceof ActionPushDuplicate || + action instanceof ActionAdd || + action instanceof ActionAdd2 || + action instanceof ActionSubtract || + action instanceof ActionModulo || + action instanceof ActionMultiply || + action instanceof ActionBitXor || + action instanceof ActionBitAnd || + action instanceof ActionBitOr || + action instanceof ActionBitLShift || + action instanceof ActionBitRShift || + action instanceof ActionEquals || + action instanceof ActionNot || + action instanceof ActionIf)) { + break; + } + + if (action instanceof ActionPush) { + ActionPush push = (ActionPush) action; + boolean ok = true; + for (Object value : push.values) { + if (value instanceof ConstantIndex) { + ok = false; + break; + } + } + if (!ok) { + break; + } + } + + idx++; + + if (action instanceof ActionIf) { + ActionIf aif = (ActionIf) action; + if (EcmaScript.toBoolean(stack.pop().getResult())) { + System.out.println("if true"); + long address = aif.getAddress() + aif.getTotalActionLength() + aif.getJumpOffset(); + idx = actions.indexOf(actions.getByAddress(address)); + if (idx == -1) { + throw new TranslateException("If target not found: " + address); + } + } + } + + if (stack.allItemsFixed()) { + result.idx = idx == actions.size() ? idx - 1 : idx; + result.instructionsProcessed = instructionsProcessed; + result.stack.clear(); + result.stack.addAll(stack); + } + } + } catch (EmptyStackException | TranslateException | InterruptedException ex) { + } + } + + class ExecutionResult { + public int idx = -1; + public int instructionsProcessed = -1; + public TranslateStack stack = new TranslateStack(); + public Object resultValue; + } +} diff --git a/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java b/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java new file mode 100644 index 000000000..799d7d55d --- /dev/null +++ b/src/com/jpexs/decompiler/flash/action/deobfuscation/FixItemCounterTranslateStack.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010-2014 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.deobfuscation; + +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateStack; + +/** + * + * @author JPEXS + */ +public class FixItemCounterTranslateStack extends TranslateStack { + + private int fixItemCount = Integer.MAX_VALUE; + + @Override + public GraphTargetItem pop() { + GraphTargetItem result = super.pop(); + int itemCount = size(); + if (itemCount < fixItemCount) { + fixItemCount = itemCount; + } + return result; + } + + @Override + public synchronized GraphTargetItem remove(int index) { + if (index < fixItemCount) { + fixItemCount = index; + } + return super.remove(index); + } + + public boolean allItemsFixed() { + return size() <= fixItemCount; + } + + public int getFixItemCount() { + return fixItemCount; + } +} diff --git a/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java b/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java index d3dae4d12..e73033c89 100644 --- a/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java +++ b/src/com/jpexs/decompiler/flash/action/swf5/ActionPushDuplicate.java @@ -36,8 +36,7 @@ public class ActionPushDuplicate extends Action { @Override public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) { - GraphTargetItem value = stack.pop(); - stack.push(value); + GraphTargetItem value = stack.peek(); stack.push(value); value.moreSrc.add(new GraphSourceItemPos(this, 0)); }