From 0e1a76f279b3b6b00e6ec79b71168d9b6c4b5691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 6 Jul 2015 09:12:29 +0200 Subject: [PATCH] AS3 register deobfuscator improved --- .../decompiler/flash/abc/avm2/AVM2Code.java | 10 +- .../AVM2DeobfuscatorRegisters.java | 199 +++++++----------- .../deobfuscation/AVM2DeobfuscatorSimple.java | 97 ++++----- .../flash/abc/types/MethodBody.java | 19 +- .../flash/ActionScript3DeobfuscatorTest.java | 5 +- .../flash/gui/dumpview/DumpTree.java | 2 +- 6 files changed, 149 insertions(+), 183 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 5e3f64ae2..54af4c5dd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -773,7 +773,7 @@ public class AVM2Code implements Cloneable { } } - public AVM2Code(ABCInputStream ais) throws IOException { + public AVM2Code(ABCInputStream ais, MethodBody body) throws IOException { Map codeMap = new TreeMap<>(); DumpInfo diParent = ais.dumpInfo; List addresses = new ArrayList<>(); @@ -789,6 +789,13 @@ public class AVM2Code implements Cloneable { long startPos = ais.getPosition(); addresses.add(startPos); + if (body != null) { + for (ABCException e : body.exceptions) { + addresses.add((long) e.start); + addresses.add((long) e.end); + addresses.add((long) e.target); + } + } loopaddr: while (!addresses.isEmpty() || !switchAddresses.isEmpty() || !unAdresses.isEmpty()) { @@ -919,6 +926,7 @@ public class AVM2Code implements Cloneable { for (int c = 2; c < actualOperands.length; c++) { addresses.add(beforeSwitchPos + actualOperands[c]); } + unAdresses.add(ais.getPosition()); continue loopaddr; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java index 4ebb64a3e..c41906a9e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java @@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -43,9 +44,8 @@ import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateException; import com.jpexs.decompiler.graph.TranslateStack; -import java.util.AbstractList; import java.util.ArrayList; -import java.util.EmptyStackException; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -70,61 +70,65 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { @Override public void deobfuscate(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody abody) throws InterruptedException { + //System.err.println("regdeo:" + path); removeUnreachableActions(abody.getCode(), cpool, trait, minfo, abody); - - Map outFirstAssigned = new HashMap<>(); - Map outFirstAssignments = new HashMap<>(); - Map outAssignCount1 = new HashMap<>(); - Map outAssignCount2 = new HashMap<>(); - - Map singleRegisters = new HashMap<>(); - - List ignored = new ArrayList<>(); - Map registers = new HashMap<>(); - - boolean extended = true; + /*for (AVM2Instruction ins : abody.getCode().code) { + System.err.println("" + ins.offset + ": " + ins); + }*/ + Set ignoredRegs = new HashSet<>(); MethodBody body = abody; - if (extended) { - body = abody.clone(); - getFirstRegistersUsage(outAssignCount1, outFirstAssigned, outFirstAssignments, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, ignored, registers); - ignored.addAll(outFirstAssignments.values()); - registers.putAll(outFirstAssigned); - - replaceSingleUseRegisters(registers, ignored, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); - - super.deobfuscate(path, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); - removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); - - //second pass - ignore all first assignments - registers.clear(); - ignored.clear(); - outFirstAssignments.clear(); - getFirstRegistersUsage(outAssignCount2, new HashMap<>(), outFirstAssignments, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, ignored, registers); - - for (int regId : outAssignCount1.keySet()) { - int ac = outAssignCount2.containsKey(regId) ? outAssignCount2.get(regId) : 0; - if (ac == 0) { - singleRegisters.put(regId, outFirstAssigned.get(regId)); - } - } - body = abody; - } else { - getFirstRegistersUsage(outAssignCount1, outFirstAssigned, outFirstAssignments, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, ignored, registers); - for (int regId : outAssignCount1.keySet()) { - int ac = outAssignCount1.get(regId); - if (ac == 1) { - singleRegisters.put(regId, outFirstAssigned.get(regId)); - } - } + body = abody.clone(); + Reference assignment = new Reference<>(null); + ignoredRegs.clear(); + for (int i = 0; i < body.getLocalReservedCount(); i++) { + ignoredRegs.add(i); } - //body.max_regs - replaceSingleUseRegisters(singleRegisters, null, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); - super.deobfuscate(path, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + int setReg = 0; + List listedRegs = new ArrayList<>(); + List listedLastBodies = new ArrayList<>(); + Set ignoredRegGets = new HashSet<>(); + + while (setReg > -1) { + MethodBody bodybefore = body; + body = bodybefore.clone(); + setReg = getFirstRegisterSetter(assignment, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, ignoredRegs, ignoredRegGets); + //System.err.println("setreg " + setReg + " ass:" + assignment.getVal()); + if (setReg < 0) { + break; + } + //if there is second assignment + if (listedRegs.contains(setReg)) { + //System.err.println("second assignment of loc" + setReg + ", ignoring"); + int lindex = listedRegs.indexOf(setReg); + body = listedLastBodies.get(lindex); //switch to body before + ignoredRegs.add(setReg); //this is not obfuscated + for (int i = listedRegs.size() - 1; i >= lindex; i--) { + int r = listedRegs.get(i); + listedRegs.remove(i); + listedLastBodies.remove(i); + ignoredRegGets.remove(r); + } + continue; + } + + if ((assignment.getVal().definition instanceof SetLocalTypeIns) || (assignment.getVal().definition instanceof GetLocalTypeIns /*First usage -> value undefined*/)) { + super.removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, Arrays.asList(assignment.getVal())); + } + if (assignment.getVal().definition instanceof GetLocalTypeIns) { + ignoredRegGets.add(setReg); + } + listedRegs.add(setReg); + listedLastBodies.add(bodybefore); + } + + abody.exceptions = body.exceptions; + abody.setCode(body.getCode()); removeUnreachableActions(body.getCode(), cpool, trait, minfo, body); + //System.err.println("/deo"); } private void replaceSingleUseRegisters(Map singleRegisters, List setInss, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) { @@ -149,45 +153,19 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { } } - private void getFirstRegistersUsage(Map outAssignCount, Map outFirstAssigned, Map outFirstAssignments, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body, List ignoredAss, Map registers) { + private int getFirstRegisterSetter(Reference assignment, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body, Set ignoredRegisters, Set ignoredGets) { AVM2Code code = body.getCode(); Map ret = new HashMap<>(); if (code.code.isEmpty()) { - return; + return -1; } ExecutionResult res = new ExecutionResult(); - visitCode(new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, res, registers, ignoredAss); - for (int reg : res.assignCount.keySet()) { - if (res.firstAssigned.get(reg) != null && res.firstAssigned.get(reg).isCompileTime()) { - outAssignCount.put(reg, res.assignCount.get(reg)); - outFirstAssigned.put(reg, res.firstAssigned.get(reg)); - outFirstAssignments.put(reg, res.firstAssignInstruction.get(reg)); - } - } + return visitCode(assignment, new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, res, ignoredRegisters, ignoredGets); } - /* - private Map getSingleUseRegisters(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) { - AVM2Code code = body.getCode(); - Map ret = new HashMap<>(); - if (code.code.isEmpty()) { - return ret; - } - - ExecutionResult res = new ExecutionResult(); - visitCode(new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, res); - for (int reg : res.assignCount.keySet()) { - if (res.assignCount.get(reg) == 1) { - ret.put(reg, res.lastAssigned.get(reg)); - } - } - - return ret; - }*/ - - private void visitCode(Set visited, TranslateStack stack, int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result, Map registers, List ignoredAss) { + private int visitCode(Reference assignment, Set visited, TranslateStack stack, int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result, Set ignored, Set ignoredGets) { List output = new ArrayList<>(); AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex); localData.localRegs.put(0, new NullAVM2Item(null));//this @@ -212,40 +190,33 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { AVM2Instruction action = code.code.get(idx); InstructionDefinition def = action.definition; //System.err.println("" + idx + ": " + action + " stack:" + stack.size()); - if (action.definition instanceof GetLocalTypeIns) { - stack.push(registers.get(((GetLocalTypeIns) action.definition).getRegisterId(action))); - } else if (action.definition instanceof SetLocalTypeIns) { - SetLocalTypeIns slt = (SetLocalTypeIns) def; - GraphTargetItem regVal = stack.pop();//localData.localRegs.get(regId); - int regId = slt.getRegisterId(action); - if (!result.assignCount.containsKey(regId)) { - result.assignCount.put(regId, 0); - } - boolean isIgnored = false; - for (AVM2Instruction ins : ignoredAss) { - if (action == ins) { - isIgnored = true; - break; - } - } - if (isIgnored) { - } else { - result.assignCount.put(regId, result.assignCount.get(regId) + 1); - //GraphTargetItem regVal = localData.localRegs.get(regId); - if (regVal == null || !regVal.getNotCoerced().isCompileTime()) { - result.assignCount.put(regId, Integer.MAX_VALUE); - } else { - if (result.assignCount.get(regId) == 1) { - result.firstAssigned.put(regId, regVal.getNotCoerced()); - result.firstAssignInstruction.put(regId, action); + action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); + + //if (!(def instanceof KillIns)) + if (def instanceof SetLocalTypeIns) { + int regId = ((SetLocalTypeIns) def).getRegisterId(action); + if (!ignored.contains(regId)) { + assignment.setVal(action); + return regId; + } + } else if (def instanceof GetLocalTypeIns) { + int regId = ((GetLocalTypeIns) def).getRegisterId(action); + if (!ignored.contains(regId) && !ignoredGets.contains(regId)) { + assignment.setVal(action); + return regId; + } + } else { + for (int p = 0; p < action.definition.operands.length; p++) { + int op = action.definition.operands[p]; + if (op == AVM2Code.DAT_REGISTER_INDEX) { + int regId = action.operands[p]; + if (!ignored.contains(regId)) { + assignment.setVal(action); + return regId; } - result.lastAssigned.put(regId, regVal.getNotCoerced()); } } - //assignCount - } else { - action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); } idx++; @@ -328,14 +299,6 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { //ignore } } - } - - class ExecutionResult { - - public Map assignCount = new HashMap<>(); - - public Map lastAssigned = new HashMap<>(); - public Map firstAssigned = new HashMap<>(); - public Map firstAssignInstruction = new HashMap<>(); + return -1; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java index f0cd601d0..0ea7ae817 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java @@ -48,6 +48,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsI import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; @@ -60,6 +61,8 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; 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.CoerceAIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns; import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; @@ -77,6 +80,7 @@ import com.jpexs.decompiler.flash.ecma.Undefined; import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.NotCompileTimeItem; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateException; import com.jpexs.decompiler.graph.TranslateStack; @@ -86,6 +90,7 @@ import java.util.ArrayList; import java.util.EmptyStackException; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @@ -156,60 +161,21 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { } } - private boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { + protected boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body, List inlineIns) throws InterruptedException { AVM2Code code = body.getCode(); if (code.code.size() == 0) { return false; } + Map staticRegs = new HashMap<>(); + for (AVM2Instruction ins : inlineIns) { + if (ins.definition instanceof GetLocalTypeIns) { + staticRegs.put(((GetLocalTypeIns) ins.definition).getRegisterId(ins), new UndefinedAVM2Item(ins)); + } + } for (int i = 0; i < code.code.size(); i++) { ExecutionResult result = new ExecutionResult(); - executeActions(classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result); - - /*if (result.idx != -1) { - int newIstructionCount = 1; // jump - if (!result.stack.isEmpty()) { - newIstructionCount += result.stack.size(); - } - - if (newIstructionCount < result.instructionsProcessed) //if (result.isIf) - { - AVM2Instruction target = code.code.get(result.idx); - AVM2Instruction prevAction = code.code.get(i); - int idelta = 0; - - if (result.stack.isEmpty() && prevAction.definition instanceof JumpIns) { - prevAction.operands[0] = ((int) (target.offset - prevAction.offset - prevAction.getBytes().length)); - } else { - if (!result.stack.isEmpty()) { - for (GraphTargetItem graphTargetItem : result.stack) { - if (graphTargetItem instanceof PopItem) { - continue; - } - AVM2Instruction ins = makePush(graphTargetItem.getResult(), cpool); - if (ins != null) { - code.insertInstruction(i + (idelta++), ins, body); - //prevAction = ins; - } else { - throw new TranslateException("Cannot push: " + graphTargetItem); - } - - } - } - - AVM2Instruction jump = new AVM2Instruction(0, new JumpIns(), new int[]{0}); - code.insertInstruction(i + (idelta++), jump, body); - - jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length)); - - } - - removeUnreachableActions(code, cpool, trait, minfo, body); - removeZeroJumps(code, body); - - i = -1; - } - }*/ + executeActions(staticRegs, classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result, inlineIns); } return false; @@ -237,7 +203,10 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { localData.isStatic = isStatic; localData.classIndex = classIndex; localData.localRegs = new HashMap<>(); - for (int i = 0; i < body.max_regs; i++) { + for (int i = 0; i < body.getLocalReservedCount(); i++) { + localData.localRegs.put(i, new NotCompileTimeItem(null, new UndefinedAVM2Item(null))); + } + for (int i = body.getLocalReservedCount(); i < body.max_regs; i++) { localData.localRegs.put(i, new UndefinedAVM2Item(null)); } localData.scopeStack = new ScopeStack(true); @@ -259,7 +228,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { return localData; } - private void executeActions(int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result) { + private void executeActions(Map staticRegs, int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result, List inlineIns) { List output = new ArrayList<>(); AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex); @@ -288,8 +257,28 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { } else { action.translate(localData, stack, output, Graph.SOP_USE_STATIC, ""); } + InstructionDefinition def = action.definition; + if (inlineIns.contains(action)) { + if (def instanceof SetLocalTypeIns) { + int regId = ((SetLocalTypeIns) def).getRegisterId(action); + staticRegs.put(regId, localData.localRegs.get(regId).getNotCoerced()); + code.replaceInstruction(idx, new AVM2Instruction(0, new DeobfuscatePopIns(), new int[]{}), body); + } + } + if (def instanceof GetLocalTypeIns) { + int regId = ((GetLocalTypeIns) def).getRegisterId(action); + if (staticRegs.containsKey(regId)) { + stack.pop(); + AVM2Instruction pushins = makePush(abc.constants, staticRegs.get(regId)); + code.replaceInstruction(idx, pushins, body); + stack.push(staticRegs.get(regId)); + action = pushins; + def = action.definition; + } + } + Class allowedDefs[] = new Class[]{ PushByteIns.class, PushShortIns.class, @@ -326,7 +315,8 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { StrictEqualsIns.class, PopIns.class, GetLocalTypeIns.class, - NewFunctionIns.class + NewFunctionIns.class, + CoerceOrConvertTypeIns.class }; boolean ok = false; @@ -342,10 +332,9 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { if (def instanceof GetLocalTypeIns) { int regId = ((GetLocalTypeIns) def).getRegisterId(action); - if (regId > 0 && localData.localRegs.get(regId) instanceof UndefinedAVM2Item) { - //System.err.println(""+); + if (staticRegs.containsKey(regId)) { stack.pop(); - stack.push(new UndefinedAVM2Item(action)); + stack.push(staticRegs.get(regId)); } else { break; } @@ -435,7 +424,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { AVM2Code code = body.getCode(); code.fixJumps(body); removeUnreachableActions(code, cpool, trait, minfo, body); - removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body); + removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, new ArrayList<>()); removeZeroJumps(code, body); } 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 7f9046fad..6183ca61f 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 @@ -121,7 +121,7 @@ public final class MethodBody implements Cloneable { AVM2Code avm2Code; try { ABCInputStream ais = new ABCInputStream(new MemoryInputStream(codeBytes)); - avm2Code = new AVM2Code(ais); + avm2Code = new AVM2Code(ais, this); avm2Code.removeWrongIndices(abc.constants); } catch (UnknownInstructionCode | IOException ex) { avm2Code = new AVM2Code(); @@ -218,6 +218,17 @@ public final class MethodBody implements Cloneable { getCode().insertInstruction(pos, instruction, mapOffsetsAfterIns, this); } + public int getLocalReservedCount() { + int pos = abc.method_info.get(this.method_info).param_types.length + 1; + if (abc.method_info.get(this.method_info).flagNeed_arguments()) { + pos++; + } + if (abc.method_info.get(this.method_info).flagNeed_rest()) { + pos++; + } + return pos; + } + public HashMap getLocalRegNames(ABC abc) { HashMap ret = new HashMap<>(); for (int i = 1; i <= abc.method_info.get(this.method_info).param_types.length; i++) { @@ -247,9 +258,6 @@ public final class MethodBody implements Cloneable { } public void convert(final String path, ScriptExportMode exportMode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final AVM2ConstantPool constants, final List method_info, final ScopeStack scopeStack, final boolean isStaticInitializer, final GraphTextWriter writer, final List fullyQualifiedNames, final Traits initTraits, boolean firstLevel) throws InterruptedException { - /*if (!path.contains("forcedWidth")) { - return; - }*/ if (debugMode) { System.err.println("Decompiling " + path); } @@ -296,9 +304,6 @@ public final class MethodBody implements Cloneable { } public GraphTextWriter toString(final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final AVM2ConstantPool constants, final List method_info, final GraphTextWriter writer, final List fullyQualifiedNames) throws InterruptedException { - /*if (!path.contains("forcedWidth")) { - return writer; - }*/ if (exportMode != ScriptExportMode.AS) { getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer); } else { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java index e12f9589b..e3340291d 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java @@ -54,6 +54,7 @@ public class ActionScript3DeobfuscatorTest extends ActionStript2TestBase { Configuration.autoDeobfuscate.set(true); Configuration.deobfuscationOldMode.set(false); Configuration.decimalAddress.set(false); + Configuration.decompilationTimeoutSingleMethod.set(Integer.MAX_VALUE); swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false); } @@ -178,10 +179,10 @@ public class ActionScript3DeobfuscatorTest extends ActionStript2TestBase { fail("if true OnTrue removed"); } if (!res.contains("\"OK2\"")) { - fail("if false OnFalse removed" + res); + fail("if false OnFalse removed"); } if (res.contains("\"FAIL1\"")) { - fail("if true OnFalse not removed"); + fail("if true OnFalse not removed:"); } if (res.contains("\"FAIL2\"")) { fail("if false OnTrue not removed"); diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java index f5f66adaa..0453aa0bf 100644 --- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java +++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java @@ -253,7 +253,7 @@ public class DumpTree extends JTree { ABCInputStream ais = new ABCInputStream(new MemoryInputStream(data, 0, prevLength + (int) dumpInfo.lengthBytes)); ais.seek(prevLength); ais.dumpInfo = dumpInfo; - new AVM2Code(ais); + new AVM2Code(ais, null /*FIXME! Pass correct body!*/); } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); }