12/28/2014 - Improved the outdated version pane by including an
automatic downloader - http://i.imgur.com/4MXeBGb.png -
http://i.imgur.com/v50Pghe.png - http://i.imgur.com/bVZqxZ2.png -
http://i.imgur.com/l8nIMzD.png
12/28/2014 - Updated CFR to cfr_0.92.jar
12/31/2014 - Adrianherrera updated the Malicious Code Scanner to detect
the security manager being set to null.
**HAPPY NEW YEAR**
01/01/2015 - Added refresh class on decompiler/pane view change
01/01/2015 - Moved all of the settings into a settings pane
01/01/2015 - Added some debug code when you first start it up, it also
includes how long it took to fully load up.
01/02/2015 - Cached the busy icon.
01/02/2015 - ADDED APK SUPPORT, had to downgrade to ASM 3.3, which means
losing some annotation debugging for the Bytecode Decompiler.
01/03/2015 - Wrapped the search pane in a JScrollPane.
01/06/2015 - Added save as DEX and import .dex files.
This commit is contained in:
Kalen Kinloch 2015-01-06 04:54:14 -08:00
parent 8adee814cc
commit bb95011f47
29 changed files with 673 additions and 311 deletions

View file

@ -1,4 +1,4 @@
Bytecode Viewer is an Advanced Lightweight Java Bytecode Viewer, GUI Procyon Java Decompiler, GUI CFR Java Decompiler, GUI FernFlower Java Decompiler, GUI Jar-Jar, Hex Viewer, Code Searcher, Debugger and more. Bytecode Viewer is an Advanced Lightweight Java Bytecode Viewer, GUI APK Decompiler, GUI DEX Decompiler, GUI Procyon Java Decompiler, GUI CFR Java Decompiler, GUI FernFlower Java Decompiler, GUI Jar-Jar, Hex Viewer, Code Searcher, Debugger and more.
It's written completely in Java, and it's open sourced. It's currently being maintained and developed by Konloch. It's written completely in Java, and it's open sourced. It's currently being maintained and developed by Konloch.
There is also a plugin system that will allow you to interact with the loaded classfiles, for example you can write a String deobfuscator, a malicious code searcher, or something else you can think of. There is also a plugin system that will allow you to interact with the loaded classfiles, for example you can write a String deobfuscator, a malicious code searcher, or something else you can think of.
@ -38,15 +38,15 @@ Report Bugs (or below): https://github.com/Konloch/bytecode-viewer/issues
Discussion Forum: https://the.bytecode.club/forumdisplay.php?fid=69 Discussion Forum: https://the.bytecode.club/forumdisplay.php?fid=69
Key Features: Key Features:
Java Decompiler - It uses a modified version of FernFlower, Procyon and CFR. Java Decompiler - It utilizes FernFlower, Procyon and CFR for decompilation.
Bytecode Decompiler - A modified version of CFIDE's. Bytecode Decompiler - A modified version of CFIDE's.
Hex Viewer - Powered by JHexPane. Hex Viewer - Powered by JHexPane.
Each Decompiler/Viewer is toggleable. Each Decompiler/Viewer is toggleable, you can also select what will display on each pane.
Fully Featured Search System. Fully Featured Search System - Search through strings, functions, variables and more!
A Plugin System With Built In Plugins. (Show All Strings, Malicious Code Scanner, String Decrypters, etc) A Plugin System With Built In Plugins - (Show All Strings, Malicious Code Scanner, String Decrypters, etc)
Fully Featured Scripting System That Supports Groovy, Python And Ruby. Fully Featured Scripting System That Supports Groovy, Python And Ruby.
Recent Files & Recent Plugins.
EZ-Inject - Graphically insert hooks and debugging code, invoke main and start the program. EZ-Inject - Graphically insert hooks and debugging code, invoke main and start the program.
Recent Files & Recent Plugins.
And more! Give it a try for yourself! And more! Give it a try for yourself!
Are you a Java Reverse Engineer? Do you want to learn? Are you a Java Reverse Engineer? Do you want to learn?
@ -219,3 +219,15 @@ Changelog:
12/20/2014 - If the class file does not start with CAFEBABE it won't be processed. 12/20/2014 - If the class file does not start with CAFEBABE it won't be processed.
12/20/2014 - Properly handled file not found error. 12/20/2014 - Properly handled file not found error.
12/21/2014 - Fixed the Refresh Class causing a dupe. 12/21/2014 - Fixed the Refresh Class causing a dupe.
--- 2.5.0 ---:
12/28/2014 - Improved the outdated version pane by including an automatic downloader - http://i.imgur.com/4MXeBGb.png - http://i.imgur.com/v50Pghe.png - http://i.imgur.com/bVZqxZ2.png - http://i.imgur.com/l8nIMzD.png
12/28/2014 - Updated CFR to cfr_0.92.jar
12/31/2014 - Adrianherrera updated the Malicious Code Scanner to detect the security manager being set to null.
**HAPPY NEW YEAR**
01/01/2015 - Added refresh class on decompiler/pane view change
01/01/2015 - Moved all of the settings into a settings pane
01/01/2015 - Added some debug code when you first start it up, it also includes how long it took to fully load up.
01/02/2015 - Cached the busy icon.
01/02/2015 - ADDED APK SUPPORT, had to downgrade to ASM 3.3, which means losing some annotation debugging for the Bytecode Decompiler.
01/03/2015 - Wrapped the search pane in a JScrollPane.
01/06/2015 - Added save as DEX and import .dex files.

BIN
libs/asm-all-3.3.1.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
libs/dex-ir-1.12.jar Normal file

Binary file not shown.

BIN
libs/dex-reader-1.15.jar Normal file

Binary file not shown.

BIN
libs/dex-tools-0.0.9.15.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
libs/dx.jar Normal file

Binary file not shown.

BIN
libs/jar-rename-1.6.jar Normal file

Binary file not shown.

BIN
libs/jasmin-p2.5.jar Normal file

Binary file not shown.

View file

