mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-20 19:35:37 +00:00
AS3: Jump deobfuscation improved
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.deobfuscation;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
|
||||
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;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* AVM2 Deobfuscator removing single assigned local registers.
|
||||
*
|
||||
* Example: var a = true; var b = false; ... if(a){ ...ok }else{ not executed }
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple {
|
||||
|
||||
//private final int executionLimit = 30000;
|
||||
@Override
|
||||
public void actionListParsed(ActionList actions, SWF swf) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deobfuscate(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException {
|
||||
|
||||
//body.getCode().markMappedOffsets();
|
||||
//removeUnreachableActions(body.getCode(), cpool, trait, minfo, body);
|
||||
AVM2Code code = body.getCode();
|
||||
|
||||
boolean found;
|
||||
do {
|
||||
found = false;
|
||||
Map<Integer, List<Integer>> refs = body.getCode().visitCode(body);
|
||||
loopi:
|
||||
for (int i = 0; i < code.code.size(); i++) {
|
||||
AVM2Instruction ins = code.code.get(i);
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
long targetAddr = ins.offset + ins.operands[0] + ins.getBytes().length;
|
||||
{
|
||||
for (int r : refs.get(i)) {
|
||||
if (r >= 0) { //Not Exception start/end
|
||||
AVM2Instruction srcIns = code.code.get(r);
|
||||
|
||||
if ((srcIns.definition instanceof JumpIns) || ((srcIns.definition instanceof IfTypeIns) && (r != i - 1))) {
|
||||
{
|
||||
int oldop = srcIns.operands[0];
|
||||
srcIns.operands[0] = (int) (targetAddr - (srcIns.offset + srcIns.getBytes().length));
|
||||
if (srcIns.operands[0] != oldop) {
|
||||
found = true;
|
||||
System.err.println("found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
removeUnreachableActions(body.getCode(), cpool, trait, minfo, body);
|
||||
} while (found);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,12 +14,14 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2;
|
||||
package com.jpexs.decompiler.flash.abc.avm2.deobfuscation;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
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;
|
||||
@@ -139,13 +141,6 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
AVM2Instruction action = code.code.get(idx);
|
||||
instructionsProcessed++;
|
||||
|
||||
|
||||
/*if (action.definition instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) action.definition).getRegisterId(action);//stack.peek().getResult().toString();
|
||||
if (!localData.localRegs.containsKey(regId)) {
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
action.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
|
||||
InstructionDefinition def = action.definition;
|
||||
|
||||
@@ -14,11 +14,14 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2;
|
||||
package com.jpexs.decompiler.flash.abc.avm2.deobfuscation;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.FixItemCounterTranslateStack;
|
||||
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;
|
||||
@@ -37,6 +40,11 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns;
|
||||
@@ -311,7 +319,14 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
EqualsIns.class,
|
||||
NotIns.class,
|
||||
IfTypeIns.class,
|
||||
JumpIns.class
|
||||
JumpIns.class,
|
||||
EqualsIns.class,
|
||||
LessEqualsIns.class,
|
||||
GreaterEqualsIns.class,
|
||||
GreaterThanIns.class,
|
||||
LessThanIns.class,
|
||||
StrictEqualsIns.class,
|
||||
PopIns.class
|
||||
};
|
||||
|
||||
boolean ok = false;
|
||||
@@ -20,10 +20,11 @@ import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.ABCInputStream;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2DeobfuscatorRegisters;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2DeobfuscatorSimple;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorRegisters;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorSimple;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.CodeStats;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorJumps;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
@@ -203,7 +204,7 @@ public final class MethodBody implements Cloneable {
|
||||
if (exportMode != ScriptExportMode.AS) {
|
||||
getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer);
|
||||
} else {
|
||||
//if (!path.contains("@")) {
|
||||
//if (!path.contains("RemoveAllPopup")) {
|
||||
if (!Configuration.decompile.get()) {
|
||||
writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine();
|
||||
return;
|
||||
@@ -247,7 +248,7 @@ public final class MethodBody implements Cloneable {
|
||||
if (exportMode != ScriptExportMode.AS) {
|
||||
getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer);
|
||||
} else {
|
||||
//if (!path.contains("@")) {
|
||||
//if (!path.contains("RemoveAllPopup")) {
|
||||
if (!Configuration.decompile.get()) {
|
||||
//writer.startMethod(this.method_info);
|
||||
writer.appendNoHilight(Helper.getDecompilationSkippedComment()).newLine();
|
||||
@@ -291,6 +292,8 @@ public final class MethodBody implements Cloneable {
|
||||
} else {
|
||||
new AVM2DeobfuscatorSimple().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b);
|
||||
new AVM2DeobfuscatorRegisters().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b);
|
||||
new AVM2DeobfuscatorJumps().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, method_info.get(this.method_info), b);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public class MethodInfo {
|
||||
}
|
||||
}
|
||||
|
||||
public int[] param_types;
|
||||
public int[] param_types = new int[]{};
|
||||
|
||||
public int ret_type;
|
||||
|
||||
@@ -74,9 +74,9 @@ public class MethodInfo {
|
||||
|
||||
public int flags;
|
||||
|
||||
public ValueKind[] optional;
|
||||
public ValueKind[] optional = new ValueKind[0];
|
||||
|
||||
public int[] paramNames;
|
||||
public int[] paramNames = new int[0];
|
||||
|
||||
private MethodBody body;
|
||||
|
||||
|
||||
@@ -431,11 +431,12 @@ public class Graph {
|
||||
TranslateStack stack = new TranslateStack(path);
|
||||
List<Loop> loops = new ArrayList<>();
|
||||
getLoops(localData, heads.get(0), loops, null);
|
||||
/*System.out.println("<loops>");
|
||||
/*1
|
||||
System.err.println("<loops>");
|
||||
for (Loop el : loops) {
|
||||
System.out.println(el);
|
||||
System..println(el);
|
||||
}
|
||||
System.out.println("</loops>");*/
|
||||
System.err.println("</loops>");*/
|
||||
getPrecontinues(path, localData, null, heads.get(0), allParts, loops, null);
|
||||
/*System.err.println("<loopspre>");
|
||||
for (Loop el : loops) {
|
||||
@@ -1378,7 +1379,7 @@ public class Graph {
|
||||
}
|
||||
if (el.phase != 1) {
|
||||
if (debugMode) {
|
||||
//System.err.println("ignoring loop "+el);
|
||||
System.err.println("ignoring loop " + el);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1418,18 +1419,9 @@ public class Graph {
|
||||
if (currentLoop != null) {
|
||||
currentLoop.phase = 0;
|
||||
}
|
||||
/*switch (part.stopPartType) {
|
||||
case AND_OR:
|
||||
part.setAndOrStack(stack); //Save stack for later use
|
||||
break;
|
||||
|
||||
case COMMONPART:
|
||||
part.setCommonPartStack(stack); //Save stack for later use
|
||||
break;
|
||||
|
||||
case NONE:
|
||||
break;
|
||||
}*/
|
||||
if (debugMode) {
|
||||
System.err.println("Stopped on part " + part);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1562,19 +1554,19 @@ public class Graph {
|
||||
|
||||
List<GraphPart> nps;
|
||||
nps = part.nextParts;
|
||||
boolean isEmpty = nps.get(0) == nps.get(1);
|
||||
|
||||
GraphPart next = getCommonPart(localData, nps, loops);
|
||||
TranslateStack trueStack = (TranslateStack) stack.clone();
|
||||
TranslateStack falseStack = (TranslateStack) stack.clone();
|
||||
trueStack.clear();
|
||||
falseStack.clear();
|
||||
/*int trueStackSizeBefore = trueStack.size();
|
||||
int falseStackSizeBefore = falseStack.size();
|
||||
*/
|
||||
boolean isEmpty = nps.get(0) == nps.get(1);
|
||||
|
||||
if (isEmpty) {
|
||||
next = nps.get(0);
|
||||
}
|
||||
boolean hasOntrue = nps.get(1) != next;
|
||||
boolean hasOnFalse = nps.get(0) != next;
|
||||
|
||||
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
|
||||
|
||||
@@ -1583,12 +1575,12 @@ public class Graph {
|
||||
}
|
||||
|
||||
List<GraphTargetItem> onTrue = new ArrayList<>();
|
||||
if (!isEmpty) {
|
||||
if (!isEmpty && hasOntrue) {
|
||||
onTrue = printGraph(visited, prepareBranchLocalData(localData), trueStack, allParts, part, nps.get(1), stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
|
||||
}
|
||||
List<GraphTargetItem> onFalse = new ArrayList<>();
|
||||
|
||||
if (!isEmpty) {
|
||||
if (!isEmpty && hasOnFalse) {
|
||||
onFalse = printGraph(visited, prepareBranchLocalData(localData), falseStack, allParts, part, nps.get(0), stopPart2, loops, null, staticOperation, path, recursionLevel + 1);
|
||||
}
|
||||
//List<GraphTargetItem> out2 = new ArrayList<>();
|
||||
|
||||
Reference in New Issue
Block a user