mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 21:20:45 +00:00
Deobfuscation simplified
This commit is contained in:
@@ -71,6 +71,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
|
||||
@@ -927,7 +928,7 @@ public class AVM2Code implements Serializable {
|
||||
}
|
||||
if (ins.labelname != null) {
|
||||
writer.appendNoHilight(ins.labelname + ":");
|
||||
} else if (offsets.contains(ofs)) {
|
||||
} else if (Configuration.showAllAddresses.get() || offsets.contains(ofs)) {
|
||||
writer.appendNoHilight("ofs" + Helper.formatAddress(ofs) + ":");
|
||||
}
|
||||
/*for (int e = 0; e < body.exceptions.length; e++) {
|
||||
@@ -2375,7 +2376,7 @@ public class AVM2Code implements Serializable {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static int removeTraps(HashMap<Integer, List<Integer>> refs, boolean secondPass, boolean indeterminate, List<Object> localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, AVM2GraphSource code, int ip, HashMap<Integer, Integer> visited, HashMap<Integer, HashMap<Integer, GraphTargetItem>> visitedStates, HashMap<GraphSourceItem, Decision> decisions, String path, int recursionLevel) throws InterruptedException {
|
||||
private static int removeTraps(HashMap<Integer, List<Integer>> refs, boolean secondPass, boolean indeterminate, List<Object> localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, AVM2GraphSource code, int ip, HashMap<Integer, Integer> visited, HashMap<Integer, HashMap<Integer, GraphTargetItem>> visitedStates, HashMap<AVM2Instruction, Decision> decisions, String path, int recursionLevel) throws InterruptedException {
|
||||
if (Thread.interrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
@@ -2427,20 +2428,16 @@ public class AVM2Code implements Serializable {
|
||||
}
|
||||
}*/
|
||||
|
||||
GraphSourceItem ins = code.get(ip);
|
||||
|
||||
if (ins instanceof AVM2Instruction) {
|
||||
AVM2Instruction ains = (AVM2Instruction) ins;
|
||||
//Errorneous code inserted by some obfuscators
|
||||
if (ains.definition instanceof NewObjectIns) {
|
||||
if (ains.operands[0] > stack.size()) {
|
||||
ains.setIgnored(true, 0);
|
||||
}
|
||||
AVM2Instruction ins = code.get(ip);
|
||||
//Errorneous code inserted by some obfuscators
|
||||
if (ins.definition instanceof NewObjectIns) {
|
||||
if (ins.operands[0] > stack.size()) {
|
||||
ins.setIgnored(true, 0);
|
||||
}
|
||||
if (ains.definition instanceof NewArrayIns) {
|
||||
if (ains.operands[0] > stack.size()) {
|
||||
ains.setIgnored(true, 0);
|
||||
}
|
||||
}
|
||||
if (ins.definition instanceof NewArrayIns) {
|
||||
if (ins.operands[0] > stack.size()) {
|
||||
ins.setIgnored(true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2482,7 +2479,7 @@ public class AVM2Code implements Serializable {
|
||||
|
||||
|
||||
|
||||
if ((ins instanceof AVM2Instruction) && (((AVM2Instruction) ins).definition instanceof NewFunctionIns)) {
|
||||
if (((AVM2Instruction) ins).definition instanceof NewFunctionIns) {
|
||||
stack.push(new BooleanAVM2Item(null, true));
|
||||
} else {
|
||||
localData.set(15, ip);
|
||||
@@ -2490,17 +2487,14 @@ public class AVM2Code implements Serializable {
|
||||
}
|
||||
|
||||
|
||||
if (ins instanceof AVM2Instruction) {
|
||||
AVM2Instruction ains = (AVM2Instruction) ins;
|
||||
if (ains.definition instanceof SetLocalTypeIns) {
|
||||
SetLocalTypeIns slt = (SetLocalTypeIns) ains.definition;
|
||||
int regId = slt.getRegisterId(ains);
|
||||
if (indeterminate) {
|
||||
HashMap<Integer, GraphTargetItem> registers = (HashMap<Integer, GraphTargetItem>) localData.get(2);
|
||||
GraphTargetItem regVal = registers.get(regId);
|
||||
if (regVal.isCompileTime()) {
|
||||
registers.put(regId, new NotCompileTimeItem(null, regVal));
|
||||
}
|
||||
if (ins.definition instanceof SetLocalTypeIns) {
|
||||
SetLocalTypeIns slt = (SetLocalTypeIns) ins.definition;
|
||||
int regId = slt.getRegisterId(ins);
|
||||
if (indeterminate) {
|
||||
HashMap<Integer, GraphTargetItem> registers = (HashMap<Integer, GraphTargetItem>) localData.get(2);
|
||||
GraphTargetItem regVal = registers.get(regId);
|
||||
if (regVal.isCompileTime()) {
|
||||
registers.put(regId, new NotCompileTimeItem(null, regVal));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2512,8 +2506,11 @@ public class AVM2Code implements Serializable {
|
||||
|
||||
if (ins.isBranch() || ins.isJump()) {
|
||||
List<Integer> branches = ins.getBranches(code);
|
||||
if ((ins instanceof AVM2Instruction) && ((AVM2Instruction) ins).definition instanceof IfTypeIns
|
||||
&& (!(((AVM2Instruction) ins).definition instanceof JumpIns)) && (!stack.isEmpty()) && (stack.peek().isCompileTime()) && (!stack.peek().hasSideEffect())) {
|
||||
if (((AVM2Instruction) ins).definition instanceof IfTypeIns
|
||||
&& (!(((AVM2Instruction) ins).definition instanceof JumpIns))
|
||||
&& (!stack.isEmpty())
|
||||
&& (stack.peek().isCompileTime())
|
||||
&& (!stack.peek().hasSideEffect())) {
|
||||
boolean condition = EcmaScript.toBoolean(stack.peek().getResult());
|
||||
if (debugMode) {
|
||||
if (condition) {
|
||||
@@ -2629,7 +2626,7 @@ public class AVM2Code implements Serializable {
|
||||
break;
|
||||
}
|
||||
ip++;
|
||||
};
|
||||
}
|
||||
if (ip < 0) {
|
||||
System.out.println("Visited Negative: " + ip);
|
||||
}
|
||||
@@ -2637,16 +2634,17 @@ public class AVM2Code implements Serializable {
|
||||
}
|
||||
|
||||
public static int removeTraps(ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, List<Object> localData, AVM2GraphSource code, int addr, String path, HashMap<Integer, List<Integer>> refs) throws InterruptedException {
|
||||
HashMap<GraphSourceItem, AVM2Code.Decision> decisions = new HashMap<>();
|
||||
HashMap<AVM2Instruction, 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, 0);
|
||||
int cnt = 0;
|
||||
for (GraphSourceItem src : decisions.keySet()) {
|
||||
for (AVM2Instruction src : decisions.keySet()) {
|
||||
Decision dec = decisions.get(src);
|
||||
if (dec != null) {
|
||||
if ((src instanceof AVM2Instruction) && (((AVM2Instruction) src).definition instanceof LookupSwitchIns)) {
|
||||
if (((AVM2Instruction) src).definition instanceof LookupSwitchIns) {
|
||||
AVM2Instruction asrc = (AVM2Instruction) src;
|
||||
if (dec.casesUsed.size() == 1) {
|
||||
for (int c : dec.casesUsed) {
|
||||
src.setFixBranch(c);
|
||||
asrc.setFixBranch(c);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.jpexs.decompiler.flash.abc.avm2.graph;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
@@ -57,7 +58,7 @@ public class AVM2GraphSource extends GraphSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphSourceItem get(int pos) {
|
||||
public AVM2Instruction get(int pos) {
|
||||
return code.code.get(pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -350,13 +350,11 @@ public class AVM2Instruction implements Serializable, GraphSourceItem {
|
||||
this.ignored = ignored;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFixBranch(int pos) {
|
||||
this.fixedBranch = pos;
|
||||
}
|
||||
private int fixedBranch = -1;
|
||||
|
||||
@Override
|
||||
public int getFixBranch() {
|
||||
return fixedBranch;
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ public class Action implements GraphSourceItem {
|
||||
}
|
||||
}
|
||||
|
||||
if (importantOffsets.contains(offset)) {
|
||||
if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) {
|
||||
if (lastPush) {
|
||||
writer.newLine();
|
||||
lastPush = false;
|
||||
@@ -488,8 +488,6 @@ public class Action implements GraphSourceItem {
|
||||
writer.appendNoHilight(":");
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (a.replaceWith != null) {
|
||||
if (lastPush) {
|
||||
writer.newLine();
|
||||
@@ -536,26 +534,24 @@ public class Action implements GraphSourceItem {
|
||||
|
||||
writer.append("", offset);
|
||||
|
||||
int fixBranch = -1;
|
||||
if (a instanceof ActionIf) {
|
||||
ActionIf aif = (ActionIf) a;
|
||||
if (aif.jumpUsed && !aif.ignoreUsed) {
|
||||
aif.setFixBranch(0);
|
||||
fixBranch = 0;
|
||||
}
|
||||
if (!aif.jumpUsed && aif.ignoreUsed) {
|
||||
aif.setFixBranch(1);
|
||||
fixBranch = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int fixBranch = a.getFixBranch();
|
||||
|
||||
if (fixBranch > -1) {
|
||||
if (a instanceof ActionIf) {
|
||||
writer.appendNoHilight("ffdec_deobfuscatepop").newLine();
|
||||
if (fixBranch == 0) { //jump
|
||||
writer.appendNoHilight("jump loc");
|
||||
writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getBytes(version).length + ((ActionIf) a).getJumpOffset()));
|
||||
} else {
|
||||
//nojump, ignore
|
||||
}
|
||||
writer.appendNoHilight("FFDec_DeobfuscatePop").newLine();
|
||||
if (fixBranch == 0) { //jump
|
||||
writer.appendNoHilight("Jump loc");
|
||||
writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getBytes(version).length + ((ActionIf) a).getJumpOffset()));
|
||||
} else {
|
||||
//nojump, ignore
|
||||
}
|
||||
} else {
|
||||
a.getASMSourceReplaced(list, importantOffsets, constantPool, version, exportMode, writer);
|
||||
@@ -564,7 +560,7 @@ public class Action implements GraphSourceItem {
|
||||
writer.appendNoHilight(add);
|
||||
if (!(a instanceof ActionPush)) {
|
||||
writer.newLine();
|
||||
};
|
||||
}
|
||||
}
|
||||
if (a instanceof ActionPush) {
|
||||
lastPush = true;
|
||||
@@ -1266,17 +1262,6 @@ public class Action implements GraphSourceItem {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFixBranch(int pos) {
|
||||
this.fixedBranch = pos;
|
||||
}
|
||||
private int fixedBranch = -1;
|
||||
|
||||
@Override
|
||||
public int getFixBranch() {
|
||||
return fixedBranch;
|
||||
}
|
||||
|
||||
public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value) {
|
||||
GraphTargetItem ret = get;
|
||||
if (ret instanceof GetVariableActionItem) {
|
||||
|
||||
@@ -214,7 +214,13 @@ public class ActionListReader {
|
||||
if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) {
|
||||
maxRecursionLevel++;
|
||||
}
|
||||
if (a instanceof ActionIf) {
|
||||
ActionIf aif = (ActionIf) a;
|
||||
aif.ignoreUsed = false;
|
||||
aif.jumpUsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
deobfustaceActionListAtPosRecursive(listeners, new ArrayList<GraphTargetItem>(), new HashMap<Long, List<GraphSourceItemContainer>>(), containerSWFOffset, localData, stack, cpool, actionMap, ip, ip, retdups, ip, endIp, path, new HashMap<Integer, Integer>(), false, new HashMap<Integer, HashMap<String, GraphTargetItem>>(), version, 0, maxRecursionLevel);
|
||||
|
||||
if (!retdups.isEmpty()) {
|
||||
@@ -759,24 +765,17 @@ public class ActionListReader {
|
||||
break;
|
||||
}
|
||||
} else if (top.isCompileTime() && (!top.hasSideEffect())) {
|
||||
((ActionIf) a).compileTime = true;
|
||||
if (debugMode) {
|
||||
System.err.print("is compiletime -> ");
|
||||
}
|
||||
if (EcmaScript.toBoolean(top.getResult())) {
|
||||
newip = pos + aif.getJumpOffset();
|
||||
aif.jumpUsed = true;
|
||||
if (aif.ignoreUsed) {
|
||||
aif.compileTime = false;
|
||||
}
|
||||
if (debugMode) {
|
||||
System.err.println("jump");
|
||||
}
|
||||
} else {
|
||||
aif.ignoreUsed = true;
|
||||
if (aif.jumpUsed) {
|
||||
aif.compileTime = false;
|
||||
}
|
||||
if (debugMode) {
|
||||
System.err.println("ignore");
|
||||
}
|
||||
|
||||
@@ -60,10 +60,15 @@ public class ASMParser {
|
||||
} else if (symb.type == ASMParsedSymbol.TYPE_COMMENT) {
|
||||
if (!list.isEmpty()) {
|
||||
String cmt = (String) symb.value;
|
||||
if (cmt.equals("compileTime")) {
|
||||
if (cmt.equals("compileTimeJump")) {
|
||||
Action a = list.get(list.size() - 1);
|
||||
if (a instanceof ActionIf) {
|
||||
((ActionIf) a).compileTime = true;
|
||||
((ActionIf) a).ignoreUsed = false;
|
||||
}
|
||||
} else if (cmt.equals("compileTimeIgnore")) {
|
||||
Action a = list.get(list.size() - 1);
|
||||
if (a instanceof ActionIf) {
|
||||
((ActionIf) a).jumpUsed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,8 @@ public class ActionIf extends Action {
|
||||
|
||||
private int offset;
|
||||
public String identifier;
|
||||
public boolean compileTime;
|
||||
public boolean jumpUsed = false;
|
||||
public boolean ignoreUsed = false;
|
||||
public boolean jumpUsed = true;
|
||||
public boolean ignoreUsed = true;
|
||||
|
||||
public int getJumpOffset() {
|
||||
return offset;
|
||||
@@ -85,7 +84,7 @@ public class ActionIf extends Action {
|
||||
@Override
|
||||
public String getASMSource(List<? extends GraphSourceItem> container, List<Long> knownAddreses, List<String> constantPool, int version, ExportMode exportMode) {
|
||||
String ofsStr = Helper.formatAddress(getAddress() + getBytes(version).length + offset);
|
||||
return "If loc" + ofsStr + (compileTime ? " ;compileTime" : "");
|
||||
return "If loc" + ofsStr + (!jumpUsed ? " ;compileTimeIgnore" : (!ignoreUsed ? " ;compileTimeJump" : ""));
|
||||
}
|
||||
|
||||
public ActionIf(FlasmLexer lexer) throws IOException, ParseException {
|
||||
|
||||
@@ -69,6 +69,10 @@ public class Configuration {
|
||||
public static final ConfigurationItem<Boolean> removeNops = null;
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
public static final ConfigurationItem<Boolean> showHexOnlyButton = null;
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
public static final ConfigurationItem<Boolean> decimalAddress = null;
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
public static final ConfigurationItem<Boolean> showAllAddresses = null;
|
||||
|
||||
/**
|
||||
* Debug mode = throwing an error when comparing original file and
|
||||
|
||||
@@ -44,9 +44,5 @@ public interface GraphSourceItem extends Serializable {
|
||||
|
||||
public void setIgnored(boolean ignored, int pos);
|
||||
|
||||
public void setFixBranch(int pos);
|
||||
|
||||
public int getFixBranch();
|
||||
|
||||
public boolean isDeobfuscatePop();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.helpers;
|
||||
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.helpers.Freed;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
|
||||
@@ -122,6 +123,9 @@ public class Helper {
|
||||
* @return String representation of the address
|
||||
*/
|
||||
public static String formatAddress(long number) {
|
||||
if (Configuration.decimalAddress.get()) {
|
||||
return padZeros(Long.toString(number), 4);
|
||||
}
|
||||
return padZeros(Long.toHexString(number), 4);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user