not resolving unusualTags in DefineSprite for parallel speedup off too

improved AS3 deobfsucation
This commit is contained in:
Jindra Petřík
2016-02-18 10:32:12 +01:00
parent 7e399c598c
commit 36220f2de3
8 changed files with 105 additions and 38 deletions

View File

@@ -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<Tag> future = executor.submit(new TagResolutionTask((TagStub) tag, di, level, parallel1, skipUnusualTags, lazy));
futureResults.add(future);

View File

@@ -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;
}
}
}

View File

@@ -75,6 +75,11 @@ public class ThisAVM2Item extends AVM2Item {
return null;
}
@Override
public Boolean getResultAsBoolean() {
return true;
}
@Override
public String toString() {
return "this";

View File

@@ -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<Integer> 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<GraphTargetItem> 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<GraphTargetItem> objectType, Reference<GraphTargetItem> propertyType, Reference<Integer> propertyIndex, Reference<ValueKind> propertyValue, Reference<ABC> 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,

View File

@@ -69,6 +69,7 @@ public final class MethodBody implements Cloneable {
@Internal
public boolean deleted;
@Internal
boolean debugMode = false;
public int method_info;

View File

@@ -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() {

View File

@@ -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();

View File

@@ -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) {