From eb557e34675af328ddf6c054deaffc677b0c8108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 9 Jul 2015 06:44:34 +0200 Subject: [PATCH] Issue #956 Invalid jump offsets warning --- .../decompiler/flash/abc/avm2/AVM2Code.java | 61 ++++++++++--------- .../deobfuscation/AVM2DeobfuscatorSimple.java | 3 +- .../flash/abc/types/MethodBody.java | 3 +- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 9300defb2..64afffcfe 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1992,12 +1992,13 @@ public class AVM2Code implements Cloneable { } } - public void fixJumps(MethodBody body) { + public void fixJumps(final String path, MethodBody body) throws InterruptedException { buildCache(); if (code.isEmpty()) { return; } AVM2Instruction lastInstuction = code.get(code.size() - 1); + final List insAddrToRemove = new ArrayList<>(); final long endOffset = lastInstuction.offset + lastInstuction.getBytesLength(); updateOffsets(new OffsetUpdater() { @@ -2008,25 +2009,26 @@ public class AVM2Code implements Cloneable { @Override public int updateOperandOffset(long insAddr, long targetAddress, int offset) { - if (targetAddress > endOffset) { - // jump to the end - return (int) (offset - targetAddress + endOffset); + if (targetAddress > endOffset || targetAddress < 0 || posCache.indexOf(targetAddress) == -1) { + insAddrToRemove.add(insAddr); } - if (targetAddress < 0) { - // jump to the first instuction - return (int) (offset - targetAddress); - } - - int targetPos = posCache.indexOf(targetAddress); - if (targetPos == -1) { - // jump to the end - return (int) (offset - targetAddress + endOffset); - } - return offset; } }, body); + + boolean someIgnored = false; + for (Long insAddr : insAddrToRemove) { + int pos = posCache.indexOf(insAddr); + if (pos > -1) { + code.get(pos).ignored = true; + someIgnored = true; + } + } + if (someIgnored) { + Logger.getLogger(AVM2Code.class.getName()).log(Level.WARNING, path + ": One or more invalid jump offsets found in the code. Those instructions were ignored."); + } + removeIgnored(body); } public void checkValidOffsets(MethodBody body) { @@ -2227,7 +2229,7 @@ public class AVM2Code implements Cloneable { } private int removeTrapsOld(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, ABC abc, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException { - removeDeadCode(constants, trait, info, body); + removeDeadCode(body); AVM2LocalData localData = new AVM2LocalData(); localData.isStatic = isStatic; localData.classIndex = classIndex; @@ -2250,9 +2252,9 @@ public class AVM2Code implements Cloneable { localData.refs = refs; localData.code = this; int ret = 0; - ret += removeTraps(constants, trait, info, body, localData, new AVM2GraphSource(this, false, -1, -1, new HashMap<>(), new ScopeStack(), abc, body, new HashMap<>(), new ArrayList<>(), new HashMap<>(), refs), 0, path, refs); - removeIgnored(constants, trait, info, body); - removeDeadCode(constants, trait, info, body); + ret += removeTrapsOld(constants, trait, info, body, localData, new AVM2GraphSource(this, false, -1, -1, new HashMap<>(), new ScopeStack(), abc, body, new HashMap<>(), new ArrayList<>(), new HashMap<>(), refs), 0, path, refs); + removeIgnored(body); + removeDeadCode(body); return ret; } @@ -2783,7 +2785,7 @@ public class AVM2Code implements Cloneable { logger.log(Level.FINE, null, ex); } invalidateCache(); - removeDeadCode(constants, trait, info, body); + removeDeadCode(body); } public void restoreControlFlow(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException { @@ -2815,7 +2817,7 @@ public class AVM2Code implements Cloneable { invalidateCache(); }*/ - public void removeIgnored(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException { + public void removeIgnored(MethodBody body) throws InterruptedException { //System.err.println("removing ignored..."); for (int i = 0; i < code.size(); i++) { if (code.get(i).ignored) { @@ -2826,7 +2828,7 @@ public class AVM2Code implements Cloneable { //System.err.println("/ignored removed"); } - public int removeDeadCode(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body) throws InterruptedException { + public int removeDeadCode(MethodBody body) throws InterruptedException { invalidateCache(); HashMap> refs = visitCode(body); int cnt = 0; @@ -2838,7 +2840,7 @@ public class AVM2Code implements Cloneable { } } - removeIgnored(constants, trait, info, body); + removeIgnored(body); for (int i = code.size() - 1; i >= 0; i--) { AVM2Instruction ins = code.get(i); @@ -2850,7 +2852,7 @@ public class AVM2Code implements Cloneable { } } - removeIgnored(constants, trait, info, body); + removeIgnored(body); return cnt; } @@ -3053,7 +3055,7 @@ public class AVM2Code implements Cloneable { } @SuppressWarnings("unchecked") - private static int removeTraps(HashMap> refs, boolean secondPass, boolean indeterminate, AVM2LocalData localData, TranslateStack stack, List output, AVM2GraphSource code, int ip, HashMap visited, HashMap> visitedStates, HashMap decisions, String path, int recursionLevel) throws InterruptedException { + private static int removeTrapsOld(HashMap> refs, boolean secondPass, boolean indeterminate, AVM2LocalData localData, TranslateStack stack, List output, AVM2GraphSource code, int ip, HashMap visited, HashMap> visitedStates, HashMap decisions, String path, int recursionLevel) throws InterruptedException { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); } @@ -3288,7 +3290,7 @@ public class AVM2Code implements Cloneable { for (int b : branches) { TranslateStack brStack = (TranslateStack) stack.clone(); if (b >= 0) { //useVisited || (!ins.isJump()) - ret += removeTraps(refs, secondPass, indeterminate, prepareBranchLocalData(localData), brStack, output, code, b, visited, visitedStates, decisions, path, recursionLevel + 1); + ret += removeTrapsOld(refs, secondPass, indeterminate, prepareBranchLocalData(localData), brStack, output, code, b, visited, visitedStates, decisions, path, recursionLevel + 1); } else { if (debugMode) { System.out.println("Negative branch:" + b); @@ -3306,9 +3308,9 @@ public class AVM2Code implements Cloneable { return ret; } - public static int removeTraps(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, AVM2LocalData localData, AVM2GraphSource code, int addr, String path, HashMap> refs) throws InterruptedException { + public static int removeTrapsOld(AVM2ConstantPool constants, Trait trait, MethodInfo info, MethodBody body, AVM2LocalData localData, AVM2GraphSource code, int addr, String path, HashMap> refs) throws InterruptedException { HashMap decisions = new HashMap<>(); - removeTraps(refs, false, false, localData, new TranslateStack(path), new ArrayList<>(), code, code.adr2pos(addr), new HashMap<>(), new HashMap<>(), decisions, path, 0); + removeTrapsOld(refs, false, false, localData, new TranslateStack(path), new ArrayList<>(), code, code.adr2pos(addr), new HashMap<>(), new HashMap<>(), decisions, path, 0); int cnt = 0; for (AVM2Instruction src : decisions.keySet()) { Decision dec = decisions.get(src); @@ -3332,8 +3334,7 @@ public class AVM2Code implements Cloneable { } } } - //int cnt = removeTraps(refs, true, false, localData, new TranslateStack(), new ArrayList(), code, code.adr2pos(addr), new HashMap(), new HashMap>(), decisions, path); - code.getCode().removeIgnored(constants, trait, info, body); + code.getCode().removeIgnored(body); return cnt; } /*public static int removeTraps(AVM2LocalData localData, AVM2GraphSource code, int addr) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java index 0e19a9271..beef52bdc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java @@ -178,7 +178,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { } protected void removeUnreachableActions(AVM2Code code, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { - code.removeDeadCode(cpool, trait, minfo, body); + code.removeDeadCode(body); } protected boolean removeZeroJumps(AVM2Code actions, MethodBody body) { @@ -422,7 +422,6 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener { public void deobfuscate(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { AVM2Code code = body.getCode(); - code.fixJumps(body); removeUnreachableActions(code, cpool, trait, minfo, body); removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body, new ArrayList<>()); removeZeroJumps(code, body); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 6df43e5c5..6b8577c31 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -163,7 +163,7 @@ public final class MethodBody implements Cloneable { } public int removeDeadCode(AVM2ConstantPool constants, Trait trait, MethodInfo info) throws InterruptedException { - return getCode().removeDeadCode(constants, trait, info, this); + return getCode().removeDeadCode(this); } public void restoreControlFlow(AVM2ConstantPool constants, Trait trait, MethodInfo info) throws InterruptedException { @@ -349,6 +349,7 @@ public final class MethodBody implements Cloneable { public MethodBody convertMethodBody(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, AVM2ConstantPool constants, List method_info, ScopeStack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, Traits initTraits) throws InterruptedException { MethodBody body = clone(); body.getCode().markMappedOffsets(); + body.getCode().fixJumps(path, body); if (Configuration.autoDeobfuscate.get()) { try {