Improved deobfuscation

This commit is contained in:
Jindra Petk
2013-08-03 08:49:17 +02:00
parent 3fdfaa5b56
commit ae0ad85df2
24 changed files with 415 additions and 170 deletions

View File

@@ -61,6 +61,7 @@ import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Stack;
@@ -90,6 +91,10 @@ public class SWFInputStream extends InputStream {
private ByteArrayOutputStream buffer;
private static boolean DEOBFUSCATION_ALL_CODE_IN_PREVIOUS_TAG = (Boolean) Configuration.getConfig("deobfuscateUsePrevTagOnly", true);
public int getVersion() {
return version;
}
public int getBufferLength() {
return buffer.size();
}
@@ -636,33 +641,6 @@ public class SWFInputStream extends InputStream {
if (ins.isBranch() || ins.isJump()) {
if (deobfuscate && (ins instanceof ActionIf) && !stack.isEmpty() && (stack.peek().isCompileTime() && (!stack.peek().hasSideEffect()))) {
ActionIf aif = (ActionIf) ins;
if (aif.ignoreUsed && (!aif.jumpUsed)) {
ins.setIgnored(true, 0);
}
if ((!aif.ignoreUsed) && aif.jumpUsed) {
ActionJump jmpIns = new ActionJump(aif.getJumpOffset());
((ActionJump) jmpIns).setAddress(aif.getAddress(), version);
code.set(ip, (ActionJump) jmpIns);
}
if ((aif.ignoreUsed && (!aif.jumpUsed)) || ((!aif.ignoreUsed) && aif.jumpUsed)) {
List<GraphSourceItemPos> needed = stack.peek().getNeededSources();
for (GraphSourceItemPos ig : needed) {
/*if (ig.item instanceof ActionPush) {
if (!((ActionPush) ig.item).ignoredParts.contains(ig.pos)) {
((ActionPush) ig.item).ignoredParts.add(ig.pos);
if (((ActionPush) ig.item).ignoredParts.size() == ((ActionPush) ig.item).values.size()) {
((Action) ig.item).setIgnored(true, 0);
}
}
} else {
}*/
((Action) ig.item).setIgnored(true, ig.pos);
}
}
boolean condition = EcmaScript.toBoolean(stack.peek().getResult());
if (debugMode) {
if (condition) {
@@ -683,7 +661,7 @@ public class SWFInputStream extends InputStream {
@SuppressWarnings("unchecked")
Stack<GraphTargetItem> brStack = (Stack<GraphTargetItem>) stack.clone();
if (b >= 0) {
getConstantPool(listeners, cpool, localData, brStack, output, code, b, constantPools, visited, version, endIp, path);
getConstantPool(listeners, cpool, prepareLocalBranch(localData), brStack, output, code, b, constantPools, visited, version, endIp, path);
} else {
if (debugMode) {
System.out.println("Negative branch:" + b);
@@ -714,6 +692,20 @@ public class SWFInputStream extends InputStream {
return ret;
}
private static List<Object> prepareLocalBranch(List<Object> localData) {
@SuppressWarnings("unchecked")
HashMap<Integer, String> regNames = (HashMap<Integer, String>) localData.get(0);
@SuppressWarnings("unchecked")
HashMap<String, GraphTargetItem> variables = (HashMap<String, GraphTargetItem>) localData.get(1);
@SuppressWarnings("unchecked")
HashMap<String, GraphTargetItem> functions = (HashMap<String, GraphTargetItem>) localData.get(2);
List<Object> ret = new ArrayList<>();
ret.add(new HashMap<Integer, String>(regNames));
ret.add(new HashMap<String, GraphTargetItem>(variables));
ret.add(new HashMap<String, GraphTargetItem>(functions));
return ret;
}
/**
* Reads list of actions from the stream. Reading ends with
* ActionEndFlag(=0) or end of the stream.
@@ -747,7 +739,7 @@ public class SWFInputStream extends InputStream {
method = 2;
goesPrev = readActionListAtPos(true, localData, stack, cpool, sis, rri, ip, retdups, ip);
}*/
goesPrev = readActionListAtPos(listeners, new ArrayList<GraphTargetItem>(), new HashMap<Long, List<GraphSourceItemContainer>>(), address, containerSWFOffset, false, true, localData, stack, cpool, sis, rri, ip, retdups, ip, endip, path);
goesPrev = readActionListAtPos(listeners, new ArrayList<GraphTargetItem>(), new HashMap<Long, List<GraphSourceItemContainer>>(), address, containerSWFOffset, localData, stack, cpool, sis, rri, ip, retdups, ip, endip, path, new HashMap<Integer, Integer>());
if (goesPrev) {
} else {
@@ -777,15 +769,6 @@ public class SWFInputStream extends InputStream {
}
List<ConstantPool> pools;
StringBuilder br = new StringBuilder();
for (int i = 0; i < ret.size(); i++) {
br.append(i);
br.append(", loc");
br.append(Helper.formatAddress(((Action) ret.get(i)).getAddress()));
br.append(": ");
br.append(((Action) ret.get(i)).getASMSource(new ArrayList<GraphSourceItem>(), new ArrayList<Long>(), cpool.constants, version, false));
br.append("\r\n");
}
ret = Action.removeNops(0, ret, version, 0, path);
pools = getConstantPool(listeners, new ActionGraphSource(ret, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), 0, version, path);
@@ -815,7 +798,7 @@ public class SWFInputStream extends InputStream {
}
@SuppressWarnings("unchecked")
private static boolean readActionListAtPos(List<DisassemblyListener> listeners, List<GraphTargetItem> output, HashMap<Long, List<GraphSourceItemContainer>> containers, long address, long containerSWFOffset, boolean notCompileTime, boolean enableVariables, List<Object> localData, Stack<GraphTargetItem> stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List<Action> ret, int startIp, int endip, String path) throws IOException {
private static boolean readActionListAtPos(List<DisassemblyListener> listeners, List<GraphTargetItem> output, HashMap<Long, List<GraphSourceItemContainer>> containers, long address, long containerSWFOffset, List<Object> localData, Stack<GraphTargetItem> stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List<Action> ret, int startIp, int endip, String path, Map<Integer, Integer> visited) throws IOException {
boolean debugMode = false;
boolean decideBranch = false;
@@ -826,7 +809,14 @@ public class SWFInputStream extends InputStream {
long filePos = rri.getPos();
Scanner sc = new Scanner(System.in, "utf-8");
int prevIp = ip;
loopip:
while (((endip == -1) || (endip > ip)) && (a = sis.readAction(rri)) != null) {
if (!visited.containsKey(ip)) {
visited.put(ip, 0);
}
int curVisited = visited.get(ip);
curVisited++;
visited.put(ip, curVisited);
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).progress("Reading", rri.getCount(), rri.length());
}
@@ -908,9 +898,6 @@ public class SWFInputStream extends InputStream {
ensureCapacity(ret, ip);
int newip = -1;
if (!enableVariables && (!(ret.get(ip) instanceof ActionNop))) {
break;
}
if (a instanceof ActionConstantPool) {
if (cpool == null) {
@@ -943,22 +930,13 @@ public class SWFInputStream extends InputStream {
} else if (next.equals("c")) {
goaif = true;
}
} else if (deobfuscate && top.isCompileTime() && (!top.hasSideEffect()) && ((!top.isVariableComputed()) || (top.isVariableComputed() && enableVariables && (!notCompileTime)))) {
//if(top.isCompileTime()) {
//if(false){
if (enableVariables) {
((ActionIf) a).compileTime = true;
}
} else if (deobfuscate && top.isCompileTime() && (!top.hasSideEffect())) {
((ActionIf) a).compileTime = true;
if (debugMode) {
System.err.print("is compiletime -> ");
}
if (EcmaScript.toBoolean(top.getResult())) {
newip = rri.getPos() + aif.getJumpOffset();
//rri.setPos(newip);
if (((!enableVariables) || (!top.isVariableComputed())) && (!aif.ignoreUsed)) {
a = new ActionJump(aif.getJumpOffset());
a.setAddress(aif.getAddress(), SWF.DEFAULT_VERSION);
}
aif.jumpUsed = true;
if (aif.ignoreUsed) {
aif.compileTime = false;
@@ -974,32 +952,7 @@ public class SWFInputStream extends InputStream {
if (debugMode) {
System.err.println("ignore");
}
if (((!enableVariables) || (!top.isVariableComputed())) && (!aif.jumpUsed)) {
//a = new ActionNop();
aif.setIgnored(true, 0);
//a.setAddress(aif.getAddress(), SWF.DEFAULT_VERSION);
}
}
if (((!enableVariables) || (!top.isVariableComputed())) && (!(aif.jumpUsed && aif.ignoreUsed))) {
List<GraphSourceItemPos> needed = top.getNeededSources();
for (GraphSourceItemPos ig : needed) {
if (ig.item == null) {
continue;
}
if (ig.item instanceof ActionPush) {
if (!((ActionPush) ig.item).ignoredParts.contains(ig.pos)) {
((ActionPush) ig.item).ignoredParts.add(ig.pos);
if (((ActionPush) ig.item).ignoredParts.size() == ((ActionPush) ig.item).values.size()) {
((Action) ig.item).setIgnored(true, 0);
}
}
} else {
((Action) ig.item).setIgnored(true, 0);
}
}
}
} else {
if (debugMode) {
System.err.println("goaif");
@@ -1025,9 +978,9 @@ public class SWFInputStream extends InputStream {
}
}
} catch (RuntimeException ex) {
if (!enableVariables) {
throw ex;
}
/*if (!enableVariables) {
throw ex;
}*/
log.log(Level.SEVERE, "Disassembly exception", ex);
break;
}
@@ -1064,9 +1017,14 @@ public class SWFInputStream extends InputStream {
output2s.add(new ArrayList<GraphTargetItem>());
continue;
}
List<Object> localData2 = Helper.toList(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
List<Object> localData2;
List<GraphTargetItem> output2 = new ArrayList<>();
readActionListAtPos(listeners, output2, containers, address, containerSWFOffset, notCompileTime, enableVariables, localData2, new Stack<GraphTargetItem>(), cpool, sis, rri, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName));
if ((cnt instanceof ActionDefineFunction) || (cnt instanceof ActionDefineFunction2)) {
localData2 = Helper.toList(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
} else {
localData2 = localData;
}
readActionListAtPos(listeners, output2, containers, address, containerSWFOffset, localData2, new Stack<GraphTargetItem>(), cpool, sis, rri, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited);
output2s.add(output2);
endAddr += size;
}
@@ -1098,14 +1056,33 @@ public class SWFInputStream extends InputStream {
}
aif.ignoreUsed = true;
aif.jumpUsed = true;
if (curVisited > 1) {
List<Integer> branches = new ArrayList<>();
branches.add(rri.getPos() + aif.getJumpOffset());
branches.add(rri.getPos());
for (int br : branches) {
int visc = 0;
if (visited.containsKey(br)) {
visc = visited.get(br);
}
if (visc == 0) {//<curVisited){
ip = br;
prevIp = ip;
rri.setPos(br);
continue loopip;
}
}
break loopip;
}
int oldPos = rri.getPos();
@SuppressWarnings("unchecked")
Stack<GraphTargetItem> substack = (Stack<GraphTargetItem>) stack.clone();
if (readActionListAtPos(listeners, output, containers, address, containerSWFOffset, true, enableVariables, localData, substack, cpool, sis, rri, rri.getPos() + aif.getJumpOffset(), ret, startIp, endip, path)) {
if (readActionListAtPos(listeners, output, containers, address, containerSWFOffset, prepareLocalBranch(localData), substack, cpool, sis, rri, rri.getPos() + aif.getJumpOffset(), ret, startIp, endip, path, visited)) {
retv = true;
}
rri.setPos(oldPos);
notCompileTime = true;
}
prevIp = ip;
if (a.isExit()) {

View File

@@ -1483,6 +1483,30 @@ public class AVM2Code implements Serializable {
code.add(pos, instruction);
}
@SuppressWarnings("unchecked")
private static List<Object> prepareBranchLocalData(List<Object> localData) {
List<Object> ret = new ArrayList<>();
ret.add(localData.get(0)); //isStatic
ret.add(localData.get(1)); //classIndex
ret.add(new HashMap<Integer, GraphTargetItem>((HashMap<Integer, GraphTargetItem>) localData.get(2)));
ret.add((Stack<GraphTargetItem>) ((Stack<GraphTargetItem>) localData.get(3)).clone());
ret.add(localData.get(4)); //constants
ret.add(localData.get(5)); //method_info
ret.add(localData.get(6)); //body
ret.add(localData.get(7)); //abc
ret.add(localData.get(8)); //localgetNames
ret.add(localData.get(9));
ret.add(localData.get(10));
ret.add(localData.get(11));
ret.add(localData.get(12));
ret.add(localData.get(13));
ret.add(localData.get(14));
ret.add(localData.get(15));
ret.add(localData.get(16));
ret.add(localData.get(17));
return ret;
}
public int removeTraps(ConstantPool constants, MethodBody body, ABC abc, int scriptIndex, int classIndex, boolean isStatic, String path) {
removeDeadCode(constants, body);
List<Object> localData = new ArrayList<>();
@@ -2212,6 +2236,14 @@ public class AVM2Code implements Serializable {
}
int curVisited;
if (!visited.containsKey(ip)) {
curVisited = 1;
} else {
curVisited = visited.get(ip) + 1;
}
visited.put(ip, curVisited);
List<Integer> r = refs.get(ip);
/*if (r != null) {
if (r.size() > 1) {
@@ -2245,6 +2277,16 @@ public class AVM2Code implements Serializable {
}
if (debugMode) {
System.out.println((useVisited ? "useV " : "") + (secondPass ? "secondPass " : "") + "Visit " + ip + ": " + ins + " stack:" + Highlighting.stripHilights(stack.toString()));
HashMap<Integer, GraphTargetItem> registers = (HashMap<Integer, GraphTargetItem>) localData.get(2);
System.out.print("Registers:");
for (int reg : registers.keySet()) {
try {
System.out.print(" r" + reg + ": " + registers.get(reg).getResult());
} catch (NullPointerException npe) {
System.out.print(" r" + reg + ": " + "null");
}
}
System.out.println("");
}
if (secondPass) {
/*if ((ins instanceof AVM2Instruction) && (((AVM2Instruction) ins).definition instanceof PopIns)) {
@@ -2349,12 +2391,26 @@ public class AVM2Code implements Serializable {
}
dec.jumpUsed = true;
dec.skipUsed = true;
if (curVisited > 1) {
for (int b : branches) {
int visc = 0;
if (visited.containsKey(b)) {
visc = visited.get(b);
}
if (visc == 0) {//<curVisited){
ip = b;
continue iploop;
}
}
break;
}
}
for (int b : branches) {
Stack<GraphTargetItem> brStack = (Stack<GraphTargetItem>) stack.clone();
if (b >= 0) {
ret += removeTraps(refs, secondPass, useVisited || (!ins.isJump()), localData, brStack, output, code, b, visited, visitedStates, decisions, path);
if (b >= 0) { //useVisited || (!ins.isJump())
ret += removeTraps(refs, secondPass, false, prepareBranchLocalData(localData), brStack, output, code, b, visited, visitedStates, decisions, path);
} else {
if (debugMode) {
System.out.println("Negative branch:" + b);
@@ -2375,8 +2431,30 @@ public class AVM2Code implements Serializable {
public static int removeTraps(ConstantPool constants, MethodBody body, List<Object> localData, AVM2GraphSource code, int addr, String path, HashMap<Integer, List<Integer>> refs) {
HashMap<GraphSourceItem, AVM2Code.Decision> decisions = new HashMap<>();
removeTraps(refs, false, false, localData, new Stack<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), code, code.adr2pos(addr), new HashMap<Integer, Integer>(), new HashMap<Integer, HashMap<Integer, GraphTargetItem>>(), decisions, path);
localData.set(2, new HashMap<Integer, GraphTargetItem>());
int cnt = removeTraps(refs, true, false, localData, new Stack<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), code, code.adr2pos(addr), new HashMap<Integer, Integer>(), new HashMap<Integer, HashMap<Integer, GraphTargetItem>>(), decisions, path);
int cnt = 0;
for (GraphSourceItem src : decisions.keySet()) {
Decision dec = decisions.get(src);
if (dec != null) {
if ((src instanceof AVM2Instruction) && (((AVM2Instruction) src).definition instanceof LookupSwitchIns)) {
if (dec.casesUsed.size() == 1) {
for (int c : dec.casesUsed) {
src.setFixBranch(c);
cnt++;
}
}
} else {
if (dec.jumpUsed && !dec.skipUsed) {
src.setFixBranch(0);
cnt++;
}
if (!dec.jumpUsed && dec.skipUsed) {
src.setFixBranch(1);
cnt++;
}
}
}
}
//int cnt = removeTraps(refs, true, false, localData, new Stack<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), code, code.adr2pos(addr), new HashMap<Integer, Integer>(), new HashMap<Integer, HashMap<Integer, GraphTargetItem>>(), decisions, path);
code.getCode().removeIgnored(constants, body);
return cnt;
}

View File

@@ -57,14 +57,18 @@ public class DecLocalIIns extends InstructionDefinition {
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regIndex = ins.operands[0];
output.add(new DecLocalAVM2Item(ins, regIndex));
if (localRegs.containsKey(regIndex)) {
localRegs.put(regIndex, new NotCompileTimeAVM2Item(ins, new SubtractAVM2Item(ins, localRegs.get(regIndex), new IntegerValueAVM2Item(ins, Long.valueOf(1)))));
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> regAssignCount, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regId = ins.operands[0];
output.add(new DecLocalAVM2Item(ins, regId));
if (localRegs.containsKey(regId)) {
localRegs.put(regId, new SubtractAVM2Item(ins, localRegs.get(regId), new IntegerValueAVM2Item(ins, Long.valueOf(1))));
} else {
//localRegs.put(regIndex, new SubtractAVM2Item(ins, new IntegerValueAVM2Item(ins, new Long(0)), new IntegerValueAVM2Item(ins, new Long(1))));
}
if (!regAssignCount.containsKey(regId)) {
regAssignCount.put(regId, 0);
}
regAssignCount.put(regId, regAssignCount.get(regId) + 1);
}
}

View File

@@ -57,13 +57,17 @@ public class DecLocalIns extends InstructionDefinition {
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regIndex = ins.operands[0];
output.add(new DecLocalAVM2Item(ins, regIndex));
if (localRegs.containsKey(regIndex)) {
localRegs.put(regIndex, new NotCompileTimeAVM2Item(ins, new SubtractAVM2Item(ins, localRegs.get(regIndex), new IntegerValueAVM2Item(ins, Long.valueOf(1)))));
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> regAssignCount, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regId = ins.operands[0];
output.add(new DecLocalAVM2Item(ins, regId));
if (localRegs.containsKey(regId)) {
localRegs.put(regId, new SubtractAVM2Item(ins, localRegs.get(regId), new IntegerValueAVM2Item(ins, Long.valueOf(1))));
} else {
//localRegs.put(regIndex, new SubtractAVM2Item(ins, new IntegerValueAVM2Item(ins, new Long(0)), new IntegerValueAVM2Item(ins, new Long(1))));
}
if (!regAssignCount.containsKey(regId)) {
regAssignCount.put(regId, 0);
}
regAssignCount.put(regId, regAssignCount.get(regId) + 1);
}
}

View File

@@ -37,17 +37,24 @@ public abstract class GetLocalTypeIns extends InstructionDefinition {
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> regAssignCount, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regId = getRegisterId(ins);
GraphTargetItem computedValue = localRegs.get(regId);
if (!isRegisterCompileTime(regId, ip, refs, code)) {
int assignCount = 0;
if (regAssignCount.containsKey(regId)) {
assignCount = regAssignCount.get(regId);
}
if (assignCount > 5) { //Do not allow change register more than 5 - for deobfuscation
computedValue = new NotCompileTimeAVM2Item(ins, computedValue);
}
if (computedValue == null) {
if (!localRegNames.containsKey(regId)) {
computedValue = new UndefinedAVM2Item(null); //In some obfuscated code there seems to be reading of undefined registers
}
}
/*if (!isRegisterCompileTime(regId, ip, refs, code)) {
computedValue = new NotCompileTimeAVM2Item(ins, computedValue);
}
if (computedValue == null) {
if (!localRegNames.containsKey(regId)) {
computedValue = new UndefinedAVM2Item(null); //In some obfuscated code there seems to be reading of undefined registers
}
}*/
stack.push(new LocalRegAVM2Item(ins, regId, computedValue));
}

View File

@@ -37,13 +37,17 @@ public class IncLocalIIns extends InstructionDefinition {
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regIndex = ins.operands[0];
output.add(new IncLocalAVM2Item(ins, regIndex));
if (localRegs.containsKey(regIndex)) {
localRegs.put(regIndex, new NotCompileTimeAVM2Item(ins, new AddAVM2Item(ins, localRegs.get(regIndex), new IntegerValueAVM2Item(ins, Long.valueOf(1)))));
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> regAssignCount, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regId = ins.operands[0];
output.add(new IncLocalAVM2Item(ins, regId));
if (localRegs.containsKey(regId)) {
localRegs.put(regId, new AddAVM2Item(ins, localRegs.get(regId), new IntegerValueAVM2Item(ins, Long.valueOf(1))));
} else {
//localRegs.put(regIndex, new AddAVM2Item(ins, null, new IntegerValueAVM2Item(ins, new Long(1))));
}
if (!regAssignCount.containsKey(regId)) {
regAssignCount.put(regId, 0);
}
regAssignCount.put(regId, regAssignCount.get(regId) + 1);
}
}

View File

@@ -37,13 +37,17 @@ public class IncLocalIns extends InstructionDefinition {
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regIndex = ins.operands[0];
output.add(new IncLocalAVM2Item(ins, regIndex));
if (localRegs.containsKey(regIndex)) {
localRegs.put(regIndex, new NotCompileTimeAVM2Item(ins, new AddAVM2Item(ins, localRegs.get(regIndex), new IntegerValueAVM2Item(ins, Long.valueOf(1)))));
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> regAssignCount, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regId = ins.operands[0];
output.add(new IncLocalAVM2Item(ins, regId));
if (localRegs.containsKey(regId)) {
localRegs.put(regId, new AddAVM2Item(ins, localRegs.get(regId), new IntegerValueAVM2Item(ins, Long.valueOf(1))));
} else {
//localRegs.put(regIndex, new AddAVM2Item(ins, null, new IntegerValueAVM2Item(ins, new Long(1))));
}
if (!regAssignCount.containsKey(regId)) {
regAssignCount.put(regId, 0);
}
regAssignCount.put(regId, regAssignCount.get(regId) + 1);
}
}

View File

@@ -47,15 +47,20 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<GraphTargetItem> output, com.jpexs.decompiler.flash.abc.types.MethodBody body, com.jpexs.decompiler.flash.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> regAssignCount, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
int regId = getRegisterId(ins);
GraphTargetItem value = (GraphTargetItem) stack.pop();
if (localRegs.containsKey(regId)) {
localRegs.put(regId, new NotCompileTimeAVM2Item(ins, value));
} else {
localRegs.put(regId, value);
/*if (localRegs.containsKey(regId)) {
localRegs.put(regId, new NotCompileTimeAVM2Item(ins, value));
} else {
localRegs.put(regId, value);
}*/
localRegs.put(regId, value);
if (!regAssignCount.containsKey(regId)) {
regAssignCount.put(regId, 0);
}
localRegsAssignmentIps.put(regId, ip);
regAssignCount.put(regId, regAssignCount.get(regId) + 1);
//localRegsAssignmentIps.put(regId, ip);
if (value instanceof NewActivationAVM2Item) {
return;
}
@@ -63,7 +68,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S
return;
}
if (value.getNotCoerced() instanceof IncrementAVM2Item) {
GraphTargetItem inside = ((IncrementAVM2Item) value.getNotCoerced()).object.getNotCoerced().getThroughDuplicate();
GraphTargetItem inside = ((IncrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate();
if (inside instanceof LocalRegAVM2Item) {
if (((LocalRegAVM2Item) inside).regIndex == regId) {
if (stack.size() > 0) {
@@ -71,7 +76,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S
if (top == inside) {
stack.pop();
stack.push(new PostIncrementAVM2Item(ins, inside));
} else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).object == inside)) {
} else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).value == inside)) {
stack.pop();
stack.push(new PreIncrementAVM2Item(ins, inside));
} else {
@@ -86,7 +91,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S
}
if (value.getNotCoerced() instanceof DecrementAVM2Item) {
GraphTargetItem inside = ((DecrementAVM2Item) value.getNotCoerced()).object.getNotCoerced().getThroughDuplicate();
GraphTargetItem inside = ((DecrementAVM2Item) value.getNotCoerced()).value.getNotCoerced().getThroughDuplicate();
if (inside instanceof LocalRegAVM2Item) {
if (((LocalRegAVM2Item) inside).regIndex == regId) {
if (stack.size() > 0) {
@@ -94,7 +99,7 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S
if (top == inside) {
stack.pop();
stack.push(new PostDecrementAVM2Item(ins, inside));
} else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).object == inside)) {
} else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).value == inside)) {
stack.pop();
stack.push(new PreDecrementAVM2Item(ins, inside));
} else {

View File

@@ -52,7 +52,7 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns
FullMultinameAVM2Item multiname = resolveMultiname(stack, constants, multinameIndex, ins);
GraphTargetItem obj = (GraphTargetItem) stack.pop();
if (value.getThroughDuplicate().getThroughRegister().getThroughDuplicate() instanceof IncrementAVM2Item) {
GraphTargetItem inside = ((IncrementAVM2Item) value.getThroughDuplicate().getThroughRegister().getThroughDuplicate()).object.getThroughRegister().getNotCoerced().getThroughDuplicate();
GraphTargetItem inside = ((IncrementAVM2Item) value.getThroughDuplicate().getThroughRegister().getThroughDuplicate()).value.getThroughRegister().getNotCoerced().getThroughDuplicate();
if (inside instanceof GetPropertyAVM2Item) {
GetPropertyAVM2Item insideProp = ((GetPropertyAVM2Item) inside);
if (insideProp.propertyName.compareSame(multiname)) {
@@ -68,7 +68,7 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns
if (top == insideProp) {
stack.pop();
stack.push(new PostIncrementAVM2Item(ins, insideProp));
} else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).object == inside)) {
} else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).value == inside)) {
stack.pop();
stack.push(new PreIncrementAVM2Item(ins, insideProp));
} else {
@@ -84,7 +84,7 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns
}
if (value.getThroughDuplicate().getThroughRegister().getThroughDuplicate() instanceof DecrementAVM2Item) {
GraphTargetItem inside = ((DecrementAVM2Item) value.getThroughDuplicate().getThroughRegister().getThroughDuplicate()).object.getThroughRegister().getNotCoerced().getThroughDuplicate();
GraphTargetItem inside = ((DecrementAVM2Item) value.getThroughDuplicate().getThroughRegister().getThroughDuplicate()).value.getThroughRegister().getNotCoerced().getThroughDuplicate();
if (inside instanceof GetPropertyAVM2Item) {
GetPropertyAVM2Item insideProp = ((GetPropertyAVM2Item) inside);
if (insideProp.propertyName.compareSame(multiname)) {
@@ -100,7 +100,7 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns
if (top == insideProp) {
stack.pop();
stack.push(new PostDecrementAVM2Item(ins, insideProp));
} else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).object == inside)) {
} else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).value == inside)) {
stack.pop();
stack.push(new PreDecrementAVM2Item(ins, insideProp));
} else {

View File

@@ -105,7 +105,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns {
}
if (value.getNotCoerced().getThroughDuplicate() instanceof IncrementAVM2Item) {
GraphTargetItem inside = ((IncrementAVM2Item) value.getNotCoerced()).object.getThroughRegister().getNotCoerced().getThroughDuplicate();
GraphTargetItem inside = ((IncrementAVM2Item) value.getNotCoerced()).value.getThroughRegister().getNotCoerced().getThroughDuplicate();
if (inside instanceof GetSlotAVM2Item) {
GetSlotAVM2Item slotItem = (GetSlotAVM2Item) inside;
if ((slotItem.scope.getThroughRegister() == obj.getThroughRegister())
@@ -115,7 +115,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns {
if (top == inside) {
stack.pop();
stack.push(new PostIncrementAVM2Item(ins, inside));
} else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).object == inside)) {
} else if ((top instanceof IncrementAVM2Item) && (((IncrementAVM2Item) top).value == inside)) {
stack.pop();
stack.push(new PreIncrementAVM2Item(ins, inside));
} else {
@@ -130,7 +130,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns {
}
if (value.getNotCoerced().getThroughDuplicate() instanceof DecrementAVM2Item) {
GraphTargetItem inside = ((DecrementAVM2Item) value.getNotCoerced()).object.getThroughRegister().getNotCoerced().getThroughDuplicate();
GraphTargetItem inside = ((DecrementAVM2Item) value.getNotCoerced()).value.getThroughRegister().getNotCoerced().getThroughDuplicate();
if (inside instanceof GetSlotAVM2Item) {
GetSlotAVM2Item slotItem = (GetSlotAVM2Item) inside;
if ((slotItem.scope.getThroughRegister() == obj.getThroughRegister())
@@ -140,7 +140,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns {
if (top == inside) {
stack.pop();
stack.push(new PostDecrementAVM2Item(ins, inside));
} else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).object == inside)) {
} else if ((top instanceof DecrementAVM2Item) && (((DecrementAVM2Item) top).value == inside)) {
stack.pop();
stack.push(new PreDecrementAVM2Item(ins, inside));
} else {

View File

@@ -18,21 +18,30 @@ package com.jpexs.decompiler.flash.abc.avm2.model;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
public class DecrementAVM2Item extends AVM2Item {
public GraphTargetItem object;
public DecrementAVM2Item(AVM2Instruction instruction, GraphTargetItem object) {
super(instruction, PRECEDENCE_ADDITIVE);
this.object = object;
this.value = object;
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return object.toString(constants, localRegNames, fullyQualifiedNames) + hilight("-1");
return value.toString(constants, localRegNames, fullyQualifiedNames) + hilight("-1");
}
@Override
public boolean isCompileTime() {
return value.isCompileTime();
}
@Override
public Object getResult() {
return EcmaScript.toNumber(value.getResult()) - 1;
}
}

View File

@@ -18,21 +18,30 @@ package com.jpexs.decompiler.flash.abc.avm2.model;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
public class IncrementAVM2Item extends AVM2Item {
public GraphTargetItem object;
public IncrementAVM2Item(AVM2Instruction instruction, GraphTargetItem object) {
super(instruction, PRECEDENCE_ADDITIVE);
this.object = object;
this.value = object;
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return object.toString(constants, localRegNames, fullyQualifiedNames) + hilight("+1");
return value.toString(constants, localRegNames, fullyQualifiedNames) + hilight("+1");
}
@Override
public boolean isCompileTime() {
return value.isCompileTime();
}
@Override
public Object getResult() {
return EcmaScript.toNumber(value.getResult()) + 1;
}
}

View File

@@ -29,12 +29,21 @@ public class LocalRegAVM2Item extends AVM2Item {
public int regIndex;
public GraphTargetItem computedValue;
private Object computedResult;
private boolean isCT = false;
public LocalRegAVM2Item(AVM2Instruction instruction, int regIndex, GraphTargetItem computedValue) {
super(instruction, PRECEDENCE_PRIMARY);
this.regIndex = regIndex;
if (computedValue == null) {
//computedValue = new UndefinedAVM2Item(instruction);
computedResult = null;
} else {
if (computedValue.isCompileTime()) {
computedResult = computedValue.getResult();
isCT = true;
} else {
computedResult = null;
}
}
this.computedValue = computedValue;
}
@@ -57,18 +66,15 @@ public class LocalRegAVM2Item extends AVM2Item {
@Override
public Object getResult() {
if (computedValue == null) {
if (computedResult == null) {
return new Undefined();
}
return computedValue.getResult();
return computedResult;
}
@Override
public boolean isCompileTime() {
if (computedValue == null) {
return false;
}
return computedValue.isCompileTime();
return isCT;
}
}

View File

@@ -47,7 +47,7 @@ public class NotCompileTimeAVM2Item extends AVM2Item {
@Override
public GraphTargetItem getThroughNotCompilable() {
if(object==null){
if (object == null) {
return object;
}
return object.getThroughNotCompilable();

View File

@@ -125,8 +125,8 @@ public class MethodBody implements Cloneable, Serializable {
if ((Boolean) Configuration.getConfig("autoDeobfuscate", true)) {
try {
deobfuscated.removeTraps(constants, b, abc, scriptIndex, classIndex, isStatic, path);
} catch (Exception ex) {
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Error during remove traps", ex);
} catch (Exception | StackOverflowError ex) {
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Error during remove traps in " + path, ex);
}
}
//deobfuscated.restoreControlFlow(constants, b);

View File

@@ -536,13 +536,23 @@ public class Action implements GraphSourceItem {
ret.append(Highlighting.hilighOffset("", offset));
if (a instanceof ActionIf) {
ActionIf aif = (ActionIf) a;
if (aif.jumpUsed && !aif.ignoreUsed) {
aif.setFixBranch(0);
}
if (!aif.jumpUsed && aif.ignoreUsed) {
aif.setFixBranch(1);
}
}
int fixBranch = a.getFixBranch();
if (fixBranch > -1) {
if (a instanceof ActionIf) {
ret.append("pop\r\n");
ret.append("ffdec_deobfuscatepop\r\n");
if (fixBranch == 0) { //jump
ret.append("jump ofs");
ret.append(Helper.formatAddress(offset + ((ActionIf) a).getJumpOffset()));
ret.append("jump loc");
ret.append(Helper.formatAddress(a.getAddress() + a.getBytes(version).length + ((ActionIf) a).getJumpOffset()));
} else {
//nojump, ignore
}
@@ -1337,10 +1347,10 @@ public class Action implements GraphSourceItem {
if (o instanceof Long) {
return (Long) o;
}
if(o instanceof String){
try{
return Double.parseDouble((String)o);
}catch(NumberFormatException nfe){
if (o instanceof String) {
try {
return Double.parseDouble((String) o);
} catch (NumberFormatException nfe) {
return 0;
}
}

View File

@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.flashlite.ActionFSCommand2;
import com.jpexs.decompiler.flash.action.flashlite.ActionStrictMode;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.special.ActionDeobfuscatePop;
import com.jpexs.decompiler.flash.action.special.ActionNop;
import com.jpexs.decompiler.flash.action.special.ActionStore;
import com.jpexs.decompiler.flash.action.swf3.*;
@@ -282,6 +283,8 @@ public class ASMParser {
if (!ignoreNops) {
a = (new ActionNop());
}
} else if (instructionName.equals("FFDec_DeobfuscatePop".toLowerCase())) {
a = new ActionDeobfuscatePop();
}/* else if(instructionName.startsWith("ofs")) {
continue;
}*/ else {

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.action.special;
import com.jpexs.decompiler.flash.action.swf4.ActionPop;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class ActionDeobfuscatePop extends ActionPop {
public ActionDeobfuscatePop() {
}
@Override
public String toString() {
return "FFDec_DeobfuscatePop";
}
@Override
public void translate(List<Object> localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, int staticOperation, String path) {
if (stack.isEmpty()) {
return;
}
GraphTargetItem val = stack.pop();
}
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.action.swf3;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -25,8 +27,11 @@ import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.clauses.IfFrameLoadedActionItem;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
import com.jpexs.decompiler.flash.action.special.ActionEnd;
import com.jpexs.decompiler.flash.action.special.ActionStore;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
@@ -46,15 +51,48 @@ public class ActionWaitForFrame extends Action implements ActionStore {
skipCount = sis.readUI8();
skipped = new ArrayList<>();
for (int i = 0; i < skipCount; i++) {
skipped.add(sis.readAction());
Action a = sis.readAction();
if (a instanceof ActionEnd) {
skipCount = i;
break;
}
if (a == null) {
skipCount = i;
break;
}
skipped.add(a);
}
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
if (deobfuscate) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i = 0; i < skipCount; i++) {
baos.write(skipped.get(i).getBytes(sis.getVersion()));
}
baos.write(new ActionEnd().getBytes(sis.getVersion()));
SWFInputStream sis2 = new SWFInputStream(new ByteArrayInputStream(baos.toByteArray()), sis.getVersion());
skipped = sis2.readActionList(new ArrayList<DisassemblyListener>(), 0, 0, "");
if (!skipped.isEmpty()) {
if (skipped.get(skipped.size() - 1) instanceof ActionEnd) {
skipped.remove(skipped.size() - 1);
}
}
skipCount = skipped.size();
}
}
@Override
public String toString() {
return "WaitForFrame";
}
@Override
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, boolean hex) {
String ret = "WaitForFrame " + frame + " " + skipCount;
for (int i = 0; i < skipped.size(); i++) {
ret += "\r\n" + skipped.get(i).toString();
if (skipped.get(i) instanceof ActionEnd) {
break;
}
ret += "\r\n" + skipped.get(i).getASMSource(container, knownAddreses, constantPool, version, hex);
}
return ret;
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.action.swf4;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -24,8 +26,11 @@ import com.jpexs.decompiler.flash.action.ActionGraph;
import com.jpexs.decompiler.flash.action.model.clauses.IfFrameLoadedActionItem;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
import com.jpexs.decompiler.flash.action.special.ActionEnd;
import com.jpexs.decompiler.flash.action.special.ActionStore;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
@@ -59,7 +64,32 @@ public class ActionWaitForFrame2 extends Action implements ActionStore {
skipCount = sis.readUI8();
skipped = new ArrayList<>();
for (int i = 0; i < skipCount; i++) {
skipped.add(sis.readAction());
Action a = sis.readAction();
if (a instanceof ActionEnd) {
skipCount = i;
break;
}
if (a == null) {
skipCount = i;
break;
}
skipped.add(a);
}
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
if (deobfuscate) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i = 0; i < skipCount; i++) {
baos.write(skipped.get(i).getBytes(sis.getVersion()));
}
baos.write(new ActionEnd().getBytes(sis.getVersion()));
SWFInputStream sis2 = new SWFInputStream(new ByteArrayInputStream(baos.toByteArray()), sis.getVersion());
skipped = sis2.readActionList(new ArrayList<DisassemblyListener>(), 0, 0, "");
if (!skipped.isEmpty()) {
if (skipped.get(skipped.size() - 1) instanceof ActionEnd) {
skipped.remove(skipped.size() - 1);
}
}
skipCount = skipped.size();
}
}
@@ -82,9 +112,17 @@ public class ActionWaitForFrame2 extends Action implements ActionStore {
@Override
public String toString() {
return "WaitForFrame2";
}
@Override
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, boolean hex) {
String ret = "WaitForFrame2 " + skipCount;
for (Action a : skipped) {
ret += "\r\n" + a.toString();
for (int i = 0; i < skipped.size(); i++) {
if (skipped.get(i) instanceof ActionEnd) {
break;
}
ret += "\r\n" + skipped.get(i).getASMSource(container, knownAddreses, constantPool, version, hex);
}
return ret;
}

View File

@@ -77,10 +77,11 @@ public class RenameDialog extends AppDialog implements ActionListener {
cancelButton.addActionListener(this);
add(panButtons, BorderLayout.SOUTH);
setModalityType(ModalityType.APPLICATION_MODAL);
View.centerScreen(this);
View.setWindowIcon(this);
setTitle(translate("dialog.title"));
getRootPane().setDefaultButton(okButton);
pack();
View.centerScreen(this);
}
@Override

View File

@@ -128,9 +128,10 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT
depthMap.put(pot.getDepth(), charId);
characterId = (charId);
} else {
Integer chi= (depthMap.get(pot.getDepth()));
if(chi!=null)
characterId = chi;
Integer chi = (depthMap.get(pot.getDepth()));
if (chi != null) {
characterId = chi;
}
}
}
if (characterId == -1) {

View File

@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.helpers.Helper;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -47,6 +48,7 @@ public class DoActionTag extends Tag implements ASMSource {
/**
* Constructor
*
* @param swf
* @param data Data bytes
* @param version SWF version
* @param pos

View File

@@ -175,12 +175,12 @@ public abstract class TextTag extends CharacterTag implements BoundedTag {
updateRect(textBounds, x + rect.Xmin, y + rect.Ymin);
updateRect(textBounds, x + rect.Xmax, y + rect.Ymax);
int adv = entry.glyphAdvance;
int defaultAdvance;
if (font.hasLayout()) {
defaultAdvance = 20 * (int) Math.round((double) textHeight * font.getGlyphAdvance(entry.glyphIndex) / (font.getDivider() * 1024.0));
} else {
defaultAdvance = 20 * FontTag.getSystemFontAdvance(aFont, font.glyphToChar(tags, entry.glyphIndex));
defaultAdvance = 20 * FontTag.getSystemFontAdvance(aFont, font.glyphToChar(tags, entry.glyphIndex));
}
letterSpacing = adv - defaultAdvance;
x += adv;