From 09aeafb77b798e5a0f26ec7f3eca72324274e31c Mon Sep 17 00:00:00 2001 From: Honfika Date: Sun, 1 Dec 2013 13:55:08 +0100 Subject: [PATCH] Deobfuscation simplified --- .../decompiler/flash/abc/avm2/AVM2Code.java | 66 +++++++++---------- .../flash/abc/avm2/graph/AVM2GraphSource.java | 3 +- .../avm2/instructions/AVM2Instruction.java | 2 - .../jpexs/decompiler/flash/action/Action.java | 39 ++++------- .../flash/action/ActionListReader.java | 13 ++-- .../flash/action/parser/pcode/ASMParser.java | 9 ++- .../flash/action/swf4/ActionIf.java | 7 +- .../flash/configuration/Configuration.java | 4 ++ .../decompiler/graph/GraphSourceItem.java | 4 -- trunk/src/com/jpexs/helpers/Helper.java | 4 ++ 10 files changed, 70 insertions(+), 81 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 71bf77486..7175299aa 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -71,6 +71,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.ecma.EcmaScript; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; @@ -927,7 +928,7 @@ public class AVM2Code implements Serializable { } if (ins.labelname != null) { writer.appendNoHilight(ins.labelname + ":"); - } else if (offsets.contains(ofs)) { + } else if (Configuration.showAllAddresses.get() || offsets.contains(ofs)) { writer.appendNoHilight("ofs" + Helper.formatAddress(ofs) + ":"); } /*for (int e = 0; e < body.exceptions.length; e++) { @@ -2375,7 +2376,7 @@ public class AVM2Code implements Serializable { } @SuppressWarnings("unchecked") - private static int removeTraps(HashMap> refs, boolean secondPass, boolean indeterminate, List localData, Stack stack, List output, AVM2GraphSource code, int ip, HashMap visited, HashMap> visitedStates, HashMap decisions, String path, int recursionLevel) throws InterruptedException { + private static int removeTraps(HashMap> refs, boolean secondPass, boolean indeterminate, List localData, Stack stack, List output, AVM2GraphSource code, int ip, HashMap visited, HashMap> visitedStates, HashMap decisions, String path, int recursionLevel) throws InterruptedException { if (Thread.interrupted()) { throw new InterruptedException(); } @@ -2427,20 +2428,16 @@ public class AVM2Code implements Serializable { } }*/ - GraphSourceItem ins = code.get(ip); - - if (ins instanceof AVM2Instruction) { - AVM2Instruction ains = (AVM2Instruction) ins; - //Errorneous code inserted by some obfuscators - if (ains.definition instanceof NewObjectIns) { - if (ains.operands[0] > stack.size()) { - ains.setIgnored(true, 0); - } + AVM2Instruction ins = code.get(ip); + //Errorneous code inserted by some obfuscators + if (ins.definition instanceof NewObjectIns) { + if (ins.operands[0] > stack.size()) { + ins.setIgnored(true, 0); } - if (ains.definition instanceof NewArrayIns) { - if (ains.operands[0] > stack.size()) { - ains.setIgnored(true, 0); - } + } + if (ins.definition instanceof NewArrayIns) { + if (ins.operands[0] > stack.size()) { + ins.setIgnored(true, 0); } } @@ -2482,7 +2479,7 @@ public class AVM2Code implements Serializable { - if ((ins instanceof AVM2Instruction) && (((AVM2Instruction) ins).definition instanceof NewFunctionIns)) { + if (((AVM2Instruction) ins).definition instanceof NewFunctionIns) { stack.push(new BooleanAVM2Item(null, true)); } else { localData.set(15, ip); @@ -2490,17 +2487,14 @@ public class AVM2Code implements Serializable { } - if (ins instanceof AVM2Instruction) { - AVM2Instruction ains = (AVM2Instruction) ins; - if (ains.definition instanceof SetLocalTypeIns) { - SetLocalTypeIns slt = (SetLocalTypeIns) ains.definition; - int regId = slt.getRegisterId(ains); - if (indeterminate) { - HashMap registers = (HashMap) localData.get(2); - GraphTargetItem regVal = registers.get(regId); - if (regVal.isCompileTime()) { - registers.put(regId, new NotCompileTimeItem(null, regVal)); - } + if (ins.definition instanceof SetLocalTypeIns) { + SetLocalTypeIns slt = (SetLocalTypeIns) ins.definition; + int regId = slt.getRegisterId(ins); + if (indeterminate) { + HashMap registers = (HashMap) localData.get(2); + GraphTargetItem regVal = registers.get(regId); + if (regVal.isCompileTime()) { + registers.put(regId, new NotCompileTimeItem(null, regVal)); } } } @@ -2512,8 +2506,11 @@ public class AVM2Code implements Serializable { if (ins.isBranch() || ins.isJump()) { List branches = ins.getBranches(code); - if ((ins instanceof AVM2Instruction) && ((AVM2Instruction) ins).definition instanceof IfTypeIns - && (!(((AVM2Instruction) ins).definition instanceof JumpIns)) && (!stack.isEmpty()) && (stack.peek().isCompileTime()) && (!stack.peek().hasSideEffect())) { + if (((AVM2Instruction) ins).definition instanceof IfTypeIns + && (!(((AVM2Instruction) ins).definition instanceof JumpIns)) + && (!stack.isEmpty()) + && (stack.peek().isCompileTime()) + && (!stack.peek().hasSideEffect())) { boolean condition = EcmaScript.toBoolean(stack.peek().getResult()); if (debugMode) { if (condition) { @@ -2629,7 +2626,7 @@ public class AVM2Code implements Serializable { break; } ip++; - }; + } if (ip < 0) { System.out.println("Visited Negative: " + ip); } @@ -2637,16 +2634,17 @@ public class AVM2Code implements Serializable { } public static int removeTraps(ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, List localData, AVM2GraphSource code, int addr, String path, HashMap> refs) throws InterruptedException { - HashMap decisions = new HashMap<>(); + HashMap decisions = new HashMap<>(); removeTraps(refs, false, false, localData, new Stack(), new ArrayList(), code, code.adr2pos(addr), new HashMap(), new HashMap>(), decisions, path, 0); int cnt = 0; - for (GraphSourceItem src : decisions.keySet()) { + for (AVM2Instruction src : decisions.keySet()) { Decision dec = decisions.get(src); if (dec != null) { - if ((src instanceof AVM2Instruction) && (((AVM2Instruction) src).definition instanceof LookupSwitchIns)) { + if (((AVM2Instruction) src).definition instanceof LookupSwitchIns) { + AVM2Instruction asrc = (AVM2Instruction) src; if (dec.casesUsed.size() == 1) { for (int c : dec.casesUsed) { - src.setFixBranch(c); + asrc.setFixBranch(c); cnt++; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java index 8ff31c45e..8b852b1a5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java @@ -3,6 +3,7 @@ package com.jpexs.decompiler.flash.abc.avm2.graph; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphSource; @@ -57,7 +58,7 @@ public class AVM2GraphSource extends GraphSource { } @Override - public GraphSourceItem get(int pos) { + public AVM2Instruction get(int pos) { return code.code.get(pos); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instruction.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instruction.java index cf34c5832..723c1ec47 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instruction.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instruction.java @@ -350,13 +350,11 @@ public class AVM2Instruction implements Serializable, GraphSourceItem { this.ignored = ignored; } - @Override public void setFixBranch(int pos) { this.fixedBranch = pos; } private int fixedBranch = -1; - @Override public int getFixBranch() { return fixedBranch; } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index 20587983e..815b2a132 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -478,7 +478,7 @@ public class Action implements GraphSourceItem { } } - if (importantOffsets.contains(offset)) { + if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { if (lastPush) { writer.newLine(); lastPush = false; @@ -488,8 +488,6 @@ public class Action implements GraphSourceItem { writer.appendNoHilight(":"); } - - if (a.replaceWith != null) { if (lastPush) { writer.newLine(); @@ -536,26 +534,24 @@ public class Action implements GraphSourceItem { writer.append("", offset); + int fixBranch = -1; if (a instanceof ActionIf) { ActionIf aif = (ActionIf) a; if (aif.jumpUsed && !aif.ignoreUsed) { - aif.setFixBranch(0); + fixBranch = 0; } if (!aif.jumpUsed && aif.ignoreUsed) { - aif.setFixBranch(1); + fixBranch = 1; } } - - int fixBranch = a.getFixBranch(); + if (fixBranch > -1) { - if (a instanceof ActionIf) { - writer.appendNoHilight("ffdec_deobfuscatepop").newLine(); - if (fixBranch == 0) { //jump - writer.appendNoHilight("jump loc"); - writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getBytes(version).length + ((ActionIf) a).getJumpOffset())); - } else { - //nojump, ignore - } + writer.appendNoHilight("FFDec_DeobfuscatePop").newLine(); + if (fixBranch == 0) { //jump + writer.appendNoHilight("Jump loc"); + writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getBytes(version).length + ((ActionIf) a).getJumpOffset())); + } else { + //nojump, ignore } } else { a.getASMSourceReplaced(list, importantOffsets, constantPool, version, exportMode, writer); @@ -564,7 +560,7 @@ public class Action implements GraphSourceItem { writer.appendNoHilight(add); if (!(a instanceof ActionPush)) { writer.newLine(); - }; + } } if (a instanceof ActionPush) { lastPush = true; @@ -1266,17 +1262,6 @@ public class Action implements GraphSourceItem { return 0; } - @Override - public void setFixBranch(int pos) { - this.fixedBranch = pos; - } - private int fixedBranch = -1; - - @Override - public int getFixBranch() { - return fixedBranch; - } - public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value) { GraphTargetItem ret = get; if (ret instanceof GetVariableActionItem) { diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java index bd9c1228f..7baa8a9e7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -214,7 +214,13 @@ public class ActionListReader { if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) { maxRecursionLevel++; } + if (a instanceof ActionIf) { + ActionIf aif = (ActionIf) a; + aif.ignoreUsed = false; + aif.jumpUsed = false; + } } + deobfustaceActionListAtPosRecursive(listeners, new ArrayList(), new HashMap>(), containerSWFOffset, localData, stack, cpool, actionMap, ip, ip, retdups, ip, endIp, path, new HashMap(), false, new HashMap>(), version, 0, maxRecursionLevel); if (!retdups.isEmpty()) { @@ -759,24 +765,17 @@ public class ActionListReader { break; } } else if (top.isCompileTime() && (!top.hasSideEffect())) { - ((ActionIf) a).compileTime = true; if (debugMode) { System.err.print("is compiletime -> "); } if (EcmaScript.toBoolean(top.getResult())) { newip = pos + aif.getJumpOffset(); aif.jumpUsed = true; - if (aif.ignoreUsed) { - aif.compileTime = false; - } if (debugMode) { System.err.println("jump"); } } else { aif.ignoreUsed = true; - if (aif.jumpUsed) { - aif.compileTime = false; - } if (debugMode) { System.err.println("ignore"); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java b/trunk/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java index 47d643c8e..fdc6c821c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java @@ -60,10 +60,15 @@ public class ASMParser { } else if (symb.type == ASMParsedSymbol.TYPE_COMMENT) { if (!list.isEmpty()) { String cmt = (String) symb.value; - if (cmt.equals("compileTime")) { + if (cmt.equals("compileTimeJump")) { Action a = list.get(list.size() - 1); if (a instanceof ActionIf) { - ((ActionIf) a).compileTime = true; + ((ActionIf) a).ignoreUsed = false; + } + } else if (cmt.equals("compileTimeIgnore")) { + Action a = list.get(list.size() - 1); + if (a instanceof ActionIf) { + ((ActionIf) a).jumpUsed = false; } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java index c25292474..556ce4871 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java @@ -37,9 +37,8 @@ public class ActionIf extends Action { private int offset; public String identifier; - public boolean compileTime; - public boolean jumpUsed = false; - public boolean ignoreUsed = false; + public boolean jumpUsed = true; + public boolean ignoreUsed = true; public int getJumpOffset() { return offset; @@ -85,7 +84,7 @@ public class ActionIf extends Action { @Override public String getASMSource(List container, List knownAddreses, List constantPool, int version, ExportMode exportMode) { String ofsStr = Helper.formatAddress(getAddress() + getBytes(version).length + offset); - return "If loc" + ofsStr + (compileTime ? " ;compileTime" : ""); + return "If loc" + ofsStr + (!jumpUsed ? " ;compileTimeIgnore" : (!ignoreUsed ? " ;compileTimeJump" : "")); } public ActionIf(FlasmLexer lexer) throws IOException, ParseException { diff --git a/trunk/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/trunk/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 85bcb294c..377bb3e91 100644 --- a/trunk/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/trunk/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -69,6 +69,10 @@ public class Configuration { public static final ConfigurationItem removeNops = null; @ConfigurationDefaultBoolean(false) public static final ConfigurationItem showHexOnlyButton = null; + @ConfigurationDefaultBoolean(false) + public static final ConfigurationItem decimalAddress = null; + @ConfigurationDefaultBoolean(false) + public static final ConfigurationItem showAllAddresses = null; /** * Debug mode = throwing an error when comparing original file and diff --git a/trunk/src/com/jpexs/decompiler/graph/GraphSourceItem.java b/trunk/src/com/jpexs/decompiler/graph/GraphSourceItem.java index d571403bc..ea15d2b06 100644 --- a/trunk/src/com/jpexs/decompiler/graph/GraphSourceItem.java +++ b/trunk/src/com/jpexs/decompiler/graph/GraphSourceItem.java @@ -44,9 +44,5 @@ public interface GraphSourceItem extends Serializable { public void setIgnored(boolean ignored, int pos); - public void setFixBranch(int pos); - - public int getFixBranch(); - public boolean isDeobfuscatePop(); } diff --git a/trunk/src/com/jpexs/helpers/Helper.java b/trunk/src/com/jpexs/helpers/Helper.java index a98d64828..a4ef1c2e3 100644 --- a/trunk/src/com/jpexs/helpers/Helper.java +++ b/trunk/src/com/jpexs/helpers/Helper.java @@ -16,6 +16,7 @@ */ package com.jpexs.helpers; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.Freed; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; @@ -122,6 +123,9 @@ public class Helper { * @return String representation of the address */ public static String formatAddress(long number) { + if (Configuration.decimalAddress.get()) { + return padZeros(Long.toString(number), 4); + } return padZeros(Long.toHexString(number), 4); }