@ -8,6 +8,9 @@ import java.io.BufferedReader;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URI; import java.net.URI;
@ -18,6 +21,7 @@ import java.util.Map.Entry;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.UIManager; import javax.swing.UIManager;
@ -62,14 +66,16 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager;
* TODO: * TODO:
* The import jar method eats up a lot of memory, look into some how reducing this. * The import jar method eats up a lot of memory, look into some how reducing this.
* Add a tool to build a flowchart of all the classes, and what methods execute what classes, and those method, read chatlog * Add a tool to build a flowchart of all the classes, and what methods execute what classes, and those method, read chatlog
* Add obfuscation * Add obfuscation:
* Add integer boxing and other obfuscation methods contra implemented
* Insert unadded/debug opcodes to try to fuck up decompilers
* ClassAnylyzterAdapter
* Add progress bars on saving all zips/java decompile jar * Add progress bars on saving all zips/java decompile jar
* Add the jump/save mark system Ida Pro has. * Add the jump/save mark system Ida Pro has.
* Add integer boxing and other obfuscation methods contra implemented
* Insert unadded/debug opcodes to try to fuck up decompilers
* ClassAnylyzterAdapter
* Add class annotations to bytecode decompiler. * Add class annotations to bytecode decompiler.
* Option to make the bytecode pane automatically scroll to where the source code pane is * Option to make the bytecode pane automatically scroll to where the source code pane is
* Replacing all string field calls with the string instance - would require EZ-Injection to run code?
* Spiffy up the plugin console with red text optional, would require JTextPane, not JTextArea.
* *
* ----Beta 1.0.0-----: * ----Beta 1.0.0-----:
* 10/4/2014 - Designed a POC GUI, still needs a lot of work. * 10/4/2014 - Designed a POC GUI, still needs a lot of work.
@ -236,6 +242,18 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager;
* 12/20/2014 - If the class file does not start with CAFEBABE it won't be processed. * 12/20/2014 - If the class file does not start with CAFEBABE it won't be processed.
* 12/20/2014 - Properly handled file not found error. * 12/20/2014 - Properly handled file not found error.
* 12/21/2014 - Fixed the Refresh Class causing a dupe. * 12/21/2014 - Fixed the Refresh Class causing a dupe.
* -----2.5.0-----:
* 12/28/2014 - Improved the outdated version pane by including an automatic downloader - http://i.imgur.com/4MXeBGb.png - http://i.imgur.com/v50Pghe.png - http://i.imgur.com/bVZqxZ2.png - http://i.imgur.com/l8nIMzD.png
* 12/28/2014 - Updated CFR to cfr_0.92.jar
* 12/31/2014 - Adrianherrera updated the Malicious Code Scanner to detect the security manager being set to null.
* **HAPPY NEW YEAR**
* 01/01/2015 - Added refresh class on decompiler/pane view change
* 01/01/2015 - Moved all of the settings into a settings pane
* 01/01/2015 - Added some debug code when you first start it up, it also includes how long it took to fully load up.
* 01/02/2015 - Cached the busy icon.
* 01/02/2015 - ADDED APK SUPPORT, had to downgrade to ASM 3.3, which means losing some annotation debugging for the Bytecode Decompiler.
* 01/03/2015 - Wrapped the search pane in a JScrollPane.
* 01/06/2015 - Added save as DEX and import .dex files.
* *
* @author Konloch * @author Konloch
* *
@ -256,9 +274,11 @@ public class BytecodeViewer {
private static ArrayList<String> recentFiles = DiskReader.loadArrayList(filesName, false); private static ArrayList<String> recentFiles = DiskReader.loadArrayList(filesName, false);
private static ArrayList<String> recentPlugins = DiskReader.loadArrayList(pluginsName, false); private static ArrayList<String> recentPlugins = DiskReader.loadArrayList(pluginsName, false);
public static boolean runningObfuscation = false; public static boolean runningObfuscation = false;
public static String version = "2.4.0"; public static String version = "2.5.0";
private static long start = System.currentTimeMillis();
public static void main(String[] args) { public static void main(String[] args) {
System.out.println("https://the.bytecode.club - Created by @Konloch - Bytecode Viewer " + version);
iconList = new ArrayList<BufferedImage>(); iconList = new ArrayList<BufferedImage>();
int size = 16; int size = 16;
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
@ -295,7 +315,7 @@ public class BytecodeViewer {
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0"); "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0");
BufferedReader reader = new BufferedReader( BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream())); new InputStreamReader(connection.getInputStream()));
String version = reader.readLine(); final String version = reader.readLine();
reader.close(); reader.close();
if (!BytecodeViewer.version.equals(version)) { if (!BytecodeViewer.version.equals(version)) {
connection = (HttpURLConnection) new URL( connection = (HttpURLConnection) new URL(
@ -312,11 +332,13 @@ public class BytecodeViewer {
readme.add(s); readme.add(s);
reader.close(); reader.close();
String changelog = ""; String changelog = "Unable to load change log, please try again later."+nl;
boolean trigger = false; boolean trigger = false;
for(String st : readme) { for(String st : readme) {
if(st.equals("--- "+version+" ---:")) if(st.equals("--- "+version+" ---:")) {
changelog = "";
trigger = true; trigger = true;
}
if(trigger == true && !st.equals("--- "+version+" ---:")) { if(trigger == true && !st.equals("--- "+version+" ---:")) {
if(st.startsWith("--- ")) if(st.startsWith("--- "))
@ -336,8 +358,8 @@ public class BytecodeViewer {
+ nl + nl
+ changelog + changelog
+ nl + nl
+ "Would you like to automatically open the download page? (https://github.com/Konloch/bytecode-viewer/releases)"); + "What would you like to do?");
Object[] options = new String[] { "Yes", "No" }; Object[] options = new String[] { "Open The Download Page", "Download The Updated Jar", "Do Nothing" };
pane.setOptions(options); pane.setOptions(options);
JDialog dialog = pane.createDialog(BytecodeViewer.viewer, JDialog dialog = pane.createDialog(BytecodeViewer.viewer,
"Bytecode Viewer - Outdated Version"); "Bytecode Viewer - Outdated Version");
@ -356,6 +378,92 @@ public class BytecodeViewer {
showMessage("Cannot open the page, please manually type it."); showMessage("Cannot open the page, please manually type it.");
} }
} }
if(result == 1) {
JFileChooser fc = new JFileChooser();
try {
fc.setCurrentDirectory(new File(".").getAbsoluteFile()); //set the current working directory
} catch(Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
fc.setFileFilter(viewer.new JarFileFilter());
fc.setFileHidingEnabled(false);
fc.setAcceptAllFileFilterUsed(false);
int returnVal = fc.showSaveDialog(viewer);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
if(!file.getAbsolutePath().endsWith(".jar"))
file = new File(file.getAbsolutePath()+".jar");
if(file.exists()) {
pane = new JOptionPane("The file " + file + " exists, would you like to overwrite it?");
options = new String[] { "Yes", "No" };
pane.setOptions(options);
dialog = pane.createDialog(BytecodeViewer.viewer,
"Bytecode Viewer - Overwrite File");
dialog.setVisible(true);
obj = pane.getValue();
result = -1;
for (int k = 0; k < options.length; k++)
if (options[k].equals(obj))
result = k;
if (result != 0)
return;
file.delete();
}
final File finalFile = file;
Thread downloadThread = new Thread() {
@Override
public void run() {
try {
InputStream is = new URL("https://github.com/Konloch/bytecode-viewer/releases/download/v"+version+"/BytecodeViewer."+version+".jar").openConnection().getInputStream();
FileOutputStream fos = new FileOutputStream(finalFile);
try {
System.out.println("Downloading from https://github.com/Konloch/bytecode-viewer/releases/download/v"+version+"/BytecodeViewer."+version+".jar");
byte[] buffer = new byte[8192];
int len;
int downloaded = 0;
boolean flag = false;
showMessage("Downloading the jar in the background, when it's finished you will be alerted with another message box."+nl+nl+"Expect this to take several minutes.");
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
fos.flush();
downloaded += 8192;
int mbs = downloaded / 1048576;
if(mbs % 5 == 0 && mbs != 0) {
if(!flag)
System.out.println("Downloaded " + mbs + "MBs so far");
flag = true;
} else
flag = false;
}
} finally {
try {
if (is != null) {
is.close();
}
} finally {
if (fos != null) {
fos.flush();
fos.close();
}
}
}
System.out.println("Download finished!");
showMessage("Download successful! You can find the updated jar at " + finalFile.getAbsolutePath());
} catch(FileNotFoundException e) {
showMessage("Unable to download, the jar file has not been uploaded yet, please try again later in an hour.");
} catch(Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
}
};
downloadThread.start();
}
}
} }
} catch (Exception e) { } catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
@ -368,10 +476,11 @@ public class BytecodeViewer {
if (args.length >= 1) if (args.length >= 1)
for (String s : args) { for (String s : args) {
openFiles(new File[] { new File(s) }); openFiles(new File[] { new File(s) }, true);
} }
viewer.setVisible(true); viewer.setVisible(true);
System.out.println("Start up took " + ((System.currentTimeMillis() - start) / 1000) + " seconds");
} }
public static ClassNode getClassNode(String name) { public static ClassNode getClassNode(String name) {
@ -398,52 +507,75 @@ public class BytecodeViewer {
return a; return a;
} }
public static void openFiles(File[] files) { public static void openFiles(File[] files, boolean recentFiles) {
for (File f : files) if(recentFiles)
BytecodeViewer.addRecentFile(f); for (File f : files)
BytecodeViewer.addRecentFile(f);
BytecodeViewer.viewer.setC(true);
BytecodeViewer.viewer.setIcon(true); BytecodeViewer.viewer.setIcon(true);
boolean update = true; boolean update = true;
for (final File f : files) { for (final File f : files) {
final String fn = f.getName(); final String fn = f.getName();
if (fn.endsWith(".jar")) { if(!f.exists()) {
try { update = false;
JarUtils.put(f, BytecodeViewer.loadedClasses); showMessage("The file " + f.getAbsolutePath() + " could not be found.");
} catch (final Exception e) { } else {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); if (fn.endsWith(".jar") || fn.endsWith(".zip")) {
} try {
JarUtils.put(f, BytecodeViewer.loadedClasses);
} else if (fn.endsWith(".class")) { } catch (final Exception e) {
try { new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
byte[] bytes = JarUtils.getBytes(new FileInputStream(f));
String cafebabe = String.format("%02X", bytes[0])
+ String.format("%02X", bytes[1])
+ String.format("%02X", bytes[2])
+ String.format("%02X", bytes[3]);
if(cafebabe.toLowerCase().equals("cafebabe")) {
final ClassNode cn = JarUtils.getNode(bytes);
BytecodeViewer.loadedClasses.put(cn.name, cn);
} else {
showMessage(fn+": Header does not start with CAFEBABE, ignoring.");
update = false; update = false;
} }
} catch (java.io.FileNotFoundException e) {
showMessage("The file " + f.getAbsolutePath() + " could not be found."); } else if (fn.endsWith(".class")) {
update = false; try {
} catch (final Exception e) { byte[] bytes = JarUtils.getBytes(new FileInputStream(f));
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); String cafebabe = String.format("%02X", bytes[0])
+ String.format("%02X", bytes[1])
+ String.format("%02X", bytes[2])
+ String.format("%02X", bytes[3]);
if(cafebabe.toLowerCase().equals("cafebabe")) {
final ClassNode cn = JarUtils.getNode(bytes);
BytecodeViewer.loadedClasses.put(cn.name, cn);
} else {
showMessage(fn+": Header does not start with CAFEBABE, ignoring.");
update = false;
}
} catch (final Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
update = false;
}
} else if(fn.endsWith(".apk")) {
Thread t = new Thread() {
@Override
public void run() {
try {
String name = getRandomizedName()+".jar";
File output = new File(tempDirectory + fs + name);
Dex2Jar.dex2Jar(f, output);
BytecodeViewer.viewer.setIcon(false);
openFiles(new File[]{output}, false);
} catch (final Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
}
};
t.start();
return;
} }
} }
} }
BytecodeViewer.viewer.setC(false);
BytecodeViewer.viewer.setIcon(false); BytecodeViewer.viewer.setIcon(false);
if(update) if(update)
MainViewerGUI.getComponent(FileNavigationPane.class).updateTree(); try {
} MainViewerGUI.getComponent(FileNavigationPane.class).updateTree();
} catch(java.lang.NullPointerException e) {
}
}
public static void startPlugin(File plugin) { public static void startPlugin(File plugin) {
if (!plugin.exists()) if (!plugin.exists())
@ -462,21 +594,8 @@ public class BytecodeViewer {
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static void resetWorkSpace() { public static void resetWorkSpace(boolean ask) {
JOptionPane pane = new JOptionPane( if(!ask) {
"Are you sure you want to reset the workspace?\n\rIt will also reset your file navigator and search.");
Object[] options = new String[] { "Yes", "No" };
pane.setOptions(options);
JDialog dialog = pane.createDialog(viewer,
"Bytecode Viewer - Reset Workspace");
dialog.show();
Object obj = pane.getValue();
int result = -1;
for (int k = 0; k < options.length; k++)
if (options[k].equals(obj))
result = k;
if (result == 0) {
loadedResources.clear(); loadedResources.clear();
loadedClasses.clear(); loadedClasses.clear();
MainViewerGUI.getComponent(FileNavigationPane.class) MainViewerGUI.getComponent(FileNavigationPane.class)
@ -485,6 +604,30 @@ public class BytecodeViewer {
MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace(); MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace();
the.bytecode.club.bytecodeviewer.api.BytecodeViewer the.bytecode.club.bytecodeviewer.api.BytecodeViewer
.getClassNodeLoader().clear(); .getClassNodeLoader().clear();
} else {
JOptionPane pane = new JOptionPane(
"Are you sure you want to reset the workspace?\n\rIt will also reset your file navigator and search.");
Object[] options = new String[] { "Yes", "No" };
pane.setOptions(options);
JDialog dialog = pane.createDialog(viewer,
"Bytecode Viewer - Reset Workspace");
dialog.show();
Object obj = pane.getValue();
int result = -1;
for (int k = 0; k < options.length; k++)
if (options[k].equals(obj))
result = k;
if (result == 0) {
loadedResources.clear();
loadedClasses.clear();
MainViewerGUI.getComponent(FileNavigationPane.class)
.resetWorkspace();
MainViewerGUI.getComponent(WorkPane.class).resetWorkspace();
MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace();
the.bytecode.club.bytecodeviewer.api.BytecodeViewer
.getClassNodeLoader().clear();
}
} }
} }
@ -546,7 +689,7 @@ public class BytecodeViewer {
m.addActionListener(new ActionListener() { m.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
JMenuItem m = (JMenuItem) e.getSource(); JMenuItem m = (JMenuItem) e.getSource();
openFiles(new File[] { new File(m.getText()) }); openFiles(new File[] { new File(m.getText()) }, true);
} }
}); });
viewer.mnRecentFiles.add(m); viewer.mnRecentFiles.add(m);
@ -569,18 +712,32 @@ public class BytecodeViewer {
public static void cleanup() { public static void cleanup() {
tempF = new File(tempDirectory); tempF = new File(tempDirectory);
while (tempF.exists()) { // delete dirs
try { try {
FileUtils.deleteDirectory(tempF); FileUtils.deleteDirectory(tempF);
} catch (Exception e) { } catch (Exception e) {
}
} }
while (!tempF.exists()) while (!tempF.exists()) // keep making dirs
// keep making dirs
tempF.mkdir(); tempF.mkdir();
} }
public static ArrayList<String> createdRandomizedNames = new ArrayList<String>();
public static String getRandomizedName() {
boolean generated = false;
String name = "";
while(!generated) {
String randomizedName = MiscUtils.randomString(25);
if(!createdRandomizedNames.contains(randomizedName)) {
createdRandomizedNames.add(randomizedName);
name = randomizedName;
generated = true;
}
}
return name;
}
public static String getBCVDirectory() { public static String getBCVDirectory() {
File f = new File(System.getProperty("user.home") + fs File f = new File(System.getProperty("user.home") + fs
+ ".Bytecode-Viewer"); + ".Bytecode-Viewer");

View file

@ -0,0 +1,35 @@
package the.bytecode.club.bytecodeviewer;
import java.io.File;
/**
* A simple 'wrapper' for Dex2Jar.
*
* @author Konloch
*
*/
public class Dex2Jar {
public static void dex2Jar(File input, File output) {
try {
com.googlecode.dex2jar.tools.Dex2jarCmd.main(new String[]{"--force", input.getAbsolutePath()});
String realOutput = input.getName().replaceAll(".apk", "-dex2jar.jar");
File realOutputF = new File(realOutput);
realOutputF.renameTo(output);
} catch(Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
}
public static void saveAsDex(File input, File output) {
try {
com.googlecode.dex2jar.tools.Jar2Dex.main(new String[]{"--force", input.getAbsolutePath()});
String realOutput = input.getName().replaceAll(".jar", "-jar2dex.dex");
File realOutputF = new File(realOutput);
realOutputF.renameTo(output);
} catch(Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
}
}

View file

@ -9,10 +9,9 @@ import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream; import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
@ -28,13 +27,13 @@ import org.objectweb.asm.tree.ClassNode;
public class JarUtils { public class JarUtils {
private static JarInputStream jis; private static ZipInputStream jis;
private static JarEntry entry; private static ZipEntry entry;
public static void put(final File jarFile, public static void put(final File jarFile,
final HashMap<String, ClassNode> clazzList) throws IOException { final HashMap<String, ClassNode> clazzList) throws IOException {
jis = new JarInputStream(new FileInputStream(jarFile)); jis = new ZipInputStream(new FileInputStream(jarFile));
while ((entry = jis.getNextJarEntry()) != null) { while ((entry = jis.getNextEntry()) != null) {
try { try {
final String name = entry.getName(); final String name = entry.getName();
if (!name.endsWith(".class")) { if (!name.endsWith(".class")) {
@ -56,7 +55,7 @@ public class JarUtils {
} }
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
} finally { } finally {
jis.closeEntry(); jis.closeEntry();
} }

View file

@ -0,0 +1,23 @@
package the.bytecode.club.bytecodeviewer;
import java.util.Random;
public class MiscUtils {
private static final String AB = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static final String AN = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
private static Random rnd = new Random();
public static String randomString(int len) {
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
sb.append(AB.charAt(rnd.nextInt(AB.length())));
return sb.toString();
}
public static String randomStringNum(int len) {
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
sb.append(AN.charAt(rnd.nextInt(AN.length())));
return sb.toString();
}
}

View file

@ -95,44 +95,46 @@ public class Settings {
DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.debugHelpers.isSelected()), false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.debugHelpers.isSelected()), false);
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "deprecated", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "deprecated", false);
DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.chckbxmntmNewCheckItem_12.isSelected()), false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.chckbxmntmNewCheckItem_12.isSelected()), false);
if(BytecodeViewer.viewer.decompilerGroup1.isSelected(BytecodeViewer.viewer.panel1None.getModel())) if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1None.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "0", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "0", false);
else if(BytecodeViewer.viewer.decompilerGroup1.isSelected(BytecodeViewer.viewer.panel1Proc.getModel())) else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1Proc.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "1", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "1", false);
else if(BytecodeViewer.viewer.decompilerGroup1.isSelected(BytecodeViewer.viewer.panel1CFR.getModel())) else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1CFR.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "2", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "2", false);
else if(BytecodeViewer.viewer.decompilerGroup1.isSelected(BytecodeViewer.viewer.panel1Fern.getModel())) else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1Fern.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "3", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "3", false);
else if(BytecodeViewer.viewer.decompilerGroup1.isSelected(BytecodeViewer.viewer.panel1Bytecode.getModel())) else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1Bytecode.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "4", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "4", false);
else if(BytecodeViewer.viewer.decompilerGroup1.isSelected(BytecodeViewer.viewer.panel1Hexcode.getModel())) else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1Hexcode.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false);
if(BytecodeViewer.viewer.decompilerGroup2.isSelected(BytecodeViewer.viewer.panel2None.getModel())) if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2None.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "0", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "0", false);
else if(BytecodeViewer.viewer.decompilerGroup2.isSelected(BytecodeViewer.viewer.panel2Proc.getModel())) else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2Proc.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "1", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "1", false);
else if(BytecodeViewer.viewer.decompilerGroup2.isSelected(BytecodeViewer.viewer.panel2CFR.getModel())) else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2CFR.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "2", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "2", false);
else if(BytecodeViewer.viewer.decompilerGroup2.isSelected(BytecodeViewer.viewer.panel2Fern.getModel())) else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2Fern.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "3", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "3", false);
else if(BytecodeViewer.viewer.decompilerGroup2.isSelected(BytecodeViewer.viewer.panel2Bytecode.getModel())) else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2Bytecode.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "4", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "4", false);
else if(BytecodeViewer.viewer.decompilerGroup2.isSelected(BytecodeViewer.viewer.panel2Hexcode.getModel())) else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2Hexcode.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false);
if(BytecodeViewer.viewer.decompilerGroup3.isSelected(BytecodeViewer.viewer.panel3None.getModel())) if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3None.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "0", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "0", false);
else if(BytecodeViewer.viewer.decompilerGroup3.isSelected(BytecodeViewer.viewer.panel3Proc.getModel())) else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3Proc.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "1", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "1", false);
else if(BytecodeViewer.viewer.decompilerGroup3.isSelected(BytecodeViewer.viewer.panel3CFR.getModel())) else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3CFR.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "2", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "2", false);
else if(BytecodeViewer.viewer.decompilerGroup3.isSelected(BytecodeViewer.viewer.panel3Fern.getModel())) else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3Fern.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "3", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "3", false);
else if(BytecodeViewer.viewer.decompilerGroup3.isSelected(BytecodeViewer.viewer.panel3Bytecode.getModel())) else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3Bytecode.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "4", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "4", false);
else if(BytecodeViewer.viewer.decompilerGroup3.isSelected(BytecodeViewer.viewer.panel3Hexcode.getModel())) else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3Hexcode.getModel()))
DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false);
DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.refreshOnChange.isSelected()), false);
} catch(Exception e) { } catch(Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
} }
@ -222,43 +224,45 @@ public class Settings {
BytecodeViewer.viewer.chckbxmntmNewCheckItem_12.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 80, false))); BytecodeViewer.viewer.chckbxmntmNewCheckItem_12.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 80, false)));
int decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 81, false)); int decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 81, false));
if(decompiler == 0) if(decompiler == 0)
BytecodeViewer.viewer.decompilerGroup1.setSelected(BytecodeViewer.viewer.panel1None.getModel(), true); BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1None.getModel(), true);
else if(decompiler == 1) else if(decompiler == 1)
BytecodeViewer.viewer.decompilerGroup1.setSelected(BytecodeViewer.viewer.panel1Proc.getModel(), true); BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1Proc.getModel(), true);
else if(decompiler == 2) else if(decompiler == 2)
BytecodeViewer.viewer.decompilerGroup1.setSelected(BytecodeViewer.viewer.panel1CFR.getModel(), true); BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1CFR.getModel(), true);
else if(decompiler == 3) else if(decompiler == 3)
BytecodeViewer.viewer.decompilerGroup1.setSelected(BytecodeViewer.viewer.panel1Fern.getModel(), true); BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1Fern.getModel(), true);
else if(decompiler == 4) else if(decompiler == 4)
BytecodeViewer.viewer.decompilerGroup1.setSelected(BytecodeViewer.viewer.panel1Bytecode.getModel(), true); BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1Bytecode.getModel(), true);
else if(decompiler == 5) else if(decompiler == 5)
BytecodeViewer.viewer.decompilerGroup1.setSelected(BytecodeViewer.viewer.panel1Hexcode.getModel(), true); BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1Hexcode.getModel(), true);
decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 82, false)); decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 82, false));
if(decompiler == 0) if(decompiler == 0)
BytecodeViewer.viewer.decompilerGroup2.setSelected(BytecodeViewer.viewer.panel2None.getModel(), true); BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2None.getModel(), true);
else if(decompiler == 1) else if(decompiler == 1)
BytecodeViewer.viewer.decompilerGroup2.setSelected(BytecodeViewer.viewer.panel2Proc.getModel(), true); BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2Proc.getModel(), true);
else if(decompiler == 2) else if(decompiler == 2)
BytecodeViewer.viewer.decompilerGroup2.setSelected(BytecodeViewer.viewer.panel2CFR.getModel(), true); BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2CFR.getModel(), true);
else if(decompiler == 3) else if(decompiler == 3)
BytecodeViewer.viewer.decompilerGroup2.setSelected(BytecodeViewer.viewer.panel2Fern.getModel(), true); BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2Fern.getModel(), true);
else if(decompiler == 4) else if(decompiler == 4)
BytecodeViewer.viewer.decompilerGroup2.setSelected(BytecodeViewer.viewer.panel2Bytecode.getModel(), true); BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2Bytecode.getModel(), true);
else if(decompiler == 5) else if(decompiler == 5)
BytecodeViewer.viewer.decompilerGroup2.setSelected(BytecodeViewer.viewer.panel2Hexcode.getModel(), true); BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2Hexcode.getModel(), true);
decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 83, false)); decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 83, false));
if(decompiler == 0) if(decompiler == 0)
BytecodeViewer.viewer.decompilerGroup3.setSelected(BytecodeViewer.viewer.panel3None.getModel(), true); BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3None.getModel(), true);
else if(decompiler == 1) else if(decompiler == 1)
BytecodeViewer.viewer.decompilerGroup3.setSelected(BytecodeViewer.viewer.panel3Proc.getModel(), true); BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3Proc.getModel(), true);
else if(decompiler == 2) else if(decompiler == 2)
BytecodeViewer.viewer.decompilerGroup3.setSelected(BytecodeViewer.viewer.panel3CFR.getModel(), true); BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3CFR.getModel(), true);
else if(decompiler == 3) else if(decompiler == 3)
BytecodeViewer.viewer.decompilerGroup3.setSelected(BytecodeViewer.viewer.panel3Fern.getModel(), true); BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3Fern.getModel(), true);
else if(decompiler == 4) else if(decompiler == 4)
BytecodeViewer.viewer.decompilerGroup3.setSelected(BytecodeViewer.viewer.panel3Bytecode.getModel(), true); BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3Bytecode.getModel(), true);
else if(decompiler == 5) else if(decompiler == 5)
BytecodeViewer.viewer.decompilerGroup3.setSelected(BytecodeViewer.viewer.panel3Hexcode.getModel(), true); BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3Hexcode.getModel(), true);
BytecodeViewer.viewer.refreshOnChange.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 84, false)));
} catch(Exception e) { } catch(Exception e) {
//ignore because errors are expected, first start up and outdated settings. //ignore because errors are expected, first start up and outdated settings.
} }

