From 36220f2de3fcf5ecc82fc980d9e3004de4fb94cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 18 Feb 2016 10:32:12 +0100 Subject: [PATCH] not resolving unusualTags in DefineSprite for parallel speedup off too improved AS3 deobfsucation --- .../decompiler/flash/SWFInputStream.java | 43 ++++++++------- .../AVM2DeobfuscatorSimpleOld.java | 52 ++++++++++++++----- .../flash/abc/avm2/model/ThisAVM2Item.java | 5 ++ .../avm2/parser/script/PropertyAVM2Item.java | 28 ++++++++-- .../flash/abc/types/MethodBody.java | 1 + .../jpexs/decompiler/flash/tags/TagStub.java | 8 ++- .../decompiler/graph/GraphTargetItem.java | 4 ++ .../jpexs/decompiler/graph/model/NotItem.java | 2 +- 8 files changed, 105 insertions(+), 38 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java index 1e4f499b5..1dd68af40 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -1164,31 +1164,15 @@ public class SWFInputStream implements AutoCloseable { long pos = getPos(); newDumpLevel(null, "TAG"); try { - tag = readTag(timelined, level, pos, parseTags && !parallel1, parallel1, skipUnusualTags, lazy); + tag = readTag(timelined, level, pos, false, parallel1, skipUnusualTags, lazy); } catch (EOFException | EndOfStreamException ex) { tag = null; } - DumpInfo di = dumpInfo; - if (di != null && tag != null) { - di.name = tag.getName(); - } - endDumpLevel(tag == null ? null : tag.getId()); - if (tag == null) { - break; - } - tag.setTimelined(timelined); - if (!parallel1) { - tags.add(tag); - } - if (Configuration.dumpTags.get() && level == 0) { - dumpTag(System.out, tag, tags.size() - 1, level); - } - - boolean doParse; + boolean doParse = true; if (!skipUnusualTags) { doParse = true; - } else { + } else if (tag != null) { switch (tag.getId()) { case FileAttributesTag.ID: // FileAttributes if (tag instanceof TagStub) { @@ -1229,6 +1213,27 @@ public class SWFInputStream implements AutoCloseable { } } + + if (parseTags && !parallel1 && doParse && (tag instanceof TagStub)) { + tag = resolveTag((TagStub) tag, level, parallel, skipUnusualTags, lazy); + } + DumpInfo di = dumpInfo; + if (di != null && tag != null) { + di.name = tag.getName(); + } + endDumpLevel(tag == null ? null : tag.getId()); + if (tag == null) { + break; + } + + tag.setTimelined(timelined); + if (!parallel1) { + tags.add(tag); + } + if (Configuration.dumpTags.get() && level == 0) { + dumpTag(System.out, tag, tags.size() - 1, level); + } + if (parseTags && doParse && parallel1 && tag instanceof TagStub && executor != null) { Future future = executor.submit(new TagResolutionTask((TagStub) tag, di, level, parallel1, skipUnusualTags, lazy)); futureResults.add(future); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java index 8a3cf51c8..d13e8e274 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java @@ -76,10 +76,12 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.TypeOfIns; import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NewArrayAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; @@ -233,7 +235,9 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter { } AVM2Instruction ins = code.code.get(idx); - if (ins.definition instanceof NewFunctionIns) { + InstructionDefinition def = ins.definition; + //System.err.println("" + ins + " stack size:" + stack.size()); + /*if (ins.definition instanceof NewFunctionIns) { if (idx + 1 < code.code.size()) { if (code.code.get(idx + 1).definition instanceof PopIns) { code.removeInstruction(idx + 1, body); @@ -241,18 +245,44 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter { continue; } } - } else { + } else */ + { // do not throw EmptyStackException, much faster int requiredStackSize = ins.getStackPopCount(localData); if (stack.size() < requiredStackSize) { return; } + //Do not duplicate, whole tree, simplify first. (Simplify always?) + if (def instanceof DupIns) { + stack.simplify(); + } + + if (def instanceof PopIns) { + if (!stack.isEmpty()) { + //System.err.println("pop:" + stack.peek().getClass()); + if (stack.peek() instanceof NewFunctionAVM2Item) { + AVM2Instruction fins = ((AVM2Instruction) stack.peek().getSrc()); + AVM2Instruction nins = idx + 1 < code.code.size() ? code.code.get(idx + 1) : null; + if (fins.definition instanceof NewFunctionIns) { + int fidx = code.code.indexOf(fins); + code.removeInstruction(fidx, body); + } + int nidx = code.code.indexOf(ins); + code.removeInstruction(nidx, body); + if (nins == null) { + idx = code.code.size(); + } else { + idx = code.code.indexOf(nins); + } + continue; + } + } + } + ins.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); } - InstructionDefinition def = ins.definition; - if (inlineIns.contains(ins)) { if (def instanceof SetLocalTypeIns) { int regId = ((SetLocalTypeIns) def).getRegisterId(ins); @@ -332,7 +362,8 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter { || def instanceof GetPropertyIns || def instanceof CoerceOrConvertTypeIns || def instanceof ConstructIns - || def instanceof CallIns) { + || def instanceof CallIns + || def instanceof TypeOfIns) { ok = true; } @@ -361,16 +392,14 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter { stack.pop(); stack.push(staticRegs.get(regId)); - } else { + } else if (regId > 0) { break; } } - boolean ifed = false; if (def instanceof JumpIns) { long address = ins.getTargetAddress(); idx = code.adr2pos(address); - if (idx == -1) { throw new TranslateException("Jump target not found: " + address); } @@ -380,15 +409,14 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter { } GraphTargetItem top = stack.pop(); - Object res = top.getResult(); + Boolean res = top.getResultAsBoolean(); long address = ins.getTargetAddress(); int nidx = code.adr2pos(address);//code.indexOf(code.getByAddress(address)); AVM2Instruction tarIns = code.code.get(nidx); //Some IfType instructions need more than 1 operand, we must pop out all of them int stackCount = -def.getStackDelta(ins, abc); - - if (EcmaScript.toBoolean(res)) { + if (res) { //System.err.println("replacing " + ins + " on " + idx + " with jump"); AVM2Instruction jumpIns = new AVM2Instruction(0, AVM2Instructions.Jump, new int[]{0}); //jumpIns.operands[0] = ins.operands[0] /*- ins.getBytes().length*/ + jumpIns.getBytes().length; @@ -424,7 +452,7 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter { } if (ifed) { - break; + //break; } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ThisAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ThisAVM2Item.java index 0524b5c7e..39a911205 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ThisAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ThisAVM2Item.java @@ -75,6 +75,11 @@ public class ThisAVM2Item extends AVM2Item { return null; } + @Override + public Boolean getResultAsBoolean() { + return true; + } + @Override public String toString() { return "this"; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java index d8d239a13..0bbd9bd49 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java @@ -42,7 +42,9 @@ import com.jpexs.decompiler.graph.model.LocalData; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -92,16 +94,28 @@ public class PropertyAVM2Item extends AssignableAVM2Item { return abc.getSelectedAbc().constants.getNamespaceSetId(nssa, true); } - public static GraphTargetItem multinameToType(int m_index, AVM2ConstantPool constants) { + private static GraphTargetItem multinameToType(Set visited, int m_index, AVM2ConstantPool constants) { + if (visited.contains(m_index)) { + Logger.getLogger(PropertyAVM2Item.class.getName()).log(Level.WARNING, "Recursive typename detected"); + return null; + } if (m_index == 0) { return TypeItem.UNBOUNDED; } Multiname m = constants.getMultiname(m_index); if (m.kind == Multiname.TYPENAME) { - GraphTargetItem obj = multinameToType(m.qname_index, constants); + visited.add(m_index); + GraphTargetItem obj = multinameToType(visited, m.qname_index, constants); + if (obj == null) { + return null; + } List params = new ArrayList<>(); for (int pm : m.params) { - params.add(multinameToType(pm, constants)); + GraphTargetItem r = multinameToType(visited, pm, constants); + if (r == null) { + return null; + } + params.add(r); } return new ApplyTypeAVM2Item(null, null, obj, params); } else { @@ -109,6 +123,10 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } } + public static GraphTargetItem multinameToType(int m_index, AVM2ConstantPool constants) { + return multinameToType(new HashSet<>(), m_index, constants); + } + public void resolve(boolean mustExist, SourceGeneratorLocalData localData, Reference objectType, Reference propertyType, Reference propertyIndex, Reference propertyValue, Reference propertyValueABC) throws CompilationException { GraphTargetItem thisType = new TypeItem(localData.getFullClass()); GraphTargetItem objType = null; @@ -474,7 +492,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { return objType; }*/ - /* + /* public GraphTargetItem resolvePropertyType() { if (index != null) { return TypeItem.UNBOUNDED; @@ -515,7 +533,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { return TypeItem.UNBOUNDED; } */ - /* public int resolveProperty() { + /* public int resolveProperty() { if (index != null) { return abc.constants.getMultinameId(new Multiname(Multiname.MULTINAMEL, abc.constants.getStringId(propertyName, true), 0, diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 8be0aca69..21df89e4a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -69,6 +69,7 @@ public final class MethodBody implements Cloneable { @Internal public boolean deleted; + @Internal boolean debugMode = false; public int method_info; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/TagStub.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/TagStub.java index 2f415b8a5..3510eef98 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/TagStub.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/TagStub.java @@ -21,6 +21,8 @@ import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.helpers.ByteArrayRange; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -55,7 +57,11 @@ public class TagStub extends Tag { */ @Override public void getData(SWFOutputStream sos) { - throw new Error("TagStub.getData call is not supported."); + try { + sos.write(getOriginalData()); + } catch (IOException ex) { + Logger.getLogger(TagStub.class.getName()).log(Level.SEVERE, null, ex); + } } public SWFInputStream getDataStream() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index 1eacb1cf3..2045e2ff9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -390,6 +390,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return EcmaScript.toString(getResult()); } + public Boolean getResultAsBoolean() { + return EcmaScript.toBoolean(getResult()); + } + public String toStringNoQuotes(LocalData localData) { // todo: honfika: this method should not be called, maybe we should throw an exception return toString(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java index b0e5c59fa..52ff32738 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/NotItem.java @@ -40,7 +40,7 @@ public class NotItem extends UnaryOpItem implements LogicalOpItem, Inverted { @Override public Object getResult() { - return getResult(value.getResult()); + return !value.getResultAsBoolean(); } public static Boolean getResult(Object obj) {