mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-19 21:22:18 +00:00
AS3 deobfuscation from commandline.
Separated deobfuscation settings
This commit is contained in:
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.ClassPath;
|
||||
import com.jpexs.decompiler.flash.abc.RenameType;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
@@ -2859,4 +2860,19 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
public String toString() {
|
||||
return getShortFileName();
|
||||
}
|
||||
|
||||
public void deobfuscate(DeobfuscationLevel level) throws InterruptedException {
|
||||
List<ABCContainerTag> atags = getAbcList();
|
||||
|
||||
for (ABCContainerTag tag : atags) {
|
||||
if (level == DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE) {
|
||||
tag.getABC().removeDeadCode();
|
||||
} else if (level == DeobfuscationLevel.LEVEL_REMOVE_TRAPS) {
|
||||
tag.getABC().removeTraps();
|
||||
} else if (level == DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW) {
|
||||
tag.getABC().removeTraps();
|
||||
tag.getABC().restoreControlFlow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.jpexs.decompiler.flash.abc.avm2.deobfuscation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public enum DeobfuscationLevel {
|
||||
|
||||
LEVEL_REMOVE_DEAD_CODE(1),
|
||||
LEVEL_REMOVE_TRAPS(2),
|
||||
LEVEL_RESTORE_CONTROL_FLOW(3);
|
||||
|
||||
private final int level;
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
DeobfuscationLevel(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.RenameType;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.pcode.ASM3Parser;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.pcode.MissingSymbolHandler;
|
||||
@@ -314,6 +315,10 @@ public class CommandLineArgumentParser {
|
||||
out.println(" " + (cnt++) + ") -replace <infile> <outfile> (<characterId1>|<scriptName1>) <importDataFile1> [methodBodyIndex1] [(<characterId2>|<scriptName2>) <importDataFile2> [methodBodyIndex2]]...");
|
||||
out.println(" ...replaces the data of the specified BinaryData, Image, DefineSound tag or Script");
|
||||
out.println(" ...methodBodyIndexN parameter should be specified if and only if the imported entity is an AS3 P-Code");
|
||||
out.println(" " + (cnt++) + ") -deobfuscate <level> <infile> <outfile>");
|
||||
out.println(" ...Deobfuscates AS3 P-code in <infile> and saves result to <outfile>");
|
||||
out.println(" ...<level> can be one of: controlflow/3/max, traps/2, deadcode/1");
|
||||
out.println(" ...WARNING: The deobfuscation result is still probably far enough to be openable by other decompilers.");
|
||||
printCmdLineUsageExamples(out);
|
||||
}
|
||||
|
||||
@@ -329,11 +334,12 @@ public class CommandLineArgumentParser {
|
||||
out.println("java -jar ffdec.jar -format script:pcode,text:plain -export script,text,image \"C:\\decompiled\" myfile.swf");
|
||||
out.println("java -jar ffdec.jar -format fla:cs5.5 -export fla \"C:\\sources\\myfile.fla\" myfile.swf");
|
||||
out.println("java -jar ffdec.jar -dumpSWF myfile.swf");
|
||||
out.println("java -jar ffdec.jar -compress myfile.swf myfiledec.swf");
|
||||
out.println("java -jar ffdec.jar -decompress myfiledec.swf myfile.swf");
|
||||
out.println("java -jar ffdec.jar -compress myfile.swf myfilecomp.swf");
|
||||
out.println("java -jar ffdec.jar -decompress myfile.swf myfiledec.swf");
|
||||
out.println("java -jar ffdec.jar -onerror ignore -export script \"C:\\decompiled\" myfile.swf");
|
||||
out.println("java -jar ffdec.jar -onerror retry 5 -export script \"C:\\decompiled\" myfile.swf");
|
||||
out.println("java -jar ffdec.jar -config autoDeobfuscate=1,parallelSpeedUp=0 -export script \"C:\\decompiled\" myfile.swf");
|
||||
out.println("java -jar ffdec.jar -deobfuscate max myas3file_secure.swf myas3file.swf");
|
||||
out.println("");
|
||||
out.println("Instead of \"java -jar ffdec.jar\" you can use ffdec.bat on Windows, ffdec.sh on Linux/MacOs");
|
||||
}
|
||||
@@ -470,6 +476,8 @@ public class CommandLineArgumentParser {
|
||||
parseXml2Swf(args);
|
||||
} else if (command.equals("extract")) {
|
||||
parseExtract(args);
|
||||
} else if (command.equals("deobfuscate")) {
|
||||
parseDeobfuscate(args);
|
||||
} else if (command.equals("renameinvalididentifiers")) {
|
||||
parseRenameInvalidIdentifiers(args);
|
||||
} else if (command.equals("dumpswf")) {
|
||||
@@ -1317,6 +1325,75 @@ public class CommandLineArgumentParser {
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseDeobfuscate(Stack<String> args) {
|
||||
if (args.size() < 3) {
|
||||
badArguments();
|
||||
}
|
||||
String mode = args.pop();
|
||||
DeobfuscationLevel lev = null;
|
||||
switch (mode) {
|
||||
case "controlflow":
|
||||
case "max":
|
||||
case "3":
|
||||
lev = DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW;
|
||||
break;
|
||||
case "traps":
|
||||
case "2":
|
||||
lev = DeobfuscationLevel.LEVEL_REMOVE_TRAPS;
|
||||
break;
|
||||
case "deadcode":
|
||||
case "1":
|
||||
lev = DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE;
|
||||
break;
|
||||
default:
|
||||
System.err.println("Invalid level, must be one of: controlflow,traps,deadcode or 1,2, 3/max");
|
||||
System.exit(1);
|
||||
break;
|
||||
}
|
||||
File inFile = new File(args.pop());
|
||||
File outFile = new File(args.pop());
|
||||
File tmpFile = null;
|
||||
if (inFile.equals(outFile)) {
|
||||
try {
|
||||
tmpFile = File.createTempFile("ffdec_deobf_", ".swf");
|
||||
outFile = tmpFile;
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Unable to create temp file");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
try (FileInputStream is = new FileInputStream(inFile);
|
||||
FileOutputStream fos = new FileOutputStream(outFile)) {
|
||||
SWF swf = new SWF(is, Configuration.parallelSpeedUp.get());
|
||||
if (!swf.isAS3()) {
|
||||
System.out.println("Warning: The file is not AS3. Only AS3 deobfuscation from commandline is available.");
|
||||
System.exit(0);
|
||||
}
|
||||
swf.deobfuscate(lev);
|
||||
swf.saveTo(fos);
|
||||
if (tmpFile != null) {
|
||||
inFile.delete();
|
||||
tmpFile.renameTo(inFile);
|
||||
tmpFile = null;
|
||||
System.out.println("" + inFile + " overwritten.");
|
||||
}
|
||||
System.out.println("OK");
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.err.println("File not found.");
|
||||
System.exit(1);
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.SEVERE, null, ex);
|
||||
System.exit(1);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(CommandLineArgumentParser.class.getName()).log(Level.SEVERE, "Error", ex);
|
||||
System.exit(1);
|
||||
} finally {
|
||||
if (tmpFile != null && tmpFile.exists()) {
|
||||
tmpFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseCompress(Stack<String> args) {
|
||||
if (args.size() < 2) {
|
||||
badArguments();
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.RenameType;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.configuration.ConfigurationItem;
|
||||
@@ -2222,11 +2223,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
ABCPanel aBCPanel = getABCPanel();
|
||||
if (deobfuscationDialog.processAllCheckbox.isSelected()) {
|
||||
for (ABCContainerTag tag : abcPanel.getAbcList()) {
|
||||
if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_DEAD_CODE) {
|
||||
if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE.getLevel()) {
|
||||
tag.getABC().removeDeadCode();
|
||||
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_TRAPS) {
|
||||
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationLevel.LEVEL_REMOVE_TRAPS.getLevel()) {
|
||||
tag.getABC().removeTraps();
|
||||
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_RESTORE_CONTROL_FLOW) {
|
||||
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW.getLevel()) {
|
||||
tag.getABC().removeTraps();
|
||||
tag.getABC().restoreControlFlow();
|
||||
}
|
||||
@@ -2237,11 +2238,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
Trait t = abcPanel.decompiledTextArea.getCurrentTrait();
|
||||
ABC abc = abcPanel.abc;
|
||||
if (bi != -1) {
|
||||
if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_DEAD_CODE) {
|
||||
if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE.getLevel()) {
|
||||
abc.bodies.get(bi).removeDeadCode(abc.constants, t, abc.method_info.get(abc.bodies.get(bi).method_info));
|
||||
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_TRAPS) {
|
||||
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationLevel.LEVEL_REMOVE_TRAPS.getLevel()) {
|
||||
abc.bodies.get(bi).removeTraps(abc.constants, abc, t, decompiledTextArea.getScriptLeaf().scriptIndex, decompiledTextArea.getClassIndex(), decompiledTextArea.getIsStatic(), ""/*FIXME*/);
|
||||
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_RESTORE_CONTROL_FLOW) {
|
||||
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW.getLevel()) {
|
||||
abc.bodies.get(bi).removeTraps(abc.constants, abc, t, decompiledTextArea.getScriptLeaf().scriptIndex, decompiledTextArea.getClassIndex(), decompiledTextArea.getIsStatic(), ""/*FIXME*/);
|
||||
abc.bodies.get(bi).restoreControlFlow(abc.constants, t, abc.method_info.get(abc.bodies.get(bi).method_info));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui.abc;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel;
|
||||
import com.jpexs.decompiler.flash.gui.AppDialog;
|
||||
import com.jpexs.decompiler.flash.gui.View;
|
||||
import java.awt.Component;
|
||||
@@ -43,12 +45,6 @@ public class DeobfuscationDialog extends AppDialog {
|
||||
|
||||
private int result = ERROR_OPTION;
|
||||
|
||||
public static final int LEVEL_REMOVE_DEAD_CODE = 1;
|
||||
|
||||
public static final int LEVEL_REMOVE_TRAPS = 2;
|
||||
|
||||
public static final int LEVEL_RESTORE_CONTROL_FLOW = 3;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public DeobfuscationDialog() {
|
||||
setDefaultCloseOperation(HIDE_ON_CLOSE);
|
||||
@@ -68,9 +64,9 @@ public class DeobfuscationDialog extends AppDialog {
|
||||
Hashtable<Integer, JLabel> labelTable = new Hashtable<>();
|
||||
//labelTable.put(LEVEL_NONE, new JLabel("None"));
|
||||
|
||||
labelTable.put(LEVEL_REMOVE_DEAD_CODE, new JLabel(translate("deobfuscation.removedeadcode")));
|
||||
labelTable.put(LEVEL_REMOVE_TRAPS, new JLabel(translate("deobfuscation.removetraps")));
|
||||
labelTable.put(LEVEL_RESTORE_CONTROL_FLOW, new JLabel(translate("deobfuscation.restorecontrolflow")));
|
||||
labelTable.put(DeobfuscationLevel.LEVEL_REMOVE_DEAD_CODE.getLevel(), new JLabel(translate("deobfuscation.removedeadcode")));
|
||||
labelTable.put(DeobfuscationLevel.LEVEL_REMOVE_TRAPS.getLevel(), new JLabel(translate("deobfuscation.removetraps")));
|
||||
labelTable.put(DeobfuscationLevel.LEVEL_RESTORE_CONTROL_FLOW.getLevel(), new JLabel(translate("deobfuscation.restorecontrolflow")));
|
||||
codeProcessingLevel.setLabelTable(labelTable);
|
||||
|
||||
codeProcessingLevel.setPaintLabels(true);
|
||||
|
||||
Reference in New Issue
Block a user