View file

@ -53,10 +53,12 @@ public class BytecodeViewer {
* Used to load classes/jars into BCV. * Used to load classes/jars into BCV.
* *
* @param files * @param files
* an array of the files you want loaded. * an array of the files you want loaded.
* @param recentFiles
* if it should save to the recent files menu.
*/ */
public static void openFiles(File[] files) { public static void openFiles(File[] files, boolean recentFiles) {
the.bytecode.club.bytecodeviewer.BytecodeViewer.openFiles(files); the.bytecode.club.bytecodeviewer.BytecodeViewer.openFiles(files, recentFiles);
} }
/** /**
@ -93,9 +95,12 @@ public class BytecodeViewer {
/** /**
* This will ask the user if they really want to reset the workspace, then * This will ask the user if they really want to reset the workspace, then
* it'll reset the work space. * it'll reset the work space.
*
* @param ask
* if it should ask the user about resetting the workspace
*/ */
public static void resetWorkSpace() { public static void resetWorkSpace(boolean ask) {
the.bytecode.club.bytecodeviewer.BytecodeViewer.resetWorkSpace(); the.bytecode.club.bytecodeviewer.BytecodeViewer.resetWorkSpace(ask);
} }
/** /**

View file

@ -183,9 +183,17 @@ public class InstructionPrinter {
sb.append(nameOpcode(min.getOpcode()) + " " + min.owner + " " sb.append(nameOpcode(min.getOpcode()) + " " + min.owner + " "
+ min.name + "("); + min.name + "(");
String desc = Type.getType(min.desc).getClassName(); String desc = min.desc;
if (desc == null || desc.equals("null")) try {
desc = min.desc; if(Type.getType(min.desc) != null)
desc = Type.getType(min.desc).getClassName();
if (desc == null || desc.equals("null"))
desc = min.desc;
} catch(java.lang.ArrayIndexOutOfBoundsException e) {
}
sb.append(desc); sb.append(desc);
sb.append(");"); sb.append(");");
@ -224,9 +232,16 @@ public class InstructionPrinter {
protected String printTypeInsnNode(TypeInsnNode tin) { protected String printTypeInsnNode(TypeInsnNode tin) {
try { try {
String desc = Type.getType(tin.desc).getClassName(); String desc = tin.desc;
if (desc == null || desc.equals("null")) try {
desc = tin.desc; if(Type.getType(tin.desc) != null)
desc = Type.getType(tin.desc).getClassName();
if (desc == null || desc.equals("null"))
desc = tin.desc;
} catch(java.lang.ArrayIndexOutOfBoundsException e) {
}
return nameOpcode(tin.getOpcode()) + " " + desc; return nameOpcode(tin.getOpcode()) + " " + desc;
} catch (Exception e) { } catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);

View file

@ -116,14 +116,14 @@ public class MethodNodeDecompiler {
addAttrList(m.invisibleAnnotations, "invisAnno", sb, insnPrinter); addAttrList(m.invisibleAnnotations, "invisAnno", sb, insnPrinter);
addAttrList(m.invisibleAnnotations, "invisLocalVarAnno", sb, addAttrList(m.invisibleAnnotations, "invisLocalVarAnno", sb,
insnPrinter); insnPrinter);
addAttrList(m.invisibleTypeAnnotations, "invisTypeAnno", sb, /*addAttrList(m.invisibleTypeAnnotations, "invisTypeAnno", sb,
insnPrinter); insnPrinter);*/
addAttrList(m.localVariables, "localVar", sb, insnPrinter); addAttrList(m.localVariables, "localVar", sb, insnPrinter);
addAttrList(m.visibleAnnotations, "visAnno", sb, insnPrinter); addAttrList(m.visibleAnnotations, "visAnno", sb, insnPrinter);
addAttrList(m.visibleLocalVariableAnnotations, "visLocalVarAnno", /*addAttrList(m.visibleLocalVariableAnnotations, "visLocalVarAnno",
sb, insnPrinter); sb, insnPrinter);
addAttrList(m.visibleTypeAnnotations, "visTypeAnno", sb, addAttrList(m.visibleTypeAnnotations, "visTypeAnno", sb,
insnPrinter); insnPrinter);*/
for (Object o : m.tryCatchBlocks) { for (Object o : m.tryCatchBlocks) {
TryCatchBlockNode tcbn = (TryCatchBlockNode) o; TryCatchBlockNode tcbn = (TryCatchBlockNode) o;

View file

@ -455,60 +455,60 @@ public class ClassViewer extends JPanel {
PaneUpdaterThread t; PaneUpdaterThread t;
public void startPaneUpdater(final JButton button) { public void startPaneUpdater(final JButton button) {
if (BytecodeViewer.viewer.decompilerGroup1 if (BytecodeViewer.viewer.panelGroup1
.isSelected(BytecodeViewer.viewer.panel1None.getModel())) .isSelected(BytecodeViewer.viewer.panel1None.getModel()))
pane1 = 0; pane1 = 0;
else if (BytecodeViewer.viewer.decompilerGroup1 else if (BytecodeViewer.viewer.panelGroup1
.isSelected(BytecodeViewer.viewer.panel1Proc.getModel())) .isSelected(BytecodeViewer.viewer.panel1Proc.getModel()))
pane1 = 1; pane1 = 1;
else if (BytecodeViewer.viewer.decompilerGroup1 else if (BytecodeViewer.viewer.panelGroup1
.isSelected(BytecodeViewer.viewer.panel1CFR.getModel())) .isSelected(BytecodeViewer.viewer.panel1CFR.getModel()))
pane1 = 2; pane1 = 2;
else if (BytecodeViewer.viewer.decompilerGroup1 else if (BytecodeViewer.viewer.panelGroup1
.isSelected(BytecodeViewer.viewer.panel1Fern.getModel())) .isSelected(BytecodeViewer.viewer.panel1Fern.getModel()))
pane1 = 3; pane1 = 3;
else if (BytecodeViewer.viewer.decompilerGroup1 else if (BytecodeViewer.viewer.panelGroup1
.isSelected(BytecodeViewer.viewer.panel1Bytecode.getModel())) .isSelected(BytecodeViewer.viewer.panel1Bytecode.getModel()))
pane1 = 4; pane1 = 4;
else if (BytecodeViewer.viewer.decompilerGroup1 else if (BytecodeViewer.viewer.panelGroup1
.isSelected(BytecodeViewer.viewer.panel1Hexcode.getModel())) .isSelected(BytecodeViewer.viewer.panel1Hexcode.getModel()))
pane1 = 5; pane1 = 5;
if (BytecodeViewer.viewer.decompilerGroup2 if (BytecodeViewer.viewer.panelGroup2
.isSelected(BytecodeViewer.viewer.panel2None.getModel())) .isSelected(BytecodeViewer.viewer.panel2None.getModel()))
pane2 = 0; pane2 = 0;
else if (BytecodeViewer.viewer.decompilerGroup2 else if (BytecodeViewer.viewer.panelGroup2
.isSelected(BytecodeViewer.viewer.panel2Proc.getModel())) .isSelected(BytecodeViewer.viewer.panel2Proc.getModel()))
pane2 = 1; pane2 = 1;
else if (BytecodeViewer.viewer.decompilerGroup2 else if (BytecodeViewer.viewer.panelGroup2
.isSelected(BytecodeViewer.viewer.panel2CFR.getModel())) .isSelected(BytecodeViewer.viewer.panel2CFR.getModel()))
pane2 = 2; pane2 = 2;
else if (BytecodeViewer.viewer.decompilerGroup2 else if (BytecodeViewer.viewer.panelGroup2
.isSelected(BytecodeViewer.viewer.panel2Fern.getModel())) .isSelected(BytecodeViewer.viewer.panel2Fern.getModel()))
pane2 = 3; pane2 = 3;
else if (BytecodeViewer.viewer.decompilerGroup2 else if (BytecodeViewer.viewer.panelGroup2
.isSelected(BytecodeViewer.viewer.panel2Bytecode.getModel())) .isSelected(BytecodeViewer.viewer.panel2Bytecode.getModel()))
pane2 = 4; pane2 = 4;
else if (BytecodeViewer.viewer.decompilerGroup2 else if (BytecodeViewer.viewer.panelGroup2
.isSelected(BytecodeViewer.viewer.panel2Hexcode.getModel())) .isSelected(BytecodeViewer.viewer.panel2Hexcode.getModel()))
pane2 = 5; pane2 = 5;
if (BytecodeViewer.viewer.decompilerGroup3 if (BytecodeViewer.viewer.panelGroup3
.isSelected(BytecodeViewer.viewer.panel3None.getModel())) .isSelected(BytecodeViewer.viewer.panel3None.getModel()))
pane3 = 0; pane3 = 0;
else if (BytecodeViewer.viewer.decompilerGroup3 else if (BytecodeViewer.viewer.panelGroup3
.isSelected(BytecodeViewer.viewer.panel3Proc.getModel())) .isSelected(BytecodeViewer.viewer.panel3Proc.getModel()))
pane3 = 1; pane3 = 1;
else if (BytecodeViewer.viewer.decompilerGroup3 else if (BytecodeViewer.viewer.panelGroup3
.isSelected(BytecodeViewer.viewer.panel3CFR.getModel())) .isSelected(BytecodeViewer.viewer.panel3CFR.getModel()))
pane3 = 2; pane3 = 2;
else if (BytecodeViewer.viewer.decompilerGroup3 else if (BytecodeViewer.viewer.panelGroup3
.isSelected(BytecodeViewer.viewer.panel3Fern.getModel())) .isSelected(BytecodeViewer.viewer.panel3Fern.getModel()))
pane3 = 3; pane3 = 3;
else if (BytecodeViewer.viewer.decompilerGroup3 else if (BytecodeViewer.viewer.panelGroup3
.isSelected(BytecodeViewer.viewer.panel3Bytecode.getModel())) .isSelected(BytecodeViewer.viewer.panel3Bytecode.getModel()))
pane3 = 4; pane3 = 4;
else if (BytecodeViewer.viewer.decompilerGroup3 else if (BytecodeViewer.viewer.panelGroup3
.isSelected(BytecodeViewer.viewer.panel3Hexcode.getModel())) .isSelected(BytecodeViewer.viewer.panel3Hexcode.getModel()))
pane3 = 5; pane3 = 5;

View file

@ -238,7 +238,7 @@ public class FileNavigationPane extends VisibleComponent implements
public void filesDropped(final File[] files) { public void filesDropped(final File[] files) {
if (files.length < 1) if (files.length < 1)
return; return;
BytecodeViewer.openFiles(files); BytecodeViewer.openFiles(files, true);
} }
public void updateTree() { public void updateTree() {

View file

@ -24,6 +24,7 @@ import javax.swing.JCheckBoxMenuItem;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Dex2Jar;
import the.bytecode.club.bytecodeviewer.FileChangeNotifier; import the.bytecode.club.bytecodeviewer.FileChangeNotifier;
import the.bytecode.club.bytecodeviewer.JarUtils; import the.bytecode.club.bytecodeviewer.JarUtils;
import the.bytecode.club.bytecodeviewer.decompilers.java.CFRDecompiler; import the.bytecode.club.bytecodeviewer.decompilers.java.CFRDecompiler;
@ -44,6 +45,7 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import javax.swing.JRadioButtonMenuItem; import javax.swing.JRadioButtonMenuItem;
import javax.swing.JCheckBox;
public class MainViewerGUI extends JFrame implements FileChangeNotifier { public class MainViewerGUI extends JFrame implements FileChangeNotifier {
@ -248,10 +250,10 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
"Light Obfuscation"); "Light Obfuscation");
private final JMenuItem mntmNewMenuItem_11 = new JMenuItem("Rename Classes"); private final JMenuItem mntmNewMenuItem_11 = new JMenuItem("Rename Classes");
private final JSeparator separator_2 = new JSeparator(); private final JSeparator separator_2 = new JSeparator();
public final ButtonGroup decompilerGroup1 = new ButtonGroup(); public final ButtonGroup panelGroup1 = new ButtonGroup();
public final ButtonGroup decompilerGroup2 = new ButtonGroup(); public final ButtonGroup panelGroup2 = new ButtonGroup();
public final ButtonGroup decompilerGroup3 = new ButtonGroup(); public final ButtonGroup panelGroup3 = new ButtonGroup();
private final JMenu mnNewMenu_6 = new JMenu("View"); private final JMenu mnNewMenu_6 = new JMenu("View Panes");
private final JMenu mnNewMenu_7 = new JMenu("Pane 1"); private final JMenu mnNewMenu_7 = new JMenu("Pane 1");
private final JMenu mnNewMenu_8 = new JMenu("Pane 2"); private final JMenu mnNewMenu_8 = new JMenu("Pane 2");
private final JMenu mnNewMenu_9 = new JMenu("Pane 3"); private final JMenu mnNewMenu_9 = new JMenu("Pane 3");
@ -293,6 +295,11 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
"Hexcode"); "Hexcode");
private final JMenuItem mntmNewMenuItem_12 = new JMenuItem("Save Java File.."); private final JMenuItem mntmNewMenuItem_12 = new JMenuItem("Save Java File..");
public WorkPane workPane = new WorkPane(this); public WorkPane workPane = new WorkPane(this);
private final JMenu mnSettings = new JMenu("Settings");
private final JSeparator separator_6 = new JSeparator();
public final JCheckBox refreshOnChange = new JCheckBox("Refresh On View Change");
final MainViewerGUI This = this;
public void setC(boolean busy) { public void setC(boolean busy) {
if (busy) { if (busy) {
@ -332,18 +339,17 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
} }
} }
ImageIcon busy = new ImageIcon(getClass().getResource("/resources/1.gif"));
ImageIcon busyB64 = new ImageIcon(BytecodeViewer.b642IMG("R0lGODlhEAALAPQAAP///wAAANra2tDQ0Orq6gcHBwAAAC8vL4KCgmFhYbq6uiMjI0tLS4qKimVlZb6+vicnJwUFBU9PT+bm5tjY2PT09Dk5Odzc3PLy8ra2tqCgoMrKyu7u7gAAAAAAAAAAACH5BAkLAAAAIf4aQ3JlYXRlZCB3aXRoIGFqYXhsb2FkLmluZm8AIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJCwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJCwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHTuBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V55zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAAABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7"));
private final JMenuItem mntmSaveAsApk = new JMenuItem("Save As DEX..");
public void setIcon(final boolean busy) { public void setIcon(final boolean busy) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
public void run() { public void run() {
if (busy) { if (busy) {
try { try {
mntmNewMenuItem_4.setIcon(new ImageIcon(getClass() mntmNewMenuItem_4.setIcon(This.busy);
.getResource("/resources/1.gif")));
} catch (NullPointerException e) { } catch (NullPointerException e) {
mntmNewMenuItem_4.setIcon(new ImageIcon( mntmNewMenuItem_4.setIcon(busyB64);
BytecodeViewer
.b642IMG("R0lGODlhEAALAPQAAP///wAAANra2tDQ0Orq6gcHBwAAAC8vL4KCgmFhYbq6uiMjI0tLS4qKimVlZb6+vicnJwUFBU9PT+bm5tjY2PT09Dk5Odzc3PLy8ra2tqCgoMrKyu7u7gAAAAAAAAAAACH5BAkLAAAAIf4aQ3JlYXRlZCB3aXRoIGFqYXhsb2FkLmluZm8AIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAALAAAFLSAgjmRpnqSgCuLKAq5AEIM4zDVw03ve27ifDgfkEYe04kDIDC5zrtYKRa2WQgAh+QQJCwAAACwAAAAAEAALAAAFJGBhGAVgnqhpHIeRvsDawqns0qeN5+y967tYLyicBYE7EYkYAgAh+QQJCwAAACwAAAAAEAALAAAFNiAgjothLOOIJAkiGgxjpGKiKMkbz7SN6zIawJcDwIK9W/HISxGBzdHTuBNOmcJVCyoUlk7CEAAh+QQJCwAAACwAAAAAEAALAAAFNSAgjqQIRRFUAo3jNGIkSdHqPI8Tz3V55zuaDacDyIQ+YrBH+hWPzJFzOQQaeavWi7oqnVIhACH5BAkLAAAALAAAAAAQAAsAAAUyICCOZGme1rJY5kRRk7hI0mJSVUXJtF3iOl7tltsBZsNfUegjAY3I5sgFY55KqdX1GgIAIfkECQsAAAAsAAAAABAACwAABTcgII5kaZ4kcV2EqLJipmnZhWGXaOOitm2aXQ4g7P2Ct2ER4AMul00kj5g0Al8tADY2y6C+4FIIACH5BAkLAAAALAAAAAAQAAsAAAUvICCOZGme5ERRk6iy7qpyHCVStA3gNa/7txxwlwv2isSacYUc+l4tADQGQ1mvpBAAIfkECQsAAAAsAAAAABAACwAABS8gII5kaZ7kRFGTqLLuqnIcJVK0DeA1r/u3HHCXC/aKxJpxhRz6Xi0ANAZDWa+kEAA7"),
""));
} }
} else } else
mntmNewMenuItem_4.setIcon(null); mntmNewMenuItem_4.setIcon(null);
@ -354,92 +360,65 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
public MainViewerGUI() { public MainViewerGUI() {
this.setIconImages(BytecodeViewer.iconList); this.setIconImages(BytecodeViewer.iconList);
decompilerGroup1.add(panel1None); panelGroup1.add(panel1None);
decompilerGroup1.add(panel1Fern); panelGroup1.add(panel1Fern);
decompilerGroup1.add(panel1Proc); panelGroup1.add(panel1Proc);
decompilerGroup1.add(panel1CFR); panelGroup1.add(panel1CFR);
decompilerGroup1.add(panel1Bytecode); panelGroup1.add(panel1Bytecode);
decompilerGroup1.add(panel1Hexcode); panelGroup1.add(panel1Hexcode);
decompilerGroup1.setSelected(panel1Proc.getModel(), true); panelGroup1.setSelected(panel1Proc.getModel(), true);//my one true love
decompilerGroup2.add(panel2None); panelGroup2.add(panel2None);
decompilerGroup2.add(panel2Fern); panelGroup2.add(panel2Fern);
decompilerGroup2.add(panel2Proc); panelGroup2.add(panel2Proc);
decompilerGroup2.add(panel2CFR); panelGroup2.add(panel2CFR);
decompilerGroup2.add(panel2Bytecode); panelGroup2.add(panel2Bytecode);
decompilerGroup2.add(panel2Hexcode); panelGroup2.add(panel2Hexcode);
decompilerGroup2.setSelected(panel2Bytecode.getModel(), true); panelGroup2.setSelected(panel2Bytecode.getModel(), true);
decompilerGroup3.add(panel3None); panelGroup3.add(panel3None);
decompilerGroup3.add(panel3Fern); panelGroup3.add(panel3Fern);
decompilerGroup3.add(panel3Proc); panelGroup3.add(panel3Proc);
decompilerGroup3.add(panel3CFR); panelGroup3.add(panel3CFR);
decompilerGroup3.add(panel3Bytecode); panelGroup3.add(panel3Bytecode);
decompilerGroup3.add(panel3Hexcode); panelGroup3.add(panel3Hexcode);
decompilerGroup3.setSelected(panel3None.getModel(), true); panelGroup3.setSelected(panel3None.getModel(), true);
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(refreshOnChange.isSelected()) {
if(workPane.getCurrentClass() == null)
return;
workPane.refreshClass.doClick();
}
}
};
panel1None.addActionListener(listener);
panel1Fern.addActionListener(listener);
panel1Proc.addActionListener(listener);
panel1CFR.addActionListener(listener);
panel1Bytecode.addActionListener(listener);
panel1Hexcode.addActionListener(listener);
panel2None.addActionListener(listener);
panel2Fern.addActionListener(listener);
panel2Proc.addActionListener(listener);
panel2CFR.addActionListener(listener);
panel2Bytecode.addActionListener(listener);
panel2Hexcode.addActionListener(listener);
panel3None.addActionListener(listener);
panel3Fern.addActionListener(listener);
panel3Proc.addActionListener(listener);
panel3CFR.addActionListener(listener);
panel3Bytecode.addActionListener(listener);
panel3Hexcode.addActionListener(listener);
obfuscatorGroup.add(strongObf); obfuscatorGroup.add(strongObf);
obfuscatorGroup.add(lightObf); obfuscatorGroup.add(lightObf);
obfuscatorGroup.setSelected(strongObf.getModel(), true); obfuscatorGroup.setSelected(strongObf.getModel(), true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// fernflower
rbr.setSelected(true);
rsy.setSelected(false);
din.setSelected(true);
das.setSelected(true);
dgs.setSelected(false);
den.setSelected(true);
uto.setSelected(true);
udv.setSelected(true);
fdi.setSelected(true);
asc.setSelected(false);
debugHelpers.setSelected(true);
// cfr
decodeenumswitch.setSelected(true);
sugarenums.setSelected(true);
decodestringswitch.setSelected(true);
arrayiter.setSelected(true);
collectioniter.setSelected(true);
innerclasses.setSelected(true);
removeboilerplate.setSelected(true);
removeinnerclasssynthetics.setSelected(true);
decodelambdas.setSelected(true);
hidebridgemethods.setSelected(true);
liftconstructorinit.setSelected(true);
removedeadmethods.setSelected(true);
removebadgenerics.setSelected(true);
sugarasserts.setSelected(true);
sugarboxing.setSelected(true);
showversion.setSelected(true);
decodefinally.setSelected(true);
tidymonitors.setSelected(true);
lenient.setSelected(false);
dumpclasspath.setSelected(false);
comments.setSelected(true);
forcetopsort.setSelected(true);
forcetopsortaggress.setSelected(true);
forceexceptionprune.setSelected(true);
stringbuffer.setSelected(false);
stringbuilder.setSelected(true);
silent.setSelected(true);
recover.setSelected(true);
eclipse.setSelected(true);
override.setSelected(true);
showinferrable.setSelected(true);
aexagg.setSelected(true);
forcecondpropagate.setSelected(true);
hideutf.setSelected(true);
hidelongstrings.setSelected(false);
commentmonitor.setSelected(false);
allowcorrecting.setSelected(true);
labelledblocks.setSelected(true);
j14classobj.setSelected(false);
hidelangimports.setSelected(true);
recoverytypeclash.setSelected(true);
recoverytypehints.setSelected(true);
forceturningifs.setSelected(true);
forloopaggcapture.setSelected(true);
// procyon // procyon
/* none */ /* none */
// other
chckbxmntmAppendBrackets.setSelected(true);
chckbxmntmNewCheckItem_12.setSelected(true); chckbxmntmNewCheckItem_12.setSelected(true);
setJMenuBar(menuBar); setJMenuBar(menuBar);
@ -447,10 +426,9 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
JMenu mnNewMenu = new JMenu("File"); JMenu mnNewMenu = new JMenu("File");
menuBar.add(mnNewMenu); menuBar.add(mnNewMenu);
final JFrame This = this;
mntmNewWorkspace.addActionListener(new ActionListener() { mntmNewWorkspace.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) { public void actionPerformed(ActionEvent arg0) {
BytecodeViewer.resetWorkSpace(); BytecodeViewer.resetWorkSpace(true);
} }
}); });
@ -458,7 +436,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mntmLoadJar.addActionListener(new ActionListener() { mntmLoadJar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser(); JFileChooser fc = new JFileChooser();
fc.setFileFilter(new JarZipClassFileFilter()); fc.setFileFilter(new APKDEXJarZipClassFileFilter());
fc.setFileHidingEnabled(false); fc.setFileHidingEnabled(false);
fc.setAcceptAllFileFilterUsed(false); fc.setAcceptAllFileFilterUsed(false);
int returnVal = fc.showOpenDialog(This); int returnVal = fc.showOpenDialog(This);
@ -467,7 +445,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
try { try {
BytecodeViewer.viewer.setC(true); BytecodeViewer.viewer.setC(true);
BytecodeViewer.openFiles(new File[] { fc BytecodeViewer.openFiles(new File[] { fc
.getSelectedFile() }); .getSelectedFile() }, true);
BytecodeViewer.viewer.setC(false); BytecodeViewer.viewer.setC(false);
} catch (Exception e1) { } catch (Exception e1) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e1); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e1);
@ -515,6 +493,55 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
}); });
mnNewMenu.add(mntmNewMenuItem_3); mnNewMenu.add(mntmNewMenuItem_3);
mntmSaveAsApk.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new DexFileFilter());
fc.setFileHidingEnabled(false);
fc.setAcceptAllFileFilterUsed(false);
int returnVal = fc.showSaveDialog(MainViewerGUI.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
final File file = fc.getSelectedFile();
if(file.exists()) {
JOptionPane pane = new JOptionPane(
"Are you sure you wish to overwrite this existing file?");
Object[] options = new String[] { "Yes", "No" };
pane.setOptions(options);
JDialog dialog = pane.createDialog(BytecodeViewer.viewer,
"Bytecode Viewer - Overwrite File");
dialog.setVisible(true);
Object obj = pane.getValue();
int result = -1;
for (int k = 0; k < options.length; k++)
if (options[k].equals(obj))
result = k;
if (result == 0) {
file.delete();
} else {
return;
}
}
Thread t = new Thread() {
@Override
public void run() {
BytecodeViewer.viewer.setIcon(true);
String input = BytecodeViewer.tempDirectory+BytecodeViewer.fs+BytecodeViewer.getRandomizedName()+".jar";
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), input);
String output = file.getAbsolutePath();
if (!output.endsWith(".dex"))
output = output + ".dex";
Dex2Jar.saveAsDex(new File(input), new File(output));
BytecodeViewer.viewer.setIcon(false);
}
};
t.start();
}
}
});
mnNewMenu.add(mntmSaveAsApk);
mnNewMenu.add(mntmSave); mnNewMenu.add(mntmSave);
mntmNewMenuItem.addActionListener(new ActionListener() { mntmNewMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) { public void actionPerformed(ActionEvent arg0) {
@ -696,7 +723,6 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
JMenuItem mntmExit = new JMenuItem("Exit"); JMenuItem mntmExit = new JMenuItem("Exit");
mntmExit.addActionListener(new ActionListener() { mntmExit.addActionListener(new ActionListener() {
@SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent arg0) { public void actionPerformed(ActionEvent arg0) {
JOptionPane pane = new JOptionPane( JOptionPane pane = new JOptionPane(
"Are you sure you want to exit?"); "Are you sure you want to exit?");
@ -704,7 +730,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
pane.setOptions(options); pane.setOptions(options);
JDialog dialog = pane.createDialog(BytecodeViewer.viewer, JDialog dialog = pane.createDialog(BytecodeViewer.viewer,
"Bytecode Viewer - Exit"); "Bytecode Viewer - Exit");
dialog.show(); dialog.setVisible(true);
Object obj = pane.getValue(); Object obj = pane.getValue();
int result = -1; int result = -1;
for (int k = 0; k < options.length; k++) for (int k = 0; k < options.length; k++)
@ -762,37 +788,86 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu_9.add(panel3Hexcode); mnNewMenu_9.add(panel3Hexcode);
menuBar.add(mnNewMenu_4); menuBar.add(mnSettings);
mnNewMenu_4.add(chckbxmntmNewCheckItem_6); mnSettings.add(refreshOnChange);
mnNewMenu_4.add(chckbxmntmNewCheckItem_11); mnSettings.add(separator_6);
mnSettings.add(mnNewMenu_4);
mnNewMenu_4.add(chckbxmntmShowDebugLine); mnNewMenu_4.add(chckbxmntmNewCheckItem_6);
mnNewMenu_4.add(chckbxmntmNewCheckItem_3); mnNewMenu_4.add(chckbxmntmNewCheckItem_11);
mnNewMenu_4.add(chckbxmntmNewCheckItem_4); mnNewMenu_4.add(chckbxmntmShowDebugLine);
mnNewMenu_4.add(chckbxmntmNewCheckItem_7); mnNewMenu_4.add(chckbxmntmNewCheckItem_3);
mnNewMenu_4.add(chckbxmntmSimplifyMemberReferences); mnNewMenu_4.add(chckbxmntmNewCheckItem_4);
mnNewMenu_4.add(mnMergeVariables); mnNewMenu_4.add(chckbxmntmNewCheckItem_7);
mnNewMenu_4.add(chckbxmntmNewCheckItem_8); mnNewMenu_4.add(chckbxmntmSimplifyMemberReferences);
mnNewMenu_4.add(chckbxmntmNewCheckItem_9); mnNewMenu_4.add(mnMergeVariables);
mnNewMenu_4.add(chckbxmntmNewCheckItem_10); mnNewMenu_4.add(chckbxmntmNewCheckItem_8);
mnNewMenu_4.add(chckbxmntmNewCheckItem_2); mnNewMenu_4.add(chckbxmntmNewCheckItem_9);
mnNewMenu_4.add(chckbxmntmNewCheckItem_5); mnNewMenu_4.add(chckbxmntmNewCheckItem_10);
mnNewMenu_4.add(chckbxmntmNewCheckItem_1); mnNewMenu_4.add(chckbxmntmNewCheckItem_2);
menuBar.add(mnNewMenu_3); mnNewMenu_4.add(chckbxmntmNewCheckItem_5);
mnNewMenu_4.add(chckbxmntmNewCheckItem_1);
// cfr
decodeenumswitch.setSelected(true);
sugarenums.setSelected(true);
decodestringswitch.setSelected(true);
arrayiter.setSelected(true);
collectioniter.setSelected(true);
innerclasses.setSelected(true);
removeboilerplate.setSelected(true);
removeinnerclasssynthetics.setSelected(true);
decodelambdas.setSelected(true);
hidebridgemethods.setSelected(true);
liftconstructorinit.setSelected(true);
removedeadmethods.setSelected(true);
removebadgenerics.setSelected(true);
sugarasserts.setSelected(true);
sugarboxing.setSelected(true);
showversion.setSelected(true);
decodefinally.setSelected(true);
tidymonitors.setSelected(true);
lenient.setSelected(false);
dumpclasspath.setSelected(false);
comments.setSelected(true);
forcetopsort.setSelected(true);
forcetopsortaggress.setSelected(true);
forceexceptionprune.setSelected(true);
stringbuffer.setSelected(false);
stringbuilder.setSelected(true);
silent.setSelected(true);
recover.setSelected(true);
eclipse.setSelected(true);
override.setSelected(true);
showinferrable.setSelected(true);
aexagg.setSelected(true);
forcecondpropagate.setSelected(true);
hideutf.setSelected(true);
hidelongstrings.setSelected(false);
commentmonitor.setSelected(false);
allowcorrecting.setSelected(true);
labelledblocks.setSelected(true);
j14classobj.setSelected(false);
hidelangimports.setSelected(true);
recoverytypeclash.setSelected(true);
recoverytypehints.setSelected(true);
forceturningifs.setSelected(true);
forloopaggcapture.setSelected(true);
mnSettings.add(mnNewMenu_3);
mnNewMenu_3.add(decodeenumswitch); mnNewMenu_3.add(decodeenumswitch);
@ -881,9 +956,20 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu_3.add(forceturningifs); mnNewMenu_3.add(forceturningifs);
mnNewMenu_3.add(forloopaggcapture); mnNewMenu_3.add(forloopaggcapture);
// fernflower
rbr.setSelected(true);
rsy.setSelected(false);
din.setSelected(true);
das.setSelected(true);
dgs.setSelected(false);
den.setSelected(true);
uto.setSelected(true);
udv.setSelected(true);
fdi.setSelected(true);
asc.setSelected(false);
JMenu mnDecompilerSettings = new JMenu("FernFlower"); JMenu mnDecompilerSettings = new JMenu("FernFlower");
menuBar.add(mnDecompilerSettings); mnSettings.add(mnDecompilerSettings);
dc4.setSelected(true); dc4.setSelected(true);
mnDecompilerSettings.add(dc4); mnDecompilerSettings.add(dc4);
nns.setSelected(true); nns.setSelected(true);
@ -910,9 +996,12 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnDecompilerSettings.add(udv); mnDecompilerSettings.add(udv);
mnDecompilerSettings.add(fdi); mnDecompilerSettings.add(fdi);
mnDecompilerSettings.add(asc); mnDecompilerSettings.add(asc);
debugHelpers.setSelected(true);
// other
chckbxmntmAppendBrackets.setSelected(true);
JMenu mnBytecodeDecompilerSettings = new JMenu("Bytecode Decompiler"); JMenu mnBytecodeDecompilerSettings = new JMenu("Bytecode Decompiler");
menuBar.add(mnBytecodeDecompilerSettings); mnSettings.add(mnBytecodeDecompilerSettings);
mnBytecodeDecompilerSettings.add(debugHelpers); mnBytecodeDecompilerSettings.add(debugHelpers);
@ -1157,7 +1246,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
} }
} }
public class JarZipClassFileFilter extends FileFilter { public class APKDEXJarZipClassFileFilter extends FileFilter {
@Override @Override
public boolean accept(File f) { public boolean accept(File f) {
if (f.isDirectory()) if (f.isDirectory())
@ -1165,15 +1254,16 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
String extension = getExtension(f); String extension = getExtension(f);
if (extension != null) if (extension != null)
return (extension.equals("jar") || extension.equals("zip") || extension return (extension.equals("jar") || extension.equals("zip")
.equals("class")); || extension.equals("class") || extension.equals("apk")
|| extension.equals("dex"));
return false; return false;
} }
@Override @Override
public String getDescription() { public String getDescription() {
return "Class Files or Zip/Jar Archives"; return "APKs, DEX, Class Files or Zip/Jar Archives";
} }
public String getExtension(File f) { public String getExtension(File f) {
@ -1256,7 +1346,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
String extension = getExtension(f); String extension = getExtension(f);
if (extension != null) if (extension != null)
return (extension.equals("Java")); return (extension.equals("java"));
return false; return false;
} }
@ -1277,4 +1367,34 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
return ext; return ext;
} }
} }
public class DexFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
if (extension != null)
return (extension.equals("dex"));
return false;
}
@Override
public String getDescription() {
return "Android DEX Files";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
} }

