AS2 deobfuscation fixes

This commit is contained in:
honfika@gmail.com
2014-09-20 19:23:04 +02:00
parent c407d49b85
commit 3d9e2b76ed
4 changed files with 94 additions and 23 deletions

View File

@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.AppResources;
import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.action.model.ActionItem;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
@@ -54,7 +55,9 @@ import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.ecma.Null;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
@@ -391,6 +394,23 @@ public class Action implements GraphSourceItem {
}
}
/**
* Converts list of actions to ASM source
*
* @param listeners
* @param address
* @param list List of actions
* @param version SWF version
* @param exportMode PCode or hex?
* @return source ASM
*
*/
public static String actionsToString(List<DisassemblyListener> listeners, long address, ActionList list, int version, ScriptExportMode exportMode) {
HilightedTextWriter writer = new HilightedTextWriter(new CodeFormatting(), false);
actionsToString(listeners, address, list, version, exportMode, writer);
return writer.toString();
}
/**
* Converts list of actions to ASM source
*
@@ -671,6 +691,21 @@ public class Action implements GraphSourceItem {
return actionsToTree(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>(), actions, version, staticOperation, path);
}
/**
* Converts list of actions to ActionScript source code
*
* @param asm
* @param actions List of actions
* @param path
* @return source
* @throws java.lang.InterruptedException
*/
public static String actionsToSource(final ASMSource asm, final List<Action> actions, final String path) throws InterruptedException {
HilightedTextWriter writer = new HilightedTextWriter(new CodeFormatting(), false);
actionsToSource(asm, actions, path, writer);
return writer.toString();
}
/**
* Converts list of actions to ActionScript source code
*
@@ -685,12 +720,13 @@ public class Action implements GraphSourceItem {
List<GraphTargetItem> tree = null;
Throwable convertException = null;
int timeout = Configuration.decompilationTimeoutSingleMethod.get();
final int version = asm == null ? SWF.DEFAULT_VERSION : asm.getSwf().version;
try {
tree = CancellableWorker.call(new Callable<List<GraphTargetItem>>() {
@Override
public List<GraphTargetItem> call() throws Exception {
int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC;
List<GraphTargetItem> tree = actionsToTree(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>(), actions, asm.getSwf().version, staticOperation, path);
List<GraphTargetItem> tree = actionsToTree(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>(), actions, version, staticOperation, path);
Graph.graphToString(tree, new NulWriter(), new LocalData());
return tree;
}
@@ -707,7 +743,9 @@ public class Action implements GraphSourceItem {
}
writer.continueMeasure();
asm.getActionSourcePrefix(writer);
if (asm != null) {
asm.getActionSourcePrefix(writer);
}
if (convertException == null) {
Graph.graphToString(tree, writer, new LocalData());
} else if (convertException instanceof TimeoutException) {
@@ -717,7 +755,9 @@ public class Action implements GraphSourceItem {
Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error in: " + path, convertException);
Helper.appendErrorComment(writer, convertException);
}
asm.getActionSourceSuffix(writer);
if (asm != null) {
asm.getActionSourceSuffix(writer);
}
}
/**

View File

@@ -186,4 +186,17 @@ public class ActionList extends ArrayList<Action> {
}
}
@Override
public String toString() {
return Action.actionsToString(new ArrayList<DisassemblyListener>(), 0, this, SWF.DEFAULT_VERSION, ScriptExportMode.PCODE);
}
public String toSource() {
try {
return Action.actionsToSource(null, this, "");
} catch (InterruptedException ex) {
Logger.getLogger(ActionList.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}

View File

@@ -49,11 +49,15 @@ 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.ActionDecrement;
import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction;
import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal;
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
import com.jpexs.decompiler.flash.action.swf5.ActionIncrement;
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.action.swf6.ActionGreater;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener;
import com.jpexs.decompiler.graph.Graph;
@@ -215,9 +219,10 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
return false;
}
ActionConstantPool cPool = getConstantPool(actions);
for (int i = 0; i < actions.size(); i++) {
ExecutionResult result = new ExecutionResult();
executeActions(actions, i, actions.size() - 1, result, fakeFunctions);
executeActions(actions, i, actions.size() - 1, cPool, result, fakeFunctions);
if (result.idx != -1) {
int newIstructionCount = 1; // jump
@@ -285,12 +290,26 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
return false;
}
private void executeActions(ActionList actions, int idx, int endIdx, ExecutionResult result, Map<String, Object> fakeFunctions) {
private ActionConstantPool getConstantPool(ActionList actions) {
ActionConstantPool cPool = null;
for (Action action : actions) {
if (action instanceof ActionConstantPool) {
if (cPool != null) {
// there are multiple constant pools
return null;
}
cPool = (ActionConstantPool) action;
}
}
return cPool;
}
private void executeActions(ActionList actions, int idx, int endIdx, ActionConstantPool constantPool, ExecutionResult result, Map<String, Object> fakeFunctions) {
List<GraphTargetItem> output = new ArrayList<>();
ActionLocalData localData = new ActionLocalData();
FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack();
int instructionsProcessed = 0;
ActionConstantPool constantPool = null;
ActionConstantPool lastConstantPool = null;
try {
while (true) {
@@ -311,7 +330,7 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
}
System.out.println();*/
if (action instanceof ActionConstantPool) {
constantPool = (ActionConstantPool) action;
lastConstantPool = (ActionConstantPool) action;
}
if (action instanceof ActionDefineLocal) {
@@ -348,6 +367,8 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
|| action instanceof ActionPushDuplicate
|| action instanceof ActionAdd
|| action instanceof ActionAdd2
|| action instanceof ActionIncrement
|| action instanceof ActionDecrement
|| action instanceof ActionSubtract
|| action instanceof ActionModulo
|| action instanceof ActionMultiply
@@ -361,6 +382,8 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
|| action instanceof ActionGetVariable
|| action instanceof ActionSetVariable
|| action instanceof ActionEquals
|| action instanceof ActionEquals2
|| action instanceof ActionGreater
|| action instanceof ActionNot
|| action instanceof ActionIf
|| action instanceof ActionConstantPool
@@ -374,7 +397,7 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
ActionPush push = (ActionPush) action;
boolean ok = true;
for (Object value : push.values) {
if (value instanceof ConstantIndex || value instanceof RegisterNumber) {
if ((constantPool == null && value instanceof ConstantIndex) || value instanceof RegisterNumber) {
ok = false;
break;
}
@@ -418,7 +441,7 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
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.constantPool = lastConstantPool;
result.variables.clear();
for (String variableName : localData.variables.keySet()) {
Object value = localData.variables.get(variableName).getResult();
@@ -458,7 +481,7 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
ExecutionResult result = new ExecutionResult();
List<Action> lastActions = actions.getContainerLastActions(action);
int lastActionIdx = actions.indexOf(lastActions.get(0));
executeActions(actions, i + 1, lastActionIdx, result, null);
executeActions(actions, i + 1, lastActionIdx, null, result, null);
if (result.resultValue != null) {
results.put(def.functionName, result.resultValue);
for (int j = i; j <= lastActionIdx; j++) {