mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-03 03:34:19 +00:00
Merge origin/master
This commit is contained in:
@@ -17,11 +17,9 @@
|
||||
package com.jpexs.decompiler.flash.abc;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.ConvertException;
|
||||
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.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugFileIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns;
|
||||
@@ -54,7 +52,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
@@ -1176,7 +1176,7 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
writer.newLine();
|
||||
|
||||
List<Long> offsets = new ArrayList<>();
|
||||
Set<Long> importantOffsets = getImportantOffsets(body);
|
||||
if (body != null) {
|
||||
writer.appendNoHilight("body").newLine();
|
||||
|
||||
@@ -1197,28 +1197,26 @@ public class AVM2Code implements Cloneable {
|
||||
writer.newLine();
|
||||
|
||||
for (int e = 0; e < body.exceptions.length; e++) {
|
||||
ABCException exception = body.exceptions[e];
|
||||
writer.appendNoHilight("try");
|
||||
|
||||
writer.appendNoHilight(" from ");
|
||||
writer.appendNoHilight("ofs");
|
||||
writer.appendNoHilight(Helper.formatAddress(body.exceptions[e].start));
|
||||
offsets.add((long) body.exceptions[e].start);
|
||||
writer.appendNoHilight(Helper.formatAddress(exception.start));
|
||||
|
||||
writer.appendNoHilight(" to ");
|
||||
writer.appendNoHilight("ofs");
|
||||
writer.appendNoHilight(Helper.formatAddress(body.exceptions[e].end));
|
||||
offsets.add((long) body.exceptions[e].end);
|
||||
writer.appendNoHilight(Helper.formatAddress(exception.end));
|
||||
|
||||
writer.appendNoHilight(" target ");
|
||||
writer.appendNoHilight("ofs");
|
||||
writer.appendNoHilight(Helper.formatAddress(body.exceptions[e].target));
|
||||
offsets.add((long) body.exceptions[e].target);
|
||||
writer.appendNoHilight(Helper.formatAddress(exception.target));
|
||||
|
||||
writer.appendNoHilight(" type ");
|
||||
writer.hilightSpecial(body.exceptions[e].type_index == 0 ? "null" : constants.getMultiname(body.exceptions[e].type_index).toString(constants, new ArrayList<>()), HighlightSpecialType.TRY_TYPE, e);
|
||||
writer.hilightSpecial(exception.type_index == 0 ? "null" : constants.getMultiname(exception.type_index).toString(constants, new ArrayList<>()), HighlightSpecialType.TRY_TYPE, e);
|
||||
|
||||
writer.appendNoHilight(" name ");
|
||||
writer.hilightSpecial(body.exceptions[e].name_index == 0 ? "null" : constants.getMultiname(body.exceptions[e].name_index).toString(constants, new ArrayList<>()), HighlightSpecialType.TRY_NAME, e);
|
||||
writer.hilightSpecial(exception.name_index == 0 ? "null" : constants.getMultiname(exception.name_index).toString(constants, new ArrayList<>()), HighlightSpecialType.TRY_NAME, e);
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
@@ -1226,21 +1224,6 @@ public class AVM2Code implements Cloneable {
|
||||
writer.newLine();
|
||||
writer.appendNoHilight("code").newLine();
|
||||
|
||||
for (AVM2Instruction ins : code) {
|
||||
offsets.addAll(ins.getOffsets());
|
||||
}
|
||||
for (AVM2Instruction ins : code) {
|
||||
if (ins.replaceWith != null) {
|
||||
for (Object o : ins.replaceWith) {
|
||||
if (o instanceof ControlFlowTag) {
|
||||
ControlFlowTag cft = (ControlFlowTag) o;
|
||||
if (cft.name.equals("appendjump")) {
|
||||
offsets.add((long) pos2adr(cft.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int ip = 0;
|
||||
int largeLimit = 20000;
|
||||
boolean markOffsets = code.size() <= largeLimit;
|
||||
@@ -1255,7 +1238,7 @@ public class AVM2Code implements Cloneable {
|
||||
writer.appendNoHilight(Helper.bytesToHexString(ins.getBytes()));
|
||||
writer.newLine();
|
||||
}
|
||||
if (Configuration.showAllAddresses.get() || offsets.contains(ofs)) {
|
||||
if (Configuration.showAllAddresses.get() || importantOffsets.contains(ofs)) {
|
||||
writer.appendNoHilight("ofs" + Helper.formatAddress(ofs) + ":");
|
||||
}
|
||||
/*for (int e = 0; e < body.exceptions.length; e++) {
|
||||
@@ -1329,6 +1312,33 @@ public class AVM2Code implements Cloneable {
|
||||
return writer;
|
||||
}
|
||||
|
||||
public Set<Long> getImportantOffsets(MethodBody body) {
|
||||
Set<Long> ret = new HashSet<>();
|
||||
if (body != null) {
|
||||
for (ABCException exception : body.exceptions) {
|
||||
ret.add((long) exception.start);
|
||||
ret.add((long) exception.end);
|
||||
ret.add((long) exception.target);
|
||||
}
|
||||
}
|
||||
|
||||
for (AVM2Instruction ins : code) {
|
||||
ret.addAll(ins.getOffsets());
|
||||
if (ins.replaceWith != null) {
|
||||
for (Object o : ins.replaceWith) {
|
||||
if (o instanceof ControlFlowTag) {
|
||||
ControlFlowTag cft = (ControlFlowTag) o;
|
||||
if (cft.name.equals("appendjump")) {
|
||||
ret.add((long) pos2adr(cft.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int adr2pos(long address) throws ConvertException {
|
||||
return adr2pos(address, false);
|
||||
}
|
||||
@@ -1383,12 +1393,6 @@ public class AVM2Code implements Cloneable {
|
||||
return (int) (ins.offset + ins.getBytesLength());
|
||||
}
|
||||
|
||||
private List<Integer> unknownJumps;
|
||||
|
||||
private List<Integer> ignoredIns;
|
||||
|
||||
boolean isCatched = false;
|
||||
|
||||
/**
|
||||
* Test for killed register. CalcKilledStats must be called before
|
||||
*
|
||||
@@ -1516,11 +1520,6 @@ public class AVM2Code implements Cloneable {
|
||||
iploop:
|
||||
while (ip <= end) {
|
||||
|
||||
if (ignoredIns.contains(ip)) {
|
||||
ip++;
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean processTry = processJumps;
|
||||
//addr = pos2adr(ip);
|
||||
//int ipfix = fixIPAfterDebugLine(ip);
|
||||
@@ -1531,10 +1530,6 @@ public class AVM2Code implements Cloneable {
|
||||
break;
|
||||
}
|
||||
|
||||
if (unknownJumps.contains(ip)) {
|
||||
unknownJumps.remove(Integer.valueOf(ip));
|
||||
throw new UnknownJumpException(stack, ip, output);
|
||||
}
|
||||
if (visited[ip]) {
|
||||
//logger.warning(path + ": Code already visited, ofs:" + Helper.formatAddress(pos2adr(ip)) + ", ip:" + ip);
|
||||
break;
|
||||
@@ -1840,8 +1835,6 @@ public class AVM2Code implements Cloneable {
|
||||
|
||||
public void initToSource() {
|
||||
toSourceCount = 0;
|
||||
unknownJumps = new ArrayList<>();
|
||||
ignoredIns = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void injectDeclarations(List<GraphTargetItem> list, boolean[] declaredRegisters, List<Slot> declaredSlots, ABC abc, MethodBody body) {
|
||||
@@ -2073,7 +2066,7 @@ public class AVM2Code implements Cloneable {
|
||||
for (Long insAddr : insAddrToRemove) {
|
||||
int pos = adr2posNoEx(insAddr);
|
||||
if (pos > -1) {
|
||||
code.get(pos).ignored = true;
|
||||
code.get(pos).setIgnored(true, 0);
|
||||
someIgnored = true;
|
||||
}
|
||||
}
|
||||
@@ -2174,14 +2167,9 @@ public class AVM2Code implements Cloneable {
|
||||
* @param body
|
||||
*/
|
||||
public void replaceInstruction(int pos, AVM2Instruction instruction, MethodBody body) {
|
||||
if (pos < 0) {
|
||||
pos = 0;
|
||||
}
|
||||
if (pos > code.size()) {
|
||||
pos = code.size();
|
||||
}
|
||||
instruction.offset = code.get(pos).offset;
|
||||
int oldByteCount = code.get(pos).getBytesLength();
|
||||
AVM2Instruction oldInstruction = code.get(pos);
|
||||
instruction.offset = oldInstruction.offset;
|
||||
int oldByteCount = oldInstruction.getBytesLength();
|
||||
int newByteCount = instruction.getBytesLength();
|
||||
int byteDelta = newByteCount - oldByteCount;
|
||||
|
||||
@@ -2209,7 +2197,6 @@ public class AVM2Code implements Cloneable {
|
||||
}, body);
|
||||
}
|
||||
code.set(pos, instruction);
|
||||
//checkValidOffsets(body);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2555,7 +2542,6 @@ public class AVM2Code implements Cloneable {
|
||||
for (int i = 2; i < ins.operands.length; i++) {
|
||||
toVisit.add(adr2pos(pos2adr(ip) + ins.operands[i]));
|
||||
toVisitLast.add(ip);
|
||||
//visitCode(, ip, refs);
|
||||
}
|
||||
ip = adr2pos(pos2adr(ip) + ins.operands[0]);
|
||||
continue;
|
||||
@@ -2573,7 +2559,6 @@ public class AVM2Code implements Cloneable {
|
||||
try {
|
||||
toVisit.add(adr2pos(pos2adr(ip) + ins.getBytesLength() + ins.operands[0]));
|
||||
toVisitLast.add(ip);
|
||||
//visitCode(adr2pos(pos2adr(ip) + ins.getBytesLength() + ins.operands[0]), ip, refs);
|
||||
} catch (ConvertException ex) {
|
||||
logger.log(Level.FINE, null, ex);
|
||||
}
|
||||
@@ -2604,119 +2589,6 @@ public class AVM2Code implements Cloneable {
|
||||
return refs;
|
||||
}
|
||||
|
||||
private int visitCodeTrap(int ip, int[] visited, AVM2Instruction prev, AVM2Instruction prev2) {
|
||||
int ret = 0;
|
||||
while (ip < visited.length) {
|
||||
visited[ip]++;
|
||||
if (visited[ip] > 1) {
|
||||
break;
|
||||
}
|
||||
AVM2Instruction ins = code.get(ip);
|
||||
if (ins.definition instanceof ThrowIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof ReturnValueIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof ReturnVoidIns) {
|
||||
break;
|
||||
}
|
||||
if (ins.definition instanceof LookupSwitchIns) {
|
||||
try {
|
||||
for (int i = 2; i < ins.operands.length; i++) {
|
||||
ret += visitCodeTrap(adr2pos(pos2adr(ip) + ins.operands[i]), visited, prev, prev2);
|
||||
}
|
||||
ip = adr2pos(pos2adr(ip) + ins.operands[0]);
|
||||
prev2 = prev;
|
||||
prev = ins;
|
||||
continue;
|
||||
} catch (ConvertException ex) {
|
||||
}
|
||||
}
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
try {
|
||||
ip = adr2pos(pos2adr(ip) + ins.getBytesLength() + ins.operands[0]);
|
||||
prev2 = prev;
|
||||
prev = ins;
|
||||
continue;
|
||||
} catch (ConvertException ex) {
|
||||
logger.log(Level.FINE, null, ex);
|
||||
}
|
||||
} else if (ins.definition instanceof IfTypeIns) {
|
||||
if ((prev != null) && (prev2 != null)) {
|
||||
if ((prev.definition instanceof PushByteIns) && (prev2.definition instanceof PushByteIns)) {
|
||||
if (ins.definition instanceof IfEqIns) {
|
||||
prev.ignored = true;
|
||||
prev2.ignored = true;
|
||||
if (prev.operands[0] == prev2.operands[0]) {
|
||||
ins.definition = AVM2Code.instructionSet[AVM2Instructions.Jump];
|
||||
visited[ip]--;
|
||||
} else {
|
||||
ins.ignored = true;
|
||||
ip++;
|
||||
}
|
||||
ret++;
|
||||
continue;
|
||||
}
|
||||
if (ins.definition instanceof IfNeIns) {
|
||||
prev.ignored = true;
|
||||
prev2.ignored = true;
|
||||
if (prev.operands[0] != prev2.operands[0]) {
|
||||
ins.definition = AVM2Code.instructionSet[AVM2Instructions.Jump];
|
||||
visited[ip]--;
|
||||
} else {
|
||||
ins.ignored = true;
|
||||
ip++;
|
||||
}
|
||||
ret++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((prev != null) && ins.definition instanceof IfTrueIns) {
|
||||
if (prev.definition instanceof PushTrueIns) {
|
||||
prev.ignored = true;
|
||||
ins.definition = AVM2Code.instructionSet[AVM2Instructions.Jump];
|
||||
visited[ip]--;
|
||||
ret++;
|
||||
continue;
|
||||
} else if (prev.definition instanceof PushFalseIns) {
|
||||
prev.ignored = true;
|
||||
ins.ignored = true;
|
||||
ret++;
|
||||
ip++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((prev != null) && ins.definition instanceof IfFalseIns) {
|
||||
if (prev.definition instanceof PushFalseIns) {
|
||||
prev.ignored = true;
|
||||
ins.definition = AVM2Code.instructionSet[AVM2Instructions.Jump];
|
||||
visited[ip]--;
|
||||
ret++;
|
||||
continue;
|
||||
} else if (prev.definition instanceof PushTrueIns) {
|
||||
prev.ignored = true;
|
||||
ins.ignored = true;
|
||||
ret++;
|
||||
ip++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
ret += visitCodeTrap(adr2pos(pos2adr(ip) + ins.getBytesLength() + ins.operands[0]), visited, prev, prev2);
|
||||
} catch (ConvertException ex) {
|
||||
logger.log(Level.FINE, null, ex);
|
||||
}
|
||||
}
|
||||
ip++;
|
||||
prev2 = prev;
|
||||
prev = ins;
|
||||
};
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
private static class ControlFlowTag {
|
||||
|
||||
public String name;
|
||||
@@ -2819,26 +2691,24 @@ public class AVM2Code implements Cloneable {
|
||||
|
||||
}
|
||||
|
||||
private void restoreControlFlowPass(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, boolean secondpass) throws InterruptedException {
|
||||
private void restoreControlFlowPass(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException {
|
||||
try {
|
||||
HashMap<Integer, List<Integer>> refs;
|
||||
int[] visited2 = new int[code.size()];
|
||||
refs = visitCode(body);
|
||||
HashMap<Integer, List<Object>> appended = new HashMap<>();
|
||||
/*if (secondpass) {
|
||||
restoreControlFlow(code.size() - 1, refs, visited2, appended);
|
||||
} else*/ {
|
||||
restoreControlFlow(0, refs, visited2, appended);
|
||||
for (ABCException e : body.exceptions) {
|
||||
try {
|
||||
restoreControlFlow(adr2pos(e.start, true), refs, visited2, appended);
|
||||
restoreControlFlow(adr2pos(e.target), refs, visited2, appended);
|
||||
restoreControlFlow(adr2pos(e.end, true), refs, visited2, appended);
|
||||
} catch (ConvertException ex) {
|
||||
logger.log(Level.FINE, null, ex);
|
||||
}
|
||||
|
||||
restoreControlFlow(0, refs, visited2, appended);
|
||||
for (ABCException e : body.exceptions) {
|
||||
try {
|
||||
restoreControlFlow(adr2pos(e.start, true), refs, visited2, appended);
|
||||
restoreControlFlow(adr2pos(e.target), refs, visited2, appended);
|
||||
restoreControlFlow(adr2pos(e.end, true), refs, visited2, appended);
|
||||
} catch (ConvertException ex) {
|
||||
logger.log(Level.FINE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
for (int ip : appended.keySet()) {
|
||||
code.get(ip).replaceWith = appended.get(ip);
|
||||
}
|
||||
@@ -2861,7 +2731,6 @@ public class AVM2Code implements Cloneable {
|
||||
} else {
|
||||
acode.code.get(i).mappedOffset = pos2adr(tpos);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
this.code = acode.code;
|
||||
@@ -2874,38 +2743,13 @@ public class AVM2Code implements Cloneable {
|
||||
}
|
||||
|
||||
public void restoreControlFlow(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException {
|
||||
restoreControlFlowPass(constants, trait, info, body, false);
|
||||
//restoreControlFlowPass(constants, body, true);
|
||||
restoreControlFlowPass(constants, trait, info, body);
|
||||
}
|
||||
/*
|
||||
public void removeIgnored(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException {
|
||||
try {
|
||||
List<Integer> outputMap = new ArrayList<>();
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false);
|
||||
toASMSource(constants, trait, info, body, outputMap, ScriptExportMode.PCODE, writer);
|
||||
String src = writer.toString();
|
||||
AVM2Code acode = ASM3Parser.parse(new StringReader(src), constants, trait, body, info);
|
||||
for (int i = 0; i < acode.code.size(); i++) {
|
||||
if (outputMap.size() > i) {
|
||||
int tpos = outputMap.get(i);
|
||||
if (tpos == -1) {
|
||||
} else if (code.get(tpos).mappedOffset >= 0) {
|
||||
acode.code.get(i).mappedOffset = code.get(tpos).mappedOffset;
|
||||
} else {
|
||||
acode.code.get(i).mappedOffset = pos2adr(tpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.code = acode.code;
|
||||
} catch (IOException | AVM2ParseException ex) {
|
||||
}
|
||||
invalidateCache();
|
||||
}*/
|
||||
|
||||
public void removeIgnored(MethodBody body) throws InterruptedException {
|
||||
//System.err.println("removing ignored...");
|
||||
for (int i = 0; i < code.size(); i++) {
|
||||
if (code.get(i).ignored) {
|
||||
if (code.get(i).isIgnored()) {
|
||||
removeInstruction(i, body);
|
||||
i--;
|
||||
}
|
||||
@@ -2918,8 +2762,7 @@ public class AVM2Code implements Cloneable {
|
||||
int cnt = 0;
|
||||
for (int i = code.size() - 1; i >= 0; i--) {
|
||||
if (refs.get(i).isEmpty()) {
|
||||
code.get(i).ignored = true;
|
||||
//removeInstruction(i, body);
|
||||
code.get(i).setIgnored(true, 0);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
@@ -2930,7 +2773,7 @@ public class AVM2Code implements Cloneable {
|
||||
AVM2Instruction ins = code.get(i);
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
if (ins.operands[0] == 0) {
|
||||
ins.ignored = true;
|
||||
ins.setIgnored(true, 0);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
@@ -2941,7 +2784,8 @@ public class AVM2Code implements Cloneable {
|
||||
return cnt;
|
||||
}
|
||||
|
||||
public void inlineJumpExit() {
|
||||
public boolean inlineJumpExit() {
|
||||
boolean modified = false;
|
||||
int csize = code.size();
|
||||
for (int i = 0; i < csize; i++) {
|
||||
AVM2Instruction ins = code.get(i);
|
||||
@@ -2955,6 +2799,7 @@ public class AVM2Code implements Cloneable {
|
||||
AVM2Instruction ins2 = code.get(ni);
|
||||
if (ins2.isExit()) {
|
||||
code.set(i, new AVM2Instruction(ofs, ins2.definition, ins2.operands));
|
||||
// todo: honfika: why to add 3 NOPs?
|
||||
AVM2Instruction nopIns;
|
||||
nopIns = new AVM2Instruction(ofs + 1, AVM2Instructions.Nop, null);
|
||||
code.add(i + 1, nopIns);
|
||||
@@ -2964,14 +2809,16 @@ public class AVM2Code implements Cloneable {
|
||||
code.add(i + 3, nopIns);
|
||||
i += 3;
|
||||
csize = code.size();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
} catch (ConvertException ex) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
//ofs += insLen;
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
public void markMappedOffsets() {
|
||||
@@ -3436,9 +3283,7 @@ public class AVM2Code implements Cloneable {
|
||||
ret.code = codeCopy;
|
||||
}
|
||||
|
||||
ret.ignoredIns = new ArrayList<>();
|
||||
ret.killedRegs = new HashMap<>();
|
||||
ret.unknownJumps = new ArrayList<>();
|
||||
return ret;
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
throw new RuntimeException();
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
|
||||
import com.jpexs.decompiler.flash.abc.types.Decimal;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.flash.abc.types.Namespace;
|
||||
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.helpers.HashArrayList;
|
||||
@@ -563,4 +567,36 @@ public class AVM2ConstantPool implements Cloneable {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
public AVM2Instruction makePush(Object ovalue) {
|
||||
if (ovalue instanceof Long) {
|
||||
long value = (Long) ovalue;
|
||||
if (value >= -128 && value <= 127) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{(int) (long) value});
|
||||
} else if (value >= -32768 && value <= 32767) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{((int) (long) value) & 0xffff});
|
||||
} else {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{getIntId(value, true)});
|
||||
}
|
||||
}
|
||||
if (ovalue instanceof Double) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{getDoubleId((Double) ovalue, true)});
|
||||
}
|
||||
if (ovalue instanceof String) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{getStringId((String) ovalue, true)});
|
||||
}
|
||||
if (ovalue instanceof Boolean) {
|
||||
if ((Boolean) ovalue) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushTrue, null);
|
||||
}
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushFalse, null);
|
||||
}
|
||||
if (ovalue == Null.INSTANCE) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushNull, null);
|
||||
}
|
||||
if (ovalue == Undefined.INSTANCE) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushUndefined, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,6 @@ public class LocalDataArea {
|
||||
|
||||
public Object returnValue;
|
||||
|
||||
public String executionException;
|
||||
|
||||
public AVM2RuntimeInfo runtimeInfo;
|
||||
|
||||
private byte[] domainMemory;
|
||||
@@ -64,6 +62,5 @@ public class LocalDataArea {
|
||||
localRegisters.clear();
|
||||
jump = null;
|
||||
returnValue = null;
|
||||
executionException = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
*/
|
||||
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.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;
|
||||
@@ -37,10 +35,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.NotCompileTimeItem;
|
||||
@@ -59,7 +54,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AVM2DeobfuscatorGetSet implements SWFDecompilerListener {
|
||||
public class AVM2DeobfuscatorGetSet extends SWFDecompilerAdapter {
|
||||
|
||||
private static final UndefinedAVM2Item UNDEFINED_ITEM = new UndefinedAVM2Item(null, null);
|
||||
|
||||
@@ -67,43 +62,6 @@ public class AVM2DeobfuscatorGetSet implements SWFDecompilerListener {
|
||||
|
||||
private final int executionLimit = 30000;
|
||||
|
||||
@Override
|
||||
public void actionListParsed(ActionList actions, SWF swf) {
|
||||
|
||||
}
|
||||
|
||||
protected AVM2Instruction makePush(Object ovalue, AVM2ConstantPool cpool) {
|
||||
if (ovalue instanceof Long) {
|
||||
long value = (Long) ovalue;
|
||||
if (value >= -128 && value <= 127) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{(int) (long) value});
|
||||
} else if (value >= -32768 && value <= 32767) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{((int) (long) value) & 0xffff});
|
||||
} else {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{cpool.getIntId(value, true)});
|
||||
}
|
||||
}
|
||||
if (ovalue instanceof Double) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{cpool.getDoubleId((Double) ovalue, true)});
|
||||
}
|
||||
if (ovalue instanceof String) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{cpool.getStringId((String) ovalue, true)});
|
||||
}
|
||||
if (ovalue instanceof Boolean) {
|
||||
if ((Boolean) ovalue) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushTrue, null);
|
||||
}
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushFalse, null);
|
||||
}
|
||||
if (ovalue == Null.INSTANCE) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushNull, null);
|
||||
}
|
||||
if (ovalue == Undefined.INSTANCE) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushUndefined, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean removeObfuscationGetSets(int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, List<AVM2Instruction> inlineIns) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
if (code.code.isEmpty()) {
|
||||
@@ -253,28 +211,6 @@ public class AVM2DeobfuscatorGetSet implements SWFDecompilerListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionTreeCreated(List<GraphTargetItem> tree, SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] proxyFileCatched(byte[] data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swfParsed(SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abcParsed(ABC abc, SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodBodyParsed(MethodBody body, SWF swf) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
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.instructions.AVM2Instruction;
|
||||
@@ -24,7 +23,7 @@ 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.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -36,19 +35,11 @@ import java.util.Map;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple {
|
||||
|
||||
//private final int executionLimit = 30000;
|
||||
@Override
|
||||
public void actionListParsed(ActionList actions, SWF swf) {
|
||||
|
||||
}
|
||||
public class AVM2DeobfuscatorJumps extends SWFDecompilerAdapter {
|
||||
|
||||
@Override
|
||||
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
|
||||
|
||||
//body.getCode().markMappedOffsets();
|
||||
//removeUnreachableInstructions(body.getCode(), cpool, trait, minfo, body);
|
||||
AVM2Code code = body.getCode();
|
||||
|
||||
boolean found;
|
||||
@@ -66,12 +57,10 @@ public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple {
|
||||
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.getBytesLength()));
|
||||
if (srcIns.operands[0] != oldop) {
|
||||
found = true;
|
||||
}
|
||||
int oldop = srcIns.operands[0];
|
||||
srcIns.operands[0] = (int) (targetAddr - (srcIns.offset + srcIns.getBytesLength()));
|
||||
if (srcIns.operands[0] != oldop) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,7 +68,8 @@ public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple {
|
||||
}
|
||||
}
|
||||
}
|
||||
removeUnreachableInstructions(body.getCode(), body);
|
||||
|
||||
code.removeDeadCode(body);
|
||||
} while (found);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
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.LocalDataArea;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException;
|
||||
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;
|
||||
@@ -31,13 +31,11 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIn
|
||||
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;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
@@ -45,11 +43,13 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -61,11 +61,6 @@ import java.util.Set;
|
||||
*/
|
||||
public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
|
||||
@Override
|
||||
public void actionListParsed(ActionList actions, SWF swf) {
|
||||
|
||||
}
|
||||
|
||||
private Set<Integer> getRegisters(AVM2Code code) {
|
||||
Set<Integer> regs = new HashSet<>();
|
||||
for (AVM2Instruction ins : code.code) {
|
||||
@@ -95,7 +90,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
//System.err.println("regdeo:" + path);
|
||||
|
||||
MethodBody originalBody = body;
|
||||
removeUnreachableInstructions(body.getCode(), body);
|
||||
body.getCode().removeDeadCode(body);
|
||||
Set<Integer> ignoredRegs = new HashSet<>();
|
||||
|
||||
int localReservedCount = body.getLocalReservedCount();
|
||||
@@ -116,7 +111,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
|
||||
MethodBody bodybefore = body;
|
||||
body = bodybefore.clone();
|
||||
setReg = getFirstRegisterSetter(assignmentRef, classIndex, isStatic, scriptIndex, abc, body, ignoredRegs, ignoredRegGets);
|
||||
setReg = getFirstRegisterSetter(assignmentRef, body, abc, ignoredRegs, ignoredRegGets);
|
||||
//System.err.println("setreg " + setReg + " ass:" + assignmentRef.getVal());
|
||||
if (setReg < 0) {
|
||||
break;
|
||||
@@ -140,7 +135,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
AVM2Instruction assignment = assignmentRef.getVal();
|
||||
InstructionDefinition def = assignment.definition;
|
||||
if ((def instanceof SetLocalTypeIns) || (def instanceof GetLocalTypeIns /*First usage -> value undefined*/)) {
|
||||
super.removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, body, Arrays.asList(assignment));
|
||||
super.removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, body, assignment);
|
||||
}
|
||||
|
||||
if (def instanceof GetLocalTypeIns) {
|
||||
@@ -153,7 +148,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
|
||||
originalBody.exceptions = body.exceptions;
|
||||
originalBody.setCode(body.getCode());
|
||||
removeUnreachableInstructions(body.getCode(), body);
|
||||
body.getCode().removeDeadCode(body);
|
||||
//System.err.println("/deo");
|
||||
}
|
||||
|
||||
@@ -178,31 +173,30 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
GetLocalTypeIns glt = (GetLocalTypeIns) ins.definition;
|
||||
int regId = glt.getRegisterId(ins);
|
||||
if (singleRegisters.containsKey(regId)) {
|
||||
code.replaceInstruction(i, makePush(singleRegisters.get(regId).getResult(), cpool), body);
|
||||
code.replaceInstruction(i, cpool.makePush(singleRegisters.get(regId).getResult()), body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getFirstRegisterSetter(Reference<AVM2Instruction> assignment, int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, Set<Integer> ignoredRegisters, Set<Integer> ignoredGets) throws InterruptedException {
|
||||
private int getFirstRegisterSetter(Reference<AVM2Instruction> assignment, MethodBody body, ABC abc, Set<Integer> ignoredRegisters, Set<Integer> ignoredGets) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
|
||||
if (code.code.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return visitCode(assignment, new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, ignoredRegisters, ignoredGets);
|
||||
return visitCode(assignment, new HashSet<>(), new Stack<>(), body, abc, code, 0, code.code.size() - 1, ignoredRegisters, ignoredGets);
|
||||
}
|
||||
|
||||
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, Set<Integer> ignored, Set<Integer> ignoredGets) throws InterruptedException {
|
||||
List<GraphTargetItem> output = new ArrayList<>();
|
||||
AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex);
|
||||
initLocalRegs(localData, body.getLocalReservedCount(), body.max_regs);
|
||||
localData.localRegs.put(0, new NullAVM2Item(null, null)); // this
|
||||
private int visitCode(Reference<AVM2Instruction> assignment, Set<Integer> visited, Stack<Object> stack, MethodBody body, ABC abc, AVM2Code code, int idx, int endIdx, Set<Integer> ignored, Set<Integer> ignoredGets) throws InterruptedException {
|
||||
LocalDataArea localData = new LocalDataArea();
|
||||
initLocalRegs(localData, body.getLocalReservedCount(), body.max_regs, false);
|
||||
localData.localRegisters.put(0, Null.INSTANCE); // this
|
||||
|
||||
List<Integer> toVisit = new ArrayList<>();
|
||||
toVisit.add(idx);
|
||||
List<TranslateStack> toVisitStacks = new ArrayList<>();
|
||||
List<Stack<Object>> toVisitStacks = new ArrayList<>();
|
||||
toVisitStacks.add(stack);
|
||||
outer:
|
||||
while (!toVisit.isEmpty()) {
|
||||
@@ -227,12 +221,17 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
//System.err.println("" + idx + ": " + ins + " stack:" + stack.size());
|
||||
|
||||
// do not throw EmptyStackException, much faster
|
||||
int requiredStackSize = ins.getStackPopCount(localData);
|
||||
int requiredStackSize = def.getStackPopCount(ins, abc);
|
||||
if (stack.size() < requiredStackSize) {
|
||||
continue outer;
|
||||
}
|
||||
|
||||
ins.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
|
||||
localData.operandStack = stack;
|
||||
try {
|
||||
ins.definition.execute(localData, abc.constants, ins);
|
||||
} catch (AVM2ExecutionException ex) {
|
||||
Logger.getLogger(AVM2DeobfuscatorRegisters.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
|
||||
//if (!(def instanceof KillIns))
|
||||
if (def instanceof SetLocalTypeIns) {
|
||||
@@ -312,7 +311,9 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
continue;
|
||||
}
|
||||
toVisit.add(nidx);
|
||||
toVisitStacks.add((TranslateStack) stack.clone());
|
||||
@SuppressWarnings("unchecked")
|
||||
Stack<Object> cloneStack = (Stack<Object>) stack.clone();
|
||||
toVisitStacks.add(cloneStack);
|
||||
}
|
||||
}
|
||||
/*if (ins.definition instanceof IfTypeIns) {
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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.BaseLocalData;
|
||||
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.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.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.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;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
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.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* AVM2 Deobfuscator removing single assigned local registers.
|
||||
*
|
||||
* Example: var a = true; var b = false; ... if(a){ ...ok }else{ not executed }
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AVM2DeobfuscatorRegistersOld extends AVM2DeobfuscatorSimpleOld {
|
||||
|
||||
private Set<Integer> getRegisters(AVM2Code code) {
|
||||
Set<Integer> regs = new HashSet<>();
|
||||
for (AVM2Instruction ins : code.code) {
|
||||
InstructionDefinition def = ins.definition;
|
||||
if (def instanceof SetLocalTypeIns) {
|
||||
int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
|
||||
regs.add(regId);
|
||||
} else if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
|
||||
regs.add(regId);
|
||||
} else {
|
||||
for (int p = 0; p < ins.definition.operands.length; p++) {
|
||||
int op = ins.definition.operands[p];
|
||||
if (op == AVM2Code.DAT_REGISTER_INDEX || op == AVM2Code.DAT_LOCAL_REG_INDEX) {
|
||||
int regId = ins.operands[p];
|
||||
regs.add(regId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return regs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
|
||||
//System.err.println("regdeo:" + path);
|
||||
|
||||
MethodBody originalBody = body;
|
||||
body.getCode().removeDeadCode(body);
|
||||
Set<Integer> ignoredRegs = new HashSet<>();
|
||||
|
||||
int localReservedCount = body.getLocalReservedCount();
|
||||
for (int i = 0; i < localReservedCount; i++) {
|
||||
ignoredRegs.add(i);
|
||||
}
|
||||
|
||||
int setReg = 0;
|
||||
List<Integer> listedRegs = new ArrayList<>();
|
||||
List<MethodBody> listedLastBodies = new ArrayList<>();
|
||||
Set<Integer> ignoredRegGets = new HashSet<>();
|
||||
Reference<AVM2Instruction> assignmentRef = new Reference<>(null);
|
||||
|
||||
while (setReg > -1) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
MethodBody bodybefore = body;
|
||||
body = bodybefore.clone();
|
||||
setReg = getFirstRegisterSetter(assignmentRef, classIndex, isStatic, scriptIndex, abc, body, ignoredRegs, ignoredRegGets);
|
||||
//System.err.println("setreg " + setReg + " ass:" + assignmentRef.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;
|
||||
}
|
||||
|
||||
AVM2Instruction assignment = assignmentRef.getVal();
|
||||
InstructionDefinition def = assignment.definition;
|
||||
if ((def instanceof SetLocalTypeIns) || (def instanceof GetLocalTypeIns /*First usage -> value undefined*/)) {
|
||||
super.removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, body, Arrays.asList(assignment));
|
||||
}
|
||||
|
||||
if (def instanceof GetLocalTypeIns) {
|
||||
ignoredRegGets.add(setReg);
|
||||
}
|
||||
|
||||
listedRegs.add(setReg);
|
||||
listedLastBodies.add(bodybefore);
|
||||
}
|
||||
|
||||
originalBody.exceptions = body.exceptions;
|
||||
originalBody.setCode(body.getCode());
|
||||
body.getCode().removeDeadCode(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) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
|
||||
for (int i = 0; i < code.code.size(); i++) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
AVM2Instruction ins = code.code.get(i);
|
||||
if (((setInss == null) || setInss.contains(ins)) && (ins.definition instanceof SetLocalTypeIns)) {
|
||||
SetLocalTypeIns slt = (SetLocalTypeIns) ins.definition;
|
||||
int regId = slt.getRegisterId(ins);
|
||||
if (singleRegisters.containsKey(regId)) {
|
||||
code.replaceInstruction(i, new AVM2Instruction(ins.offset, DeobfuscatePopIns.getInstance(), null), body);
|
||||
}
|
||||
}
|
||||
|
||||
if (ins.definition instanceof GetLocalTypeIns) {
|
||||
GetLocalTypeIns glt = (GetLocalTypeIns) ins.definition;
|
||||
int regId = glt.getRegisterId(ins);
|
||||
if (singleRegisters.containsKey(regId)) {
|
||||
code.replaceInstruction(i, cpool.makePush(singleRegisters.get(regId).getResult()), body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getFirstRegisterSetter(Reference<AVM2Instruction> assignment, int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, Set<Integer> ignoredRegisters, Set<Integer> ignoredGets) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
|
||||
if (code.code.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return visitCode(assignment, new HashSet<>(), new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, ignoredRegisters, ignoredGets);
|
||||
}
|
||||
|
||||
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, Set<Integer> ignored, Set<Integer> ignoredGets) throws InterruptedException {
|
||||
List<GraphTargetItem> output = new ArrayList<>();
|
||||
AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex);
|
||||
initLocalRegs(localData, body.getLocalReservedCount(), body.max_regs);
|
||||
localData.localRegs.put(0, new NullAVM2Item(null, null)); // this
|
||||
|
||||
List<Integer> toVisit = new ArrayList<>();
|
||||
toVisit.add(idx);
|
||||
List<TranslateStack> toVisitStacks = new ArrayList<>();
|
||||
toVisitStacks.add(stack);
|
||||
outer:
|
||||
while (!toVisit.isEmpty()) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
idx = toVisit.remove(0);
|
||||
stack = toVisitStacks.remove(0);
|
||||
|
||||
while (true) {
|
||||
if (idx > endIdx) {
|
||||
break;
|
||||
}
|
||||
if (visited.contains(idx)) {
|
||||
break;
|
||||
}
|
||||
visited.add(idx);
|
||||
|
||||
AVM2Instruction ins = code.code.get(idx);
|
||||
InstructionDefinition def = ins.definition;
|
||||
//System.err.println("" + idx + ": " + ins + " stack:" + stack.size());
|
||||
|
||||
// do not throw EmptyStackException, much faster
|
||||
int requiredStackSize = ins.getStackPopCount(localData);
|
||||
if (stack.size() < requiredStackSize) {
|
||||
continue outer;
|
||||
}
|
||||
|
||||
ins.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
|
||||
|
||||
//if (!(def instanceof KillIns))
|
||||
if (def instanceof SetLocalTypeIns) {
|
||||
int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
|
||||
if (!ignored.contains(regId)) {
|
||||
assignment.setVal(ins);
|
||||
return regId;
|
||||
}
|
||||
} else if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
|
||||
if (!ignored.contains(regId) && !ignoredGets.contains(regId)) {
|
||||
assignment.setVal(ins);
|
||||
return regId;
|
||||
}
|
||||
} else {
|
||||
for (int p = 0; p < ins.definition.operands.length; p++) {
|
||||
int op = ins.definition.operands[p];
|
||||
if (op == AVM2Code.DAT_REGISTER_INDEX/* || op == AVM2Code.DAT_LOCAL_REG_INDEX ???*/) {
|
||||
int regId = ins.operands[p];
|
||||
if (!ignored.contains(regId)) {
|
||||
assignment.setVal(ins);
|
||||
return regId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idx++;
|
||||
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
|
||||
long address = ins.offset + ins.getBytesLength() + ins.operands[0];
|
||||
idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address));
|
||||
if (idx == -1) {
|
||||
throw new TranslateException("Jump target not found: " + address);
|
||||
}
|
||||
}
|
||||
|
||||
if (ins.isBranch()) {
|
||||
List<Integer> branches = ins.getBranches(new GraphSource() {
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphSourceItem get(int pos) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public int adr2pos(long adr) {
|
||||
return code.adr2pos(adr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long pos2adr(int pos) {
|
||||
return code.pos2adr(pos);
|
||||
}
|
||||
});
|
||||
idx = branches.get(0);
|
||||
for (int n = 1; n < branches.size(); n++) {
|
||||
//visitCode(visited, (TranslateStack) stack.clone(), classIndex, isStatic, body, scriptIndex, abc, code, branches.get(n), endIdx, result);
|
||||
int nidx = branches.get(n);
|
||||
if (visited.contains(nidx)) {
|
||||
continue;
|
||||
}
|
||||
toVisit.add(nidx);
|
||||
toVisitStacks.add((TranslateStack) stack.clone());
|
||||
}
|
||||
}
|
||||
/*if (ins.definition instanceof IfTypeIns) {
|
||||
long address = ins.offset + ins.getBytes().length + ins.operands[0];
|
||||
int newIdx = code.adr2pos(address);
|
||||
if (newIdx == -1) {
|
||||
throw new TranslateException("If target not found: " + address);
|
||||
}
|
||||
visitCode(visited, (TranslateStack) stack.clone(), classIndex, isStatic, body, scriptIndex, abc, code, newIdx, endIdx, result);
|
||||
}*/
|
||||
|
||||
if (ins.definition instanceof ReturnValueIns) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins.definition instanceof ThrowIns) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins.definition instanceof ReturnVoidIns) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,10 @@
|
||||
*/
|
||||
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.LocalDataArea;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException;
|
||||
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;
|
||||
@@ -71,144 +69,63 @@ 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.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.NullAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
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.flash.helpers.SWFDecompilerAdapter;
|
||||
import com.jpexs.decompiler.flash.helpers.collections.FixItemCounterStack;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
import com.jpexs.decompiler.graph.model.TrueItem;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
|
||||
private static final UndefinedAVM2Item UNDEFINED_ITEM = new UndefinedAVM2Item(null, null);
|
||||
|
||||
private static final NotCompileTimeItem NOT_COMPILE_TIME_UNDEFINED_ITEM = new NotCompileTimeItem(null, null, UNDEFINED_ITEM);
|
||||
public class AVM2DeobfuscatorSimple extends SWFDecompilerAdapter {
|
||||
|
||||
private final int executionLimit = 30000;
|
||||
|
||||
@Override
|
||||
public void actionListParsed(ActionList actions, SWF swf) {
|
||||
|
||||
}
|
||||
|
||||
protected AVM2Instruction makePush(Object ovalue, AVM2ConstantPool cpool) {
|
||||
if (ovalue instanceof Long) {
|
||||
long value = (Long) ovalue;
|
||||
if (value >= -128 && value <= 127) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{(int) (long) value});
|
||||
} else if (value >= -32768 && value <= 32767) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{((int) (long) value) & 0xffff});
|
||||
} else {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{cpool.getIntId(value, true)});
|
||||
}
|
||||
}
|
||||
if (ovalue instanceof Double) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{cpool.getDoubleId((Double) ovalue, true)});
|
||||
}
|
||||
if (ovalue instanceof String) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{cpool.getStringId((String) ovalue, true)});
|
||||
}
|
||||
if (ovalue instanceof Boolean) {
|
||||
if ((Boolean) ovalue) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushTrue, null);
|
||||
}
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushFalse, null);
|
||||
}
|
||||
if (ovalue instanceof Null) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushNull, null);
|
||||
}
|
||||
if (ovalue instanceof Undefined) {
|
||||
return new AVM2Instruction(0, AVM2Instructions.PushUndefined, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected AVM2Instruction makePush(AVM2ConstantPool cpool, GraphTargetItem graphTargetItem) {
|
||||
AVM2Instruction ins = null;
|
||||
if (graphTargetItem instanceof IntegerValueAVM2Item) {
|
||||
IntegerValueAVM2Item iv = (IntegerValueAVM2Item) graphTargetItem;
|
||||
return makePush(iv.value, cpool);
|
||||
} else if (graphTargetItem instanceof FloatValueAVM2Item) {
|
||||
FloatValueAVM2Item fv = (FloatValueAVM2Item) graphTargetItem;
|
||||
return makePush(fv.value, cpool);
|
||||
} else if (graphTargetItem instanceof StringAVM2Item) {
|
||||
StringAVM2Item fv = (StringAVM2Item) graphTargetItem;
|
||||
return makePush(fv.getValue(), cpool);
|
||||
} else if (graphTargetItem instanceof TrueItem) {
|
||||
return makePush(Boolean.TRUE, cpool);
|
||||
} else if (graphTargetItem instanceof FalseItem) {
|
||||
return makePush(Boolean.FALSE, cpool);
|
||||
} else if (graphTargetItem instanceof NullAVM2Item) {
|
||||
return makePush(Null.INSTANCE, cpool);
|
||||
} else if (graphTargetItem instanceof UndefinedAVM2Item) {
|
||||
return makePush(Undefined.INSTANCE, cpool);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, List<AVM2Instruction> inlineIns) throws InterruptedException {
|
||||
protected boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, AVM2Instruction inlineIns) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
if (code.code.isEmpty()) {
|
||||
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, null));
|
||||
}
|
||||
Map<Integer, Object> staticRegs = new HashMap<>();
|
||||
if (inlineIns != null && inlineIns.definition instanceof GetLocalTypeIns) {
|
||||
staticRegs.put(((GetLocalTypeIns) inlineIns.definition).getRegisterId(inlineIns), Undefined.INSTANCE);
|
||||
}
|
||||
|
||||
if (code.code.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex);
|
||||
FixItemCounterStack stack = new FixItemCounterStack();
|
||||
LocalDataArea localData = new LocalDataArea();
|
||||
localData.operandStack = stack;
|
||||
|
||||
int localReservedCount = body.getLocalReservedCount();
|
||||
for (int i = 0; i < code.code.size(); i++) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
localData.scopeStack.clear();
|
||||
localData.localRegs.clear();
|
||||
localData.localRegAssignmentIps.clear();
|
||||
localData.localRegs.clear();
|
||||
initLocalRegs(localData, localReservedCount, body.max_regs);
|
||||
localData.clear();
|
||||
initLocalRegs(localData, localReservedCount, body.max_regs, i == 0);
|
||||
|
||||
executeInstructions(staticRegs, body, abc, code, localData, i, code.code.size() - 1, null, inlineIns);
|
||||
if (executeInstructions(staticRegs, body, abc, code, localData, i, code.code.size() - 1, null, inlineIns)) {
|
||||
code.removeDeadCode(body);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void removeUnreachableInstructions(AVM2Code code, MethodBody body) throws InterruptedException {
|
||||
code.removeDeadCode(body);
|
||||
}
|
||||
|
||||
protected boolean removeZeroJumps(AVM2Code code, MethodBody body) throws InterruptedException {
|
||||
boolean result = false;
|
||||
for (int i = 0; i < code.code.size(); i++) {
|
||||
@@ -228,37 +145,21 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool cpool, MethodBody body, boolean isStatic, int classIndex) {
|
||||
AVM2LocalData localData = new AVM2LocalData();
|
||||
localData.isStatic = isStatic;
|
||||
localData.classIndex = classIndex;
|
||||
localData.localRegs = new HashMap<>(body.max_regs);
|
||||
localData.localRegAssignmentIps = new HashMap<>();
|
||||
localData.scopeStack = new ScopeStack(true);
|
||||
localData.methodBody = body;
|
||||
localData.abc = abc;
|
||||
localData.localRegNames = new HashMap<>();
|
||||
localData.scriptIndex = scriptIndex;
|
||||
localData.ip = 0;
|
||||
localData.code = body.getCode();
|
||||
return localData;
|
||||
}
|
||||
|
||||
protected void initLocalRegs(AVM2LocalData localData, int localReservedCount, int maxRegs) {
|
||||
protected void initLocalRegs(LocalDataArea localData, int localReservedCount, int maxRegs, boolean executeFromFirst) {
|
||||
for (int i = 0; i < localReservedCount; i++) {
|
||||
localData.localRegs.put(i, NOT_COMPILE_TIME_UNDEFINED_ITEM);
|
||||
localData.localRegisters.put(i, NotCompileTime.INSTANCE);
|
||||
}
|
||||
for (int i = localReservedCount; i < maxRegs; i++) {
|
||||
localData.localRegs.put(i, UNDEFINED_ITEM);
|
||||
localData.localRegisters.put(i, executeFromFirst ? Undefined.INSTANCE : NotCompileTime.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeInstructions(Map<Integer, GraphTargetItem> staticRegs, MethodBody body, ABC abc, AVM2Code code, AVM2LocalData localData, int idx, int endIdx, ExecutionResult result, List<AVM2Instruction> inlineIns) throws InterruptedException {
|
||||
List<GraphTargetItem> output = new ArrayList<>();
|
||||
|
||||
FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack("");
|
||||
private boolean executeInstructions(Map<Integer, Object> staticRegs, MethodBody body, ABC abc, AVM2Code code, LocalDataArea localData, int idx, int endIdx, ExecutionResult result, AVM2Instruction inlineIns) throws InterruptedException {
|
||||
int instructionsProcessed = 0;
|
||||
|
||||
FixItemCounterStack stack = (FixItemCounterStack) localData.operandStack;
|
||||
Set<Long> refs = code.getImportantOffsets(body);
|
||||
boolean modified = false;
|
||||
while (true) {
|
||||
if (idx > endIdx) {
|
||||
break;
|
||||
@@ -269,56 +170,83 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
}
|
||||
|
||||
AVM2Instruction ins = code.code.get(idx);
|
||||
if (ins.definition instanceof NewFunctionIns) {
|
||||
if (idx + 1 < code.code.size()) {
|
||||
if (code.code.get(idx + 1).definition instanceof PopIns) {
|
||||
code.removeInstruction(idx + 1, body);
|
||||
code.removeInstruction(idx, body);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do not throw EmptyStackException, much faster
|
||||
int requiredStackSize = ins.getStackPopCount(localData);
|
||||
if (stack.size() < requiredStackSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
ins.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
|
||||
if (instructionsProcessed > 0 && refs.contains(ins.offset)) {
|
||||
break;
|
||||
}
|
||||
|
||||
modified = modified | code.inlineJumpExit();
|
||||
InstructionDefinition def = ins.definition;
|
||||
|
||||
if (inlineIns.contains(ins)) {
|
||||
if (inlineIns == ins) {
|
||||
if (def instanceof SetLocalTypeIns) {
|
||||
int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
|
||||
staticRegs.put(regId, localData.localRegs.get(regId).getNotCoerced());
|
||||
staticRegs.put(regId, localData.localRegisters.get(regId));
|
||||
code.replaceInstruction(idx, new AVM2Instruction(0, DeobfuscatePopIns.getInstance(), null), body);
|
||||
}
|
||||
}
|
||||
if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
|
||||
if (staticRegs.containsKey(regId)) {
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
stack.pop();
|
||||
AVM2Instruction pushins = makePush(abc.constants, staticRegs.get(regId));
|
||||
AVM2Instruction pushins = abc.constants.makePush(staticRegs.get(regId));
|
||||
if (pushins == null) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
code.replaceInstruction(idx, pushins, body);
|
||||
stack.push(staticRegs.get(regId));
|
||||
ins = pushins;
|
||||
def = ins.definition;
|
||||
}
|
||||
}
|
||||
|
||||
if (def instanceof NewFunctionIns) {
|
||||
if (idx + 1 < code.code.size()) {
|
||||
if (code.code.get(idx + 1).definition instanceof PopIns) {
|
||||
code.removeInstruction(idx + 1, body);
|
||||
code.removeInstruction(idx, body);
|
||||
modified = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do not throw EmptyStackException, much faster
|
||||
int requiredStackSize = def.getStackPopCount(ins, abc);
|
||||
if (stack.size() < requiredStackSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (requiredStackSize > 0 && !def.isNotCompileTimeSupported()) {
|
||||
boolean notCompileTime = false;
|
||||
for (int i = 0; i < requiredStackSize; i++) {
|
||||
if (stack.peek(i + 1) == NotCompileTime.INSTANCE) {
|
||||
notCompileTime = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (notCompileTime) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (localData.scopeStack.size() < -def.getScopeStackDelta(ins, abc)) {
|
||||
break;
|
||||
}
|
||||
|
||||
boolean supported;
|
||||
try {
|
||||
localData.jump = null;
|
||||
supported = def.execute(localData, abc.constants, ins);
|
||||
} catch (AVM2ExecutionException ex) {
|
||||
supported = false;
|
||||
}
|
||||
|
||||
if (!supported) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean ok = false;
|
||||
// todo: honfika: order by statistics
|
||||
if (def instanceof PushByteIns
|
||||
if (def.isNotCompileTimeSupported() || def instanceof PushByteIns
|
||||
|| def instanceof PushShortIns
|
||||
|| def instanceof PushIntIns
|
||||
|| def instanceof PushDoubleIns
|
||||
@@ -361,6 +289,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
|| def instanceof StrictEqualsIns
|
||||
|| def instanceof PopIns
|
||||
|| def instanceof GetLocalTypeIns
|
||||
|| def instanceof SetLocalTypeIns
|
||||
|| def instanceof NewFunctionIns
|
||||
|| def instanceof CoerceOrConvertTypeIns) {
|
||||
ok = true;
|
||||
@@ -370,43 +299,16 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
break;
|
||||
}
|
||||
|
||||
if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
|
||||
if (staticRegs.containsKey(regId)) {
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
stack.pop();
|
||||
stack.push(staticRegs.get(regId));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean ifed = false;
|
||||
if (def instanceof JumpIns) {
|
||||
if (def instanceof IfTypeIns && !(def instanceof JumpIns)) {
|
||||
long address = ins.offset + ins.getBytesLength() + ins.operands[0];
|
||||
idx = code.adr2pos(address);
|
||||
|
||||
if (idx == -1) {
|
||||
throw new TranslateException("Jump target not found: " + address);
|
||||
}
|
||||
} else if (def instanceof IfTypeIns) {
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GraphTargetItem top = stack.pop();
|
||||
Object res = top.getResult();
|
||||
long address = ins.offset + ins.getBytesLength() + ins.operands[0];
|
||||
int nidx = code.adr2pos(address);//code.indexOf(code.getByAddress(address));
|
||||
int nidx = code.adr2pos(address);
|
||||
AVM2Instruction tarIns = code.code.get(nidx);
|
||||
|
||||
//Some IfType instructions need more than 1 operand, we must pop out all of them
|
||||
int stackCount = -def.getStackDelta(ins, abc);
|
||||
|
||||
if (EcmaScript.toBoolean(res)) {
|
||||
if (localData.jump != null) {
|
||||
//System.err.println("replacing " + ins + " on " + idx + " with jump");
|
||||
AVM2Instruction jumpIns = new AVM2Instruction(0, AVM2Instructions.Jump, new int[]{0});
|
||||
//jumpIns.operands[0] = ins.operands[0] /*- ins.getBytes().length*/ + jumpIns.getBytes().length;
|
||||
@@ -426,8 +328,9 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
//ins.definition = DeobfuscatePopIns.getInstance();
|
||||
idx++;
|
||||
}
|
||||
|
||||
modified = true;
|
||||
ifed = true;
|
||||
//break;
|
||||
} else {
|
||||
idx++;
|
||||
}
|
||||
@@ -444,36 +347,24 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
if (ifed) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (localData.jump != null) {
|
||||
idx = code.adr2pos(localData.jump);
|
||||
|
||||
if (idx == -1) {
|
||||
throw new TranslateException("Jump target not found: " + localData.jump);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionTreeCreated(List<GraphTargetItem> tree, SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] proxyFileCatched(byte[] data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swfParsed(SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abcParsed(ABC abc, SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodBodyParsed(MethodBody body, SWF swf) {
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
removeUnreachableInstructions(code, body);
|
||||
removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, body, new ArrayList<>());
|
||||
code.removeDeadCode(body);
|
||||
removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, body, null);
|
||||
removeZeroJumps(code, body);
|
||||
}
|
||||
|
||||
@@ -483,6 +374,6 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
|
||||
|
||||
public int instructionsProcessed = -1;
|
||||
|
||||
public TranslateStack stack = new TranslateStack("?");
|
||||
public Stack<Object> stack = new Stack<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
* 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.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.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.arithmetic.AddIIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DivideIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns;
|
||||
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.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;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns;
|
||||
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.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.NullAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter;
|
||||
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;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
import com.jpexs.decompiler.graph.model.TrueItem;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter {
|
||||
|
||||
private static final UndefinedAVM2Item UNDEFINED_ITEM = new UndefinedAVM2Item(null, null);
|
||||
|
||||
private static final NotCompileTimeItem NOT_COMPILE_TIME_UNDEFINED_ITEM = new NotCompileTimeItem(null, null, UNDEFINED_ITEM);
|
||||
|
||||
private final int executionLimit = 30000;
|
||||
|
||||
protected AVM2Instruction makePush(AVM2ConstantPool cpool, GraphTargetItem graphTargetItem) {
|
||||
if (graphTargetItem instanceof IntegerValueAVM2Item) {
|
||||
IntegerValueAVM2Item iv = (IntegerValueAVM2Item) graphTargetItem;
|
||||
return cpool.makePush(iv.value);
|
||||
} else if (graphTargetItem instanceof FloatValueAVM2Item) {
|
||||
FloatValueAVM2Item fv = (FloatValueAVM2Item) graphTargetItem;
|
||||
return cpool.makePush(fv.value);
|
||||
} else if (graphTargetItem instanceof StringAVM2Item) {
|
||||
StringAVM2Item fv = (StringAVM2Item) graphTargetItem;
|
||||
return cpool.makePush(fv.getValue());
|
||||
} else if (graphTargetItem instanceof TrueItem) {
|
||||
return cpool.makePush(Boolean.TRUE);
|
||||
} else if (graphTargetItem instanceof FalseItem) {
|
||||
return cpool.makePush(Boolean.FALSE);
|
||||
} else if (graphTargetItem instanceof NullAVM2Item) {
|
||||
return cpool.makePush(Null.INSTANCE);
|
||||
} else if (graphTargetItem instanceof UndefinedAVM2Item) {
|
||||
return cpool.makePush(Undefined.INSTANCE);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, List<AVM2Instruction> inlineIns) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
if (code.code.isEmpty()) {
|
||||
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, null));
|
||||
}
|
||||
}
|
||||
|
||||
if (code.code.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AVM2LocalData localData = newLocalData(scriptIndex, abc, abc.constants, body, isStatic, classIndex);
|
||||
int localReservedCount = body.getLocalReservedCount();
|
||||
for (int i = 0; i < code.code.size(); i++) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
localData.scopeStack.clear();
|
||||
localData.localRegs.clear();
|
||||
localData.localRegAssignmentIps.clear();
|
||||
localData.localRegs.clear();
|
||||
initLocalRegs(localData, localReservedCount, body.max_regs);
|
||||
|
||||
executeInstructions(staticRegs, body, abc, code, localData, i, code.code.size() - 1, null, inlineIns);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean removeZeroJumps(AVM2Code code, MethodBody body) throws InterruptedException {
|
||||
boolean result = false;
|
||||
for (int i = 0; i < code.code.size(); i++) {
|
||||
AVM2Instruction ins = code.code.get(i);
|
||||
if (ins.definition instanceof JumpIns) {
|
||||
if (ins.operands[0] == 0) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
code.removeInstruction(i, body);
|
||||
i--;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool cpool, MethodBody body, boolean isStatic, int classIndex) {
|
||||
AVM2LocalData localData = new AVM2LocalData();
|
||||
localData.isStatic = isStatic;
|
||||
localData.classIndex = classIndex;
|
||||
localData.localRegs = new HashMap<>(body.max_regs);
|
||||
localData.localRegAssignmentIps = new HashMap<>();
|
||||
localData.scopeStack = new ScopeStack(true);
|
||||
localData.methodBody = body;
|
||||
localData.abc = abc;
|
||||
localData.localRegNames = new HashMap<>();
|
||||
localData.scriptIndex = scriptIndex;
|
||||
localData.ip = 0;
|
||||
localData.code = body.getCode();
|
||||
return localData;
|
||||
}
|
||||
|
||||
protected void initLocalRegs(AVM2LocalData localData, int localReservedCount, int maxRegs) {
|
||||
for (int i = 0; i < localReservedCount; i++) {
|
||||
localData.localRegs.put(i, NOT_COMPILE_TIME_UNDEFINED_ITEM);
|
||||
}
|
||||
for (int i = localReservedCount; i < maxRegs; i++) {
|
||||
localData.localRegs.put(i, UNDEFINED_ITEM);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeInstructions(Map<Integer, GraphTargetItem> staticRegs, MethodBody body, ABC abc, AVM2Code code, AVM2LocalData localData, int idx, int endIdx, ExecutionResult result, List<AVM2Instruction> inlineIns) throws InterruptedException {
|
||||
List<GraphTargetItem> output = new ArrayList<>();
|
||||
|
||||
FixItemCounterTranslateStack stack = new FixItemCounterTranslateStack("");
|
||||
int instructionsProcessed = 0;
|
||||
|
||||
while (true) {
|
||||
if (idx > endIdx) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (instructionsProcessed > executionLimit) {
|
||||
break;
|
||||
}
|
||||
|
||||
AVM2Instruction ins = code.code.get(idx);
|
||||
if (ins.definition instanceof NewFunctionIns) {
|
||||
if (idx + 1 < code.code.size()) {
|
||||
if (code.code.get(idx + 1).definition instanceof PopIns) {
|
||||
code.removeInstruction(idx + 1, body);
|
||||
code.removeInstruction(idx, body);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do not throw EmptyStackException, much faster
|
||||
int requiredStackSize = ins.getStackPopCount(localData);
|
||||
if (stack.size() < requiredStackSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
ins.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
|
||||
}
|
||||
|
||||
InstructionDefinition def = ins.definition;
|
||||
|
||||
if (inlineIns.contains(ins)) {
|
||||
if (def instanceof SetLocalTypeIns) {
|
||||
int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
|
||||
staticRegs.put(regId, localData.localRegs.get(regId).getNotCoerced());
|
||||
code.replaceInstruction(idx, new AVM2Instruction(0, DeobfuscatePopIns.getInstance(), null), body);
|
||||
}
|
||||
}
|
||||
if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
|
||||
if (staticRegs.containsKey(regId)) {
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
stack.pop();
|
||||
AVM2Instruction pushins = makePush(abc.constants, staticRegs.get(regId));
|
||||
if (pushins == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
code.replaceInstruction(idx, pushins, body);
|
||||
stack.push(staticRegs.get(regId));
|
||||
ins = pushins;
|
||||
def = ins.definition;
|
||||
}
|
||||
}
|
||||
|
||||
boolean ok = false;
|
||||
// todo: honfika: order by statistics
|
||||
if (def instanceof PushByteIns
|
||||
|| def instanceof PushShortIns
|
||||
|| def instanceof PushIntIns
|
||||
|| def instanceof PushDoubleIns
|
||||
|| def instanceof PushStringIns
|
||||
|| def instanceof PushNullIns
|
||||
|| def instanceof PushUndefinedIns
|
||||
|| def instanceof PushFalseIns
|
||||
|| def instanceof PushTrueIns
|
||||
|| def instanceof DupIns
|
||||
|| def instanceof SwapIns
|
||||
|| def instanceof AddIns
|
||||
|| def instanceof AddIIns
|
||||
|| def instanceof SubtractIns
|
||||
|| def instanceof SubtractIIns
|
||||
|| def instanceof ModuloIns
|
||||
|| def instanceof MultiplyIns
|
||||
|| def instanceof MultiplyIIns//
|
||||
|| def instanceof DivideIns//
|
||||
|| def instanceof BitAndIns
|
||||
|| def instanceof BitXorIns
|
||||
|| def instanceof BitOrIns
|
||||
|| def instanceof LShiftIns
|
||||
|| def instanceof RShiftIns
|
||||
|| def instanceof URShiftIns
|
||||
|| def instanceof EqualsIns
|
||||
|| def instanceof NotIns
|
||||
|| def instanceof NegateIns//
|
||||
|| def instanceof NegateIIns//
|
||||
|| def instanceof IncrementIns//
|
||||
|| def instanceof IncrementIIns//
|
||||
|| def instanceof DecrementIns//
|
||||
|| def instanceof DecrementIIns //
|
||||
|| def instanceof IfTypeIns
|
||||
|| def instanceof JumpIns
|
||||
|| def instanceof EqualsIns
|
||||
|| def instanceof LessEqualsIns
|
||||
|| def instanceof GreaterEqualsIns
|
||||
|| def instanceof GreaterThanIns
|
||||
|| def instanceof LessThanIns
|
||||
|| def instanceof StrictEqualsIns
|
||||
|| def instanceof PopIns
|
||||
|| def instanceof GetLocalTypeIns
|
||||
|| def instanceof NewFunctionIns
|
||||
|| def instanceof CoerceOrConvertTypeIns) {
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (def instanceof GetLocalTypeIns) {
|
||||
int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
|
||||
if (staticRegs.containsKey(regId)) {
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
stack.pop();
|
||||
stack.push(staticRegs.get(regId));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean ifed = false;
|
||||
if (def instanceof JumpIns) {
|
||||
long address = ins.offset + ins.getBytesLength() + ins.operands[0];
|
||||
idx = code.adr2pos(address);
|
||||
|
||||
if (idx == -1) {
|
||||
throw new TranslateException("Jump target not found: " + address);
|
||||
}
|
||||
} else if (def instanceof IfTypeIns) {
|
||||
if (stack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GraphTargetItem top = stack.pop();
|
||||
Object res = top.getResult();
|
||||
long address = ins.offset + ins.getBytesLength() + ins.operands[0];
|
||||
int nidx = code.adr2pos(address);//code.indexOf(code.getByAddress(address));
|
||||
AVM2Instruction tarIns = code.code.get(nidx);
|
||||
|
||||
//Some IfType instructions need more than 1 operand, we must pop out all of them
|
||||
int stackCount = -def.getStackDelta(ins, abc);
|
||||
|
||||
if (EcmaScript.toBoolean(res)) {
|
||||
//System.err.println("replacing " + ins + " on " + idx + " with jump");
|
||||
AVM2Instruction jumpIns = new AVM2Instruction(0, AVM2Instructions.Jump, new int[]{0});
|
||||
//jumpIns.operands[0] = ins.operands[0] /*- ins.getBytes().length*/ + jumpIns.getBytes().length;
|
||||
code.replaceInstruction(idx, jumpIns, body);
|
||||
jumpIns.operands[0] = (int) (tarIns.offset - jumpIns.offset - jumpIns.getBytesLength());
|
||||
for (int s = 0; s < stackCount; s++) {
|
||||
code.insertInstruction(idx, new AVM2Instruction(ins.offset, DeobfuscatePopIns.getInstance(), null), true, body);
|
||||
}
|
||||
|
||||
idx = code.adr2pos(jumpIns.offset + jumpIns.getBytesLength() + jumpIns.operands[0]);
|
||||
} else {
|
||||
//System.err.println("replacing " + ins + " on " + idx + " with pop");
|
||||
code.replaceInstruction(idx, new AVM2Instruction(ins.offset, DeobfuscatePopIns.getInstance(), null), body);
|
||||
for (int s = 1 /*first is replaced*/; s < stackCount; s++) {
|
||||
code.insertInstruction(idx, new AVM2Instruction(ins.offset, DeobfuscatePopIns.getInstance(), null), true, body);
|
||||
}
|
||||
//ins.definition = DeobfuscatePopIns.getInstance();
|
||||
idx++;
|
||||
}
|
||||
ifed = true;
|
||||
//break;
|
||||
} else {
|
||||
idx++;
|
||||
}
|
||||
|
||||
instructionsProcessed++;
|
||||
|
||||
if (result != null && stack.allItemsFixed()) {
|
||||
result.idx = idx == code.code.size() ? idx - 1 : idx;
|
||||
result.instructionsProcessed = instructionsProcessed;
|
||||
result.stack.clear();
|
||||
result.stack.addAll(stack);
|
||||
}
|
||||
|
||||
if (ifed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
|
||||
AVM2Code code = body.getCode();
|
||||
code.removeDeadCode(body);
|
||||
removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, body, new ArrayList<>());
|
||||
removeZeroJumps(code, body);
|
||||
}
|
||||
|
||||
class ExecutionResult {
|
||||
|
||||
public int idx = -1;
|
||||
|
||||
public int instructionsProcessed = -1;
|
||||
|
||||
public TranslateStack stack = new TranslateStack("?");
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
|
||||
public String comment;
|
||||
|
||||
public boolean ignored = false;
|
||||
private boolean ignored = false;
|
||||
|
||||
public long mappedOffset = -1;
|
||||
|
||||
@@ -303,7 +303,7 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
if (ignored) {
|
||||
if (isIgnored()) {
|
||||
return " ;ignored";
|
||||
}
|
||||
if ((comment == null) || comment.isEmpty()) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
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.Multiname;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
@@ -124,6 +125,10 @@ public abstract class InstructionDefinition implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) throws AVM2ExecutionException {
|
||||
//throw new UnsupportedOperationException("Instruction " + instructionName + " not implemented");
|
||||
return false;
|
||||
@@ -164,18 +169,31 @@ public abstract class InstructionDefinition implements Serializable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void resolveMultiname(LocalDataArea localData, AVM2ConstantPool constants, int multinameIndex) {
|
||||
if (multinameIndex > 0 && multinameIndex < constants.getMultinameCount()) {
|
||||
Multiname multiname = constants.getMultiname(multinameIndex);
|
||||
if (multiname.needsName()) {
|
||||
Object name = localData.operandStack.pop();
|
||||
}
|
||||
if (multiname.needsNs()) {
|
||||
Object ns = localData.operandStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected FullMultinameAVM2Item resolveMultiname(AVM2LocalData localData, boolean property, TranslateStack stack, AVM2ConstantPool constants, int multinameIndex, AVM2Instruction ins) {
|
||||
GraphTargetItem ns = null;
|
||||
GraphTargetItem name = null;
|
||||
if (multinameIndex > 0 && multinameIndex < constants.getMultinameCount()) {
|
||||
if (constants.getMultiname(multinameIndex).needsName()) {
|
||||
Multiname multiname = constants.getMultiname(multinameIndex);
|
||||
if (multiname.needsName()) {
|
||||
name = stack.pop();
|
||||
}
|
||||
if (constants.getMultiname(multinameIndex).needsNs()) {
|
||||
if (multiname.needsNs()) {
|
||||
ns = stack.pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new FullMultinameAVM2Item(property, ins, localData.lineStartInstruction, multinameIndex, name, ns);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ConstructIns extends InstructionDefinition {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
Object obj = lda.operandStack.pop();*/
|
||||
lda.executionException = "Cannot call constructor";
|
||||
//lda.executionException = "Cannot call constructor";
|
||||
return false;
|
||||
//call construct property of obj
|
||||
//push new instance
|
||||
|
||||
@@ -48,7 +48,7 @@ public class ConstructPropIns extends InstructionDefinition {
|
||||
}*/
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
lda.executionException = "Cannot construct property";
|
||||
//lda.executionException = "Cannot construct property";
|
||||
return false;
|
||||
//create property
|
||||
//push new instance
|
||||
|
||||
@@ -43,7 +43,7 @@ public class ConstructSuperIns extends InstructionDefinition {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
Object obj = lda.operandStack.pop();*/
|
||||
lda.executionException = "Cannot call super constructor";
|
||||
//lda.executionException = "Cannot call super constructor";
|
||||
return false;
|
||||
//call construct property of obj
|
||||
//do not push anything
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.CallAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
@@ -35,18 +36,29 @@ public class CallIns extends InstructionDefinition {
|
||||
super(0x41, "call", new int[]{AVM2Code.DAT_ARG_COUNT}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
/*int argCount = ins.getParamAsLong(constants, 0).intValue();
|
||||
List<Object> passArguments = new ArrayList<Object>();
|
||||
int argCount = ins.getParamAsLong(constants, 0).intValue();
|
||||
/* List<Object> passArguments = new ArrayList<Object>();
|
||||
for (int i = argCount - 1; i >= 0; i--) {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
Object receiver = lda.operandStack.pop();
|
||||
Object function = lda.operandStack.pop();*/
|
||||
lda.executionException = "Call to unknown function";
|
||||
return false;
|
||||
}*/
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
lda.operandStack.pop();
|
||||
}
|
||||
|
||||
Object receiver = lda.operandStack.pop();
|
||||
Object function = lda.operandStack.pop();
|
||||
|
||||
//push(result)
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
//lda.executionException = "Call to unknown function";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.CallMethodAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
@@ -35,18 +36,29 @@ public class CallMethodIns extends InstructionDefinition {
|
||||
super(0x43, "callmethod", new int[]{AVM2Code.DAT_METHOD_INDEX, AVM2Code.DAT_ARG_COUNT}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
/*int methodIndex = ins.getParamAsLong(constants, 0).intValue(); //index of object's method
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
List<Object> passArguments = new ArrayList<Object>();
|
||||
//int methodIndex = ins.getParamAsLong(constants, 0).intValue(); //index of object's method
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
/*List<Object> passArguments = new ArrayList<Object>();
|
||||
for (int i = argCount - 1; i >= 0; i--) {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
Object receiver = lda.operandStack.pop();*/
|
||||
lda.executionException = "Call to unknown method";
|
||||
return false;
|
||||
}*/
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
lda.operandStack.pop();
|
||||
}
|
||||
|
||||
Object receiver = lda.operandStack.pop();
|
||||
|
||||
//push(result)
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
//lda.executionException = "Call to unknown method";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,9 +18,12 @@ package com.jpexs.decompiler.flash.abc.avm2.instructions.executing;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.CallPropertyAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
@@ -33,6 +36,33 @@ public class CallPropLexIns extends CallPropertyIns {
|
||||
instructionCode = 0x4c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
int multinameIndex = ins.operands[0];
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
/*List<Object> passArguments = new ArrayList<Object>();
|
||||
for (int i = argCount - 1; i >= 0; i--) {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}*/
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
lda.operandStack.pop();
|
||||
}
|
||||
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
resolveMultiname(lda, constants, multinameIndex);
|
||||
Object obj = lda.operandStack.pop();
|
||||
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
//lda.executionException = "Call to unknown property";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) {
|
||||
int multinameIndex = ins.operands[0];
|
||||
|
||||
@@ -36,22 +36,32 @@ public class CallPropVoidIns extends InstructionDefinition {
|
||||
super(0x4f, "callpropvoid", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
//same as callproperty
|
||||
/*
|
||||
int multinameIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
List<Object> passArguments = new ArrayList<Object>();
|
||||
int multinameIndex = ins.operands[0];
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
/*List<Object> passArguments = new ArrayList<Object>();
|
||||
for (int i = argCount - 1; i >= 0; i--) {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
Object obj = lda.operandStack.pop();*/
|
||||
lda.executionException = "Call to unknown property";
|
||||
return false;
|
||||
}*/
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
lda.operandStack.pop();
|
||||
}
|
||||
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
resolveMultiname(lda, constants, multinameIndex);
|
||||
Object obj = lda.operandStack.pop();
|
||||
|
||||
//do not push anything
|
||||
//lda.executionException = "Call to unknown property";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.CallPropertyAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
@@ -36,20 +37,31 @@ public class CallPropertyIns extends InstructionDefinition {
|
||||
super(0x46, "callproperty", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
/*int multinameIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
List<Object> passArguments = new ArrayList<Object>();
|
||||
int multinameIndex = ins.operands[0];
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
/*List<Object> passArguments = new ArrayList<Object>();
|
||||
for (int i = argCount - 1; i >= 0; i--) {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
Object obj = lda.operandStack.pop();*/
|
||||
lda.executionException = "Call to unknown property";
|
||||
return false;
|
||||
//push(result)
|
||||
}*/
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
lda.operandStack.pop();
|
||||
}
|
||||
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
resolveMultiname(lda, constants, multinameIndex);
|
||||
Object obj = lda.operandStack.pop();
|
||||
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
//lda.executionException = "Call to unknown property";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.CallStaticAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
@@ -35,18 +36,29 @@ public class CallStaticIns extends InstructionDefinition {
|
||||
super(0x44, "callstatic", new int[]{AVM2Code.DAT_METHOD_INDEX, AVM2Code.DAT_ARG_COUNT}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
/*int methodIndex = ins.getParamAsLong(constants, 0).intValue(); //index of method_info
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
List<Object> passArguments = new ArrayList<Object>();
|
||||
//int methodIndex = ins.getParamAsLong(constants, 0).intValue(); //index of method_info
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
/*List<Object> passArguments = new ArrayList<Object>();
|
||||
for (int i = argCount - 1; i >= 0; i--) {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
Object receiver = lda.operandStack.pop();*/
|
||||
lda.executionException = "Call to unknown static method";
|
||||
return false;
|
||||
}*/
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
lda.operandStack.pop();
|
||||
}
|
||||
|
||||
Object receiver = lda.operandStack.pop();
|
||||
|
||||
//push(result)
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
//lda.executionException = "Call to unknown static method";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.CallSuperAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
@@ -36,20 +37,31 @@ public class CallSuperIns extends InstructionDefinition {
|
||||
super(0x45, "callsuper", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
/*int multinameIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
List<Object> passArguments = new ArrayList<Object>();
|
||||
int multinameIndex = ins.operands[0];
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
/*List<Object> passArguments = new ArrayList<Object>();
|
||||
for (int i = argCount - 1; i >= 0; i--) {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
Object receiver = lda.operandStack.pop();*/
|
||||
lda.executionException = "Call to unknown super method";
|
||||
return false;
|
||||
//push(result)
|
||||
}*/
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
lda.operandStack.pop();
|
||||
}
|
||||
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
resolveMultiname(lda, constants, multinameIndex);
|
||||
Object receiver = lda.operandStack.pop();
|
||||
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
//lda.executionException = "Call to unknown super method";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,20 +36,31 @@ public class CallSuperVoidIns extends InstructionDefinition {
|
||||
super(0x4e, "callsupervoid", new int[]{AVM2Code.DAT_MULTINAME_INDEX, AVM2Code.DAT_ARG_COUNT}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
/*int multinameIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
List<Object> passArguments = new ArrayList<Object>();
|
||||
int multinameIndex = ins.operands[0];
|
||||
int argCount = ins.getParamAsLong(constants, 1).intValue();
|
||||
/*List<Object> passArguments = new ArrayList<Object>();
|
||||
for (int i = argCount - 1; i >= 0; i--) {
|
||||
passArguments.set(i, lda.operandStack.pop());
|
||||
}
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
Object receiver = lda.operandStack.pop();*/
|
||||
lda.executionException = "Call to unknown super method";
|
||||
return false;
|
||||
}*/
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
lda.operandStack.pop();
|
||||
}
|
||||
|
||||
//if multiname[multinameIndex] is runtime
|
||||
//pop(name) pop(ns)
|
||||
resolveMultiname(lda, constants, multinameIndex);
|
||||
Object receiver = lda.operandStack.pop();
|
||||
|
||||
//do not push anything
|
||||
//lda.executionException = "Call to unknown super method";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.DecLocalAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.SubtractAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
@@ -40,7 +41,10 @@ public class DecLocalIIns extends InstructionDefinition {
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
int locRegIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
Object obj = lda.localRegisters.get(locRegIndex);
|
||||
lda.localRegisters.put(locRegIndex, EcmaScript.toInt32(obj) - 1);
|
||||
if (obj != NotCompileTime.INSTANCE) {
|
||||
lda.localRegisters.put(locRegIndex, EcmaScript.toInt32(obj) - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.DecLocalAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.SubtractAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
@@ -40,7 +41,10 @@ public class DecLocalIns extends InstructionDefinition {
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
int locRegIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
Object obj = lda.localRegisters.get(locRegIndex);
|
||||
lda.localRegisters.put(locRegIndex, EcmaScript.toNumber(obj) - 1);
|
||||
if (obj != NotCompileTime.INSTANCE) {
|
||||
lda.localRegisters.put(locRegIndex, EcmaScript.toNumber(obj) - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.IncLocalAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.AddAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
@@ -40,7 +41,10 @@ public class IncLocalIIns extends InstructionDefinition {
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
int locRegIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
Object obj = lda.localRegisters.get(locRegIndex);
|
||||
lda.localRegisters.put(locRegIndex, EcmaScript.toInt32(obj) + 1);
|
||||
if (obj != NotCompileTime.INSTANCE) {
|
||||
lda.localRegisters.put(locRegIndex, EcmaScript.toInt32(obj) + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.IncLocalAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.AddAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
@@ -40,7 +41,10 @@ public class IncLocalIns extends InstructionDefinition {
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
int locRegIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
Object obj = lda.localRegisters.get(locRegIndex);
|
||||
lda.localRegisters.put(locRegIndex, EcmaScript.toNumber(obj) - 1);
|
||||
if (obj != NotCompileTime.INSTANCE) {
|
||||
lda.localRegisters.put(locRegIndex, EcmaScript.toNumber(obj) - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public class DeletePropertyIns extends InstructionDefinition {
|
||||
//pop(name) pop(ns)
|
||||
Object obj = lda.operandStack.pop();
|
||||
//push true if removed*/
|
||||
lda.executionException = "Cannot remove property";
|
||||
//lda.executionException = "Cannot remove property";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
@@ -35,12 +36,19 @@ public class FindPropertyIns extends InstructionDefinition {
|
||||
super(0x5e, "findproperty", new int[]{AVM2Code.DAT_MULTINAME_INDEX}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
//int multiIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
int multinameIndex = ins.operands[0];
|
||||
//if is runtime
|
||||
//pop(name), pop(ns)
|
||||
lda.executionException = "Cannot find property";
|
||||
resolveMultiname(lda, constants, multinameIndex);
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
//lda.executionException = "Cannot find property";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
@@ -35,13 +36,20 @@ public class FindPropertyStrictIns extends InstructionDefinition {
|
||||
super(0x5d, "findpropstrict", new int[]{AVM2Code.DAT_MULTINAME_INDEX}, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
//int multiIndex = ins.getParamAsLong(constants, 0).intValue();
|
||||
int multinameIndex = ins.operands[0];
|
||||
//if is runtime
|
||||
//pop(name), pop(ns)
|
||||
lda.executionException = "Cannot find property";
|
||||
return false;
|
||||
resolveMultiname(lda, constants, multinameIndex);
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
//lda.executionException = "Cannot find property";
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,6 +32,11 @@ public class PushScopeIns extends InstructionDefinition {
|
||||
super(0x30, "pushscope", new int[]{}, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotCompileTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) {
|
||||
lda.scopeStack.push(lda.operandStack.pop());
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.AsTypeAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
@@ -40,8 +41,9 @@ public class AsTypeIns extends InstructionDefinition {
|
||||
//Long typeIndex = ins.getParamAsLong(constants, 0);
|
||||
Object obj = lda.operandStack.pop();
|
||||
//if multiname[typeIndex]==obj
|
||||
lda.operandStack.push(obj);
|
||||
//lda.operandStack.push(obj);
|
||||
//else push null
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.operations.AsTypeAVM2Item;
|
||||
import com.jpexs.decompiler.flash.ecma.NotCompileTime;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
@@ -38,8 +39,9 @@ public class AsTypeLateIns extends InstructionDefinition {
|
||||
//Object objClass = lda.operandStack.pop();
|
||||
Object obj = lda.operandStack.pop();
|
||||
//if obj.class=objClass
|
||||
lda.operandStack.push(obj);
|
||||
//lda.operandStack.push(obj);
|
||||
//else push null
|
||||
lda.operandStack.push(NotCompileTime.INSTANCE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,11 @@
|
||||
package com.jpexs.decompiler.flash.abc.avm2.model;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.types.Namespace;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
package com.jpexs.decompiler.flash.action.deobfuscation;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.flash.action.ActionListReader;
|
||||
@@ -78,7 +75,8 @@ import com.jpexs.decompiler.flash.action.swf5.ActionTypeOf;
|
||||
import com.jpexs.decompiler.flash.action.swf6.ActionGreater;
|
||||
import com.jpexs.decompiler.flash.action.swf6.ActionStringGreater;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerListener;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter;
|
||||
import com.jpexs.decompiler.flash.helpers.collections.FixItemCounterStack;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
import com.jpexs.decompiler.graph.model.PushItem;
|
||||
@@ -95,7 +93,7 @@ import java.util.Stack;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionDeobfuscator implements SWFDecompilerListener {
|
||||
public class ActionDeobfuscator extends SWFDecompilerAdapter {
|
||||
|
||||
private final int executionLimit = 5000;
|
||||
|
||||
@@ -665,27 +663,6 @@ public class ActionDeobfuscator implements SWFDecompilerListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] proxyFileCatched(byte[] data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swfParsed(SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abcParsed(ABC abc, SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodBodyParsed(MethodBody body, SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
|
||||
}
|
||||
|
||||
class ExecutionResult {
|
||||
|
||||
public ActionItem item;
|
||||
|
||||
@@ -14,28 +14,19 @@
|
||||
* 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.ecma;
|
||||
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.List;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class UnknownJumpException extends RuntimeException {
|
||||
public class NotCompileTime implements Serializable {
|
||||
|
||||
public TranslateStack stack;
|
||||
public static NotCompileTime INSTANCE = new NotCompileTime();
|
||||
|
||||
public int ip;
|
||||
|
||||
public List<GraphTargetItem> output;
|
||||
|
||||
public UnknownJumpException(TranslateStack stack, int ip, List<GraphTargetItem> output) {
|
||||
this.stack = stack;
|
||||
this.ip = ip;
|
||||
this.output = output;
|
||||
private NotCompileTime() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Unknown jump to " + ip;
|
||||
return "not_compile_time";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.helpers;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.action.ActionList;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SWFDecompilerAdapter implements SWFDecompilerListener {
|
||||
|
||||
@Override
|
||||
public byte[] proxyFileCatched(byte[] data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swfParsed(SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionListParsed(ActionList actions, SWF swf) throws InterruptedException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionTreeCreated(List<GraphTargetItem> tree, SWF swf) throws InterruptedException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abcParsed(ABC abc, SWF swf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodBodyParsed(MethodBody body, SWF swf) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only called when deobfuscation is enabled and new
|
||||
* deobfuscation mode is selected
|
||||
*
|
||||
* @param path
|
||||
* @param classIndex
|
||||
* @param isStatic
|
||||
* @param scriptIndex
|
||||
* @param abc
|
||||
* @param trait
|
||||
* @param methodInfo
|
||||
* @param body
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,19 @@ public interface SWFDecompilerListener {
|
||||
|
||||
void methodBodyParsed(MethodBody body, SWF swf);
|
||||
|
||||
// this method is only called when deobfuscation is enabled and new deobfuscation mode is selected
|
||||
/**
|
||||
* this method is only called when deobfuscation is enabled and new
|
||||
* deobfuscation mode is selected
|
||||
*
|
||||
* @param path
|
||||
* @param classIndex
|
||||
* @param isStatic
|
||||
* @param scriptIndex
|
||||
* @param abc
|
||||
* @param trait
|
||||
* @param methodInfo
|
||||
* @param body
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.deobfuscation;
|
||||
package com.jpexs.decompiler.flash.helpers.collections;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
Reference in New Issue
Block a user