faster deobfuscation

This commit is contained in:
honfika@gmail.com
2015-09-09 11:02:33 +02:00
parent 28468f9173
commit d37e1a3f73
2 changed files with 96 additions and 106 deletions

View File

@@ -290,6 +290,7 @@ import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.ExitItem;
import com.jpexs.decompiler.graph.model.ScriptEndItem;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.stat.Statistics;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -1035,7 +1036,6 @@ public class AVM2Code implements Cloneable {
}
public GraphTextWriter toASMSource(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, List<Integer> outputMap, ScriptExportMode exportMode, GraphTextWriter writer) {
invalidateCache();
if (trait != null) {
if (trait instanceof TraitFunction) {
TraitFunction tf = (TraitFunction) trait;
@@ -1298,62 +1298,58 @@ public class AVM2Code implements Cloneable {
return writer;
}
private boolean cacheActual = false;
private List<Long> posCache;
private Map<Long, Integer> posCacheReverse;
private void buildCache() {
List<Long> posCache = new ArrayList<>(code.size() + 1);
Map<Long, Integer> posCacheReverse = new HashMap<>(code.size() + 1);
long a = 0;
int i = 0;
for (; i < code.size(); i++) {
AVM2Instruction ins = code.get(i);
posCache.add(ins.offset);
posCacheReverse.put(ins.offset, i);
a = ins.offset + ins.getBytesLength();
}
posCache.add(a);
posCacheReverse.put(a, i);
this.posCache = posCache;
this.posCacheReverse = posCacheReverse;
cacheActual = true;
}
public int adr2pos(long address) throws ConvertException {
return adr2pos(address, false);
}
public int adr2pos(long address, boolean nearest) throws ConvertException {
if (!cacheActual) {
buildCache();
}
Integer ret = posCacheReverse.get(address);
if (ret == null) {
if (nearest) {
for (long a : posCache) {
if (a > address) {
return posCache.indexOf(a);
}
}
int ret = adr2posNoEx(address);
if (ret < 0) {
if (nearest && address < getEndOffset()) {
return -ret - 1;
}
throw new ConvertException("Invalid jump to ofs" + Helper.formatAddress(address), -1);
}
return ret;
}
public int pos2adr(int pos) {
if (!cacheActual) {
buildCache();
private int adr2posNoEx(long address) {
int min = 0;
int max = code.size() - 1;
while (max >= min) {
int mid = (min + max) / 2;
long midValue = code.get(mid).offset;
if (midValue == address) {
return mid;
} else if (midValue < address) {
min = mid + 1;
} else {
max = mid - 1;
}
}
return posCache.get(pos).intValue();
if (address == getEndOffset()) {
return code.size();
}
return -min - 1;
}
public void invalidateCache() {
cacheActual = false;
public long pos2adr(int pos) {
if (pos == code.size()) {
return getEndOffset();
}
return (int) code.get(pos).offset;
}
public long getEndOffset() {
if (code.isEmpty()) {
return 0;
}
AVM2Instruction ins = code.get(code.size() - 1);
return (int) (ins.offset + ins.getBytesLength());
}
private List<Integer> unknownJumps;
@@ -1463,7 +1459,7 @@ public class AVM2Code implements Cloneable {
return ip;
}
public int fixAddrAfterDebugLine(int addr) throws ConvertException {
public long fixAddrAfterDebugLine(long addr) throws ConvertException {
return pos2adr(fixIPAfterDebugLine(adr2pos(addr, true)));
}
@@ -2006,13 +2002,11 @@ public class AVM2Code implements Cloneable {
}
public void fixJumps(final String path, MethodBody body) throws InterruptedException {
buildCache();
if (code.isEmpty()) {
return;
}
AVM2Instruction lastInstuction = code.get(code.size() - 1);
final List<Long> insAddrToRemove = new ArrayList<>();
final long endOffset = lastInstuction.offset + lastInstuction.getBytesLength();
final long endOffset = getEndOffset();
updateOffsets(new OffsetUpdater() {
@Override
@@ -2022,7 +2016,7 @@ public class AVM2Code implements Cloneable {
@Override
public int updateOperandOffset(long insAddr, long targetAddress, int offset) {
if (targetAddress > endOffset || targetAddress < 0 || posCache.indexOf(targetAddress) == -1) {
if (targetAddress > endOffset || targetAddress < 0 || adr2posNoEx(targetAddress) < 0) {
insAddrToRemove.add(insAddr);
}
return offset;
@@ -2032,8 +2026,8 @@ public class AVM2Code implements Cloneable {
boolean someIgnored = false;
for (Long insAddr : insAddrToRemove) {
Integer pos = posCacheReverse.get(insAddr);
if (pos != null) {
int pos = adr2posNoEx(insAddr);
if (pos > -1) {
code.get(pos).ignored = true;
someIgnored = true;
}
@@ -2045,7 +2039,6 @@ public class AVM2Code implements Cloneable {
}
public void checkValidOffsets(MethodBody body) {
invalidateCache();
updateOffsets(new OffsetUpdater() {
@Override
@@ -2097,7 +2090,6 @@ public class AVM2Code implements Cloneable {
}
}, body);
code.remove(pos);
invalidateCache();
//checkValidOffsets(body);
}
@@ -2159,7 +2151,6 @@ public class AVM2Code implements Cloneable {
}, body);
}
code.set(pos, instruction);
invalidateCache();
//checkValidOffsets(body);
}
@@ -2212,7 +2203,6 @@ public class AVM2Code implements Cloneable {
}
}, body);
code.add(pos, instruction);
invalidateCache();
//checkValidOffsets(body);
}
@@ -2270,9 +2260,15 @@ public class AVM2Code implements Cloneable {
if (Configuration.deobfuscationOldMode.get()) {
return removeTrapsOld(constants, trait, info, body, abc, scriptIndex, classIndex, isStatic, path);
} else {
new AVM2DeobfuscatorSimple().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, info, body);
new AVM2DeobfuscatorRegisters().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, info, body);
new AVM2DeobfuscatorJumps().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, info, body);
try (Statistics s = new Statistics("AVM2DeobfuscatorSimple")) {
new AVM2DeobfuscatorSimple().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, info, body);
}
try (Statistics s = new Statistics("AVM2DeobfuscatorRegisters")) {
new AVM2DeobfuscatorRegisters().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, info, body);
}
try (Statistics s = new Statistics("AVM2DeobfuscatorJumps")) {
new AVM2DeobfuscatorJumps().deobfuscate(path, classIndex, isStatic, scriptIndex, abc, constants, trait, info, body);
}
return 1;
}
}
@@ -2765,7 +2761,6 @@ public class AVM2Code implements Cloneable {
} catch (ConvertException cex) {
logger.log(Level.SEVERE, "Error during restore control flow", cex);
}
invalidateCache();
try {
List<Integer> outputMap = new ArrayList<>();
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false);
@@ -2791,7 +2786,6 @@ public class AVM2Code implements Cloneable {
} catch (AVM2ParseException ex) {
logger.log(Level.FINE, null, ex);
}
invalidateCache();
removeDeadCode(body);
}
@@ -2836,7 +2830,6 @@ public class AVM2Code implements Cloneable {
}
public int removeDeadCode(MethodBody body) throws InterruptedException {
invalidateCache();
HashMap<Integer, List<Integer>> refs = visitCode(body);
int cnt = 0;
for (int i = code.size() - 1; i >= 0; i--) {
@@ -2869,9 +2862,9 @@ public class AVM2Code implements Cloneable {
for (int i = 0; i < csize; i++) {
AVM2Instruction ins = code.get(i);
int insLen = code.get(i).getBytesLength();
int ofs = pos2adr(i);
long ofs = pos2adr(i);
if (ins.definition instanceof JumpIns) {
int targetOfs = ofs + insLen + ins.operands[0];
long targetOfs = ofs + insLen + ins.operands[0];
try {
int ni = adr2pos(targetOfs);
if (ni < code.size() && ni > -1) {
@@ -2887,7 +2880,6 @@ public class AVM2Code implements Cloneable {
code.add(i + 3, nopIns);
i += 3;
csize = code.size();
buildCache();
}
}
} catch (ConvertException ex) {
@@ -3360,7 +3352,6 @@ public class AVM2Code implements Cloneable {
ret.code = codeCopy;
}
ret.cacheActual = false;
ret.ignoredIns = new ArrayList<>();
ret.killedRegs = new HashMap<>();
ret.unknownJumps = new ArrayList<>();

View File

@@ -184,21 +184,21 @@ public class AVM2Graph extends Graph {
}
List<Integer> ignoredSwitches2 = aLocalData.ignoredSwitches2;
int ip = part.start;
int addr = this.avm2code.fixAddrAfterDebugLine(this.avm2code.pos2adr(part.start));
int maxend = -1;
long addr = avm2code.fixAddrAfterDebugLine(avm2code.pos2adr(part.start));
long maxend = -1;
List<Integer> catchedFinallys = new ArrayList<>();
List<ABCException> catchedExceptions = new ArrayList<>();
for (int e = 0; e < body.exceptions.length; e++) {
if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (addr == avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
//Add finally only when the list is empty
if (!body.exceptions[e].isFinally() || catchedExceptions.isEmpty()) {
if (!parsedExceptions.contains(body.exceptions[e])) {
if (((body.exceptions[e].end) > maxend)) {
catchedExceptions.clear();
catchedFinallys.clear();
maxend = this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end);
maxend = avm2code.fixAddrAfterDebugLine(body.exceptions[e].end);
catchedExceptions.add(body.exceptions[e]);
} else if (this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) == maxend) {
} else if (avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) == maxend) {
catchedExceptions.add(body.exceptions[e]);
}
catchedFinallys.add(e);
@@ -211,19 +211,19 @@ public class AVM2Graph extends Graph {
}
if (catchedExceptions.size() > 0) {
parsedExceptions.addAll(catchedExceptions);
int endpos = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(catchedExceptions.get(0).end));
int endpos = code.adr2pos(avm2code.fixAddrAfterDebugLine(catchedExceptions.get(0).end));
int endposStartBlock = code.adr2pos(catchedExceptions.get(0).end);
String finCatchName = "";
List<List<GraphTargetItem>> catchedCommands = new ArrayList<>();
if (this.avm2code.code.get(endpos).definition instanceof JumpIns) {
int afterCatchAddr = this.avm2code.pos2adr(endpos + 1) + this.avm2code.code.get(endpos).operands[0];
int afterCatchPos = this.avm2code.adr2pos(afterCatchAddr);
if (avm2code.code.get(endpos).definition instanceof JumpIns) {
long afterCatchAddr = avm2code.pos2adr(endpos + 1) + avm2code.code.get(endpos).operands[0];
int afterCatchPos = avm2code.adr2pos(afterCatchAddr);
final AVM2Graph t = this;
Collections.sort(catchedExceptions, new Comparator<ABCException>() {
@Override
public int compare(ABCException o1, ABCException o2) {
return t.avm2code.fixAddrAfterDebugLine(o1.target) - t.avm2code.fixAddrAfterDebugLine(o2.target);
return (int) (t.avm2code.fixAddrAfterDebugLine(o1.target) - t.avm2code.fixAddrAfterDebugLine(o2.target));
}
});
@@ -233,13 +233,13 @@ public class AVM2Graph extends Graph {
int finStart = -1;
for (int e = 0; e < body.exceptions.length; e++) {
if (body.exceptions[e].isFinally()) {
if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (afterCatchPos + 1 == code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
if (addr == avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (afterCatchPos + 1 == code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
catchedFinallys.add(e);
AVM2Instruction jmpIns = this.avm2code.code.get(code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
AVM2Instruction jmpIns = avm2code.code.get(code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
if (jmpIns.definition instanceof JumpIns) {
finStart = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
finStart = code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
GraphPart fpart = null;
for (GraphPart p : allParts) {
@@ -251,9 +251,9 @@ public class AVM2Graph extends Graph {
TranslateStack st = (TranslateStack) stack.clone();
st.clear();
int swPos = -1;
for (int f = finStart; f < this.avm2code.code.size(); f++) {
if (this.avm2code.code.get(f).definition instanceof LookupSwitchIns) {
AVM2Instruction swins = this.avm2code.code.get(f);
for (int f = finStart; f < avm2code.code.size(); f++) {
if (avm2code.code.get(f).definition instanceof LookupSwitchIns) {
AVM2Instruction swins = avm2code.code.get(f);
if (swins.operands.length >= 3) {
if (swins.operands[0] == swins.getBytesLength()) {
if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) {
@@ -311,7 +311,7 @@ public class AVM2Graph extends Graph {
for (int e = 0; e < catchedExceptions.size(); e++) {
int eendpos;
if (e < catchedExceptions.size() - 1) {
eendpos = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(catchedExceptions.get(e + 1).target)) - 2;
eendpos = code.adr2pos(avm2code.fixAddrAfterDebugLine(catchedExceptions.get(e + 1).target)) - 2;
} else {
eendpos = afterCatchPos - 1;
}
@@ -428,16 +428,16 @@ public class AVM2Graph extends Graph {
}
if (part.nextParts.isEmpty()) {
if (this.avm2code.code.get(part.end).definition instanceof ReturnValueIns) { //returns in finally clause
if (avm2code.code.get(part.end).definition instanceof ReturnValueIns) { //returns in finally clause
if (part.getHeight() >= 3) {
if (this.avm2code.code.get(part.getPosAt(part.getHeight() - 2)).definition instanceof KillIns) {
if (this.avm2code.code.get(part.getPosAt(part.getHeight() - 3)).definition instanceof GetLocalTypeIns) {
if (avm2code.code.get(part.getPosAt(part.getHeight() - 2)).definition instanceof KillIns) {
if (avm2code.code.get(part.getPosAt(part.getHeight() - 3)).definition instanceof GetLocalTypeIns) {
if (output.size() >= 2) {
if (output.get(output.size() - 2) instanceof SetLocalAVM2Item) {
ret = new ArrayList<>();
ret.addAll(output);
ret.remove(ret.size() - 1);
ret.add(new ReturnValueAVM2Item(this.avm2code.code.get(part.end), ((SetLocalAVM2Item) output.get(output.size() - 2)).value));
ret.add(new ReturnValueAVM2Item(avm2code.code.get(part.end), ((SetLocalAVM2Item) output.get(output.size() - 2)).value));
return ret;
}
}
@@ -446,7 +446,7 @@ public class AVM2Graph extends Graph {
}
}
}
if ((this.avm2code.code.get(part.end).definition instanceof LookupSwitchIns) && (ignoredSwitches.containsValue(part.end) || ignoredSwitches2.contains(part.end))) {
if ((avm2code.code.get(part.end).definition instanceof LookupSwitchIns) && (ignoredSwitches.containsValue(part.end) || ignoredSwitches2.contains(part.end))) {
ret = new ArrayList<>();
ret.addAll(output);
return ret;
@@ -455,16 +455,16 @@ public class AVM2Graph extends Graph {
&& (!stack.isEmpty())
&& (stack.peek() instanceof StrictEqAVM2Item)
&& (part.nextParts.get(0).getHeight() >= 2)
&& (this.avm2code.code.get(this.avm2code.fixIPAfterDebugLine(part.nextParts.get(0).start)).definition instanceof PushIntegerTypeIns)
&& (avm2code.code.get(avm2code.fixIPAfterDebugLine(part.nextParts.get(0).start)).definition instanceof PushIntegerTypeIns)
&& (!part.nextParts.get(0).nextParts.isEmpty())
&& (this.avm2code.code.get(part.nextParts.get(0).nextParts.get(0).end).definition instanceof LookupSwitchIns))
&& (avm2code.code.get(part.nextParts.get(0).nextParts.get(0).end).definition instanceof LookupSwitchIns))
|| ((part.nextParts.size() == 2)
&& (!stack.isEmpty())
&& (stack.peek() instanceof StrictNeqAVM2Item)
&& (part.nextParts.get(1).getHeight() >= 2)
&& (this.avm2code.code.get(this.avm2code.fixIPAfterDebugLine(part.nextParts.get(1).start)).definition instanceof PushIntegerTypeIns)
&& (avm2code.code.get(avm2code.fixIPAfterDebugLine(part.nextParts.get(1).start)).definition instanceof PushIntegerTypeIns)
&& (!part.nextParts.get(1).nextParts.isEmpty())
&& (this.avm2code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns)))) {
&& (avm2code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns)))) {
if (stack.peek() instanceof StrictEqAVM2Item) {
ignoredSwitches2.add(part.nextParts.get(0).nextParts.get(0).end);
@@ -495,12 +495,12 @@ public class AVM2Graph extends Graph {
if (tar instanceof StrictNeqAVM2Item) {
tar = ((StrictNeqAVM2Item) tar).leftSide;
}
caseValuesMap.put(this.avm2code.code.get(part.nextParts.get(reversed ? 0 : 1).start).operands[0], tar);
caseValuesMap.put(avm2code.code.get(part.nextParts.get(reversed ? 0 : 1).start).operands[0], tar);
GraphPart switchLoc = part.nextParts.get(reversed ? 0 : 1).nextParts.get(0);
while ((this.avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictNeIns)
|| (this.avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictEqIns)) {
while ((avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictNeIns)
|| (avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictEqIns)) {
part = part.nextParts.get(reversed ? 1 : 0);
translatePart(localData, part, stack, staticOperation, null);
tar = stack.pop();
@@ -510,7 +510,7 @@ public class AVM2Graph extends Graph {
if (tar instanceof StrictNeqAVM2Item) {
tar = ((StrictNeqAVM2Item) tar).leftSide;
}
if (this.avm2code.code.get(part.end).definition instanceof IfStrictNeIns) {
if (avm2code.code.get(part.end).definition instanceof IfStrictNeIns) {
reversed = false;
} else {
reversed = true;
@@ -520,7 +520,7 @@ public class AVM2Graph extends Graph {
TranslateStack sstack = new TranslateStack(path);
do {
for (int n = 0; n < numPart.getHeight(); n++) {
ins = this.avm2code.code.get(numPart.getPosAt(n));
ins = avm2code.code.get(numPart.getPosAt(n));
if (ins.definition instanceof LookupSwitchIns) {
break;
}
@@ -531,7 +531,7 @@ public class AVM2Graph extends Graph {
} else {
numPart = numPart.nextParts.get(0);
}
} while (!(this.avm2code.code.get(numPart.end).definition instanceof LookupSwitchIns));
} while (!(avm2code.code.get(numPart.end).definition instanceof LookupSwitchIns));
GraphTargetItem nt = sstack.peek();
if (!(nt instanceof IntegerValueAVM2Item)) {
@@ -539,7 +539,7 @@ public class AVM2Graph extends Graph {
}
IntegerValueAVM2Item iv = (IntegerValueAVM2Item) nt;
caseValuesMap.put((int) (long) iv.value, tar);
while (this.avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).start).definition instanceof JumpIns) {
while (avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).start).definition instanceof JumpIns) {
reversed = false;
part = part.nextParts.get(reversed ? 1 : 0);
if (part instanceof GraphPartMulti) {
@@ -549,7 +549,7 @@ public class AVM2Graph extends Graph {
}
boolean hasDefault = false;
GraphPart dp = part.nextParts.get(reversed ? 1 : 0);
while (this.avm2code.code.get(dp.start).definition instanceof JumpIns) {
while (avm2code.code.get(dp.start).definition instanceof JumpIns) {
if (dp instanceof GraphPartMulti) {
dp = ((GraphPartMulti) dp).parts.get(0);
}
@@ -561,7 +561,7 @@ public class AVM2Graph extends Graph {
TranslateStack sstack = new TranslateStack(path);
do {
for (int n = 0; n < numPart.getHeight(); n++) {
ins = this.avm2code.code.get(numPart.getPosAt(n));
ins = avm2code.code.get(numPart.getPosAt(n));
if (ins.definition instanceof LookupSwitchIns) {
break;
}
@@ -572,7 +572,7 @@ public class AVM2Graph extends Graph {
} else {
numPart = numPart.nextParts.get(0);
}
} while (!(this.avm2code.code.get(numPart.end).definition instanceof LookupSwitchIns));
} while (!(avm2code.code.get(numPart.end).definition instanceof LookupSwitchIns));
GraphTargetItem nt = sstack.peek();
if (nt instanceof IntegerValueAVM2Item) {
hasDefault = true;
@@ -688,7 +688,6 @@ public class AVM2Graph extends Graph {
return p;
}
}
ret = null;
}
}
ret = null;
@@ -700,14 +699,14 @@ public class AVM2Graph extends Graph {
}
int pos = next.start;
int addr = this.avm2code.fixAddrAfterDebugLine(avm2code.pos2adr(pos));
long addr = avm2code.fixAddrAfterDebugLine(avm2code.pos2adr(pos));
for (int e = 0; e < body.exceptions.length; e++) {
if (body.exceptions[e].isFinally()) {
if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (addr == avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (true) { //afterCatchPos + 1 == code.adr2pos(this.code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
AVM2Instruction jmpIns = this.avm2code.code.get(avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
AVM2Instruction jmpIns = avm2code.code.get(avm2code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
if (jmpIns.definition instanceof JumpIns) {
int finStart = avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
int finStart = avm2code.adr2pos(avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
if (!finallyJumps.containsKey(e)) {
finallyJumps.put(e, new ArrayList<>());
}