Skip to content

Commit da4eab1

Browse files
authored
Merge pull request #50 from LLVM-but-worse/filter
Decompile filter support
2 parents d48bde5 + 44385fa commit da4eab1

26 files changed

+185
-370
lines changed

mapleir/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
<dependency>
6969
<groupId>club.bytecode.the</groupId>
7070
<artifactId>jda</artifactId>
71-
<version>1.0.0</version>
71+
<version>1.1.0</version>
7272
</dependency>
7373
<dependency>
7474
<groupId>org.mapleir</groupId>

mapleir/src/main/java/org/mapleir/jdaplugin/DeobfuscateFilter.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
package org.mapleir.jdaplugin;
22

33
import club.bytecode.the.jda.decompilers.filter.DecompileFilter;
4+
import org.mapleir.ir.algorithms.BoissinotDestructor;
5+
import org.mapleir.ir.algorithms.ControlFlowGraphDumper;
6+
import org.mapleir.ir.cfg.ControlFlowGraph;
7+
import org.mapleir.ir.cfg.builder.ControlFlowGraphBuilder;
48
import org.objectweb.asm.tree.ClassNode;
9+
import org.objectweb.asm.tree.MethodNode;
510

611
public class DeobfuscateFilter implements DecompileFilter, MapleComponent {
712
@Override
813
public void process(ClassNode cn) {
9-
14+
if (cn == null)
15+
return;
16+
for (MethodNode mn : cn.methods) {
17+
ControlFlowGraph cfg = ControlFlowGraphBuilder.build(mn);
18+
BoissinotDestructor.leaveSSA(cfg);
19+
cfg.getLocals().realloc(cfg);
20+
(new ControlFlowGraphDumper(cfg, mn)).dump();
21+
System.out.println("Processed " + mn);
22+
}
1023
}
1124

1225
@Override

mapleir/src/main/java/org/mapleir/jdaplugin/MaplePlugin.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
1717

1818
import java.util.HashMap;
19+
import java.util.HashSet;
1920
import java.util.Map;
2021

2122
public class MaplePlugin implements JDAPlugin {
@@ -69,7 +70,8 @@ public void onExit() {
6970

7071
@Override
7172
public void onOpenFile(FileContainer fileContainer) {
72-
ApplicationClassSource app = new ApplicationClassSource(fileContainer.name, fileContainer.getClasses());
73+
// todo
74+
ApplicationClassSource app = new ApplicationClassSource(fileContainer.name, new HashSet<>());
7375
AnalysisContext newCxt = new BasicAnalysisContext.BasicContextBuilder()
7476
.setApplication(app)
7577
.setInvocationResolver(new DefaultInvocationResolver(app))

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>club.bytecode.the</groupId>
88
<artifactId>jda</artifactId>
9-
<version>1.0.0</version>
9+
<version>1.1.0</version>
1010

1111
<repositories>
1212
<repository>

src/main/java/club/bytecode/the/jda/FileChangeNotifier.java

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/main/java/club/bytecode/the/jda/FileContainer.java

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import org.objectweb.asm.tree.ClassNode;
55

66
import java.io.File;
7-
import java.util.Collection;
87
import java.util.HashMap;
98
import java.util.Map;
109

@@ -23,17 +22,7 @@ public FileContainer(File f) {
2322
public final File file;
2423
public final String name;
2524

26-
public HashMap<String, byte[]> files = new HashMap<>();
27-
private Map<String, ClassNode> classes = new HashMap<>();
28-
29-
public ClassNode getClassNode(String name) {
30-
if (classes.containsKey(name))
31-
return classes.get(name);
32-
ClassNode cn = loadClass(findClassfile(name));
33-
if (cn != null)
34-
classes.put(name, cn);
35-
return classes.get(name);
36-
}
25+
public HashMap<String, byte[]> files = new HashMap<>(); // this is assigned outside the class?!
3726

3827
public ClassNode loadClass(String name) {
3928
byte[] bytes = files.get(name);
@@ -56,18 +45,6 @@ public Map<String, byte[]> getFiles() {
5645
return files;
5746
}
5847

59-
public boolean remove(ClassNode classNode) {
60-
return classes.remove(classNode.name) != null;
61-
}
62-
63-
public void add(ClassNode classNode) {
64-
classes.put(classNode.name, classNode);
65-
}
66-
67-
public Collection<ClassNode> getClasses() {
68-
return classes.values();
69-
}
70-
7148
@Override
7249
public String toString() {
7350
return name;

src/main/java/club/bytecode/the/jda/JDA.java

Lines changed: 24 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
import club.bytecode.the.jda.gui.fileviewer.ViewerFile;
1111
import club.bytecode.the.jda.gui.navigation.FileNavigationPane;
1212
import club.bytecode.the.jda.settings.Settings;
13+
import club.bytecode.the.jda.util.GuiUtils;
14+
import club.bytecode.the.jda.util.MiscUtils;
1315
import org.apache.commons.io.FileUtils;
1416
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
1517
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
1618
import org.fife.ui.rsyntaxtextarea.folding.FoldParserManager;
17-
import org.objectweb.asm.ClassReader;
1819
import org.objectweb.asm.ClassWriter;
1920
import org.objectweb.asm.tree.ClassNode;
2021

@@ -31,8 +32,7 @@
3132

3233
public class JDA {
3334
/*per version*/
34-
public static final String version = "1.0.0";
35-
public static final boolean previewCopy = false;
35+
public static final String version = "1.1.0";
3636
/* Constants */
3737
public static final String fs = System.getProperty("file.separator");
3838
public static final String nl = System.getProperty("line.separator");
@@ -61,15 +61,16 @@ public class JDA {
6161
*/
6262
public static void main(String[] args) {
6363
try {
64+
// Fix antialiasing
65+
System.setProperty("awt.useSystemAAFontSettings", "lcd");
66+
System.setProperty("swing.aatext", "true");
67+
GuiUtils.setWmClassName("JDA");
6468
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
6569
} catch (Exception e) {
6670
new ExceptionUI(e);
6771
}
6872
try {
6973
System.out.println("JDA (BCV Fork) v" + version);
70-
if (previewCopy)
71-
showMessage("WARNING: This is a preview/dev copy, you WON'T be alerted when " + version + " is actually out if you use this." + nl +
72-
"Make sure to watch the repo: https://github.com/ecx86/jda for " + version + "'s release");
7374
getJDADirectory();
7475

7576
loadPlugins();
@@ -217,15 +218,26 @@ public static byte[] getFileBytes(ViewerFile file) {
217218
else
218219
return null;
219220
}
220-
221-
public static byte[] getClassBytes(FileContainer container, ClassNode cn) {
222-
byte[] bytes = getFileBytes(new ViewerFile(container, container.findClassfile(cn.name)));
221+
222+
public static boolean hasFile(ViewerFile file) {
223+
if (file.container == null)
224+
return false;
225+
return file.container.getFiles().containsKey(file.name);
226+
}
227+
228+
public static byte[] getClassFileBytes(FileContainer container, String className) {
229+
byte[] bytes = getFileBytes(new ViewerFile(container, container.findClassfile(className)));
223230
if (bytes == null)
224231
return null;
225-
if (cn.version < 49)
226-
bytes = fixBytes(bytes); // this is inefficient!
227232
return bytes;
228233
}
234+
235+
public static byte[] dumpClassToBytes(ClassNode cn) {
236+
// we have to do this, or else decompile filters don't work.
237+
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
238+
cn.accept(writer);
239+
return writer.toByteArray();
240+
}
229241

230242
public static final String HACK_PREFIX = "\0JDA-hack";
231243

@@ -245,31 +257,6 @@ public static String getClassName(String fullyQualifiedName) {
245257
return fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf('/') + 1);
246258
}
247259

248-
protected static byte[] fixBytes(byte[] in) {
249-
ClassReader reader = new ClassReader(in);
250-
ClassNode node = new ClassNode();
251-
reader.accept(node, ClassReader.EXPAND_FRAMES);
252-
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
253-
node.accept(writer);
254-
return writer.toByteArray();
255-
}
256-
257-
/**
258-
* Gets all of the loaded classes as an array list
259-
*
260-
* @return the loaded classes as an array list
261-
*/
262-
public static ArrayList<ClassNode> getLoadedClasses() {
263-
ArrayList<ClassNode> a = new ArrayList<>();
264-
265-
for (FileContainer container : files)
266-
for (ClassNode c : container.getClasses())
267-
if (!a.contains(c))
268-
a.add(c);
269-
270-
return a;
271-
}
272-
273260
// WTF????
274261
public static Map<String, byte[]> getLoadedBytes() {
275262
Map<String, byte[]> data = new HashMap<>();
@@ -316,10 +303,6 @@ public static void openFiles(final File[] files, boolean recentFiles, FileNaviga
316303
} catch (final Exception e) {
317304
new ExceptionUI(e);
318305
}
319-
} else if (fn.endsWith(".class")) {
320-
FileContainer container = loadClassfile(fileToOpen, fn);
321-
openFile(container);
322-
fnp.addTreeElement(container, parent);
323306
} else {
324307
HashMap<String, byte[]> files1 = new HashMap<>();
325308
byte[] bytes = JarUtils.getBytes(new FileInputStream(fileToOpen));
@@ -337,26 +320,7 @@ public static void openFiles(final File[] files, boolean recentFiles, FileNaviga
337320
}
338321
})).start();
339322
}
340-
341-
public static FileContainer loadClassfile(File fileToOpen, String fn) {
342-
try {
343-
byte[] bytes = JarUtils.getBytes(new FileInputStream(fileToOpen));
344-
String cafebabe = String.format("%02X%02X%02X%02X", bytes[0], bytes[1], bytes[2], bytes[3]);
345-
if (cafebabe.toLowerCase().equals("cafebabe")) {
346-
final ClassNode cn = JarUtils.getNode(bytes);
347-
FileContainer container = new FileContainer(fileToOpen);
348-
container.files.put(cn.name + ".class", bytes);
349-
container.add(cn);
350-
return container;
351-
} else {
352-
showMessage(fn + ": Header does not start with CAFEBABE, ignoring.");
353-
}
354-
} catch (final Exception e) {
355-
new ExceptionUI(e);
356-
}
357-
return null;
358-
}
359-
323+
360324
public static void openFile(FileContainer fc) {
361325
JDA.files.add(fc);
362326
plugins.forEach((plugin -> plugin.onOpenFile(fc)));
@@ -556,68 +520,6 @@ public static void checkHotKey(KeyEvent e) {
556520
viewer.refreshView();
557521
} else if ((e.getKeyCode() == KeyEvent.VK_W) && isCtrlDown(e) && isShiftDown(e)) {
558522
JDA.closeResources(true);
559-
} else if ((e.getKeyCode() == KeyEvent.VK_S) && isCtrlDown(e)) {
560-
if (JDA.getLoadedClasses().isEmpty()) {
561-
JDA.showMessage("First open a class, jar, or zip file.");
562-
return;
563-
}
564-
565-
Thread t = new Thread() {
566-
public void run() {
567-
JFileChooser fc = new JFileChooser();
568-
fc.setFileFilter(new FileFilter() {
569-
@Override
570-
public boolean accept(File f) {
571-
return f.isDirectory() || MiscUtils.extension(f.getAbsolutePath()).equals("zip");
572-
}
573-
574-
@Override
575-
public String getDescription() {
576-
return "Zip Archives";
577-
}
578-
});
579-
fc.setFileHidingEnabled(false);
580-
fc.setAcceptAllFileFilterUsed(false);
581-
int returnVal = fc.showSaveDialog(viewer);
582-
if (returnVal == JFileChooser.APPROVE_OPTION) {
583-
File file = fc.getSelectedFile();
584-
if (!file.getAbsolutePath().endsWith(".zip"))
585-
file = new File(file.getAbsolutePath() + ".zip");
586-
587-
if (file.exists()) {
588-
JOptionPane pane = new JOptionPane("Are you sure you wish to overwrite this existing file?");
589-
Object[] options = new String[]{"Yes", "No"};
590-
pane.setOptions(options);
591-
JDialog dialog = pane.createDialog(JDA.viewer, "JDA - Overwrite File");
592-
dialog.setVisible(true);
593-
Object obj = pane.getValue();
594-
int result = -1;
595-
for (int k = 0; k < options.length; k++)
596-
if (options[k].equals(obj))
597-
result = k;
598-
599-
if (result == 0) {
600-
file.delete();
601-
} else {
602-
return;
603-
}
604-
}
605-
606-
final File file2 = file;
607-
608-
JDA.setBusy(true);
609-
Thread t = new Thread() {
610-
@Override
611-
public void run() {
612-
JarUtils.saveAsJar(JDA.getLoadedBytes(), file2.getAbsolutePath());
613-
JDA.setBusy(false);
614-
}
615-
};
616-
t.start();
617-
}
618-
}
619-
};
620-
t.start();
621523
} else if ((e.getKeyCode() == KeyEvent.VK_W) && isCtrlDown(e)) {
622524
if (viewer.fileViewerPane.getCurrentViewer() != null)
623525
viewer.fileViewerPane.tabs.remove(viewer.fileViewerPane.getCurrentViewer());

src/main/java/club/bytecode/the/jda/api/ExceptionUI.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ private void setup(Throwable e, String author) {
6262
e.printStackTrace(new PrintWriter(sw));
6363
e.printStackTrace();
6464

65-
txtrBytecodeViewerIs.setText("JDA v" + JDA.version +
66-
", Preview Copy: " + JDA.previewCopy +
67-
JDA.nl + JDA.nl + sw.toString());
65+
txtrBytecodeViewerIs.setText("JDA v" + JDA.version + JDA.nl + JDA.nl + sw.toString());
6866
this.setLocationRelativeTo(null);
6967
this.setVisible(true);
7068
}

src/main/java/club/bytecode/the/jda/decompilers/CFRDecompiler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public JDANamespace getNamespace() {
9898
@Override
9999
public String decompileClassNode(FileContainer container, ClassNode cn) {
100100
try {
101-
byte[] bytes = JDA.getClassBytes(container, cn);
101+
byte[] bytes = JDA.dumpClassToBytes(cn);
102102
Options options = new GetOptParser().parse(generateMainMethod(), OptionsImpl.getFactory());
103103
ClassFileSourceImpl classFileSource = new ClassFileSourceImpl(options);
104104
DCCommonState dcCommonState = new DCCommonState(options, classFileSource);

0 commit comments

Comments
 (0)