From ac7f4a6f1710ebe3872707567845bb227f26e18e Mon Sep 17 00:00:00 2001 From: Honfika Date: Sat, 12 Oct 2013 12:49:06 +0200 Subject: [PATCH] test for removing extra jumps (currently fails), small issue with ActionEnd fixed --- .../instructions/InstructionDefinition.java | 5 +- .../jpexs/decompiler/flash/action/Action.java | 4 +- .../flash/action/ActionListReader.java | 47 ++++++++--- .../flash/ActionScript2AssemblerTest.java | 13 +-- .../flash/ActionScript2DeobfuscatorTest.java | 83 +++++++++++++++++++ .../decompiler/flash/ActionScript2Test.java | 4 +- .../flash/ActionStript2TestBase.java | 39 +++++++++ 7 files changed, 164 insertions(+), 31 deletions(-) create mode 100644 trunk/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java create mode 100644 trunk/test/com/jpexs/decompiler/flash/ActionStript2TestBase.java diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java index ef2cf39a4..19e49748f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java @@ -42,9 +42,6 @@ public class InstructionDefinition implements Serializable { public static final long serialVersionUID = 1L; - protected String hilighOffset(String text, long offset) { - return Highlighting.hilighOffset(text, offset); - } public int[] operands; public String instructionName = ""; public int instructionCode = 0; @@ -120,7 +117,7 @@ public class InstructionDefinition implements Serializable { if (constants.constant_multiname[multinameIndex].needsName()) { name = stack.get(pos).toString(); } else { - name = hilighOffset(constants.constant_multiname[multinameIndex].getName(constants, fullyQualifiedNames), ins.offset); + name = Highlighting.hilighOffset(constants.constant_multiname[multinameIndex].getName(constants, fullyQualifiedNames), ins.offset); } return name + ns; } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index f27f48337..988ee3ab7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -352,13 +352,15 @@ public class Action implements GraphSourceItem { */ public static byte[] actionsToBytes(List list, boolean addZero, int version) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Action lastAction = null; for (Action a : list) { try { + lastAction = a; baos.write(a.getBytes(version)); } catch (IOException e) { } } - if (addZero) { + if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { baos.write(0); } return baos.toByteArray(); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java index bb5dcc99c..48cade3f5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -132,22 +132,25 @@ public class ActionListReader { getJumps(actions, jumps); long endAddress = updateAddresses(actions, ip, version); + + // add end action + Action lastAction = actions.get(actions.size() - 1); + Action aEnd = new ActionEnd(); + if (!(lastAction instanceof ActionEnd)) { + aEnd.setAddress(endAddress, version); + actions.add(aEnd); + } else { + endAddress -= getTotalActionLength(aEnd); + } + updateJumps(actions, jumps, containerLastActions, endAddress, version); updateActionStores(actions, jumps); updateContainerSizes(actions, containerLastActions); updateActionLengths(actions, version); - // add end action - Action lastAction = actions.get(actions.size() - 1); - if (!(lastAction instanceof ActionEnd)) { - Action aEnd = new ActionEnd(); - aEnd.setAddress(endAddress, version); - actions.add(aEnd); - endAddress += getTotalActionLength(aEnd); - } - if (deobfuscate) { - return deobfuscateActionList(listeners, containerSWFOffset, actions, version, 0, path); + actions = deobfuscateActionList(listeners, containerSWFOffset, actions, version, 0, path); + removeZeroJumps(actions); } return actions; @@ -172,7 +175,7 @@ public class ActionListReader { int endIp = data.length; List retdups = new ArrayList<>(); - for (int i = 0; i <= endIp; i++) { + for (int i = 0; i < endIp; i++) { Action a = new ActionNop(); a.setAddress(i, version); retdups.add(a); @@ -431,6 +434,28 @@ public class ActionListReader { } } + private static void removeZeroJumps(List actions) { + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump)a; + if (aJump.getOffset() == 0) { + removeAction(actions, i); + i--; + } + } + } + } + + /** + * Removes an action from the action list, and updates all references + * @param actions + * @param index + */ + private static void removeAction(List actions, int index) { + + } + @SuppressWarnings("unchecked") private static Action readActionListAtPos(List listeners, long containerSWFOffset, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, diff --git a/trunk/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java b/trunk/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java index 220ca9c75..6dbd5d027 100644 --- a/trunk/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java +++ b/trunk/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java @@ -16,9 +16,7 @@ import org.testng.annotations.Test; * * @author JPEXS */ -public class ActionScript2AssemblerTest { - - private SWF swf; +public class ActionScript2AssemblerTest extends ActionStript2TestBase { @BeforeClass public void init() throws IOException { @@ -26,15 +24,6 @@ public class ActionScript2AssemblerTest { swf = new SWF(new FileInputStream("testdata/as2/as2.swf"), false); } - private DoActionTag getFirstActionTag() { - for (Tag t : swf.tags) { - if (t instanceof DoActionTag) { - return (DoActionTag) t; - } - } - return null; - } - @Test public void testModifiedConstantPools() { String actionsString = "ConstantPool \"ok\"\n" + diff --git a/trunk/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java b/trunk/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java new file mode 100644 index 000000000..621dd1974 --- /dev/null +++ b/trunk/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.parser.ParseException; +import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser; +import com.jpexs.decompiler.flash.tags.DoActionTag; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author JPEXS + */ +public class ActionScript2DeobfuscatorTest extends ActionStript2TestBase { + + @BeforeClass + public void init() throws IOException { + Configuration.setConfig("autoDeobfuscate", true); + swf = new SWF(new FileInputStream("testdata/as2/as2.swf"), false); + } + + @Test + public void testRemoveJumpsToTheNextAction() { + String actionsString = "ConstantPool \"a\" \"b\" \"c\"\n" + + "Push false register1\n" + + "StoreRegister 2\n" + + "Pop\n" + + "Push register2\n" + + "StoreRegister 0\n" + + "Push \"a\"\n" + + "StrictEquals\n" + + "If loc005a\n" + + "Push register0 \"b\"\n" + + "StrictEquals\n" + + "If loc0068\n" + + "Jump loc0048;\n" + + "loc0048:Push register0 \"c\"\n" + + "StrictEquals\n" + + "If loc0076\n" + + "Jump loc0084\n" + + "loc005a:Push 1\n" + + "Trace\n" + + "Jump loc0084\n" + + "loc0068:Push 2\n" + + "Trace\n" + + "Jump loc0084\n" + + "loc0076:Push 3\n" + + "Trace\n" + + "Jump loc0084\n" + + "loc0084:"; + try { + List actions = ASMParser.parse(0, 0, true, actionsString, swf.version, false); + + DoActionTag doa = getFirstActionTag(); + doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); + String actualResult = Action.actionsToSource(doa.getActions(swf.version), swf.version, "", false); + + assertTrue(actualResult.contains("case \"c\":")); + } catch (IOException | ParseException ex) { + fail(); + } + } +} diff --git a/trunk/test/com/jpexs/decompiler/flash/ActionScript2Test.java b/trunk/test/com/jpexs/decompiler/flash/ActionScript2Test.java index d3e662179..1f06c3469 100644 --- a/trunk/test/com/jpexs/decompiler/flash/ActionScript2Test.java +++ b/trunk/test/com/jpexs/decompiler/flash/ActionScript2Test.java @@ -30,9 +30,7 @@ import org.testng.annotations.Test; * * @author JPEXS */ -public class ActionScript2Test { - - private SWF swf; +public class ActionScript2Test extends ActionStript2TestBase { @BeforeClass public void init() throws IOException { diff --git a/trunk/test/com/jpexs/decompiler/flash/ActionStript2TestBase.java b/trunk/test/com/jpexs/decompiler/flash/ActionStript2TestBase.java new file mode 100644 index 000000000..820077f02 --- /dev/null +++ b/trunk/test/com/jpexs/decompiler/flash/ActionStript2TestBase.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.tags.Tag; + +/** + * + * @author JPEXS + */ +public class ActionStript2TestBase { + + protected SWF swf; + + protected DoActionTag getFirstActionTag() { + for (Tag t : swf.tags) { + if (t instanceof DoActionTag) { + return (DoActionTag) t; + } + } + return null; + } + +}