View file

@ -14,6 +14,14 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
/**
* A simple GUI to select the Malicious Code Scanner options.
*
* @author Konloch
* @author Adrianherrera
*
*/
public class MaliciousCodeScannerOptions extends JFrame { public class MaliciousCodeScannerOptions extends JFrame {
public MaliciousCodeScannerOptions() { public MaliciousCodeScannerOptions() {
this.setIconImages(BytecodeViewer.iconList); this.setIconImages(BytecodeViewer.iconList);

View file

@ -176,7 +176,7 @@ public class SearchingPane extends VisibleComponent {
getContentPane().setLayout(new BorderLayout()); getContentPane().setLayout(new BorderLayout());
getContentPane().add(optionPanel, BorderLayout.NORTH); getContentPane().add(new JScrollPane(optionPanel), BorderLayout.NORTH);
getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER); getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
this.tree.addTreeSelectionListener(new TreeSelectionListener() { this.tree.addTreeSelectionListener(new TreeSelectionListener() {

View file

@ -55,7 +55,7 @@ public class WorkPane extends VisibleComponent implements ActionListener {
buttonPanel = new JPanel(new FlowLayout()); buttonPanel = new JPanel(new FlowLayout());
refreshClass = new JButton("Refresh class"); refreshClass = new JButton("Refresh Class");
refreshClass.addActionListener(this); refreshClass.addActionListener(this);
buttonPanel.add(refreshClass); buttonPanel.add(refreshClass);

View file

@ -1,14 +1,15 @@
package the.bytecode.club.bytecodeviewer.obfuscators; package the.bytecode.club.bytecodeviewer.obfuscators;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Random;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.MiscUtils;
public abstract class JavaObfuscator extends Thread { public abstract class JavaObfuscator extends Thread {
@Override @Override
public void run() { public void run() {
System.out.println("mibbzz is gay");
BytecodeViewer.viewer.setIcon(true); BytecodeViewer.viewer.setIcon(true);
BytecodeViewer.runningObfuscation = true; BytecodeViewer.runningObfuscation = true;
obfuscate(); obfuscate();
@ -29,29 +30,12 @@ public abstract class JavaObfuscator extends Thread {
public static int MAX_STRING_LENGTH = 250; public static int MAX_STRING_LENGTH = 250;
public static int MIN_STRING_LENGTH = 20; public static int MIN_STRING_LENGTH = 20;
private ArrayList<String> names = new ArrayList<String>(); private ArrayList<String> names = new ArrayList<String>();
private static final String AB = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static final String AN = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
private static Random rnd = new Random();
private static String randomString(int len) {
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
sb.append(AB.charAt(rnd.nextInt(AB.length())));
return sb.toString();
}
private static String randomStringNum(int len) {
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++)
sb.append(AN.charAt(rnd.nextInt(AN.length())));
return sb.toString();
}
protected String generateUniqueName(int length) { protected String generateUniqueName(int length) {
boolean found = false; boolean found = false;
String name = ""; String name = "";
while (!found) { while (!found) {
String nameTry = randomString(1) + randomStringNum(length - 1); String nameTry = MiscUtils.randomString(1) + MiscUtils.randomStringNum(length - 1);
if (!names.contains(nameTry)) { if (!names.contains(nameTry)) {
names.add(nameTry); names.add(nameTry);
name = nameTry; name = nameTry;

View file

@ -129,7 +129,6 @@ public class EZInjection extends Plugin {
+ "), it's been blocked."); + "), it's been blocked.");
} }
@SuppressWarnings("deprecation")
@Override @Override
public void execute(ArrayList<ClassNode> classNodeList) { public void execute(ArrayList<ClassNode> classNodeList) {
BytecodeViewer.viewer.setIcon(true); BytecodeViewer.viewer.setIcon(true);

View file

@ -21,6 +21,7 @@ import the.bytecode.club.bytecodeviewer.api.PluginConsole;
* and added more stuff to search for. * and added more stuff to search for.
* *
* @author Konloch * @author Konloch
* @author Adrianherrera
* @author WaterWolf * @author WaterWolf
* *
*/ */