mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-05 18:34:45 +00:00
AS1/2 better deobfuscation
This commit is contained in:
@@ -16,8 +16,9 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.CopyOutputStream;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionGraphSource;
|
||||
import com.jpexs.decompiler.flash.action.UnknownActionException;
|
||||
import com.jpexs.decompiler.flash.action.parser.ASMParser;
|
||||
import com.jpexs.decompiler.flash.action.parser.ParseException;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionNop;
|
||||
@@ -27,6 +28,7 @@ import com.jpexs.decompiler.flash.action.swf5.*;
|
||||
import com.jpexs.decompiler.flash.action.swf6.*;
|
||||
import com.jpexs.decompiler.flash.action.swf7.*;
|
||||
import com.jpexs.decompiler.flash.action.treemodel.ConstantPool;
|
||||
import com.jpexs.decompiler.flash.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.flash.graph.GraphSourceItemPos;
|
||||
import com.jpexs.decompiler.flash.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.flash.helpers.Helper;
|
||||
@@ -76,6 +78,7 @@ public class SWFInputStream extends InputStream {
|
||||
private long percentMax;
|
||||
private List<byte[]> buffered = new ArrayList<byte[]>();
|
||||
private ByteArrayOutputStream buffer;
|
||||
private static boolean DEOBFUSCATION_ALL_CODE_IN_PREVIOUS_TAG = true;
|
||||
|
||||
public int getBufferLength() {
|
||||
return buffer.size();
|
||||
@@ -490,6 +493,68 @@ public class SWFInputStream extends InputStream {
|
||||
return readActionList(rri, version, 0);
|
||||
}
|
||||
|
||||
private static void getConstantPool(List localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, ActionGraphSource code, int ip, int lastIp, List<ConstantPool> constantPools, List<Integer> visited) {
|
||||
boolean debugMode = false;
|
||||
while ((ip > -1) && ip < code.size()) {
|
||||
/*if (visited.contains(ip)) {
|
||||
break;
|
||||
}*/
|
||||
visited.add(ip);
|
||||
lastIp = ip;
|
||||
GraphSourceItem ins = code.get(ip);
|
||||
if (debugMode) {
|
||||
System.out.println("Visit " + ip + ": " + ins + " stack:" + Highlighting.stripHilights(stack.toString()));
|
||||
}
|
||||
if (ins instanceof ActionConstantPool) {
|
||||
constantPools.add(new ConstantPool(((ActionConstantPool) ins).constantPool));
|
||||
}
|
||||
|
||||
ins.translate(localData, stack, output);
|
||||
if (ins.isExit()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ins.isBranch() || ins.isJump()) {
|
||||
|
||||
if (ins instanceof ActionIf && !stack.isEmpty() && (stack.peek().isCompileTime())) {
|
||||
boolean condition = stack.peek().toBoolean();
|
||||
if (debugMode) {
|
||||
if (condition) {
|
||||
System.out.println("JUMP");
|
||||
} else {
|
||||
System.out.println("SKIP");
|
||||
}
|
||||
}
|
||||
stack.pop();
|
||||
getConstantPool(localData, stack, output, code, condition ? (code.adr2pos(((ActionIf) ins).getAddress() + ((ActionIf) ins).getBytes(code.version).length + ((ActionIf) ins).offset)) : ip + 1, ip, constantPools, visited);
|
||||
} else {
|
||||
List<Integer> branches = ins.getBranches(code);
|
||||
for (int b : branches) {
|
||||
if (b >= 0) {
|
||||
getConstantPool(localData, stack, output, code, b, ip, constantPools, visited);
|
||||
} else {
|
||||
if (debugMode) {
|
||||
System.out.println("Negative branch:" + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
ip++;
|
||||
};
|
||||
if (ip < 0) {
|
||||
System.out.println("Visited Negative: " + ip);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ConstantPool> getConstantPool(ActionGraphSource code, int addr) {
|
||||
List<ConstantPool> ret = new ArrayList<ConstantPool>();
|
||||
List localData = Helper.toList(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
|
||||
getConstantPool(localData, new Stack<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), code, code.adr2pos(addr), 0, ret, new ArrayList<Integer>());
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads list of actions from the stream. Reading ends with ActionEndFlag(=0)
|
||||
* or end of the stream.
|
||||
@@ -508,14 +573,14 @@ public class SWFInputStream extends InputStream {
|
||||
|
||||
SWFInputStream sis = new SWFInputStream(rri, version);
|
||||
boolean goesPrev = false;
|
||||
int method = 1;
|
||||
try {
|
||||
goesPrev = readActionListAtPos(false, localData, stack, cpool, sis, rri, ip, retdups, ip);
|
||||
} catch (Exception ex) {
|
||||
method = 2;
|
||||
goesPrev = readActionListAtPos(true, localData, stack, cpool, sis, rri, ip, retdups, ip);
|
||||
}
|
||||
if (goesPrev) {
|
||||
retdups.add(0, new ActionJump(ip));
|
||||
|
||||
} else {
|
||||
for (int i = 0; i < ip; i++) {
|
||||
retdups.remove(0);
|
||||
@@ -529,8 +594,22 @@ public class SWFInputStream extends InputStream {
|
||||
}
|
||||
last = a;
|
||||
}
|
||||
|
||||
List<ConstantPool> pools = getConstantPool(new ActionGraphSource(ret, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), ip);
|
||||
|
||||
if (pools.size() == 1) {
|
||||
Action.setConstantPool(ret, pools.get(0));
|
||||
}
|
||||
if (goesPrev && (!DEOBFUSCATION_ALL_CODE_IN_PREVIOUS_TAG)) {
|
||||
ActionJump aj = new ActionJump(ip);
|
||||
int skip = aj.getBytes(version).length;
|
||||
for (Action a : ret) {
|
||||
a.setAddress(a.getAddress() + skip, version);
|
||||
}
|
||||
ret.add(0, aj);
|
||||
}
|
||||
String s = null;
|
||||
Action.setConstantPool(ret, cpool);
|
||||
//Action.setConstantPool(ret, cpool);
|
||||
|
||||
try {
|
||||
s = Highlighting.stripHilights(Action.actionsToString(ret, null, version));
|
||||
@@ -540,7 +619,6 @@ public class SWFInputStream extends InputStream {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
public static List<Boolean> dobranch = new ArrayList<Boolean>();
|
||||
|
||||
private static boolean readActionListAtPos(boolean enableVariables, List localData, Stack<GraphTargetItem> stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List<Action> ret, int startIp) throws IOException {
|
||||
boolean debugMode = false;
|
||||
@@ -568,7 +646,7 @@ public class SWFInputStream extends InputStream {
|
||||
}
|
||||
if (debugMode) {
|
||||
//if(a instanceof ActionIf){
|
||||
System.out.println(" rripos: " + rri.getPos() + " rricount:" + rri.getCount() + " ip: " + (ip - startIp) + " action(len " + a.actionLength + "): " + a + " stack:" + Highlighting.stripHilights(stack.toString()) + " " + Helper.byteArrToString(a.getBytes(SWF.DEFAULT_VERSION)));
|
||||
System.out.println(" ip: " + (ip - startIp) + " action(len " + a.actionLength + "): " + a + " stack:" + Highlighting.stripHilights(stack.toString()) + " " + Helper.byteArrToString(a.getBytes(SWF.DEFAULT_VERSION)));
|
||||
//}
|
||||
}
|
||||
/*if(a instanceof ActionConstantPool){
|
||||
@@ -577,16 +655,19 @@ public class SWFInputStream extends InputStream {
|
||||
if (a instanceof ActionPush) {
|
||||
if (cpool != null) {
|
||||
((ActionPush) a).constantPool = cpool.constants;
|
||||
cpool.count++;
|
||||
}
|
||||
}
|
||||
if (a instanceof ActionDefineFunction) {
|
||||
if (cpool != null) {
|
||||
((ActionDefineFunction) a).setConstantPool(cpool.constants);
|
||||
cpool.count++;
|
||||
}
|
||||
}
|
||||
if (a instanceof ActionDefineFunction2) {
|
||||
if (cpool != null) {
|
||||
((ActionDefineFunction2) a).setConstantPool(cpool.constants);
|
||||
cpool.count++;
|
||||
}
|
||||
}
|
||||
long newFilePos = rri.getPos();
|
||||
@@ -602,7 +683,7 @@ public class SWFInputStream extends InputStream {
|
||||
if (cpool == null) {
|
||||
cpool = new ConstantPool();
|
||||
}
|
||||
cpool.constants = ((ActionConstantPool) a).constantPool;
|
||||
cpool.setNew(((ActionConstantPool) a).constantPool);
|
||||
}
|
||||
Action beforeInsert = null;
|
||||
ActionIf aif = null;
|
||||
@@ -670,6 +751,9 @@ public class SWFInputStream extends InputStream {
|
||||
}
|
||||
|
||||
} else {
|
||||
if (debugMode) {
|
||||
System.out.println("goaif");
|
||||
}
|
||||
//throw new RuntimeException("goaif");
|
||||
goaif = true;
|
||||
}
|
||||
@@ -722,8 +806,11 @@ public class SWFInputStream extends InputStream {
|
||||
}
|
||||
|
||||
private static void ensureCapacity(List<Action> ret, int index) {
|
||||
int pos = ret.size();
|
||||
while (ret.size() <= index) {
|
||||
ret.add(new ActionNop());
|
||||
Action a = new ActionNop();
|
||||
a.setAddress(pos++, SWF.DEFAULT_VERSION);
|
||||
ret.add(a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1283,8 +1370,8 @@ public class SWFInputStream extends InputStream {
|
||||
if (actionLength > 0) {
|
||||
skip(actionLength);
|
||||
}
|
||||
//throw new UnknownActionException(actionCode);
|
||||
return new Action(actionCode, actionLength);
|
||||
throw new UnknownActionException(actionCode);
|
||||
//return new Action(actionCode, actionLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -983,10 +983,10 @@ public class Action implements GraphSourceItem {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void setConstantPool(List<Action> actions,ConstantPool cpool){
|
||||
for(Action a:actions){
|
||||
if (a instanceof ActionPush) {
|
||||
|
||||
public static void setConstantPool(List<Action> actions, ConstantPool cpool) {
|
||||
for (Action a : actions) {
|
||||
if (a instanceof ActionPush) {
|
||||
if (cpool != null) {
|
||||
((ActionPush) a).constantPool = cpool.constants;
|
||||
}
|
||||
|
||||
@@ -49,11 +49,27 @@ public class ActionGraphSource extends GraphSource {
|
||||
|
||||
@Override
|
||||
public int adr2pos(long adr) {
|
||||
return Action.adr2ip(actions, adr, version);
|
||||
int pos = 0;
|
||||
long lastAddr = 0;
|
||||
for (Action a : actions) {
|
||||
lastAddr = a.getAddress();
|
||||
if (lastAddr == adr) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
if (adr > lastAddr) {
|
||||
return actions.size();
|
||||
}
|
||||
if (adr == 0) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long pos2adr(int pos) {
|
||||
return Action.ip2adr(actions, pos, version);
|
||||
return actions.get(pos).getAddress();//Action.ip2adr(actions, pos, version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
editor.setText("; Disassembling...");
|
||||
if (Main.DO_DECOMPILE) {
|
||||
decompiledEditor.setText("//Decompiling...");
|
||||
}
|
||||
lastDisasm = asm.getASMSource(SWF.DEFAULT_VERSION);
|
||||
disassembledHilights = Highlighting.getInstrHighlights(lastDisasm);
|
||||
lastDisasm = Highlighting.stripHilights(lastDisasm);
|
||||
@@ -81,7 +85,6 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
List<com.jpexs.decompiler.flash.action.Action> as = asm.getActions(SWF.DEFAULT_VERSION);
|
||||
lastCode = as;
|
||||
com.jpexs.decompiler.flash.action.Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION);
|
||||
decompiledEditor.setText("//Decompiling...");
|
||||
String s = com.jpexs.decompiler.flash.action.Action.actionsToSource(as, SWF.DEFAULT_VERSION);
|
||||
decompiledHilights = Highlighting.getInstrHighlights(s);
|
||||
decompiledEditor.setText(Highlighting.stripHilights(s));
|
||||
|
||||
@@ -40,7 +40,7 @@ public class ActionGetVariable extends Action {
|
||||
GraphTargetItem name = stack.pop();
|
||||
GraphTargetItem computedVal = variables.get(Highlighting.stripHilights(name.toStringNoQuotes()));
|
||||
GetVariableTreeItem gvt = new GetVariableTreeItem(this, name);
|
||||
gvt.computedValue = computedVal;
|
||||
gvt.setComputedValue(computedVal);
|
||||
stack.push(gvt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ public class ActionPush extends Action {
|
||||
for (Object o : values) {
|
||||
if (o instanceof ConstantIndex) {
|
||||
if ((constantPool == null) || (((ConstantIndex) o).index >= constantPool.size())) {
|
||||
o = "CONSTANT"+((ConstantIndex) o).index;
|
||||
o = "CONSTANT" + ((ConstantIndex) o).index;
|
||||
} else {
|
||||
o = constantPool.get(((ConstantIndex) o).index);
|
||||
}
|
||||
|
||||
@@ -21,5 +21,44 @@ import java.util.List;
|
||||
|
||||
public class ConstantPool {
|
||||
|
||||
public List<List<String>> archive = new ArrayList<List<String>>();
|
||||
public List<Integer> archiveCounts = new ArrayList<Integer>();
|
||||
public List<String> constants = new ArrayList<String>();
|
||||
public int count;
|
||||
|
||||
public ConstantPool() {
|
||||
}
|
||||
|
||||
public ConstantPool(List<String> constants) {
|
||||
this.constants = constants;
|
||||
}
|
||||
|
||||
public void setNew(List<String> constants) {
|
||||
archive.add(this.constants);
|
||||
this.constants = constants;
|
||||
archiveCounts.add(count);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + count + "x " + constants.toString();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return constants.isEmpty();
|
||||
}
|
||||
|
||||
public void getLastUsed() {
|
||||
if (count > 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = archive.size() - 1; i >= 0; i--) {
|
||||
if (archiveCounts.get(i) > 0) {
|
||||
count = archiveCounts.get(i);
|
||||
constants = archive.get(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,11 @@ import java.util.List;
|
||||
public class GetVariableTreeItem extends TreeItem {
|
||||
|
||||
public GraphTargetItem name;
|
||||
public GraphTargetItem computedValue;
|
||||
private GraphTargetItem computedValue;
|
||||
private double computedNumber = 0;
|
||||
private boolean computedBool = false;
|
||||
private boolean computedCompiletime = false;
|
||||
private boolean computedVariableComputed = false;
|
||||
|
||||
public GetVariableTreeItem(GraphSourceItem instruction, GraphTargetItem value) {
|
||||
super(instruction, PRECEDENCE_PRIMARY);
|
||||
@@ -32,6 +36,9 @@ public class GetVariableTreeItem extends TreeItem {
|
||||
|
||||
@Override
|
||||
public String toString(ConstantPool constants) {
|
||||
if (computedValue == null) {
|
||||
//return "null";
|
||||
}
|
||||
//return ""+computedValue.toNumber();
|
||||
return stripQuotes(name);
|
||||
}
|
||||
@@ -53,7 +60,7 @@ public class GetVariableTreeItem extends TreeItem {
|
||||
if (computedValue == null) {
|
||||
return false;
|
||||
}
|
||||
return computedValue.isCompileTime();
|
||||
return computedCompiletime;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,7 +68,7 @@ public class GetVariableTreeItem extends TreeItem {
|
||||
if (computedValue == null) {
|
||||
return false;
|
||||
}
|
||||
return computedValue.toBoolean();
|
||||
return computedBool;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,6 +76,16 @@ public class GetVariableTreeItem extends TreeItem {
|
||||
if (computedValue == null) {
|
||||
return 0;
|
||||
}
|
||||
return computedValue.toNumber();
|
||||
return computedNumber;
|
||||
}
|
||||
|
||||
public void setComputedValue(GraphTargetItem computedValue) {
|
||||
this.computedValue = computedValue;
|
||||
if (computedValue != null) {
|
||||
computedNumber = computedValue.toNumber();
|
||||
computedBool = computedValue.toBoolean();
|
||||
computedCompiletime = computedValue.isCompileTime();
|
||||
computedVariableComputed = computedValue.isVariableComputed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.action.treemodel.DirectValueTreeItem;
|
||||
import com.jpexs.decompiler.flash.helpers.Highlighting;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -461,14 +460,14 @@ public class Graph {
|
||||
}
|
||||
}
|
||||
if (part.nextParts.size() == 2) {
|
||||
if(part.nextParts.get(0)==part.nextParts.get(1)){
|
||||
if(!stack.isEmpty()) {
|
||||
if (part.nextParts.get(0) == part.nextParts.get(1)) {
|
||||
if (!stack.isEmpty()) {
|
||||
stack.pop();
|
||||
}
|
||||
part.nextParts.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (part.nextParts.size() == 2) {
|
||||
|
||||
if ((stack.size() >= 2) && (stack.get(stack.size() - 1) instanceof NotItem) && (((NotItem) (stack.get(stack.size() - 1))).getOriginal() == stack.get(stack.size() - 2))) {
|
||||
@@ -1086,6 +1085,10 @@ public class Graph {
|
||||
expr = stack.pop();
|
||||
}
|
||||
loopBody.addAll(0, output);
|
||||
if (part.nextParts.size() == 1) {
|
||||
loopBody.addAll(printGraph(localData, stack, allParts, part, part.nextParts.get(0), stopPart, loops, forFinalCommands));
|
||||
}
|
||||
|
||||
checkContinueAtTheEnd(loopBody, currentLoop);
|
||||
|
||||
List<GraphTargetItem> addIf = new ArrayList<GraphTargetItem>();
|
||||
@@ -1111,11 +1114,7 @@ public class Graph {
|
||||
next = part.nextParts.get(reversed ? 0 : 1);
|
||||
}
|
||||
if (doWhile) {
|
||||
if (part.nextParts.size() == 1) {
|
||||
next = part.nextParts.get(0);
|
||||
} else {
|
||||
next = null;
|
||||
}
|
||||
next = null;
|
||||
}
|
||||
if (next != null) {
|
||||
GraphTargetItem ti = checkLoop(next, stopPart, loops);
|
||||
@@ -1341,7 +1340,7 @@ public class Graph {
|
||||
} else if (ins.isBranch()) {
|
||||
part.end = ip;
|
||||
allBlocks.add(part);
|
||||
List<Integer> branches = ins.getBranches(code);
|
||||
List<Integer> branches = ins.getBranches(code);
|
||||
for (int i = 0; i < branches.size(); i++) {
|
||||
part.nextParts.add(g = makeGraph(part, path + i, code, branches.get(i), ip, allBlocks, refs, visited2));
|
||||
g.refs.add(part);
|
||||
|
||||
Reference in New Issue
Block a user