AS3 DeobfuscatorJumps fix

New DeobfuscatorGroupParts (unused yet)
This commit is contained in:
Jindra Petřík
2021-11-18 15:46:11 +01:00
parent 80c9b7d601
commit 12a35d18d6
3 changed files with 244 additions and 4 deletions

View File

@@ -0,0 +1,178 @@
/*
* Copyright (C) 2010-2021 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.deobfuscation;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Stub for deobfuscator merging jump parts
*
* @author JPEXS
*/
public class AVM2DeobfuscatorGroupParts extends SWFDecompilerAdapter {
/*
blk_1
jump A
B:
blk_2
jump C
A: blk_3
jump B
C: blk_4
=>
jump A
A: jump B
B: jump C
blk_1
blk_3
blk_2
blk_4
----------------------
blk_1
jump A
B:
blk_2
jump C
A: blk_3
if B
blk_5
C: blk_4
=>
jump A
B:
blk_2
jump C
A: blk_1
blk_3
if B
blk_5
C:
blk_4
----------------------
blk_1
jump A
B:
blk_2
if C
A: blk_3
jump B
C: blk_4
=>
blk_1
jump A
B:
blk_3
blk_2
if C
A: jump B
C: blk_4
*/
@Override
public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException {
AVM2Code code = body.getCode();
code.removeDeadCode(body);
Map<Integer, List<Integer>> refs = body.getCode().visitCode(body);
for (int i = 0; i < code.code.size(); i++) {
AVM2Instruction ins = code.code.get(i);
if (ins.definition instanceof JumpIns) {
long targetAddr = ins.getTargetAddress();
int targetIp = code.adr2pos(targetAddr);
if (realRefs(refs, targetIp) == 1) {
int startIp = 0;
//find preceeding ip which is start of the "part"
for (int j = i; j >= 0; j--) {
AVM2Instruction startIns = code.code.get(j);
if (j < i && ((startIns.definition instanceof IfTypeIns) || (startIns.definition instanceof LookupSwitchIns))) {
startIp = j + 1;
break;
} else {
long srcAddr = code.pos2adr(j);
boolean exceptionMismatch = false;
for (int e = 0; e < body.exceptions.length; e++) {
boolean sourceMatch = srcAddr >= body.exceptions[e].start && srcAddr < body.exceptions[e].end;
boolean targetMatch = targetAddr >= body.exceptions[e].start && targetAddr < body.exceptions[e].end;
if (sourceMatch != targetMatch) {
exceptionMismatch = true;
break;
}
}
if (exceptionMismatch) {
startIp = j + 1;
break;
} else if (realRefs(refs, j) > 1) {
startIp = j;
break;
}
}
}
if (startIp < i) { //only when there is something to move
List<AVM2Instruction> movedInstructions = new ArrayList<>();
for (int k = startIp; k < i; k++) {
movedInstructions.add(code.code.get(startIp));
code.removeInstruction(startIp, body);
}
int newTargetIp = targetIp;
if (targetIp > i) { // forward jump
newTargetIp -= movedInstructions.size();
}
for (int m = 0; m < movedInstructions.size(); m++) {
code.insertInstruction(newTargetIp + m, movedInstructions.get(m), body);
}
i = -1;
refs = body.getCode().visitCode(body);
}
}
}
}
new AVM2DeobfuscatorJumps().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body);
}
private int realRefs(Map<Integer, List<Integer>> refs, int ip) {
int refCount = 0;
for (int r : refs.get(ip)) {
if (r >= 0) {
refCount++;
}
}
return refCount;
}
}

View File

@@ -69,7 +69,7 @@ public class AVM2DeobfuscatorJumps extends SWFDecompilerAdapter {
break;
}
}
if (!exceptionMismatch) {
if (exceptionMismatch) {
continue;
}
@@ -80,8 +80,22 @@ public class AVM2DeobfuscatorJumps extends SWFDecompilerAdapter {
for (int r : refs.get(i)) {
if (r >= 0) { //Not Exception start/end
AVM2Instruction srcIns = code.code.get(r);
srcAddr = srcIns.getAddress();
if ((srcIns.definition instanceof JumpIns) || ((srcIns.definition instanceof IfTypeIns) && (r != i - 1))) {
exceptionMismatch = false;
for (int e = 0; e < body.exceptions.length; e++) {
boolean sourceMatch = srcAddr >= body.exceptions[e].start && srcAddr < body.exceptions[e].end;
boolean targetMatch = targetAddr >= body.exceptions[e].start && targetAddr < body.exceptions[e].end;
if (sourceMatch != targetMatch) {
exceptionMismatch = true;
break;
}
}
if (exceptionMismatch) {
continue;
}
int oldop = srcIns.operands[0];
srcIns.operands[0] = (int) (targetAddr - (srcIns.getAddress() + srcIns.getBytesLength()));
if (srcIns.operands[0] != oldop) {