From 7eca256e3c053ef970729f0d9740577e4ad0ce13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sun, 11 Aug 2013 22:41:48 +0200 Subject: [PATCH] Issues #266: Unsuccessfull try to improve deobfuscation --- .../decompiler/flash/abc/avm2/AVM2Code.java | 3 +- .../avm2/instructions/AVM2Instruction.java | 5 ++ .../avm2/instructions/DeobfuscatePopIns.java | 30 +++++++ .../avm2/model/operations/AddAVM2Item.java | 2 +- .../flash/abc/avm2/parser/ASM3Parser.java | 7 ++ .../flash/abc/types/MethodBody.java | 2 +- .../jpexs/decompiler/flash/action/Action.java | 5 ++ .../action/special/ActionDeobfuscatePop.java | 5 ++ .../src/com/jpexs/decompiler/graph/Graph.java | 84 ++++++++++++++----- .../decompiler/graph/GraphSourceItem.java | 2 + 10 files changed, 121 insertions(+), 24 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/DeobfuscatePopIns.java 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 908d67b9d..267381587 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.CopyOutputStream; import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2Graph; import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2GraphSource; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf32Ins; @@ -796,7 +797,7 @@ public class AVM2Code implements Serializable { if (ins.definition instanceof IfTypeIns) { t = ""; for (int i = 0; i < -ins.definition.getStackDelta(ins, null/*IfTypeIns do not require ABCs*/); i++) { - t += new PopIns().instructionName + "\n"; + t += new DeobfuscatePopIns().instructionName + "\n"; } if (fixBranch == 0) { //jump t += new JumpIns().instructionName + " ofs" + Helper.formatAddress(ofs + ins.getBytes().length + ins.operands[0]); 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 d516e065b..aafb1e509 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 @@ -336,4 +336,9 @@ public class AVM2Instruction implements Serializable, GraphSourceItem { public int getFixBranch() { return fixedBranch; } + + @Override + public boolean isDeobfuscatePop() { + return definition instanceof DeobfuscatePopIns; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/DeobfuscatePopIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/DeobfuscatePopIns.java new file mode 100644 index 000000000..c84cad895 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/DeobfuscatePopIns.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions; + +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; + +/** + * + * @author JPEXS + */ +public class DeobfuscatePopIns extends PopIns { + + public DeobfuscatePopIns() { + instructionName = "ffdec_deobfuscatepop"; + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AddAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AddAVM2Item.java index cb1744894..8a94e9037 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AddAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AddAVM2Item.java @@ -52,7 +52,7 @@ public class AddAVM2Item extends BinaryOpItem { @Override public Object getResult() { if (EcmaScript.type(leftSide.getResult()) == EcmaType.STRING || EcmaScript.type(rightSide.getResult()) == EcmaType.STRING) { - return leftSide.getResult().toString() + rightSide.getResult().toString(); + return "" + leftSide.getResult() + rightSide.getResult(); } return EcmaScript.toNumber(leftSide.getResult()) + EcmaScript.toNumber(rightSide.getResult()); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/ASM3Parser.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/ASM3Parser.java index 6c4a9ea86..8ba718a13 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/ASM3Parser.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/ASM3Parser.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; @@ -287,6 +288,12 @@ public class ASM3Parser { break; } } + if (symb.value.toString().toLowerCase().equals("ffdec_deobfuscatepop")) { + lastIns = new AVM2Instruction(offset, new DeobfuscatePopIns(), new int[0], new byte[0]); + code.code.add(lastIns); + offset += lastIns.getBytes().length; + insFound = true; + } if (!insFound) { throw new ParseException("Invalid instruction name:" + (String) symb.value, lexer.yyline()); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 45bcdd748..657d31a75 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -36,7 +36,7 @@ import java.util.logging.Logger; public class MethodBody implements Cloneable, Serializable { - boolean debugMode = false; + boolean debugMode = true; public int method_info; public int max_stack; public int max_regs; diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index cef533c2b..a823ec23b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -1261,4 +1261,9 @@ public class Action implements GraphSourceItem { } return ret; } + + @Override + public boolean isDeobfuscatePop() { + return false; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/special/ActionDeobfuscatePop.java b/trunk/src/com/jpexs/decompiler/flash/action/special/ActionDeobfuscatePop.java index cdeab633c..9f5341d08 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/special/ActionDeobfuscatePop.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/special/ActionDeobfuscatePop.java @@ -42,4 +42,9 @@ public class ActionDeobfuscatePop extends ActionPop { } GraphTargetItem val = stack.pop(); } + + @Override + public boolean isDeobfuscatePop() { + return true; + } } diff --git a/trunk/src/com/jpexs/decompiler/graph/Graph.java b/trunk/src/com/jpexs/decompiler/graph/Graph.java index 883d16d3f..b4529acde 100644 --- a/trunk/src/com/jpexs/decompiler/graph/Graph.java +++ b/trunk/src/com/jpexs/decompiler/graph/Graph.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.graph; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.ecma.EcmaScript; import com.jpexs.decompiler.flash.helpers.Highlighting; @@ -546,10 +547,33 @@ public class Graph { return null; } - public GraphPart getNextNoJump(GraphPart part) { + public GraphPart getNextNoJump(GraphPart part, List localData) { while (code.get(part.start).isJump()) { part = part.getSubParts().get(0).nextParts.get(0); } + /*localData = prepareBranchLocalData(localData); + Stack st = new Stack<>(); + List output=new ArrayList<>(); + GraphPart startPart = part; + for (int i = part.start; i <= part.end; i++) { + GraphSourceItem src = code.get(i); + if (src.isJump()) { + part = part.nextParts.get(0); + if(st.isEmpty()){ + startPart = part; + } + i = part.start - 1; + continue; + } + try{ + src.translate(localData, st, output, SOP_USE_STATIC, ""); + }catch(Exception ex){ + return startPart; + } + if(!output.isEmpty()){ + return startPart; + } + }*/ return part; } @@ -573,11 +597,11 @@ public class Graph { } System.out.println("");*/ getPrecontinues(localData, null, heads.get(0), loops, null); - /*System.err.println(""); - for (Loop el : loops) { - System.err.println(el); - } - System.err.println("");//*/ + System.err.println(""); + for (Loop el : loops) { + System.err.println(el); + } + System.err.println("");//*/ List ret = printGraph(new ArrayList(), localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path); processIfs(ret); @@ -1124,16 +1148,25 @@ public class Graph { } if (part.nextParts.size() == 2) { - GraphPart next = getNextCommonPart(localData, part, loops);//part.getNextPartPath(loopContinues); + + List nps = new ArrayList<>(part.nextParts); + /*for(int i=0;i stopPart2 = new ArrayList<>(stopPart); if (next != null) { stopPart2.add(next); } - if (next != part.nextParts.get(0)) { - getLoops(localData, part.nextParts.get(0), loops, stopPart2, false, level + 1, visited); + if (next != nps.get(0)) { + getLoops(localData, nps.get(0), loops, stopPart2, false, level + 1, visited); } - if (next != part.nextParts.get(1)) { - getLoops(localData, part.nextParts.get(1), loops, stopPart2, false, level + 1, visited); + if (next != nps.get(1)) { + getLoops(localData, nps.get(1), loops, stopPart2, false, level + 1, visited); } if (next != null) { getLoops(localData, next, loops, stopPart, false, level, visited); @@ -1508,8 +1541,8 @@ public class Graph { */ if (part.nextParts.size() == 2) { if ((stack.size() >= 2) && (stack.get(stack.size() - 1) instanceof NotItem) && (((NotItem) (stack.get(stack.size() - 1))).getOriginal().getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { - GraphPart sp0 = getNextNoJump(part.nextParts.get(0)); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1)); + GraphPart sp0 = getNextNoJump(part.nextParts.get(0), localData); + GraphPart sp1 = getNextNoJump(part.nextParts.get(1), localData); boolean reversed = false; loopContinues = getLoopsContinues(loops); loopContinues.add(part);//??? @@ -1559,8 +1592,8 @@ public class Graph { parseNext = false; //return ret; } else if ((stack.size() >= 2) && (stack.get(stack.size() - 1).getNotCoerced() == stack.get(stack.size() - 2).getNotCoerced())) { - GraphPart sp0 = getNextNoJump(part.nextParts.get(0)); - GraphPart sp1 = getNextNoJump(part.nextParts.get(1)); + GraphPart sp0 = getNextNoJump(part.nextParts.get(0), localData); + GraphPart sp1 = getNextNoJump(part.nextParts.get(1), localData); boolean reversed = false; loopContinues = getLoopsContinues(loops); loopContinues.add(part);//??? @@ -1618,7 +1651,7 @@ public class Graph { if (parseNext) { - if (part.nextParts.size() > 2) {//alchemy direct switch + if (false && part.nextParts.size() > 2) {//alchemy direct switch GraphPart next = getMostCommonPart(localData, part.nextParts, loops); List vis = new ArrayList<>(); GraphTargetItem switchedItem = stack.pop(); @@ -1695,7 +1728,16 @@ public class Graph { } } if (nextOnePart == null) { - GraphPart next = getNextCommonPart(localData, part, loops); + + List nps = new ArrayList<>(part.nextParts); + /*for(int i=0;i trueStack = (Stack) stack.clone(); @@ -1704,10 +1746,10 @@ public class Graph { int trueStackSizeBefore = trueStack.size(); int falseStackSizeBefore = falseStack.size(); List onTrue = new ArrayList<>(); - boolean isEmpty = part.nextParts.get(0) == part.nextParts.get(1); + boolean isEmpty = nps.get(0) == nps.get(1); if (isEmpty) { - next = part.nextParts.get(0); + next = nps.get(0); } List stopPart2 = new ArrayList<>(stopPart); @@ -1715,12 +1757,12 @@ public class Graph { stopPart2.add(next); } if (!isEmpty) { - onTrue = printGraph(visited, prepareBranchLocalData(localData), trueStack, allParts, part, part.nextParts.get(1), stopPart2, loops, staticOperation, path); + onTrue = printGraph(visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, staticOperation, path); } List onFalse = new ArrayList<>(); if (!isEmpty) { - onFalse = printGraph(visited, prepareBranchLocalData(localData), falseStack, allParts, part, part.nextParts.get(0), stopPart2, loops, staticOperation, path); + onFalse = printGraph(visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, staticOperation, path); } if (isEmpty(onTrue) && isEmpty(onFalse) && (trueStack.size() > trueStackSizeBefore) && (falseStack.size() > falseStackSizeBefore)) { stack.push(new TernarOpItem(null, expr, trueStack.pop(), falseStack.pop())); diff --git a/trunk/src/com/jpexs/decompiler/graph/GraphSourceItem.java b/trunk/src/com/jpexs/decompiler/graph/GraphSourceItem.java index 024b9f51d..bd4a42850 100644 --- a/trunk/src/com/jpexs/decompiler/graph/GraphSourceItem.java +++ b/trunk/src/com/jpexs/decompiler/graph/GraphSourceItem.java @@ -47,4 +47,6 @@ public interface GraphSourceItem extends Serializable { public void setFixBranch(int pos); public int getFixBranch(); + + public boolean isDeobfuscatePop(); }