mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-12 15:20:08 +00:00
AS3 register deobfuscator improved
This commit is contained in:
@@ -773,7 +773,7 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
public AVM2Code(ABCInputStream ais) throws IOException {
|
||||
public AVM2Code(ABCInputStream ais, MethodBody body) throws IOException {
|
||||
Map<Long, AVM2Instruction> codeMap = new TreeMap<>();
|
||||
DumpInfo diParent = ais.dumpInfo;
|
||||
List<Long> addresses = new ArrayList<>();
|
||||
@@ -789,6 +789,13 @@ public class AVM2Code implements Cloneable {
|
||||
|
||||
long startPos = ais.getPosition();
|
||||
addresses.add(startPos);
|
||||
if (body != null) {
|
||||
for (ABCException e : body.exceptions) {
|
||||
addresses.add((long) e.start);
|
||||
addresses.add((long) e.end);
|
||||
addresses.add((long) e.target);
|
||||
}
|
||||
}
|
||||
|
||||
loopaddr:
|
||||
while (!addresses.isEmpty() || !switchAddresses.isEmpty() || !unAdresses.isEmpty()) {
|
||||
@@ -919,6 +926,7 @@ public class AVM2Code implements Cloneable {
|
||||
for (int c = 2; c < actualOperands.length; c++) {
|
||||
addresses.add(beforeSwitchPos + actualOperands[c]);
|
||||
}
|
||||
unAdresses.add(ais.getPosition());
|
||||
continue loopaddr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
@@ -43,9 +44,8 @@ import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -70,61 +70,65 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
|
||||
@Override
|
||||
public void deobfuscate(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody abody) throws InterruptedException {
|
||||
//System.err.println("regdeo:" + path);
|
||||
|
||||
removeUnreachableActions(abody.getCode(), cpool, trait, minfo, abody);
|
||||
|
||||
Map<Integer, GraphTargetItem> outFirstAssigned = new HashMap<>();
|
||||
Map<Integer, AVM2Instruction> outFirstAssignments = new HashMap<>();
|
||||
Map<Integer, Integer> outAssignCount1 = new HashMap<>();
|
||||
Map<Integer, Integer> outAssignCount2 = new HashMap<>();
|
||||
|
||||
Map<Integer, GraphTargetItem> singleRegisters = new HashMap<>();
|
||||
|
||||
List<AVM2Instruction> ignored = new ArrayList<>();
|
||||
Map<Integer, GraphTargetItem> registers = new HashMap<>();
|
||||
|
||||
boolean extended = true;
|
||||
/*for (AVM2Instruction ins : abody.getCode().code) {
|
||||
System.err.println("" + ins.offset + ": " + ins);
|
||||
}*/
|
||||
Set<Integer> ignoredRegs = new HashSet<>();
|
||||
|
||||
MethodBody body = abody;
|
||||
|
||||
if (extended) {
|
||||
body = abody.clone();
|
||||
getFirstRegistersUsage(outAssignCount1, outFirstAssigned, outFirstAssignments, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, ignored, registers);
|
||||
ignored.addAll(outFirstAssignments.values());
|
||||
registers.putAll(outFirstAssigned);
|
||||
|
||||
replaceSingleUseRegisters(registers, ignored, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body);
|
||||
|
||||
super.deobfuscate(path, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body);
|
||||
removeUnreachableActions(body.getCode(), cpool, trait, minfo, body);
|
||||
|
||||
//second pass - ignore all first assignments
|
||||
registers.clear();
|
||||
ignored.clear();
|
||||
outFirstAssignments.clear();
|
||||
getFirstRegistersUsage(outAssignCount2, new HashMap<>(), outFirstAssignments, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, ignored, registers);
|
||||
|
||||
for (int regId : outAssignCount1.keySet()) {
|
||||
int ac = outAssignCount2.containsKey(regId) ? outAssignCount2.get(regId) : 0;
|
||||
if (ac == 0) {
|
||||
singleRegisters.put(regId, outFirstAssigned.get(regId));
|
||||
}
|
||||
}
|
||||
body = abody;
|
||||
} else {
|
||||
getFirstRegistersUsage(outAssignCount1, outFirstAssigned, outFirstAssignments, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, ignored, registers);
|
||||
for (int regId : outAssignCount1.keySet()) {
|
||||
int ac = outAssignCount1.get(regId);
|
||||
if (ac == 1) {
|
||||
singleRegisters.put(regId, outFirstAssigned.get(regId));
|
||||
}
|
||||
}
|
||||
body = abody.clone();
|
||||
Reference<AVM2Instruction> assignment = new Reference<>(null);
|
||||
ignoredRegs.clear();
|
||||
for (int i = 0; i < body.getLocalReservedCount(); i++) {
|
||||
ignoredRegs.add(i);
|
||||
}
|
||||
|
||||
//body.max_regs
|
||||
replaceSingleUseRegisters(singleRegisters, null, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body);
|
||||
super.deobfuscate(path, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body);
|
||||
int setReg = 0;
|
||||
List<Integer> listedRegs = new ArrayList<>();
|
||||
List<MethodBody> listedLastBodies = new ArrayList<>();
|
||||
Set<Integer> ignoredRegGets = new HashSet<>();
|
||||
|
||||
while (setReg > -1) {
|
||||
MethodBody bodybefore = body;
|
||||
body = bodybefore.clone();
|
||||
setReg = getFirstRegisterSetter(assignment, classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, ignoredRegs, ignoredRegGets);
|
||||
//System.err.println("setreg " + setReg + " ass:" + assignment.getVal());
|
||||
if (setReg < 0) {
|
||||
break;
|
||||
}
|
||||
//if there is second assignment
|
||||
if (listedRegs.contains(setReg)) {
|
||||
//System.err.println("second assignment of loc" + setReg + ", ignoring");
|
||||
int lindex = listedRegs.indexOf(setReg);
|
||||
body = listedLastBodies.get(lindex); //switch to body before
|
||||
ignoredRegs.add(setReg); //this is not obfuscated
|
||||
for (int i = listedRegs.size() - 1; i >= lindex; i--) {
|
||||
int r = listedRegs.get(i);
|
||||
listedRegs.remove(i);
|
||||
listedLastBodies.remove(i);
|
||||
ignoredRegGets.remove(r);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((assignment.getVal().definition instanceof SetLocalTypeIns) || (assignment.getVal().definition instanceof GetLocalTypeIns /*First usage -> value undefined*/)) {
|
||||
super.removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, Arrays.asList(assignment.getVal()));
|
||||
}
|
||||
if (assignment.getVal().definition instanceof GetLocalTypeIns) {
|
||||
ignoredRegGets.add(setReg);
|
||||
}
|
||||
listedRegs.add(setReg);
|
||||
listedLastBodies.add(bodybefore);
|
||||
}
|
||||
|
||||
abody.exceptions = body.exceptions;
|
||||
abody.setCode(body.getCode());
|
||||
removeUnreachableActions(body.getCode(), cpool, trait, minfo, body);
|
||||
//System.err.println("/deo");
|
||||
}
|
||||
|
||||
private void replaceSingleUseRegisters(Map<Integer, GraphTargetItem> singleRegisters, List<AVM2Instruction> setInss, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) {
|
||||
@@ -149,45 +153,19 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
}
|
||||
}
|
||||
|
||||
private void getFirstRegistersUsage(Map<Integer, Integer> outAssignCount, Map<Integer, GraphTargetItem> outFirstAssigned, Map<Integer, AVM2Instruction> outFirstAssignments, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body, List<AVM2Instruction> ignoredAss, Map<Integer, GraphTargetItem> registers) {
|
||||
private int getFirstRegisterSetter(Reference<AVM2Instruction> assignment, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body, Set<Integer> ignoredRegisters, Set<Integer> ignoredGets) {
|
||||
AVM2Code code = body.getCode();
|
||||
Map<Integer, GraphTargetItem> ret = new HashMap<>();
|
||||
|
||||
if (code.code.isEmpty()) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ExecutionResult res = new ExecutionResult();
|
||||
visitCode(new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, res, registers, ignoredAss);
|
||||
for (int reg : res.assignCount.keySet()) {
|
||||
if (res.firstAssigned.get(reg) != null && res.firstAssigned.get(reg).isCompileTime()) {
|
||||
outAssignCount.put(reg, res.assignCount.get(reg));
|
||||
outFirstAssigned.put(reg, res.firstAssigned.get(reg));
|
||||
outFirstAssignments.put(reg, res.firstAssignInstruction.get(reg));
|
||||
}
|
||||
}
|
||||
return visitCode(assignment, new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, res, ignoredRegisters, ignoredGets);
|
||||
}
|
||||
/*
|
||||
private Map<Integer, GraphTargetItem> getSingleUseRegisters(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) {
|
||||
AVM2Code code = body.getCode();
|
||||
Map<Integer, GraphTargetItem> ret = new HashMap<>();
|
||||
|
||||
if (code.code.isEmpty()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ExecutionResult res = new ExecutionResult();
|
||||
visitCode(new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, res);
|
||||
for (int reg : res.assignCount.keySet()) {
|
||||
if (res.assignCount.get(reg) == 1) {
|
||||
ret.put(reg, res.lastAssigned.get(reg));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}*/
|
||||
|
||||
private void visitCode(Set<Integer> visited, TranslateStack stack, int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result, Map<Integer, GraphTargetItem> registers, List<AVM2Instruction> ignoredAss) {
|
||||
private int visitCode(Reference<AVM2Instruction> assignment, Set<Integer> visited, TranslateStack stack, int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result, Set<Integer> ignored, Set<Integer> ignoredGets) {
|
||||
List<GraphTargetItem> output = new ArrayList<>();
|
||||
AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex);
|
||||
localData.localRegs.put(0, new NullAVM2Item(null));//this
|
||||
@@ -212,40 +190,33 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
AVM2Instruction action = code.code.get(idx);
|
||||
InstructionDefinition def = action.definition;
|
||||
//System.err.println("" + idx + ": " + action + " stack:" + stack.size());
|
||||
if (action.definition instanceof GetLocalTypeIns) {
|
||||
stack.push(registers.get(((GetLocalTypeIns) action.definition).getRegisterId(action)));
|
||||
} else if (action.definition instanceof SetLocalTypeIns) {
|
||||
SetLocalTypeIns slt = (SetLocalTypeIns) def;
|
||||
GraphTargetItem regVal = stack.pop();//localData.localRegs.get(regId);
|
||||
int regId = slt.getRegisterId(action);
|
||||
if (!result.assignCount.containsKey(regId)) {
|
||||
result.assignCount.put(regId, 0);
|
||||
}
|
||||
boolean isIgnored = false;
|
||||
for (AVM2Instruction ins : ignoredAss) {
|
||||
if (action == ins) {
|
||||
isIgnored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isIgnored) {
|
||||
} else {
|
||||
result.assignCount.put(regId, result.assignCount.get(regId) + 1);
|
||||
|
||||
//GraphTargetItem regVal = localData.localRegs.get(regId);
|
||||
if (regVal == null || !regVal.getNotCoerced().isCompileTime()) {
|
||||
result.assignCount.put(regId, Integer.MAX_VALUE);
|
||||
} else {
|
||||
if (result.assignCount.get(regId) == 1) {
|
||||
result.firstAssigned.put(regId, regVal.getNotCoerced());
|
||||
result.firstAssignInstruction.put(regId, action);
|
||||
action.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
|
||||
|
||||
//if (!(def instanceof KillIns))
|
||||
if (def instanceof SetLocalTypeIns) {
|
||||
int regId = ((SetLocalTypeIns) def).getRegisterId(action);
|
||||
if (!ignored.contains(regId)) {
|
||||
assignment.setVal(action);
|
||||
return regId;
|
||||
}
|
||||
} else if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(action);
|
||||
if (!ignored.contains(regId) && !ignoredGets.contains(regId)) {
|
||||
assignment.setVal(action);
|
||||
return regId;
|
||||
}
|
||||
} else {
|
||||
for (int p = 0; p < action.definition.operands.length; p++) {
|
||||
int op = action.definition.operands[p];
|
||||
if (op == AVM2Code.DAT_REGISTER_INDEX) {
|
||||
int regId = action.operands[p];
|
||||
if (!ignored.contains(regId)) {
|
||||
assignment.setVal(action);
|
||||
return regId;
|
||||
}
|
||||
result.lastAssigned.put(regId, regVal.getNotCoerced());
|
||||
}
|
||||
}
|
||||
//assignCount
|
||||
} else {
|
||||
action.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
|
||||
}
|
||||
|
||||
idx++;
|
||||
@@ -328,14 +299,6 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ExecutionResult {
|
||||
|
||||
public Map<Integer, Integer> assignCount = new HashMap<>();
|
||||
|
||||
public Map<Integer, GraphTargetItem> lastAssigned = new HashMap<>();
|
||||
public Map<Integer, GraphTargetItem> firstAssigned = new HashMap<>();
|
||||
public Map<Integer, AVM2Instruction> firstAssignInstruction = new HashMap<>();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsI
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns;
|
||||
@@ -60,6 +61,8 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
|
||||
@@ -77,6 +80,7 @@ import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.NotCompileTimeItem;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
@@ -86,6 +90,7 @@ import java.util.ArrayList;
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -156,60 +161,21 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException {
|
||||
protected boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body, List<AVM2Instruction> inlineIns) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
if (code.code.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<Integer, GraphTargetItem> staticRegs = new HashMap<>();
|
||||
for (AVM2Instruction ins : inlineIns) {
|
||||
if (ins.definition instanceof GetLocalTypeIns) {
|
||||
staticRegs.put(((GetLocalTypeIns) ins.definition).getRegisterId(ins), new UndefinedAVM2Item(ins));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < code.code.size(); i++) {
|
||||
ExecutionResult result = new ExecutionResult();
|
||||
executeActions(classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result);
|
||||
|
||||
/*if (result.idx != -1) {
|
||||
int newIstructionCount = 1; // jump
|
||||
if (!result.stack.isEmpty()) {
|
||||
newIstructionCount += result.stack.size();
|
||||
}
|
||||
|
||||
if (newIstructionCount < result.instructionsProcessed) //if (result.isIf)
|
||||
{
|
||||
AVM2Instruction target = code.code.get(result.idx);
|
||||
AVM2Instruction prevAction = code.code.get(i);
|
||||
int idelta = 0;
|
||||
|
||||
if (result.stack.isEmpty() && prevAction.definition instanceof JumpIns) {
|
||||
prevAction.operands[0] = ((int) (target.offset - prevAction.offset - prevAction.getBytes().length));
|
||||
} else {
|
||||
if (!result.stack.isEmpty()) {
|
||||
for (GraphTargetItem graphTargetItem : result.stack) {
|
||||
if (graphTargetItem instanceof PopItem) {
|
||||
continue;
|
||||
}
|
||||
AVM2Instruction ins = makePush(graphTargetItem.getResult(), cpool);
|
||||
if (ins != null) {
|
||||
code.insertInstruction(i + (idelta++), ins, body);
|
||||
//prevAction = ins;
|
||||
} else {
|
||||
throw new TranslateException("Cannot push: " + graphTargetItem);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
AVM2Instruction jump = new AVM2Instruction(0, new JumpIns(), new int[]{0});
|
||||
code.insertInstruction(i + (idelta++), jump, body);
|
||||
|
||||
jump.operands[0] = ((int) (target.offset - jump.offset - jump.getBytes().length));
|
||||
|
||||
}
|
||||
|
||||
removeUnreachableActions(code, cpool, trait, minfo, body);
|
||||
removeZeroJumps(code, body);
|
||||
|
||||
i = -1;
|
||||
}
|
||||
}*/
|
||||
executeActions(staticRegs, classIndex, isStatic, body, scriptIndex, abc, code, i, code.code.size() - 1, result, inlineIns);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -237,7 +203,10 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
localData.isStatic = isStatic;
|
||||
localData.classIndex = classIndex;
|
||||
localData.localRegs = new HashMap<>();
|
||||
for (int i = 0; i < body.max_regs; i++) {
|
||||
for (int i = 0; i < body.getLocalReservedCount(); i++) {
|
||||
localData.localRegs.put(i, new NotCompileTimeItem(null, new UndefinedAVM2Item(null)));
|
||||
}
|
||||
for (int i = body.getLocalReservedCount(); i < body.max_regs; i++) {
|
||||
localData.localRegs.put(i, new UndefinedAVM2Item(null));
|
||||
}
|
||||
localData.scopeStack = new ScopeStack(true);
|
||||
@@ -259,7 +228,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
return localData;
|
||||
}
|
||||
|
||||
private void executeActions(int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result) {
|
||||
private void executeActions(Map<Integer, GraphTargetItem> staticRegs, int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, ExecutionResult result, List<AVM2Instruction> inlineIns) {
|
||||
List<GraphTargetItem> output = new ArrayList<>();
|
||||
AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex);
|
||||
|
||||
@@ -288,8 +257,28 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
} else {
|
||||
action.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
|
||||
}
|
||||
|
||||
InstructionDefinition def = action.definition;
|
||||
|
||||
if (inlineIns.contains(action)) {
|
||||
if (def instanceof SetLocalTypeIns) {
|
||||
int regId = ((SetLocalTypeIns) def).getRegisterId(action);
|
||||
staticRegs.put(regId, localData.localRegs.get(regId).getNotCoerced());
|
||||
code.replaceInstruction(idx, new AVM2Instruction(0, new DeobfuscatePopIns(), new int[]{}), body);
|
||||
}
|
||||
}
|
||||
if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(action);
|
||||
if (staticRegs.containsKey(regId)) {
|
||||
stack.pop();
|
||||
AVM2Instruction pushins = makePush(abc.constants, staticRegs.get(regId));
|
||||
code.replaceInstruction(idx, pushins, body);
|
||||
stack.push(staticRegs.get(regId));
|
||||
action = pushins;
|
||||
def = action.definition;
|
||||
}
|
||||
}
|
||||
|
||||
Class allowedDefs[] = new Class[]{
|
||||
PushByteIns.class,
|
||||
PushShortIns.class,
|
||||
@@ -326,7 +315,8 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
StrictEqualsIns.class,
|
||||
PopIns.class,
|
||||
GetLocalTypeIns.class,
|
||||
NewFunctionIns.class
|
||||
NewFunctionIns.class,
|
||||
CoerceOrConvertTypeIns.class
|
||||
};
|
||||
|
||||
boolean ok = false;
|
||||
@@ -342,10 +332,9 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
|
||||
if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(action);
|
||||
if (regId > 0 && localData.localRegs.get(regId) instanceof UndefinedAVM2Item) {
|
||||
//System.err.println(""+);
|
||||
if (staticRegs.containsKey(regId)) {
|
||||
stack.pop();
|
||||
stack.push(new UndefinedAVM2Item(action));
|
||||
stack.push(staticRegs.get(regId));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -435,7 +424,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
AVM2Code code = body.getCode();
|
||||
code.fixJumps(body);
|
||||
removeUnreachableActions(code, cpool, trait, minfo, body);
|
||||
removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body);
|
||||
removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, new ArrayList<>());
|
||||
removeZeroJumps(code, body);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ public final class MethodBody implements Cloneable {
|
||||
AVM2Code avm2Code;
|
||||
try {
|
||||
ABCInputStream ais = new ABCInputStream(new MemoryInputStream(codeBytes));
|
||||
avm2Code = new AVM2Code(ais);
|
||||
avm2Code = new AVM2Code(ais, this);
|
||||
avm2Code.removeWrongIndices(abc.constants);
|
||||
} catch (UnknownInstructionCode | IOException ex) {
|
||||
avm2Code = new AVM2Code();
|
||||
@@ -218,6 +218,17 @@ public final class MethodBody implements Cloneable {
|
||||
getCode().insertInstruction(pos, instruction, mapOffsetsAfterIns, this);
|
||||
}
|
||||
|
||||
public int getLocalReservedCount() {
|
||||
int pos = abc.method_info.get(this.method_info).param_types.length + 1;
|
||||
if (abc.method_info.get(this.method_info).flagNeed_arguments()) {
|
||||
pos++;
|
||||
}
|
||||
if (abc.method_info.get(this.method_info).flagNeed_rest()) {
|
||||
pos++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
public HashMap<Integer, String> getLocalRegNames(ABC abc) {
|
||||
HashMap<Integer, String> ret = new HashMap<>();
|
||||
for (int i = 1; i <= abc.method_info.get(this.method_info).param_types.length; i++) {
|
||||
@@ -247,9 +258,6 @@ public final class MethodBody implements Cloneable {
|
||||
}
|
||||
|
||||
public void convert(final String path, ScriptExportMode exportMode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final AVM2ConstantPool constants, final List<MethodInfo> method_info, final ScopeStack scopeStack, final boolean isStaticInitializer, final GraphTextWriter writer, final List<String> fullyQualifiedNames, final Traits initTraits, boolean firstLevel) throws InterruptedException {
|
||||
/*if (!path.contains("forcedWidth")) {
|
||||
return;
|
||||
}*/
|
||||
if (debugMode) {
|
||||
System.err.println("Decompiling " + path);
|
||||
}
|
||||
@@ -296,9 +304,6 @@ public final class MethodBody implements Cloneable {
|
||||
}
|
||||
|
||||
public GraphTextWriter toString(final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final AVM2ConstantPool constants, final List<MethodInfo> method_info, final GraphTextWriter writer, final List<String> fullyQualifiedNames) throws InterruptedException {
|
||||
/*if (!path.contains("forcedWidth")) {
|
||||
return writer;
|
||||
}*/
|
||||
if (exportMode != ScriptExportMode.AS) {
|
||||
getCode().toASMSource(constants, trait, method_info.get(this.method_info), this, exportMode, writer);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user