mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-25 10:55:40 +00:00
Old deobfuscation mode removed
This commit is contained in:
@@ -2341,7 +2341,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
public static ActionList getCachedActionList(ASMSource src, final List<DisassemblyListener> listeners) throws InterruptedException {
|
||||
synchronized (src) {
|
||||
SWF swf = src.getSwf();
|
||||
int deobfuscationMode = Configuration.autoDeobfuscate.get() ? (Configuration.deobfuscationOldMode.get() ? 0 : 1) : -1;
|
||||
int deobfuscationMode = Configuration.autoDeobfuscate.get() ? 1 : 0;
|
||||
if (swf != null && swf.as2PcodeCache.contains(src)) {
|
||||
ActionList result = swf.as2PcodeCache.get(src);
|
||||
if (result.deobfuscationMode == deobfuscationMode) {
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.jpexs.decompiler.flash.abc.avm2;
|
||||
import com.jpexs.decompiler.flash.EndOfStreamException;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.ABCInputStream;
|
||||
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
|
||||
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorGetSet;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorJumps;
|
||||
@@ -31,7 +30,6 @@ 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.AVM2Instructions;
|
||||
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.UnknownInstruction;
|
||||
@@ -245,9 +243,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSLateIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXAttrIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXElemIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.HasNextAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item;
|
||||
@@ -278,7 +274,6 @@ 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.dumpview.DumpInfo;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
@@ -287,13 +282,10 @@ import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
|
||||
import com.jpexs.decompiler.graph.Block;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
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;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
import com.jpexs.decompiler.graph.model.ExitItem;
|
||||
@@ -1053,6 +1045,14 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
public void markMappedOffsets() {
|
||||
int ofs = 0;
|
||||
for (int i = 0; i < code.size(); i++) {
|
||||
code.get(i).mappedOffset = ofs;
|
||||
ofs += code.get(i).getBytesLength();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
@@ -1290,26 +1290,13 @@ public class AVM2Code implements Cloneable {
|
||||
if (markOffsets) {
|
||||
writer.append("", ins.mappedOffset > -1 ? ins.mappedOffset : ofs);
|
||||
}
|
||||
int fixBranch = ins.getFixBranch();
|
||||
if (fixBranch > -1) {
|
||||
if (ins.definition instanceof IfTypeIns) {
|
||||
for (int i = 0; i < -ins.definition.getStackDelta(ins, null/*IfTypeIns do not require ABCs*/); i++) {
|
||||
writer.appendNoHilight(DeobfuscatePopIns.NAME).newLine();
|
||||
}
|
||||
if (fixBranch == 0) { // jump
|
||||
writer.appendNoHilight(JumpIns.NAME + " ofs" + Helper.formatAddress(ofs + ins.getBytesLength() + ins.operands[0]));
|
||||
} else {
|
||||
// nojump, ignore
|
||||
}
|
||||
}
|
||||
// TODO: lookupswitch ?
|
||||
|
||||
if (ins.changeJumpTo > -1) {
|
||||
writer.appendNoHilight(ins.definition.instructionName + " ofs" + Helper.formatAddress(pos2adr(ins.changeJumpTo)));
|
||||
} else {
|
||||
if (ins.changeJumpTo > -1) {
|
||||
writer.appendNoHilight(ins.definition.instructionName + " ofs" + Helper.formatAddress(pos2adr(ins.changeJumpTo)));
|
||||
} else {
|
||||
writer.appendNoHilight(ins.toStringNoAddress(constants, new ArrayList<>()));
|
||||
}
|
||||
writer.appendNoHilight(ins.toStringNoAddress(constants, new ArrayList<>()));
|
||||
}
|
||||
|
||||
writer.newLine();
|
||||
outputMap.add(ip);
|
||||
}
|
||||
@@ -2288,71 +2275,21 @@ public class AVM2Code implements Cloneable {
|
||||
//checkValidOffsets(body);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static AVM2LocalData prepareBranchLocalData(AVM2LocalData localData) {
|
||||
AVM2LocalData ret = new AVM2LocalData();
|
||||
ret.isStatic = localData.isStatic;
|
||||
ret.classIndex = localData.classIndex;
|
||||
ret.localRegs = new HashMap<>(localData.localRegs);
|
||||
ret.scopeStack = (ScopeStack) (localData.scopeStack).clone();
|
||||
ret.methodBody = localData.methodBody;
|
||||
ret.abc = localData.abc;
|
||||
ret.localRegNames = localData.localRegNames;
|
||||
ret.fullyQualifiedNames = localData.fullyQualifiedNames;
|
||||
ret.parsedExceptions = localData.parsedExceptions;
|
||||
ret.finallyJumps = localData.finallyJumps;
|
||||
ret.ignoredSwitches = localData.ignoredSwitches;
|
||||
ret.ignoredSwitches2 = localData.ignoredSwitches2;
|
||||
ret.scriptIndex = localData.scriptIndex;
|
||||
ret.localRegAssignmentIps = localData.localRegAssignmentIps;
|
||||
ret.ip = localData.ip;
|
||||
ret.refs = localData.refs;
|
||||
ret.code = localData.code;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int removeTrapsOld(Trait trait, int methodInfo, MethodBody body, ABC abc, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException {
|
||||
removeDeadCode(body);
|
||||
AVM2LocalData localData = new AVM2LocalData();
|
||||
localData.isStatic = isStatic;
|
||||
localData.classIndex = classIndex;
|
||||
localData.localRegs = new HashMap<>();
|
||||
localData.scopeStack = new ScopeStack();
|
||||
localData.methodBody = body;
|
||||
localData.abc = abc;
|
||||
localData.localRegNames = body.getLocalRegNames(abc);
|
||||
localData.scriptIndex = scriptIndex;
|
||||
localData.ip = 0;
|
||||
HashMap<Integer, List<Integer>> refs = visitCode(body);
|
||||
localData.refs = refs;
|
||||
localData.code = this;
|
||||
int ret = 0;
|
||||
ret += removeTrapsOld(trait, methodInfo, body, localData, new AVM2GraphSource(this, false, -1, -1, new HashMap<>(), new ScopeStack(), abc, body, new HashMap<>(), new ArrayList<>(), new HashMap<>(), refs), 0, path, refs);
|
||||
removeIgnored(body);
|
||||
removeDeadCode(body);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int removeTraps(Trait trait, int methodInfo, MethodBody body, ABC abc, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException {
|
||||
if (Configuration.deobfuscationOldMode.get()) {
|
||||
return removeTrapsOld(trait, methodInfo, body, abc, scriptIndex, classIndex, isStatic, path);
|
||||
} else {
|
||||
SWFDecompilerPlugin.fireAvm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorGetSet")) {
|
||||
new AVM2DeobfuscatorGetSet().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
}
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorSimple")) {
|
||||
new AVM2DeobfuscatorSimpleOld().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
}
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorRegisters")) {
|
||||
new AVM2DeobfuscatorRegistersOld().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
}
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorJumps")) {
|
||||
new AVM2DeobfuscatorJumps().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
}
|
||||
return 1;
|
||||
SWFDecompilerPlugin.fireAvm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorGetSet")) {
|
||||
new AVM2DeobfuscatorGetSet().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
}
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorSimple")) {
|
||||
new AVM2DeobfuscatorSimpleOld().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
}
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorRegisters")) {
|
||||
new AVM2DeobfuscatorRegistersOld().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
}
|
||||
try (Statistics s = new Statistics("AVM2DeobfuscatorJumps")) {
|
||||
new AVM2DeobfuscatorJumps().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
private void handleRegister(CodeStats stats, int reg) {
|
||||
@@ -2495,10 +2432,11 @@ public class AVM2Code implements Cloneable {
|
||||
nextIp = adr2pos(pos2adr(nextIp) + code.get(maxIp).operands[0]);
|
||||
}
|
||||
if (nextIp < stats.instructionStats.length) {
|
||||
int origScopePos = stats.instructionStats[nextIp].scopepos;
|
||||
int origStackPos = stats.instructionStats[nextIp].stackpos;
|
||||
InstructionStats nextIpStat = stats.instructionStats[nextIp];
|
||||
int origScopePos = nextIpStat.scopepos;
|
||||
int origStackPos = nextIpStat.stackpos;
|
||||
|
||||
if (prevStart == ex.start && ex.isFinally() && !code.get(nextIp).isExit() && stats.instructionStats[nextIp].seen) {
|
||||
if (prevStart == ex.start && ex.isFinally() && !code.get(nextIp).isExit() && nextIpStat.seen) {
|
||||
for (int i = 0; i < stats.instructionStats.length; i++) {
|
||||
stats.instructionStats[i].seen = false;
|
||||
}
|
||||
@@ -2612,7 +2550,7 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreControlFlow(int ip, HashMap<Integer, List<Integer>> refs, int[] visited2, HashMap<Integer, List<Object>> appended) throws ConvertException {
|
||||
private void restoreControlFlow(int ip, HashMap<Integer, List<Integer>> refs, int[] visited2, HashMap<Integer, List<Object>> appended) throws ConvertException {
|
||||
List<Object> buf = new ArrayList<>();
|
||||
boolean cont = false;
|
||||
int continueip;
|
||||
@@ -2832,25 +2770,6 @@ public class AVM2Code implements Cloneable {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public void markMappedOffsets() {
|
||||
int ofs = 0;
|
||||
for (int i = 0; i < code.size(); i++) {
|
||||
code.get(i).mappedOffset = ofs;
|
||||
ofs += code.get(i).getBytesLength();
|
||||
}
|
||||
}
|
||||
|
||||
private static class Decision {
|
||||
|
||||
public boolean jumpUsed = false;
|
||||
|
||||
public boolean skipUsed = false;
|
||||
|
||||
public Set<Integer> casesUsed = new HashSet<>();
|
||||
|
||||
HashMap<Integer, GraphTargetItem> registers = new HashMap<>();
|
||||
}
|
||||
|
||||
private static int getMostCommonIp(AVM2GraphSource code, List<Integer> branches) {
|
||||
List<List<Integer>> reachable = new ArrayList<>();
|
||||
for (int i = 0; i < branches.size(); i++) {
|
||||
@@ -2994,294 +2913,6 @@ public class AVM2Code implements Cloneable {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static int removeTrapsOld(HashMap<Integer, List<Integer>> refs, boolean secondPass, boolean indeterminate, AVM2LocalData localData, TranslateStack stack, List<GraphTargetItem> output, AVM2GraphSource code, int ip, HashMap<Integer, Integer> visited, HashMap<Integer, HashMap<Integer, GraphTargetItem>> visitedStates, HashMap<AVM2Instruction, Decision> decisions, String path, int recursionLevel) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
if (recursionLevel > code.size() + 1) {
|
||||
throw new TranslateException("removeTraps max recursion level reached.");
|
||||
}
|
||||
boolean debugMode = false;
|
||||
int ret = 0;
|
||||
iploop:
|
||||
while ((ip > -1) && ip < code.size()) {
|
||||
|
||||
if (false) { //useVisited) {
|
||||
if (visited.containsKey(ip)) {
|
||||
break;
|
||||
}
|
||||
if (!visited.containsKey(ip)) {
|
||||
visited.put(ip, 0);
|
||||
} else {
|
||||
visited.put(ip, visited.get(ip) + 1);
|
||||
}
|
||||
} else {
|
||||
HashMap<Integer, GraphTargetItem> currentState = localData.localRegs;
|
||||
|
||||
if (visitedStates.containsKey(ip)) {
|
||||
HashMap<Integer, GraphTargetItem> lastState = visitedStates.get(ip);
|
||||
if (lastState.equals(currentState)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
visitedStates.put(ip, (HashMap<Integer, GraphTargetItem>) currentState.clone());
|
||||
|
||||
}
|
||||
|
||||
int curVisited;
|
||||
if (!visited.containsKey(ip)) {
|
||||
curVisited = 1;
|
||||
} else {
|
||||
curVisited = visited.get(ip) + 1;
|
||||
}
|
||||
visited.put(ip, curVisited);
|
||||
|
||||
List<Integer> r = refs.get(ip);
|
||||
/*if (r != null) {
|
||||
if (r.size() > 1) {
|
||||
if (!stack.isEmpty()) {
|
||||
GraphTargetItem it = stack.pop();
|
||||
stack.push(new NotCompileTimeAVM2Item(null, it));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
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 (ins.definition instanceof NewArrayIns) {
|
||||
if (ins.operands[0] > stack.size()) {
|
||||
ins.setIgnored(true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (ins.isIgnored()) {
|
||||
ip++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (debugMode) {
|
||||
System.out.println((indeterminate ? "useV " : "") + (secondPass ? "secondPass " : "") + "Visit " + ip + ": " + ins + " stack:" + stack.toString());
|
||||
HashMap<Integer, GraphTargetItem> registers = localData.localRegs;
|
||||
System.out.print("Registers:");
|
||||
for (int reg : registers.keySet()) {
|
||||
try {
|
||||
System.out.print(" r" + reg + ": " + registers.get(reg).getResult());
|
||||
} catch (NullPointerException npe) {
|
||||
System.out.print(" r" + reg + ": " + "null");
|
||||
}
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
if (secondPass) {
|
||||
/*if ((ins instanceof AVM2Instruction) && (((AVM2Instruction) ins).definition instanceof PopIns)) {
|
||||
GraphTargetItem top = stack.peek();
|
||||
for (GraphSourceItemPos p : top.getNeededSources()) {
|
||||
if (p == null) {
|
||||
continue;
|
||||
}
|
||||
if (p.item == null) {
|
||||
continue;
|
||||
}
|
||||
if (p.item.isIgnored()) {
|
||||
ins.setIgnored(true, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if (ins.definition instanceof NewFunctionIns) {
|
||||
stack.push(new BooleanAVM2Item(null, null, true));
|
||||
} else {
|
||||
localData.ip = ip;
|
||||
ins.translate(localData, stack, output, Graph.SOP_USE_STATIC, path);
|
||||
}
|
||||
|
||||
if (ins.definition instanceof SetLocalTypeIns) {
|
||||
SetLocalTypeIns slt = (SetLocalTypeIns) ins.definition;
|
||||
int regId = slt.getRegisterId(ins);
|
||||
if (indeterminate) {
|
||||
HashMap<Integer, GraphTargetItem> registers = localData.localRegs;
|
||||
GraphTargetItem regVal = registers.get(regId);
|
||||
if (regVal.isCompileTime()) {
|
||||
registers.put(regId, new NotCompileTimeItem(null, null, regVal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ins.isExit()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins.isBranch() || ins.isJump()) {
|
||||
List<Integer> branches = ins.getBranches(code);
|
||||
if (ins.definition instanceof IfTypeIns
|
||||
&& (!(ins.definition instanceof JumpIns))
|
||||
&& (!stack.isEmpty())
|
||||
&& (stack.peek().isCompileTime())
|
||||
&& (!stack.peek().hasSideEffect())) {
|
||||
boolean condition = EcmaScript.toBoolean(stack.peek().getResult());
|
||||
if (debugMode) {
|
||||
if (condition) {
|
||||
System.out.println("JUMP");
|
||||
} else {
|
||||
System.out.println("SKIP");
|
||||
}
|
||||
}
|
||||
Decision dec = new Decision();
|
||||
if (decisions.containsKey(ins)) {
|
||||
dec = decisions.get(ins);
|
||||
} else {
|
||||
decisions.put(ins, dec);
|
||||
}
|
||||
if (condition) {
|
||||
dec.jumpUsed = true;
|
||||
} else {
|
||||
dec.skipUsed = true;
|
||||
}
|
||||
|
||||
if (branches.size() > 1) {
|
||||
if (secondPass) {
|
||||
if (condition && (dec.jumpUsed) && (!dec.skipUsed)) {
|
||||
ins.setFixBranch(0);
|
||||
//ins.definition = AVM2Code.instructionSet[AVM2Instructions.Jump];
|
||||
}
|
||||
if ((!condition) && (!dec.jumpUsed) && (dec.skipUsed)) {
|
||||
ins.setFixBranch(1);
|
||||
//ins.setIgnored(true, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
GraphTargetItem tar = stack.pop();
|
||||
/*if (secondPass && (dec.jumpUsed != dec.skipUsed)) {
|
||||
for (GraphSourceItemPos pos : tar.getNeededSources()) {
|
||||
if (pos.item instanceof AVM2Instruction) {
|
||||
if (((AVM2Instruction) pos.item).definition instanceof DupIns) {
|
||||
pos.item.setIgnored(true, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pos.item != ins) {
|
||||
pos.item.setIgnored(true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
if (branches.size() == 1) {
|
||||
ip = branches.get(0);
|
||||
} else {
|
||||
ip = condition ? branches.get(0) : branches.get(1);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
if (ins.isBranch() && (!ins.isJump())) {
|
||||
GraphTargetItem top = stack.pop();
|
||||
|
||||
Decision dec = new Decision();
|
||||
if (decisions.containsKey(ins)) {
|
||||
dec = decisions.get(ins);
|
||||
} else {
|
||||
decisions.put(ins, dec);
|
||||
}
|
||||
HashMap<Integer, GraphTargetItem> registers = localData.localRegs;
|
||||
boolean regChanged = false;
|
||||
if (!dec.registers.isEmpty()) {
|
||||
if (dec.registers.size() != registers.size()) {
|
||||
regChanged = true;
|
||||
} else {
|
||||
for (int reg : registers.keySet()) {
|
||||
if (!dec.registers.containsKey(reg)) {
|
||||
regChanged = true;
|
||||
break;
|
||||
}
|
||||
if (!registers.get(reg).isCompileTime() && dec.registers.get(reg).isCompileTime()) {
|
||||
regChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dec.registers.putAll(registers);
|
||||
dec.jumpUsed = true;
|
||||
dec.skipUsed = true;
|
||||
|
||||
if (!regChanged && ((!(top instanceof HasNextAVM2Item) && curVisited > 1) || (curVisited > 2))) {
|
||||
for (int b : branches) {
|
||||
int visc = 0;
|
||||
if (visited.containsKey(b)) {
|
||||
visc = visited.get(b);
|
||||
}
|
||||
if (visc == 0) {//<curVisited){
|
||||
ip = b;
|
||||
continue iploop;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
indeterminate = true;
|
||||
}
|
||||
|
||||
for (int b : branches) {
|
||||
TranslateStack brStack = (TranslateStack) stack.clone();
|
||||
if (b >= 0) { //useVisited || (!ins.isJump())
|
||||
ret += removeTrapsOld(refs, secondPass, indeterminate, prepareBranchLocalData(localData), brStack, output, code, b, visited, visitedStates, decisions, path, recursionLevel + 1);
|
||||
} else {
|
||||
if (debugMode) {
|
||||
System.out.println("Negative branch:" + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
ip++;
|
||||
}
|
||||
if (ip < 0 && debugMode) {
|
||||
System.out.println("Visited Negative: " + ip);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int removeTrapsOld(Trait trait, int methodInfo, MethodBody body, AVM2LocalData localData, AVM2GraphSource code, int addr, String path, HashMap<Integer, List<Integer>> refs) throws InterruptedException {
|
||||
HashMap<AVM2Instruction, AVM2Code.Decision> decisions = new HashMap<>();
|
||||
removeTrapsOld(refs, false, false, localData, new TranslateStack(path), new ArrayList<>(), code, code.adr2pos(addr), new HashMap<>(), new HashMap<>(), decisions, path, 0);
|
||||
int cnt = 0;
|
||||
for (AVM2Instruction src : decisions.keySet()) {
|
||||
Decision dec = decisions.get(src);
|
||||
if (dec != null) {
|
||||
if (src.definition instanceof LookupSwitchIns) {
|
||||
if (dec.casesUsed.size() == 1) {
|
||||
for (int c : dec.casesUsed) {
|
||||
src.setFixBranch(c);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dec.jumpUsed && !dec.skipUsed) {
|
||||
src.setFixBranch(0);
|
||||
cnt++;
|
||||
}
|
||||
if (!dec.jumpUsed && dec.skipUsed) {
|
||||
src.setFixBranch(1);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
code.getCode().removeIgnored(body);
|
||||
return cnt;
|
||||
}
|
||||
/*public static int removeTraps(AVM2LocalData localData, AVM2GraphSource code, int addr) {
|
||||
AVM2Graph.translateViaGraph(localData, "", code, new ArrayList<Integer>(), Graph.SOP_REMOVE_STATIC);
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public AVM2Code clone() {
|
||||
try {
|
||||
|
||||
@@ -57,6 +57,8 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
|
||||
public int changeJumpTo = -1;
|
||||
|
||||
public List<Object> replaceWith;
|
||||
|
||||
private int line;
|
||||
|
||||
private String file;
|
||||
@@ -329,8 +331,6 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
return s;
|
||||
}
|
||||
|
||||
public List<Object> replaceWith;
|
||||
|
||||
@Override
|
||||
public void translate(BaseLocalData localData, TranslateStack stack, List<GraphTargetItem> output, int staticOperation, String path) throws InterruptedException {
|
||||
AVM2LocalData aLocalData = (AVM2LocalData) localData;
|
||||
@@ -363,14 +363,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
|
||||
@Override
|
||||
public boolean isJump() {
|
||||
return (definition instanceof JumpIns) || (fixedBranch > -1);
|
||||
return definition instanceof JumpIns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBranch() {
|
||||
if (fixedBranch > -1) {
|
||||
return false;
|
||||
}
|
||||
return (definition instanceof IfTypeIns) || (definition instanceof LookupSwitchIns);
|
||||
}
|
||||
|
||||
@@ -389,23 +386,15 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
List<Integer> ret = new ArrayList<>();
|
||||
if (definition instanceof IfTypeIns) {
|
||||
|
||||
if (fixedBranch == -1 || fixedBranch == 0) {
|
||||
ret.add(code.adr2pos(offset + getBytesLength() + operands[0]));
|
||||
}
|
||||
ret.add(code.adr2pos(offset + getBytesLength() + operands[0]));
|
||||
if (!(definition instanceof JumpIns)) {
|
||||
if (fixedBranch == -1 || fixedBranch == 1) {
|
||||
ret.add(code.adr2pos(offset + getBytesLength()));
|
||||
}
|
||||
ret.add(code.adr2pos(offset + getBytesLength()));
|
||||
}
|
||||
}
|
||||
if (definition instanceof LookupSwitchIns) {
|
||||
if (fixedBranch == -1 || fixedBranch == 0) {
|
||||
ret.add(code.adr2pos(offset + operands[0]));
|
||||
}
|
||||
ret.add(code.adr2pos(offset + operands[0]));
|
||||
for (int k = 2; k < operands.length; k++) {
|
||||
if (fixedBranch == -1 || fixedBranch == k - 1) {
|
||||
ret.add(code.adr2pos(offset + operands[k]));
|
||||
}
|
||||
ret.add(code.adr2pos(offset + operands[k]));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -421,16 +410,6 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
this.ignored = ignored;
|
||||
}
|
||||
|
||||
public void setFixBranch(int pos) {
|
||||
this.fixedBranch = pos;
|
||||
}
|
||||
|
||||
private int fixedBranch = -1;
|
||||
|
||||
public int getFixBranch() {
|
||||
return fixedBranch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeobfuscatePop() {
|
||||
return definition instanceof DeobfuscatePopIns;
|
||||
|
||||
@@ -32,6 +32,6 @@ public class ConvertData {
|
||||
public Map<TraitSlotConst, AssignedValue> assignedValues = new HashMap<>();
|
||||
|
||||
public ConvertData() {
|
||||
deobfuscationMode = Configuration.autoDeobfuscate.get() ? (Configuration.deobfuscationOldMode.get() ? 0 : 1) : -1;
|
||||
deobfuscationMode = Configuration.autoDeobfuscate.get() ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ public final class MethodBody implements Cloneable {
|
||||
code.markMappedOffsets();
|
||||
code.fixJumps(path, body);
|
||||
|
||||
if (convertData.deobfuscationMode != -1) {
|
||||
if (convertData.deobfuscationMode != 0) {
|
||||
try {
|
||||
code.removeTraps(trait, method_info, body, abc, scriptIndex, classIndex, isStatic, path);
|
||||
} catch (ThreadDeath | InterruptedException ex) {
|
||||
@@ -405,7 +405,7 @@ public final class MethodBody implements Cloneable {
|
||||
|
||||
public String toSource() {
|
||||
ConvertData convertData = new ConvertData();
|
||||
convertData.deobfuscationMode = -1;
|
||||
convertData.deobfuscationMode = 0;
|
||||
try {
|
||||
convert(convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false);
|
||||
|
||||
@@ -838,8 +838,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC;
|
||||
List<GraphTargetItem> tree = actionsToTree(new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path);
|
||||
SWFDecompilerPlugin.fireActionTreeCreated(tree, swf);
|
||||
int deobfuscationMode = Configuration.autoDeobfuscate.get() ? (Configuration.deobfuscationOldMode.get() ? 0 : 1) : -1;
|
||||
if (deobfuscationMode == 1) {
|
||||
if (Configuration.autoDeobfuscate.get()) {
|
||||
new ActionDeobfuscator().actionTreeCreated(tree, swf);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,45 +20,26 @@ import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator;
|
||||
import com.jpexs.decompiler.flash.action.model.ConstantPool;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionEnd;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionNop;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionStore;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionEquals;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionIf;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionJump;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionPush;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister;
|
||||
import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.NotCompileTimeItem;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.stat.Statistics;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Scanner;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -169,17 +150,9 @@ public class ActionListReader {
|
||||
actions = fixActionList(actions, null);
|
||||
}
|
||||
|
||||
if (deobfuscationMode == 0) {
|
||||
if (deobfuscationMode == 1) {
|
||||
try {
|
||||
actions = deobfuscateActionListOld(listeners, actions, version, 0, path);
|
||||
updateActionLengths(actions);
|
||||
} catch (OutOfMemoryError | StackOverflowError | TranslateException ex) {
|
||||
// keep orignal (not deobfuscated) actions
|
||||
logger.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
} else if (deobfuscationMode == 1) {
|
||||
try {
|
||||
try (Statistics s = new Statistics("ActionDeobfuscatorSimpleFast")) {
|
||||
try (Statistics s = new Statistics("ActionDeobfuscator")) {
|
||||
new ActionDeobfuscator().actionListParsed(actions, sis.getSwf());
|
||||
}
|
||||
} catch (ThreadDeath | InterruptedException ex) {
|
||||
@@ -249,81 +222,6 @@ public class ActionListReader {
|
||||
return new ArrayList<>(actionMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads list of actions from the stream. Reading ends with
|
||||
* ActionEndFlag(=0) or end of the stream.
|
||||
*
|
||||
* @param listeners
|
||||
* @param actions
|
||||
* @param version
|
||||
* @param ip
|
||||
* @param path
|
||||
* @return List of actions
|
||||
* @throws IOException
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
private static ActionList deobfuscateActionListOld(List<DisassemblyListener> listeners, ActionList actions, int version, int ip, String path) throws IOException, InterruptedException {
|
||||
if (actions.isEmpty()) {
|
||||
return actions;
|
||||
}
|
||||
|
||||
Action lastAction = actions.get(actions.size() - 1);
|
||||
int endIp = (int) lastAction.getAddress();
|
||||
|
||||
List<Action> retMap = new ArrayList<>(endIp);
|
||||
for (int i = 0; i < endIp; i++) {
|
||||
retMap.add(null);
|
||||
}
|
||||
List<Action> actionMap = new ArrayList<>(endIp + 1);
|
||||
for (int i = 0; i <= endIp; i++) {
|
||||
actionMap.add(null);
|
||||
}
|
||||
for (Action a : actions) {
|
||||
actionMap.set((int) a.getAddress(), a);
|
||||
}
|
||||
|
||||
int maxRecursionLevel = 0;
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Action a = actions.get(i);
|
||||
if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) {
|
||||
maxRecursionLevel++;
|
||||
}
|
||||
if (a instanceof ActionIf) {
|
||||
ActionIf aif = (ActionIf) a;
|
||||
aif.ignoreUsed = false;
|
||||
aif.jumpUsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
deobfustaceActionListAtPosRecursiveOld(listeners,
|
||||
new ArrayList<>(),
|
||||
new HashMap<>(),
|
||||
new ActionLocalData(),
|
||||
new TranslateStack(path),
|
||||
new ConstantPool(),
|
||||
actionMap, ip, retMap, ip, endIp, path,
|
||||
new HashMap<>(), false,
|
||||
new HashMap<>(),
|
||||
version, 0, maxRecursionLevel);
|
||||
|
||||
ActionList ret = new ActionList();
|
||||
Action last = null;
|
||||
for (Action a : retMap) {
|
||||
if (a != last && a != null) {
|
||||
ret.add(a);
|
||||
}
|
||||
last = a;
|
||||
}
|
||||
ret.removeNops();
|
||||
ActionList reta = new ActionList();
|
||||
for (Object o : ret) {
|
||||
if (o instanceof Action) {
|
||||
reta.add((Action) o);
|
||||
}
|
||||
}
|
||||
return reta;
|
||||
}
|
||||
|
||||
private static long getNearAddress(ActionList actions, long address, boolean next) {
|
||||
int min = 0;
|
||||
int max = actions.size() - 1;
|
||||
@@ -997,252 +895,4 @@ public class ActionListReader {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void deobfustaceActionListAtPosRecursiveOld(List<DisassemblyListener> listeners, List<GraphTargetItem> output, HashMap<Long, List<GraphSourceItemContainer>> containers, ActionLocalData localData, TranslateStack stack, ConstantPool cpool, List<Action> actions, int ip, List<Action> ret, int startIp, int endip, String path, Map<Integer, Integer> visited, boolean indeterminate, Map<Integer, HashMap<String, GraphTargetItem>> decisionStates, int version, int recursionLevel, int maxRecursionLevel) throws IOException, InterruptedException {
|
||||
boolean debugMode = false;
|
||||
boolean decideBranch = false;
|
||||
|
||||
if (recursionLevel > maxRecursionLevel + 1) {
|
||||
throw new TranslateException("deobfustaceActionListAtPosRecursive max recursion level reached.");
|
||||
}
|
||||
|
||||
Action a;
|
||||
Scanner sc = null;
|
||||
loopip:
|
||||
while (((endip == -1) || (endip > ip)) && (a = actions.get(ip)) != null) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
int actionLen = a.getTotalActionLength();
|
||||
if (!visited.containsKey(ip)) {
|
||||
visited.put(ip, 0);
|
||||
}
|
||||
int curVisited = visited.get(ip);
|
||||
curVisited++;
|
||||
visited.put(ip, curVisited);
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
listeners.get(i).progressDeobfuscating(ip, actions.size());
|
||||
}
|
||||
int info = a.getTotalActionLength();
|
||||
|
||||
if (a instanceof ActionPush) {
|
||||
if (cpool != null) {
|
||||
((ActionPush) a).constantPool = cpool.constants;
|
||||
}
|
||||
}
|
||||
|
||||
if (debugMode) {
|
||||
String atos = a.getASMSource(new ActionList(), new HashSet<>(), ScriptExportMode.PCODE);
|
||||
if (a instanceof GraphSourceItemContainer) {
|
||||
atos = a.toString();
|
||||
}
|
||||
System.err.println("readActionListAtPos ip: " + (ip - startIp) + " (0x" + Helper.formatAddress(ip - startIp) + ") " + " action(len " + a.actionLength + "): " + atos + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Helper.stackToString(stack, LocalData.create(cpool)) + " " + Helper.byteArrToString(a.getBytes(version)));
|
||||
System.err.print("variables: ");
|
||||
for (Map.Entry<String, GraphTargetItem> v : localData.variables.entrySet()) {
|
||||
System.err.print("'" + v + "' = " + v.getValue().toString(LocalData.create(cpool)) + ", ");
|
||||
}
|
||||
System.err.println();
|
||||
String add = "";
|
||||
if (a instanceof ActionIf) {
|
||||
add = " change: " + ((ActionIf) a).getJumpOffset();
|
||||
}
|
||||
if (a instanceof ActionJump) {
|
||||
add = " change: " + ((ActionJump) a).getJumpOffset();
|
||||
}
|
||||
System.err.println(add);
|
||||
}
|
||||
|
||||
int newip = -1;
|
||||
|
||||
if (a instanceof ActionConstantPool) {
|
||||
if (cpool == null) {
|
||||
cpool = new ConstantPool();
|
||||
}
|
||||
cpool.setNew(((ActionConstantPool) a).constantPool);
|
||||
}
|
||||
ActionIf aif = null;
|
||||
boolean goaif = false;
|
||||
if (!a.isIgnored()) {
|
||||
String varname = null;
|
||||
if (a instanceof StoreTypeAction) {
|
||||
StoreTypeAction sta = (StoreTypeAction) a;
|
||||
varname = sta.getVariableName(stack, cpool);
|
||||
}
|
||||
|
||||
try {
|
||||
if (a instanceof ActionIf) {
|
||||
aif = (ActionIf) a;
|
||||
|
||||
GraphTargetItem top = stack.pop();
|
||||
int nip = ip + actionLen + aif.getJumpOffset();
|
||||
|
||||
if (decideBranch) {
|
||||
System.out.print("newip " + nip + ", ");
|
||||
System.out.print("Action: jump(j),ignore(i),compute(c)?");
|
||||
if (sc == null) {
|
||||
sc = new Scanner(System.in);
|
||||
}
|
||||
String next = sc.next();
|
||||
switch (next) {
|
||||
case "j":
|
||||
newip = nip;
|
||||
break;
|
||||
case "i":
|
||||
break;
|
||||
case "c":
|
||||
goaif = true;
|
||||
break;
|
||||
}
|
||||
} else if (top.isCompileTime() && (!top.hasSideEffect())) {
|
||||
if (debugMode) {
|
||||
System.err.print("is compiletime -> ");
|
||||
}
|
||||
if (EcmaScript.toBoolean(top.getResult())) {
|
||||
newip = nip;
|
||||
aif.jumpUsed = true;
|
||||
if (debugMode) {
|
||||
System.err.println("jump");
|
||||
}
|
||||
} else {
|
||||
aif.ignoreUsed = true;
|
||||
if (debugMode) {
|
||||
System.err.println("ignore");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (debugMode) {
|
||||
System.err.println("goaif");
|
||||
}
|
||||
goaif = true;
|
||||
}
|
||||
} else if (a instanceof ActionJump) {
|
||||
newip = ip + actionLen + ((ActionJump) a).getJumpOffset();
|
||||
} else if (!(a instanceof GraphSourceItemContainer)) {
|
||||
//return in for..in, TODO:Handle this better way
|
||||
if (((a instanceof ActionEquals) || (a instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) {
|
||||
stack.push(new DirectValueActionItem(null, null, 0, Null.INSTANCE, new ArrayList<>()));
|
||||
}
|
||||
if ((a instanceof ActionStoreRegister) && stack.isEmpty()) {
|
||||
stack.push(new DirectValueActionItem(null, null, 0, Null.INSTANCE, new ArrayList<>()));
|
||||
}
|
||||
a.translate(localData, stack, output, Graph.SOP_USE_STATIC/*Graph.SOP_SKIP_STATIC*/, path);
|
||||
}
|
||||
} catch (RuntimeException ex) {
|
||||
logger.log(Level.SEVERE, "Disassembly exception", ex);
|
||||
break;
|
||||
}
|
||||
|
||||
HashMap<String, GraphTargetItem> vars = localData.variables;
|
||||
if (varname != null) {
|
||||
GraphTargetItem varval = vars.get(varname);
|
||||
if (varval != null && varval.isCompileTime() && indeterminate) {
|
||||
vars.put(varname, new NotCompileTimeItem(null, null, varval));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < actionLen; i++) {
|
||||
ret.set(ip + i, a);
|
||||
}
|
||||
|
||||
if (a instanceof GraphSourceItemContainer) {
|
||||
GraphSourceItemContainer cnt = (GraphSourceItemContainer) a;
|
||||
if (a instanceof Action) {
|
||||
long endAddr = a.getAddress() + cnt.getHeaderSize();
|
||||
String cntName = cnt.getName();
|
||||
List<List<GraphTargetItem>> output2s = new ArrayList<>();
|
||||
for (long size : cnt.getContainerSizes()) {
|
||||
if (size == 0) {
|
||||
output2s.add(new ArrayList<>());
|
||||
continue;
|
||||
}
|
||||
ActionLocalData localData2;
|
||||
List<GraphTargetItem> output2 = new ArrayList<>();
|
||||
if ((cnt instanceof ActionDefineFunction) || (cnt instanceof ActionDefineFunction2)) {
|
||||
localData2 = new ActionLocalData();
|
||||
} else {
|
||||
localData2 = localData;
|
||||
}
|
||||
deobfustaceActionListAtPosRecursiveOld(listeners, output2, containers, localData2, new TranslateStack(path), cpool, actions, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel);
|
||||
output2s.add(output2);
|
||||
endAddr += size;
|
||||
}
|
||||
GraphSourceItem lineStartItem = null;
|
||||
if (cnt instanceof GraphSourceItem) {
|
||||
lineStartItem = (GraphSourceItem) cnt;
|
||||
}
|
||||
cnt.translateContainer(output2s, lineStartItem, stack, output, localData.regNames, localData.variables, localData.functions);
|
||||
ip = (int) endAddr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (a instanceof ActionEnd) {
|
||||
break;
|
||||
}
|
||||
if (goaif && aif != null) {
|
||||
aif.ignoreUsed = true;
|
||||
aif.jumpUsed = true;
|
||||
indeterminate = true;
|
||||
|
||||
HashMap<String, GraphTargetItem> vars = localData.variables;
|
||||
boolean stateChanged = false;
|
||||
if (decisionStates.containsKey(ip)) {
|
||||
HashMap<String, GraphTargetItem> oldstate = decisionStates.get(ip);
|
||||
if (oldstate.size() != vars.size()) {
|
||||
stateChanged = true;
|
||||
} else {
|
||||
for (String k : vars.keySet()) {
|
||||
if (!oldstate.containsKey(k)) {
|
||||
stateChanged = true;
|
||||
break;
|
||||
}
|
||||
if (!vars.get(k).isCompileTime() && oldstate.get(k).isCompileTime()) {
|
||||
stateChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HashMap<String, GraphTargetItem> curstate = new HashMap<>();
|
||||
curstate.putAll(vars);
|
||||
decisionStates.put(ip, curstate);
|
||||
|
||||
if ((!stateChanged) && curVisited > 1) {
|
||||
List<Integer> branches = new ArrayList<>();
|
||||
branches.add(ip + actionLen + aif.getJumpOffset());
|
||||
branches.add(ip + actionLen);
|
||||
for (int br : branches) {
|
||||
int visc = 0;
|
||||
if (visited.containsKey(br)) {
|
||||
visc = visited.get(br);
|
||||
}
|
||||
if (visc == 0) {//<curVisited){
|
||||
ip = br;
|
||||
continue loopip;
|
||||
}
|
||||
}
|
||||
break loopip;
|
||||
}
|
||||
|
||||
TranslateStack subStack = (TranslateStack) stack.clone();
|
||||
ActionLocalData subLocalData = new ActionLocalData(new HashMap<>(localData.regNames),
|
||||
new HashMap<>(localData.variables), new HashMap<>(localData.functions));
|
||||
deobfustaceActionListAtPosRecursiveOld(listeners, output, containers, subLocalData, subStack, cpool, actions, ip + actionLen + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel);
|
||||
}
|
||||
|
||||
if (newip > -1) {
|
||||
ip = newip;
|
||||
} else {
|
||||
ip += info;
|
||||
}
|
||||
|
||||
if (a.isExit()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (DisassemblyListener listener : listeners) {
|
||||
listener.progressDeobfuscating(ip, actions.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
@@ -60,31 +59,6 @@ public class ActionPush extends Action {
|
||||
|
||||
public List<String> constantPool;
|
||||
|
||||
public List<Integer> ignoredParts = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean isIgnored() {
|
||||
return ignoredParts.size() == values.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIgnored(boolean ignored, int pos) {
|
||||
if (ignored) {
|
||||
if (!ignoredParts.contains(pos)) {
|
||||
ignoredParts.add(pos);
|
||||
if (ignoredParts.size() == values.size()) {
|
||||
super.setIgnored(ignored, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ignoredParts.contains(pos)) {
|
||||
ignoredParts.remove(pos);
|
||||
super.setIgnored(false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ActionPush(int actionLength, SWFInputStream sis, int version) throws IOException {
|
||||
super(0x96, actionLength);
|
||||
int type;
|
||||
@@ -360,9 +334,6 @@ public class ActionPush extends Action {
|
||||
public GraphTextWriter paramsToString(GraphTextWriter writer) {
|
||||
int pos = 0;
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
if (ignoredParts.contains(i)) {
|
||||
continue;
|
||||
}
|
||||
if (pos > 0) {
|
||||
writer.appendNoHilight(" ");
|
||||
}
|
||||
@@ -404,10 +375,6 @@ public class ActionPush extends Action {
|
||||
public void translate(GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) {
|
||||
int pos = 0;
|
||||
for (Object o : values) {
|
||||
if (ignoredParts.contains(pos)) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
if (o instanceof ConstantIndex) {
|
||||
if ((constantPool == null) || (((ConstantIndex) o).index >= constantPool.size())) {
|
||||
o = "§§constant" + ((ConstantIndex) o).index;
|
||||
|
||||
@@ -92,10 +92,6 @@ public class Configuration {
|
||||
@ConfigurationCategory("script")
|
||||
public static final ConfigurationItem<Boolean> autoDeobfuscate = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
@ConfigurationCategory("")
|
||||
public static final ConfigurationItem<Boolean> deobfuscationOldMode = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
@ConfigurationCategory("")
|
||||
public static final ConfigurationItem<Boolean> cacheOnDisk = null;
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.FinalProcessLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.model.FunctionActionItem;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
@@ -298,11 +297,9 @@ public class Graph {
|
||||
getReachableParts(part, ret, loops, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Non recursive version of getReachablePartsOld
|
||||
*/
|
||||
private void getReachableParts(GraphPart part, LinkedHashSet<GraphPart> ret, List<Loop> loops, boolean first) {
|
||||
|
||||
// todo: honfika: why call with first = true parameter always?
|
||||
Stack<GraphPartQueue> stack = new Stack<>();
|
||||
GraphPartQueue queue = new GraphPartQueue();
|
||||
queue.add(part);
|
||||
@@ -386,77 +383,6 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
|
||||
private void getReachablePartsOld(GraphPart part, LinkedHashSet<GraphPart> ret, List<Loop> loops, boolean first) {
|
||||
|
||||
// todo: honfika: why call with first = true parameter always?
|
||||
if (first) {
|
||||
for (Loop l : loops) {
|
||||
l.reachableMark = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Loop currentLoop = null;
|
||||
for (Loop l : loops) {
|
||||
if ((l.phase == 1) || (l.reachableMark == 1)) {
|
||||
if (l.loopContinue == part) {
|
||||
return;
|
||||
}
|
||||
if (l.loopBreak == part) {
|
||||
return;
|
||||
}
|
||||
if (l.loopPreContinue == part) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (l.reachableMark == 0) {
|
||||
if (l.loopContinue == part) {
|
||||
l.reachableMark = 1;
|
||||
currentLoop = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<GraphPart> newparts = new ArrayList<>();
|
||||
loopnext:
|
||||
for (GraphPart next : part.nextParts) {
|
||||
for (Loop l : loops) {
|
||||
if ((l.phase == 1) || (l.reachableMark == 1)) {
|
||||
if (l.loopContinue == next) {
|
||||
continue loopnext;
|
||||
}
|
||||
if (l.loopBreak == next) {
|
||||
continue loopnext;
|
||||
}
|
||||
if (l.loopPreContinue == next) {
|
||||
continue loopnext;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!ret.contains(next)) {
|
||||
newparts.add(next);
|
||||
}
|
||||
}
|
||||
|
||||
ret.addAll(newparts);
|
||||
for (GraphPart next : newparts) {
|
||||
getReachableParts(next, ret, loops, true);
|
||||
}
|
||||
|
||||
if (currentLoop != null) {
|
||||
if (currentLoop.loopBreak != null) {
|
||||
if (!ret.contains(currentLoop.loopBreak)) {
|
||||
ret.add(currentLoop.loopBreak);
|
||||
currentLoop.reachableMark = 2;
|
||||
getReachableParts(currentLoop.loopBreak, ret, loops, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* public GraphPart getNextCommonPart(GraphPart part, List<Loop> loops) {
|
||||
return getNextCommonPart(part, new ArrayList<GraphPart>(),loops);
|
||||
}*/
|
||||
public GraphPart getNextCommonPart(BaseLocalData localData, GraphPart part, List<Loop> loops) throws InterruptedException {
|
||||
return getCommonPart(localData, part.nextParts, loops);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user