From 8bfc8ad30f93eb0152f0140752f73e58d8ac33a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Mon, 8 Jul 2013 20:39:02 +0200 Subject: [PATCH] fixed deobfuscation Issue #151 option for caching in memory instead of temp files --- trunk/src/com/jpexs/decompiler/flash/SWF.java | 2 +- .../decompiler/flash/abc/avm2/AVM2Code.java | 2 +- .../localregs/GetLocalTypeIns.java | 2 +- .../com/jpexs/decompiler/flash/gui/Main.java | 7 + .../jpexs/decompiler/flash/gui/MainFrame.java | 17 +++ .../flash/gui/abc/DecompiledEditorPane.java | 5 +- .../flash/gui/action/ActionPanel.java | 2 +- .../flash/gui/resources/MainFrame.properties | 1 + .../gui/resources/MainFrame_cs.properties | 1 + .../jpexs/decompiler/flash/helpers/Cache.java | 121 ++++++++++++++---- .../flash/tags/DefineBitsLosslessTag.java | 8 +- .../flash/tags/DefineButton2Tag.java | 2 +- .../flash/tags/DefineButtonTag.java | 2 +- .../flash/tags/DefineSpriteTag.java | 2 +- 14 files changed, 135 insertions(+), 39 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index 923e44896..47dddb91e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -2013,7 +2013,7 @@ public class SWF { mat.getRotateSkew1Float(), mat.getScaleYFloat(), mat.translateX, mat.translateY); } - private static Cache cache = new Cache(false); + private static Cache cache = Cache.getInstance(false); public void clearImageCache() { cache.clear(); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 3e7492a26..3099423d0 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1445,7 +1445,7 @@ public class AVM2Code implements Serializable { localData.add(abc.method_info); localData.add(body); localData.add(abc); - localData.add(new HashMap()); //localRegNames + localData.add(body.getLocalRegNames(abc)); //localRegNames localData.add(new ArrayList()); //fullyQualifiedNames localData.add(new ArrayList()); localData.add(new ArrayList()); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java index aeb9a489b..09d37858f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java @@ -39,7 +39,7 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { GraphTargetItem computedValue = localRegs.get(getRegisterId(ins)); if (computedValue == null) { if (!localRegNames.containsKey(getRegisterId(ins))) { - computedValue = new UndefinedTreeItem(null); + computedValue = new UndefinedTreeItem(null); //In some obfuscated code there seems to be reading of undefined registers } } stack.push(new LocalRegTreeItem(ins, getRegisterId(ins), computedValue)); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java index 699853000..6fbe204a8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java @@ -31,6 +31,7 @@ import com.jpexs.decompiler.flash.gui.jna.platform.win32.WinReg; import com.jpexs.decompiler.flash.gui.jna.platform.win32.WinUser; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; +import com.jpexs.decompiler.flash.helpers.Cache; import com.jpexs.decompiler.flash.helpers.Helper; import com.sun.jna.Platform; import com.sun.jna.WString; @@ -467,6 +468,12 @@ public class Main { View.setLookAndFeel(); Configuration.loadFromFile(getConfigFile(), getReplacementsFile()); + if ((Boolean) Configuration.getConfig("cacheOnDisk", Boolean.TRUE)) { + Cache.setStorageType(Cache.STORAGE_FILES); + } else { + Cache.setStorageType(Cache.STORAGE_MEMORY); + } + int pos = 0; if (args.length > 0) { if (args[0].equals("-debug")) { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index fa0927110..effd45db9 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -35,6 +35,7 @@ import com.jpexs.decompiler.flash.gui.abc.LineMarkedEditorPane; import com.jpexs.decompiler.flash.gui.abc.TreeElement; import com.jpexs.decompiler.flash.gui.action.ActionPanel; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; +import com.jpexs.decompiler.flash.helpers.Cache; import com.jpexs.decompiler.flash.helpers.Helper; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; @@ -224,6 +225,7 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection private JCheckBoxMenuItem miParallelSpeedUp; private JCheckBoxMenuItem miAssociate; private JCheckBoxMenuItem miDecompile; + private JCheckBoxMenuItem miCacheDisk; public void setPercent(int percent) { progressBar.setValue(percent); @@ -482,11 +484,18 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection miDecompile.setActionCommand("DISABLEDECOMPILATION"); miDecompile.addActionListener(this); + + miCacheDisk = new JCheckBoxMenuItem(translate("menu.settings.cacheOnDisk")); + miCacheDisk.setSelected((Boolean) Configuration.getConfig("cacheOnDisk", Boolean.TRUE)); + miCacheDisk.setActionCommand("CACHEONDISK"); + miCacheDisk.addActionListener(this); + JMenu menuSettings = new JMenu(translate("menu.settings")); menuSettings.add(autoDeobfuscateMenuItem); menuSettings.add(miInternalViewer); menuSettings.add(miParallelSpeedUp); menuSettings.add(miDecompile); + menuSettings.add(miCacheDisk); miAssociate = new JCheckBoxMenuItem(translate("menu.settings.addtocontextmenu")); @@ -1566,6 +1575,14 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection @Override public void actionPerformed(ActionEvent e) { switch (e.getActionCommand()) { + case "CACHEONDISK": + Configuration.setConfig("cacheOnDisk", miCacheDisk.isSelected()); + if (miCacheDisk.isSelected()) { + Cache.setStorageType(Cache.STORAGE_FILES); + } else { + Cache.setStorageType(Cache.STORAGE_MEMORY); + } + break; case "SETLANGUAGE": String newLanguage = new SelectLanguageDialog().display(); if (newLanguage != null) { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 7a1f635a0..e22419fe2 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -50,7 +50,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL private ABCPanel abcPanel; private int classIndex = -1; private boolean isStatic = false; - private Cache cache = new Cache(true); + private Cache cache = Cache.getInstance(true); public ScriptPack getScriptLeaf() { return script; @@ -254,6 +254,9 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL } private CachedDecompilation getCached(ScriptPack pack) { + if (!cache.contains(pack)) { + cacheScriptPack(pack, abcList); + } return (CachedDecompilation) cache.get(pack); } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index 078378b80..e482afca6 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -107,7 +107,7 @@ public class ActionPanel extends JPanel implements ActionListener { private String searchFor; private boolean searchIgnoreCase; private boolean searchRegexp; - private Cache cache = new Cache(true); + private Cache cache = Cache.getInstance(true); public void clearCache() { cache.clear(); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/resources/MainFrame.properties b/trunk/src/com/jpexs/decompiler/flash/gui/resources/MainFrame.properties index 6dcda99d3..45c384c5c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/resources/MainFrame.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/resources/MainFrame.properties @@ -39,6 +39,7 @@ menu.settings.parallelspeedup = Parallel SpeedUp menu.settings.disabledecompilation = Disable decompilation (Disassemble only) menu.settings.addtocontextmenu = Add FFDec to SWF files context menu menu.settings.language = Change language +menu.settings.cacheOnDisk = Use caching on disk menu.help = Help menu.help.checkupdates = Check for updates... diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/resources/MainFrame_cs.properties b/trunk/src/com/jpexs/decompiler/flash/gui/resources/MainFrame_cs.properties index 91b9de4d8..550a8cab2 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/resources/MainFrame_cs.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/resources/MainFrame_cs.properties @@ -40,6 +40,7 @@ menu.settings.parallelspeedup = Paraleln\u00ed zrychlen\u00ed menu.settings.disabledecompilation = Zak\u00e1zat dekompilaci (Pouze P-k\u00f3d) menu.settings.addtocontextmenu = P\u0159idat FFDec do kontextov\u00e9ho menu SWF menu.settings.language = Zm\u011bnit jazyk +menu.settings.cacheOnDisk = Pou\u017e\u00edvat cache na disku menu.help = N\u00e1pov\u011bda menu.help.checkupdates = Zkontrolovat novou verzi... diff --git a/trunk/src/com/jpexs/decompiler/flash/helpers/Cache.java b/trunk/src/com/jpexs/decompiler/flash/helpers/Cache.java index 168931274..9850d3913 100644 --- a/trunk/src/com/jpexs/decompiler/flash/helpers/Cache.java +++ b/trunk/src/com/jpexs/decompiler/flash/helpers/Cache.java @@ -22,7 +22,9 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.WeakHashMap; import java.util.logging.Level; @@ -35,12 +37,52 @@ import java.util.logging.Logger; public class Cache { private Map cacheFiles; + private Map cacheMemory; + private static List instances = new ArrayList<>(); + public static final int STORAGE_FILES = 1; + public static final int STORAGE_MEMORY = 2; - public Cache(boolean weak) { + public static Cache getInstance(boolean weak) { + Cache instance = new Cache(weak); + instances.add(instance); + return instance; + } + private static int storageType = STORAGE_FILES; + + public static void clearAll() { + for (Cache c : instances) { + c.clear(); + } + } + + public static void setStorageType(int storageType) { + if (storageType == Cache.storageType) { + return; + } + switch (storageType) { + case STORAGE_FILES: + case STORAGE_MEMORY: + break; + default: + throw new IllegalArgumentException("storageType must be one of STORAGE_FILES or STORAGE_MEMORY"); + } + if (storageType != Cache.storageType) { + clearAll(); + } + Cache.storageType = storageType; + } + + public static int getStorageType() { + return storageType; + } + + private Cache(boolean weak) { if (weak) { cacheFiles = new WeakHashMap<>(); + cacheMemory = new WeakHashMap<>(); } else { cacheFiles = new HashMap<>(); + cacheMemory = new HashMap<>(); } } @@ -49,6 +91,7 @@ public class Cache { } public void clear() { + cacheMemory.clear(); for (File f : cacheFiles.values()) { f.delete(); } @@ -56,43 +99,67 @@ public class Cache { } public void remove(Object key) { - if (cacheFiles.containsKey(key)) { - File f = cacheFiles.get(key); - f.delete(); - cacheFiles.remove(key); + if (storageType == STORAGE_FILES) { + if (cacheFiles.containsKey(key)) { + File f = cacheFiles.get(key); + f.delete(); + cacheFiles.remove(key); + } + } else if (storageType == STORAGE_MEMORY) { + if (cacheMemory.containsKey(key)) { + cacheMemory.remove(key); + } } + } public Object get(Object key) { - if (!cacheFiles.containsKey(key)) { + if (storageType == STORAGE_FILES) { + if (!cacheFiles.containsKey(key)) { + return null; + } + File f = cacheFiles.get(key); + try (FileInputStream fis = new FileInputStream(f)) { + ObjectInputStream ois = new ObjectInputStream(fis); + return ois.readObject(); + } catch (IOException | ClassNotFoundException ex) { + Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); + } + return null; + } else if (storageType == STORAGE_MEMORY) { + if (!cacheMemory.containsKey(key)) { + return cacheMemory.get(key); + } return null; - } - File f = cacheFiles.get(key); - try (FileInputStream fis = new FileInputStream(f)) { - ObjectInputStream ois = new ObjectInputStream(fis); - return ois.readObject(); - } catch (IOException | ClassNotFoundException ex) { - Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); } return null; } public void put(Object key, Object value) { - File temp = null; - try { - temp = File.createTempFile("ffdec_cache", ".tmp"); - } catch (IOException ex) { - Logger.getLogger(Cache.class.getName()).log(Level.SEVERE, null, ex); - return; - } - temp.deleteOnExit(); - try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(temp))) { - oos.writeObject(value); - oos.flush(); + if (storageType == STORAGE_FILES) { + File temp = null; + try { + temp = File.createTempFile("ffdec_cache", ".tmp"); + } catch (IOException ex) { + Logger.getLogger(Cache.class + .getName()).log(Level.SEVERE, null, ex); - cacheFiles.put(key, temp); - } catch (IOException ex) { - Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex); + return; + } + temp.deleteOnExit(); + try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(temp))) { + oos.writeObject(value); + oos.flush(); + + cacheFiles.put(key, temp); + + + } catch (IOException ex) { + Logger.getLogger(Helper.class + .getName()).log(Level.SEVERE, null, ex); + } + } else if (storageType == STORAGE_MEMORY) { + cacheMemory.put(key, value); } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java index 9e4b9e0c9..542f2418b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineBitsLosslessTag.java @@ -72,7 +72,7 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag { bitmapData.bitmapPixelDataPix24[pos] = new PIX24(); bitmapData.bitmapPixelDataPix24[pos].red = r; bitmapData.bitmapPixelDataPix24[pos].green = g; - bitmapData.bitmapPixelDataPix24[pos].blue = b; + bitmapData.bitmapPixelDataPix24[pos].blue = b; bitmapData.bitmapPixelDataPix24[pos].reserved = 0xff; //documentation says 0, but image is sometimes broken with 0, so there is 0xff, which works (maybe alpha?) pos++; } @@ -86,7 +86,7 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag { zlibBitmapData = zlibOS.toByteArray(); decompressed = false; } - + @Override public BufferedImage getImage(List tags) { BufferedImage bi = new BufferedImage(bitmapWidth, bitmapHeight, BufferedImage.TYPE_INT_RGB); @@ -168,8 +168,8 @@ public class DefineBitsLosslessTag extends ImageTag implements AloneTag { bitmapColorTableSize = sis.readUI8(); } zlibBitmapData = sis.readBytes(sis.available()); - } - + } + /** * Gets data bytes * diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java index d72469020..73974e13b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButton2Tag.java @@ -201,7 +201,7 @@ public class DefineButton2Tag extends CharacterTag implements Container, Bounded } return needed; } - private static Cache rectCache = new Cache(true); + private static Cache rectCache = Cache.getInstance(true); @Override public RECT getRect(HashMap allCharacters, Stack visited) { diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java index 022c8dc51..094b938b8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineButtonTag.java @@ -204,7 +204,7 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT } return needed; } - private static Cache rectCache = new Cache(true); + private static Cache rectCache = Cache.getInstance(true); @Override public RECT getRect(HashMap allCharacters, Stack visited) { diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java index 59ec67692..dc590a7b7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/DefineSpriteTag.java @@ -100,7 +100,7 @@ public class DefineSpriteTag extends CharacterTag implements Container, BoundedT } return ret; } - private static Cache rectCache = new Cache(true); + private static Cache rectCache = Cache.getInstance(true); @Override public RECT getRect(HashMap characters, Stack visited) {