This commit is contained in:
Konloch 2015-07-22 03:17:01 -06:00
parent 89bad45283
commit f7d0233df2
13 changed files with 646 additions and 252 deletions

View file

@ -1,5 +1,16 @@
<html>Bytecode Viewer (BCV) was designed to be extremely user and beginner friendly, because of this almost everything is accessible through an interface, settings, tools, etc. This means if you give BCV a try you should get the gist of it can do, however for those who don't want to run BCV until they're convinced they should use it, below is a complete list of features BCV has, and what they do. <html>Bytecode Viewer (BCV) was designed to be extremely user and beginner friendly, because of this almost everything is accessible through an interface, settings, tools, etc. This means if you give BCV a try you should get the gist of it can do, however for those who don't want to run BCV until they're convinced they should use it, below is a complete list of features BCV has, and what they do.
<h2>Command Line Interface (CLI):</h2>
<ul>
<li> -help Displays the help menu</li>
<li> -list Displays the available decompilers</li>
<li> -decompiler [decompiler] Selects the decompiler, procyon by default</li>
<li> -i [input file] Selects the input file (Jar, Class, APK, ZIP, DEX all work automatically)</li>
<li> -o [output file] Selects the output file (Java or Java-Bytecode)</li>
<li> -t [target classname] Must either be the fully qualified classname or "all" to decompile all as zip</li>
<li> -nowait Doesn't wait for the user to read the CLI messages</li>
</ul>
<h2>File:</h2> <h2>File:</h2>
<ul> <ul>
<li>Add (Ctrl + O) - If you add a jar/zip BCV will unzip it, if you add an APK or DEX file, BCV will run dex2jar then run the jar input process.</li> <li>Add (Ctrl + O) - If you add a jar/zip BCV will unzip it, if you add an APK or DEX file, BCV will run dex2jar then run the jar input process.</li>

View file

@ -16,8 +16,8 @@ import me.konloch.kontainer.io.HTTPRequest;
import the.bytecode.club.bootloader.resource.EmptyExternalResource; import the.bytecode.club.bootloader.resource.EmptyExternalResource;
import the.bytecode.club.bootloader.resource.ExternalResource; import the.bytecode.club.bootloader.resource.ExternalResource;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.CommandLineInput;
import the.bytecode.club.bytecodeviewer.ZipUtils; import the.bytecode.club.bytecodeviewer.ZipUtils;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
/** /**
* @author Konloch * @author Konloch
@ -26,18 +26,28 @@ import the.bytecode.club.bytecodeviewer.ZipUtils;
*/ */
public class Boot { public class Boot {
public static boolean globalstop = false;
public static boolean completedboot = false;
public static boolean downloading = false;
private static InitialBootScreen screen; private static InitialBootScreen screen;
private static List<String> libsList = new ArrayList<String>();
private static List<String> libsFileList = new ArrayList<String>();
private static List<String> urlList = new ArrayList<String>();
public static void boot(String[] args, int CLI) throws Exception { static {
if(CLI == CommandLineInput.STOP) try {
return; screen = new InitialBootScreen();
} catch(Exception e) {
new ExceptionUI(e);
}
}
public static void boot(String[] args, boolean CLI) throws Exception {
bootstrap(); bootstrap();
ILoader<?> loader = findLoader(); ILoader<?> loader = findLoader();
screen = new InitialBootScreen(); if(!CLI)
if(CLI == CommandLineInput.OPEN_FILE)
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -53,37 +63,32 @@ public class Boot {
screen.setVisible(false); screen.setVisible(false);
} }
}); });
/*Class<?> klass = loader.loadClass("the.bytecode.club.bytecodeviewer.BytecodeViewer");
klass.getDeclaredMethod("BOOT", new Class<?>[] { String[].class }).invoke(null, new Object[] { args });*/
if(CLI == CommandLineInput.OPEN_FILE)
BytecodeViewer.BOOT(args, false);
else {
BytecodeViewer.BOOT(args, true);
CommandLineInput.executeCommandLine(args);
} }
public static void hide() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
screen.setVisible(false);
}
});
} }
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
private static void create(ILoader<?> loader, boolean clean) throws Exception { private static void create(ILoader<?> loader, boolean clean) throws Exception {
setState("Bytecode Viewer Boot Screen - Checking Libraries..."); setState("Bytecode Viewer Boot Screen - Checking Libraries...");
final File libsDirectory = libsDir(); final File libsDirectory = libsDir();
List<String> urlList = new ArrayList<String>(); populateUrlList();
HTTPRequest req = new HTTPRequest(new URL("https://github.com/Konloch/bytecode-viewer/tree/master/libs"));
for (String s : req.read()) if(globalstop) {
if (s.contains("href=\"/Konloch/bytecode-viewer/blob/master/libs/")) { while(true) {
urlList.add("https://github.com" + s.split("<a href=")[1].split("\"")[1]); Thread.sleep(100);//just keep this thread halted.
}
} }
if (urlList.isEmpty()) { if (urlList.isEmpty()) {
JOptionPane JOptionPane.showMessageDialog(null, "Bytecode Viewer ran into an issue, for some reason github is not returning what we're expecting. Please try rebooting, if this issue persists please contact @Konloch.", "Error", JOptionPane.ERROR_MESSAGE);
.showMessageDialog(
null,
"Bytecode Viewer ran into an issue, for some reason github is not returning what we're expecting. Please try rebooting, if this issue persists please contact @Konloch.",
"Error", JOptionPane.ERROR_MESSAGE);
return; return;
} }
@ -93,12 +98,7 @@ public class Boot {
if (!libsDirectory.exists()) if (!libsDirectory.exists())
libsDirectory.mkdir(); libsDirectory.mkdir();
List<String> libsList = new ArrayList<String>(); populateLibsDirectory();
List<String> libsFileList = new ArrayList<String>();
for (File f : libsDirectory.listFiles()) {
libsList.add(f.getName());
libsFileList.add(f.getAbsolutePath());
}
screen.getProgressBar().setMaximum(urlList.size() * 2); screen.getProgressBar().setMaximum(urlList.size() * 2);
@ -106,16 +106,20 @@ public class Boot {
for (String s : urlList) { for (String s : urlList) {
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), s.length()); String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), s.length());
if (!libsList.contains(fileName)) { File file = new File(libsDirectory, fileName);
setState("Bytecode Viewer Boot Screen - Downloading " + fileName);
System.out.println("Downloading " + fileName);
boolean passed = false; boolean passed = false;
while (!passed) { while (!passed) {
if (!libsList.contains(fileName)) {
downloading = true;
setState("Bytecode Viewer Boot Screen - Downloading " + fileName + "...");
System.out.println("Downloading " + fileName);
InputStream is = null; InputStream is = null;
FileOutputStream fos = null; FileOutputStream fos = null;
try { try {
is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream(); is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream();
fos = new FileOutputStream(new File(libsDirectory, fileName)); fos = new FileOutputStream(file);
System.out.println("Downloading from " + s); System.out.println("Downloading from " + s);
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
int len; int len;
@ -133,7 +137,6 @@ public class Boot {
} else } else
flag = false; flag = false;
} }
libsFileList.add(new File(libsDirectory, fileName).getAbsolutePath());
} finally { } finally {
try { try {
if (is != null) { if (is != null) {
@ -148,8 +151,41 @@ public class Boot {
} }
} }
} }
try {
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
System.out.println("Verifying " + fileName + "...");
File f = new File(BytecodeViewer.tempDirectory, "temp");
ZipUtils.zipFile(file, f);
f.delete();
libsFileList.add(file.getAbsolutePath());
System.out.println("Download finished!"); System.out.println("Download finished!");
passed = true; passed = true;
} catch(Exception e) {
e.printStackTrace();
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
file.delete();
}
} else if(BytecodeViewer.verify) { //verify its not corrupt each boot (adds 3 seconds boot time)
try {
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
System.out.println("Verifying " + fileName + "...");
File f = new File(BytecodeViewer.tempDirectory, "temp");
ZipUtils.zipFile(file, f);
f.delete();
passed = true;
} catch(Exception e) {
e.printStackTrace();
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
libsFileList.remove(file.getAbsolutePath());
file.delete();
}
} else {
passed = true;
} }
} }
@ -200,6 +236,178 @@ public class Boot {
} }
} }
checkKrakatau();
completedCheck++;
screen.getProgressBar().setValue(completedCheck);
checkEnjarify();
completedCheck++;
screen.getProgressBar().setValue(completedCheck);
setState("Bytecode Viewer Boot Screen - Booting!");
completedboot = true;
}
public static File libsDir() {
File dir = new File(System.getProperty("user.home"), ".Bytecode-Viewer");
while (!dir.exists())
dir.mkdirs();
return new File(dir, "libs");
}
public static void setState(String s) {
screen.setTitle(s);
}
public static ILoader<?> findLoader() {
// TODO: Find from providers
// return new LibraryClassLoader();
// TODO: Catch
return AbstractLoaderFactory.find().spawnLoader();
}
private static void bootstrap() {
AbstractLoaderFactory.register(new LoaderFactory<Object>() {
@Override
public ILoader<Object> spawnLoader() {
return new ClassPathLoader();
}
});
}
public static void populateUrlList() throws Exception {
HTTPRequest req = new HTTPRequest(new URL("https://github.com/Konloch/bytecode-viewer/tree/master/libs"));
req.setTimeout(30000);
for (String s : req.read())
if (s.contains("href=\"/Konloch/bytecode-viewer/blob/master/libs/")) {
urlList.add("https://github.com" + s.split("<a href=")[1].split("\"")[1]);
}
}
public static void populateLibsDirectory() {
if(libsDir() != null)
for (File f : libsDir().listFiles()) {
libsList.add(f.getName());
libsFileList.add(f.getAbsolutePath());
}
}
public static void downloadZipsOnly() throws Exception{
for (String s : urlList) {
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), s.length());
File file = new File(libsDir(), fileName);
boolean passed = false;
while (!passed) {
if (!libsList.contains(fileName) && fileName.endsWith(".zip")) {
downloading = true;
setState("Bytecode Viewer Boot Screen - Downloading " + fileName + "...");
System.out.println("Downloading " + fileName);
InputStream is = null;
FileOutputStream fos = null;
try {
is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream();
fos = new FileOutputStream(file);
System.out.println("Downloading from " + s);
byte[] buffer = new byte[8192];
int len;
int downloaded = 0;
boolean flag = false;
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;
}
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
} finally {
if (fos != null) {
fos.flush();
}
if (fos != null) {
fos.close();
}
}
}
try {
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
System.out.println("Verifying " + fileName + "...");
File f = new File(BytecodeViewer.tempDirectory, "temp");
ZipUtils.zipFile(file, f);
f.delete();
libsFileList.add(file.getAbsolutePath());
System.out.println("Download finished!");
passed = true;
} catch(Exception e) {
e.printStackTrace();
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
file.delete();
}
} else
passed = true;
}
}
}
public static void checkEnjarify() {
setState("Bytecode Viewer Boot Screen - Checking Enjarify...");
System.out.println("Checking enjarify");
File enjarifyZip = null;
for(File f : new File(BytecodeViewer.libsDirectory).listFiles()) {
if(f.getName().toLowerCase().startsWith("enjarify-")) {
BytecodeViewer.enjarifyVersion = f.getName().split("-")[1].split("\\.")[0];
enjarifyZip = f;
}
}
for(File f : new File(BytecodeViewer.getBCVDirectory()).listFiles()) {
if(f.getName().toLowerCase().startsWith("enjarify_") && !f.getName().split("_")[1].split("\\.")[0].equals(BytecodeViewer.enjarifyVersion)) {
setState("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
System.out.println("Removing oudated " + f.getName());
try {
FileUtils.deleteDirectory(f);
} catch (Exception e) {
e.printStackTrace();
}
}
}
BytecodeViewer.enjarifyWorkingDirectory = BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion + BytecodeViewer.fs + "enjarify-master";
File enjarifyDirectory = new File(BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion);
if(!enjarifyDirectory.exists()) {
try {
setState("Bytecode Viewer Boot Screen - Updating to "+enjarifyDirectory.getName()+"...");
ZipUtils.unzipFilesToPath(enjarifyZip.getAbsolutePath(), enjarifyDirectory.getAbsolutePath());
System.out.println("Updated to enjarify v" + BytecodeViewer.enjarifyVersion);
} catch(Exception e) {
BytecodeViewer.showMessage("ERROR: There was an issue unzipping enjarify (possibly corrupt). Restart BCV."+BytecodeViewer.nl+
"If the error persists contact @Konloch.");
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
enjarifyZip.delete();
}
}
}
public static void checkKrakatau() {
setState("Bytecode Viewer Boot Screen - Checking Krakatau..."); setState("Bytecode Viewer Boot Screen - Checking Krakatau...");
System.out.println("Checking krakatau"); System.out.println("Checking krakatau");
@ -237,80 +445,5 @@ public class Boot {
krakatauZip.delete(); krakatauZip.delete();
} }
} }
completedCheck++;
screen.getProgressBar().setValue(completedCheck);
setState("Bytecode Viewer Boot Screen - Checking Enjarify...");
System.out.println("Checking enjarify");
File enjarifyZip = null;
for(File f : new File(BytecodeViewer.libsDirectory).listFiles()) {
if(f.getName().toLowerCase().startsWith("enjarify-")) {
BytecodeViewer.enjarifyVersion = f.getName().split("-")[1].split("\\.")[0];
enjarifyZip = f;
}
}
for(File f : new File(BytecodeViewer.getBCVDirectory()).listFiles()) {
if(f.getName().toLowerCase().startsWith("enjarify_") && !f.getName().split("_")[1].split("\\.")[0].equals(BytecodeViewer.enjarifyVersion)) {
setState("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
System.out.println("Removing oudated " + f.getName());
try {
FileUtils.deleteDirectory(f);
} catch (Exception e) {
e.printStackTrace();
}
}
}
BytecodeViewer.enjarifyWorkingDirectory = BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion + BytecodeViewer.fs + "enjarify-master";
File enjarifyDirectory = new File(BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion);
if(!enjarifyDirectory.exists()) {
try {
setState("Bytecode Viewer Boot Screen - Updating to "+enjarifyDirectory.getName()+"...");
ZipUtils.unzipFilesToPath(enjarifyZip.getAbsolutePath(), enjarifyDirectory.getAbsolutePath());
System.out.println("Updated to enjarify v" + BytecodeViewer.enjarifyVersion);
} catch(Exception e) {
BytecodeViewer.showMessage("ERROR: There was an issue unzipping enjarify (possibly corrupt). Restart BCV."+BytecodeViewer.nl+
"If the error persists contact @Konloch.");
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
enjarifyZip.delete();
}
}
completedCheck++;
screen.getProgressBar().setValue(completedCheck);
setState("Bytecode Viewer Boot Screen - Booting!");
}
private static File libsDir() {
File dir = new File(System.getProperty("user.home"), ".Bytecode-Viewer");
while (!dir.exists())
dir.mkdirs();
return new File(dir, "libs");
}
private static void setState(String s) {
screen.setTitle(s);
}
private static ILoader<?> findLoader() {
// TODO: Find from providers
// return new LibraryClassLoader();
// TODO: Catch
return AbstractLoaderFactory.find().spawnLoader();
}
private static void bootstrap() {
AbstractLoaderFactory.register(new LoaderFactory<Object>() {
@Override
public ILoader<Object> spawnLoader() {
return new ClassPathLoader();
}
});
} }
} }

View file

@ -15,7 +15,7 @@ import java.net.URI;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry; import java.util.List;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
@ -32,6 +32,9 @@ import org.apache.commons.io.FileUtils;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bootloader.Boot; import the.bytecode.club.bootloader.Boot;
import the.bytecode.club.bootloader.ILoader;
import the.bytecode.club.bootloader.resource.EmptyExternalResource;
import the.bytecode.club.bootloader.resource.ExternalResource;
import the.bytecode.club.bytecodeviewer.api.ClassNodeLoader; import the.bytecode.club.bytecodeviewer.api.ClassNodeLoader;
import the.bytecode.club.bytecodeviewer.gui.ClassViewer; import the.bytecode.club.bytecodeviewer.gui.ClassViewer;
import the.bytecode.club.bytecodeviewer.gui.FileNavigationPane; import the.bytecode.club.bytecodeviewer.gui.FileNavigationPane;
@ -96,6 +99,11 @@ import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
* 07/20/2015 - Bibl sexified the boot loading time. * 07/20/2015 - Bibl sexified the boot loading time.
* 07/20/2015 - Decode APK Resources is selected by default. * 07/20/2015 - Decode APK Resources is selected by default.
* 07/20/2015 - Made the security manager slightly safer, can still be targeted but not as obvious now. * 07/20/2015 - Made the security manager slightly safer, can still be targeted but not as obvious now.
* 07/20/2015 - Added CLI to the boot page.
* 07/21/2015 - Added support for offline mode incase you cannot connect to github for some reason. (kicks in after 7 seconds)
* 07/21/2015 - Added fatjar option back, incase anyone wants a 100% portable version.
* 07/21/2015 - Made it so it now shows the decompiler it's using - http://i.imgur.com/yMEzXwv.png.
* 07/21/2015 - Rewrote the file system, it now shows the path of the jar it's got loaded.
* *
* @author Konloch * @author Konloch
* *
@ -106,7 +114,10 @@ public class BytecodeViewer {
/*per version*/ /*per version*/
public static String version = "2.9.8"; public static String version = "2.9.8";
public static boolean previewCopy = true; public static boolean previewCopy = true;
public static boolean fatJar = false;
/*the rest*/ /*the rest*/
public static boolean verify = false; //eventually may be a setting
public static String[] args;
public static MainViewerGUI viewer = null; public static MainViewerGUI viewer = null;
public static ClassNodeLoader loader = new ClassNodeLoader(); //might be insecure due to assholes targeting BCV, however that's highly unlikely. public static ClassNodeLoader loader = new ClassNodeLoader(); //might be insecure due to assholes targeting BCV, however that's highly unlikely.
public static SecurityMan sm = new SecurityMan(); //might be insecure due to assholes targeting BCV, however that's highly unlikely. public static SecurityMan sm = new SecurityMan(); //might be insecure due to assholes targeting BCV, however that's highly unlikely.
@ -114,8 +125,7 @@ public class BytecodeViewer {
public static String python3 = ""; public static String python3 = "";
public static String rt = ""; public static String rt = "";
public static String library = ""; public static String library = "";
public static HashMap<String, ClassNode> loadedClasses = new HashMap<String, ClassNode>(); public static ArrayList<FileContainer> files = new ArrayList<FileContainer>(); //all of BCV's loaded files/classes/etc
public static HashMap<String, byte[]> loadedResources = new HashMap<String, byte[]>();
private static int maxRecentFiles = 25; private static int maxRecentFiles = 25;
public static String fs = System.getProperty("file.separator"); public static String fs = System.getProperty("file.separator");
public static String nl = System.getProperty("line.separator"); public static String nl = System.getProperty("line.separator");
@ -142,7 +152,7 @@ public class BytecodeViewer {
/** /**
* The version checker thread * The version checker thread
*/ */
public static Thread versionChecker = new Thread() { private static Thread versionChecker = new Thread() {
@Override @Override
public void run() { public void run() {
try { try {
@ -310,7 +320,10 @@ public class BytecodeViewer {
} }
}; };
public static Thread PingBack = new Thread() { /**
* Pings back to bytecodeviewer.com to be added into the total running statistics
*/
private static Thread PingBack = new Thread() {
@Override @Override
public void run() { public void run() {
try { try {
@ -321,6 +334,98 @@ public class BytecodeViewer {
} }
}; };
/**
* Downloads & installs the krakatau & enjarify zips
*/
private static Thread InstallFatJar = new Thread() {
@Override
public void run() {
try {
Boot.populateUrlList();
Boot.populateLibsDirectory();
Boot.downloadZipsOnly();
Boot.checkKrakatau();
Boot.checkEnjarify();
} catch(Exception e) {
e.printStackTrace();
}
}
};
/**
* Used to check incase booting failed for some reason, this kicks in as a fail safe
*/
private static Thread bootCheck = new Thread() {
boolean finished = false;
@SuppressWarnings({ "rawtypes", "unchecked" })
public void run() {
long start = System.currentTimeMillis();
while(!finished) {
if(System.currentTimeMillis() - start >= 7000) { //7 second failsafe
if(!Boot.completedboot && !Boot.downloading) {
if(Boot.libsDir() == null || Boot.libsDir().listFiles() == null || Boot.libsDir().listFiles().length <= 0) {
BytecodeViewer.showMessage(
"Github is loading extremely slow, BCV needs to download libraries from github in order"+nl+
"to work, please try ajusting your network settings or manually downloading these libraries"+nl+
"if this error persists.");
finished = true;
return;
}
Boot.setState("Bytecode Viewer Boot Screen (OFFLINE MODE) - Unable to connect to github, force booting...");
System.out.println("Unable to connect to github, force booting...");
List<String> libsList = new ArrayList<String>();
List<String> libsFileList = new ArrayList<String>();
if(Boot.libsDir() != null)
for (File f : Boot.libsDir().listFiles()) {
libsList.add(f.getName());
libsFileList.add(f.getAbsolutePath());
}
ILoader<?> loader = Boot.findLoader();
for (String s : libsFileList) {
if (s.endsWith(".jar")) {
File f = new File(s);
if (f.exists()) {
Boot.setState("Bytecode Viewer Boot Screen (OFFLINE MODE) - Force Loading Library " + f.getName());
System.out.println("Force loading library " + f.getName());
try {
ExternalResource res = new EmptyExternalResource<Object>(f.toURI().toURL());
loader.bind(res);
System.out.println("Succesfully loaded " + f.getName());
} catch (Exception e) {
e.printStackTrace();
f.delete();
JOptionPane.showMessageDialog(null, "Error, Library " + f.getName() + " is corrupt, please restart to redownload it.",
"Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
Boot.globalstop = false;
Boot.hide();
if(CommandLineInput.parseCommandLine(args) == CommandLineInput.OPEN_FILE)
BytecodeViewer.BOOT(false);
else {
BytecodeViewer.BOOT(true);
CommandLineInput.executeCommandLine(args);
}
}
finished = true;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
};
public static void pingback() { public static void pingback() {
JOptionPane pane = new JOptionPane( JOptionPane pane = new JOptionPane(
"Would you like to 'pingback' to https://bytecodeviewer.com to be counted in the global users for BCV?"); "Would you like to 'pingback' to https://bytecodeviewer.com to be counted in the global users for BCV?");
@ -366,6 +471,7 @@ public class BytecodeViewer {
* @param args files you want to open * @param args files you want to open
*/ */
public static void main(String[] args) { public static void main(String[] args) {
BytecodeViewer.args = args;
System.out.println("https://the.bytecode.club - Created by @Konloch - Bytecode Viewer " + version); System.out.println("https://the.bytecode.club - Created by @Konloch - Bytecode Viewer " + version);
System.setSecurityManager(sm); System.setSecurityManager(sm);
try { try {
@ -377,15 +483,37 @@ public class BytecodeViewer {
viewer = new MainViewerGUI(); viewer = new MainViewerGUI();
Settings.loadGUI(); Settings.loadGUI();
int CLI = CommandLineInput.parseCommandLine(args);
Boot.boot(args, CommandLineInput.parseCommandLine(args)); if(CLI == CommandLineInput.STOP)
//new BootScreen().DO_FIRST_BOOT(args, CommandLineInput.parseCommandLine(args)); return;
if(!fatJar) {
bootCheck.start();
if(CLI == CommandLineInput.OPEN_FILE)
Boot.boot(args, false);
else
Boot.boot(args, true);
} else
InstallFatJar.start();
if(CLI == CommandLineInput.OPEN_FILE)
BytecodeViewer.BOOT(false);
else {
BytecodeViewer.BOOT(true);
CommandLineInput.executeCommandLine(args);
}
} catch (Exception e) { } catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
} }
} }
public static void BOOT(String[] args, boolean cli) { /**
* Boot after all of the libraries have been loaded
* @param cli is it running CLI mode or not
*/
public static void BOOT(boolean cli) {
cleanup(); cleanup();
Runtime.getRuntime().addShutdownHook(new Thread() { Runtime.getRuntime().addShutdownHook(new Thread() {
@Override @Override
@ -442,8 +570,11 @@ public class BytecodeViewer {
* @return the ClassNode instance * @return the ClassNode instance
*/ */
public static ClassNode getClassNode(String name) { public static ClassNode getClassNode(String name) {
if (loadedClasses.containsKey(name)) for(FileContainer container : files)
return loadedClasses.get(name); for(ClassNode c : container.classes)
if(c.name.equals(name))
return c;
return null; return null;
} }
@ -453,8 +584,12 @@ public class BytecodeViewer {
* @return the file contents as a byte[] * @return the file contents as a byte[]
*/ */
public static byte[] getFileContents(String name) { public static byte[] getFileContents(String name) {
if (loadedResources.containsKey(name)) for(FileContainer container : files) {
return loadedResources.get(name); HashMap<String, byte[]> files = container.files;
if(files.containsKey(name))
return files.get(name);
}
return null; return null;
} }
@ -464,8 +599,10 @@ public class BytecodeViewer {
* @param newNode the new instance * @param newNode the new instance
*/ */
public static void updateNode(ClassNode oldNode, ClassNode newNode) { public static void updateNode(ClassNode oldNode, ClassNode newNode) {
BytecodeViewer.loadedClasses.remove(oldNode.name); for(FileContainer container : files) {
BytecodeViewer.loadedClasses.put(oldNode.name, newNode); if(container.classes.remove(oldNode))
container.classes.add(newNode);
}
} }
/** /**
@ -474,12 +611,11 @@ public class BytecodeViewer {
*/ */
public static ArrayList<ClassNode> getLoadedClasses() { public static ArrayList<ClassNode> getLoadedClasses() {
ArrayList<ClassNode> a = new ArrayList<ClassNode>(); ArrayList<ClassNode> a = new ArrayList<ClassNode>();
if (loadedClasses != null)
for (Entry<String, ClassNode> entry : loadedClasses.entrySet()) { for(FileContainer container : files)
Object value = entry.getValue(); for(ClassNode c : container.classes)
ClassNode cln = (ClassNode) value; a.add(c);
a.add(cln);
}
return a; return a;
} }
@ -604,7 +740,7 @@ public class BytecodeViewer {
} else { } else {
if (fn.endsWith(".jar") || fn.endsWith(".zip")) { if (fn.endsWith(".jar") || fn.endsWith(".zip")) {
try { try {
JarUtils.put(f, BytecodeViewer.loadedClasses); JarUtils.put(f);
} catch (final Exception e) { } catch (final Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
update = false; update = false;
@ -619,7 +755,13 @@ public class BytecodeViewer {
+ String.format("%02X", bytes[3]); + String.format("%02X", bytes[3]);
if(cafebabe.toLowerCase().equals("cafebabe")) { if(cafebabe.toLowerCase().equals("cafebabe")) {
final ClassNode cn = JarUtils.getNode(bytes); final ClassNode cn = JarUtils.getNode(bytes);
BytecodeViewer.loadedClasses.put(cn.name, cn);
FileContainer container = new FileContainer();
container.name = fn;
container.classes.add(cn);
BytecodeViewer.files.add(container);
} else { } else {
showMessage(fn+": Header does not start with CAFEBABE, ignoring."); showMessage(fn+": Header does not start with CAFEBABE, ignoring.");
update = false; update = false;
@ -630,13 +772,17 @@ public class BytecodeViewer {
} }
} else if(fn.endsWith(".apk")) { } else if(fn.endsWith(".apk")) {
try { try {
BytecodeViewer.viewer.setIcon(true);
FileContainer container = new FileContainer();
container.name = fn;
if(viewer.decodeAPKResources.isSelected()) { if(viewer.decodeAPKResources.isSelected()) {
File decodedResources = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk"); File decodedResources = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
APKTool.decodeResources(f, decodedResources); APKTool.decodeResources(f, decodedResources);
JarUtils.loadResources(decodedResources); container.files = JarUtils.loadResources(decodedResources);
} }
JarUtils.loadResources(f); container.files.putAll(JarUtils.loadResources(f));
String name = getRandomizedName()+".jar"; String name = getRandomizedName()+".jar";
File output = new File(tempDirectory + fs + name); File output = new File(tempDirectory + fs + name);
@ -646,14 +792,20 @@ public class BytecodeViewer {
else if(BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel())) else if(BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
Enjarify.apk2Jar(f, output); Enjarify.apk2Jar(f, output);
container.classes = JarUtils.loadClasses(output);
BytecodeViewer.viewer.setIcon(false); BytecodeViewer.viewer.setIcon(false);
openFiles(new File[]{output}, false); BytecodeViewer.files.add(container);
} catch (final Exception e) { } catch (final Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
} }
return; return;
} else if(fn.endsWith(".dex")) { } else if(fn.endsWith(".dex")) {
try { try {
BytecodeViewer.viewer.setIcon(true);
FileContainer container = new FileContainer();
container.name = fn;
String name = getRandomizedName()+".jar"; String name = getRandomizedName()+".jar";
File output = new File(tempDirectory + fs + name); File output = new File(tempDirectory + fs + name);
@ -662,15 +814,26 @@ public class BytecodeViewer {
else if(BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel())) else if(BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
Enjarify.apk2Jar(f, output); Enjarify.apk2Jar(f, output);
container.classes = JarUtils.loadClasses(output);
BytecodeViewer.viewer.setIcon(false); BytecodeViewer.viewer.setIcon(false);
openFiles(new File[]{output}, false); BytecodeViewer.files.add(container);
} catch (final Exception e) { } catch (final Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
} }
return; return;
} else { } else {
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
byte[] bytes = JarUtils.getBytes(new FileInputStream(f)); byte[] bytes = JarUtils.getBytes(new FileInputStream(f));
BytecodeViewer.loadedResources.put(f.getName(), bytes); files.put(f.getName(), bytes);
FileContainer container = new FileContainer();
container.name = fn;
container.files = files;
BytecodeViewer.files.add(container);
} }
} }
} }
@ -721,8 +884,7 @@ public class BytecodeViewer {
*/ */
public static void resetWorkSpace(boolean ask) { public static void resetWorkSpace(boolean ask) {
if(!ask) { if(!ask) {
loadedResources.clear(); files.clear();
loadedClasses.clear();
MainViewerGUI.getComponent(FileNavigationPane.class).resetWorkspace(); MainViewerGUI.getComponent(FileNavigationPane.class).resetWorkspace();
MainViewerGUI.getComponent(WorkPane.class).resetWorkspace(); MainViewerGUI.getComponent(WorkPane.class).resetWorkspace();
MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace(); MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace();
@ -742,8 +904,7 @@ public class BytecodeViewer {
result = k; result = k;
if (result == 0) { if (result == 0) {
loadedResources.clear(); files.clear();
loadedClasses.clear();
MainViewerGUI.getComponent(FileNavigationPane.class).resetWorkspace(); MainViewerGUI.getComponent(FileNavigationPane.class).resetWorkspace();
MainViewerGUI.getComponent(WorkPane.class).resetWorkspace(); MainViewerGUI.getComponent(WorkPane.class).resetWorkspace();
MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace(); MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace();
@ -877,19 +1038,6 @@ public class BytecodeViewer {
return name; return name;
} }
/**
* Replaces an old node with a new instance
* @param oldNode the old instance
* @param newNode the new instance
*/
public static void relocate(String name, ClassNode node) {
if (BytecodeViewer.loadedClasses.containsKey(name))
BytecodeViewer.loadedClasses.remove(name);
BytecodeViewer.loadedClasses.put(node.name, node);
}
/** /**
* Returns the BCV directory * Returns the BCV directory
* @return the static BCV directory * @return the static BCV directory

View file

@ -0,0 +1,22 @@
package the.bytecode.club.bytecodeviewer;
import java.util.ArrayList;
import java.util.HashMap;
import org.objectweb.asm.tree.ClassNode;
/**
* Represents a file container
*
* @author Konloch
*
*/
public class FileContainer {
public String name;
public HashMap<String, byte[]> files = new HashMap<String, byte[]>();
public ArrayList<ClassNode> classes = new ArrayList<ClassNode>();
}

View file

@ -33,7 +33,11 @@ public class JarUtils {
* @param clazzList the existing map of loaded classes * @param clazzList the existing map of loaded classes
* @throws IOException * @throws IOException
*/ */
public static void put(final File jarFile, final HashMap<String, ClassNode> clazzList) throws IOException { public static void put(final File jarFile) throws IOException {
FileContainer container = new FileContainer();
container.name = jarFile.getName();
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile)); ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
ZipEntry entry; ZipEntry entry;
while ((entry = jis.getNextEntry()) != null) { while ((entry = jis.getNextEntry()) != null) {
@ -41,7 +45,7 @@ public class JarUtils {
final String name = entry.getName(); final String name = entry.getName();
if (!name.endsWith(".class")) { if (!name.endsWith(".class")) {
if(!entry.isDirectory()) if(!entry.isDirectory())
BytecodeViewer.loadedResources.put(name, getBytes(jis)); files.put(name, getBytes(jis));
} else { } else {
byte[] bytes = getBytes(jis); byte[] bytes = getBytes(jis);
String cafebabe = String.format("%02X", bytes[0]) String cafebabe = String.format("%02X", bytes[0])
@ -51,7 +55,7 @@ public class JarUtils {
if(cafebabe.toLowerCase().equals("cafebabe")) { if(cafebabe.toLowerCase().equals("cafebabe")) {
try { try {
final ClassNode cn = getNode(bytes); final ClassNode cn = getNode(bytes);
clazzList.put(cn.name, cn); container.classes.add(cn);
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -67,18 +71,58 @@ public class JarUtils {
} }
} }
jis.close(); jis.close();
container.files = files;
BytecodeViewer.files.add(container);
} }
public static ArrayList<ClassNode> loadClasses(final File jarFile) throws IOException {
ArrayList<ClassNode> classes = new ArrayList<ClassNode>();
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
ZipEntry entry;
while ((entry = jis.getNextEntry()) != null) {
try {
final String name = entry.getName();
if (name.endsWith(".class")) {
byte[] bytes = getBytes(jis);
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")) {
try {
final ClassNode cn = getNode(bytes);
classes.add(cn);
} catch(Exception e) {
e.printStackTrace();
}
} else {
System.out.println(jarFile+">"+name+": Header does not start with CAFEBABE, ignoring.");
}
}
} catch(Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
} finally {
jis.closeEntry();
}
}
jis.close();
return classes;
}
/** /**
* Loads resources only, just for .APK * Loads resources only, just for .APK
* @param zipFile the input zip file * @param zipFile the input zip file
* @throws IOException * @throws IOException
*/ */
public static void loadResources(final File zipFile) throws IOException { public static HashMap<String, byte[]> loadResources(final File zipFile) throws IOException {
if(!zipFile.exists()) if(!zipFile.exists())
return; //just ignore return null; //just ignore
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
ZipInputStream jis = new ZipInputStream(new FileInputStream(zipFile)); ZipInputStream jis = new ZipInputStream(new FileInputStream(zipFile));
ZipEntry entry; ZipEntry entry;
while ((entry = jis.getNextEntry()) != null) { while ((entry = jis.getNextEntry()) != null) {
@ -86,7 +130,7 @@ public class JarUtils {
final String name = entry.getName(); final String name = entry.getName();
if (!name.endsWith(".class") && !name.endsWith(".dex")) { if (!name.endsWith(".class") && !name.endsWith(".dex")) {
if(!entry.isDirectory()) if(!entry.isDirectory())
BytecodeViewer.loadedResources.put(name, getBytes(jis)); files.put(name, getBytes(jis));
jis.closeEntry(); jis.closeEntry();
continue; continue;
@ -99,6 +143,8 @@ public class JarUtils {
} }
jis.close(); jis.close();
return files;
} }
/** /**
@ -164,8 +210,8 @@ public class JarUtils {
out.write((manifest.trim() + "\r\n\r\n").getBytes()); out.write((manifest.trim() + "\r\n\r\n").getBytes());
out.closeEntry(); out.closeEntry();
for (Entry<String, byte[]> entry : BytecodeViewer.loadedResources for(FileContainer container : BytecodeViewer.files)
.entrySet()) { for (Entry<String, byte[]> entry : container.files.entrySet()) {
String filename = entry.getKey(); String filename = entry.getKey();
if (!filename.startsWith("META-INF")) { if (!filename.startsWith("META-INF")) {
out.putNextEntry(new ZipEntry(filename)); out.putNextEntry(new ZipEntry(filename));
@ -198,8 +244,8 @@ public class JarUtils {
out.closeEntry(); out.closeEntry();
} }
for (Entry<String, byte[]> entry : BytecodeViewer.loadedResources for(FileContainer container : BytecodeViewer.files)
.entrySet()) { for (Entry<String, byte[]> entry : container.files.entrySet()) {
String filename = entry.getKey(); String filename = entry.getKey();
if (!filename.startsWith("META-INF")) { if (!filename.startsWith("META-INF")) {
out.putNextEntry(new ZipEntry(filename)); out.putNextEntry(new ZipEntry(filename));

View file

@ -77,7 +77,10 @@ public class ExceptionUI extends JFrame {
e.printStackTrace(new PrintWriter(sw)); e.printStackTrace(new PrintWriter(sw));
e.printStackTrace(); e.printStackTrace();
txtrBytecodeViewerIs.setText("Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString()); txtrBytecodeViewerIs.setText("Bytecode Viewer Version: " + BytecodeViewer.version+
", Preview Copy: " + BytecodeViewer.previewCopy +
", Fat Jar: " + BytecodeViewer.fatJar +
BytecodeViewer.nl + BytecodeViewer.nl + sw.toString());
this.setLocationRelativeTo(null); this.setLocationRelativeTo(null);
this.setVisible(true); this.setVisible(true);
} }

View file

@ -46,6 +46,8 @@ scrollPane.setViewportView(textArea);
textArea.setText("Bytecode Viewer "+BytecodeViewer.version+" is an open source program developed and maintained by Konloch (konloch@gmail.com)\r\n"+ textArea.setText("Bytecode Viewer "+BytecodeViewer.version+" is an open source program developed and maintained by Konloch (konloch@gmail.com)\r\n"+
"100% free and open sourced licensed under GPL v3 CopyLeft\r\n\r\n"+ "100% free and open sourced licensed under GPL v3 CopyLeft\r\n\r\n"+
"Settings:"+BytecodeViewer.nl+ "Settings:"+BytecodeViewer.nl+
" Preview Copy:"+BytecodeViewer.previewCopy+BytecodeViewer.nl+
" Fat Jar:"+BytecodeViewer.fatJar+BytecodeViewer.nl+
" BCV Dir: " + BytecodeViewer.getBCVDirectory()+BytecodeViewer.nl+ " BCV Dir: " + BytecodeViewer.getBCVDirectory()+BytecodeViewer.nl+
" Python 2.7 (or PyPy): " + BytecodeViewer.python+BytecodeViewer.nl+ " Python 2.7 (or PyPy): " + BytecodeViewer.python+BytecodeViewer.nl+
" Python 3.X (or PyPy): " + BytecodeViewer.python3+BytecodeViewer.nl+ " Python 3.X (or PyPy): " + BytecodeViewer.python3+BytecodeViewer.nl+

View file

@ -17,6 +17,7 @@ import java.util.ArrayList;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JSplitPane; import javax.swing.JSplitPane;
import javax.swing.JTextField; import javax.swing.JTextField;
@ -624,6 +625,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Procyon Decompiler"));
panel1.add(scrollPane); panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -650,6 +652,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel1.add(scrollPane); panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -677,6 +680,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("FernFlower Decompiler"));
panel1.add(scrollPane); panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -705,6 +709,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Bytecode Decompiler"));
panel1.add(scrollPane); panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -718,7 +723,7 @@ public class ClassViewer extends Viewer {
hex.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); hex.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
} }
if (pane1 == 6) {// bytecode if (pane1 == 6) {//smali bytecode
RSyntaxTextArea panelArea = new RSyntaxTextArea(); RSyntaxTextArea panelArea = new RSyntaxTextArea();
panelArea panelArea
.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); .setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
@ -741,6 +746,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Smali Decompiler"));
panel1.add(scrollPane); panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -768,6 +774,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Krakatau Decompiler"));
panel1.add(scrollPane); panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -799,6 +806,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Krakatau Disassembler"));
panel1.add(scrollPane); panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -826,6 +834,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("JD-GUI Decompiler"));
panel1.add(scrollPane); panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -870,6 +879,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Procyon Decompiler"));
panel2.add(scrollPane); panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -897,6 +907,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel2.add(scrollPane); panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -924,6 +935,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel2.add(scrollPane); panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -950,6 +962,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Bytecode Decompiler"));
panel2.add(scrollPane); panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -985,6 +998,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Smali Decompiler"));
panel2.add(scrollPane); panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1012,6 +1026,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Krakatau Decompiler"));
panel2.add(scrollPane); panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1041,6 +1056,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Krakatau Disassembler"));
panel2.add(scrollPane); panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1068,6 +1084,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("JD-GUI Decompiler"));
panel2.add(scrollPane); panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1113,6 +1130,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Procyon Decompiler"));
panel3.add(scrollPane); panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1140,6 +1158,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel3.add(scrollPane); panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1167,6 +1186,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel3.add(scrollPane); panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1193,6 +1213,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Bytecode Decompiler"));
panel3.add(scrollPane); panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1228,6 +1249,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Smali Decompiler"));
panel3.add(scrollPane); panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1255,6 +1277,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Krakatau Decompiler"));
panel3.add(scrollPane); panel3.add(scrollPane);
java3 = panelArea; java3 = panelArea;
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1284,6 +1307,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("Krakatau Disassembler"));
panel3.add(scrollPane); panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1311,6 +1335,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { } @Override public void keyTyped(KeyEvent arg0) { }
}); });
scrollPane.setColumnHeaderView(new JLabel("JD-GUI Decompiler"));
panel3.add(scrollPane); panel3.add(scrollPane);
java3 = panelArea; java3 = panelArea;
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue())); panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));

View file

@ -56,8 +56,8 @@ public class FileNavigationPane extends VisibleComponent implements
JButton open = new JButton("+"); JButton open = new JButton("+");
JButton close = new JButton("-"); JButton close = new JButton("-");
MyTreeNode treeRoot = new MyTreeNode("Root"); MyTreeNode treeRoot = new MyTreeNode("Loaded Files:");
MyTree tree; MyTree tree = new MyTree(treeRoot);
public FileNavigationPane(final FileChangeNotifier fcn) { public FileNavigationPane(final FileChangeNotifier fcn) {
super("ClassNavigation"); super("ClassNavigation");
@ -87,8 +87,6 @@ public class FileNavigationPane extends VisibleComponent implements
}); });
getContentPane().setLayout(new BorderLayout()); getContentPane().setLayout(new BorderLayout());
this.tree = new MyTree(treeRoot);
getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER); getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
MouseAdapter ml = new MouseAdapter() { MouseAdapter ml = new MouseAdapter() {
@ -97,7 +95,7 @@ public class FileNavigationPane extends VisibleComponent implements
if (path == null) if (path == null)
return; return;
final StringBuffer nameBuffer = new StringBuffer(); final StringBuffer nameBuffer = new StringBuffer();
for (int i = 1; i < path.getPathCount(); i++) { for (int i = 2; i < path.getPathCount(); i++) {
nameBuffer.append(path.getPathComponent(i)); nameBuffer.append(path.getPathComponent(i));
if (i < path.getPathCount() - 1) { if (i < path.getPathCount() - 1) {
nameBuffer.append("/"); nameBuffer.append("/");
@ -290,14 +288,18 @@ public class FileNavigationPane extends VisibleComponent implements
public void updateTree() { public void updateTree() {
try { try {
treeRoot.removeAllChildren(); treeRoot.removeAllChildren();
for (final Entry<String, ClassNode> entry : BytecodeViewer.loadedClasses for (FileContainer container : BytecodeViewer.files) {
.entrySet()) { MyTreeNode root = new MyTreeNode(container.name);
String name = entry.getKey(); treeRoot.add(root);
if(!container.classes.isEmpty()) {
for(ClassNode c : container.classes) {
String name = c.name;
final String[] spl = name.split("/"); final String[] spl = name.split("/");
if (spl.length < 2) { if (spl.length < 2) {
treeRoot.add(new MyTreeNode(name+".class")); root.add(new MyTreeNode(name+".class"));
} else { } else {
MyTreeNode parent = treeRoot; MyTreeNode parent = root;
for (int i1 = 0; i1 < spl.length; i1++) { for (int i1 = 0; i1 < spl.length; i1++) {
String s = spl[i1]; String s = spl[i1];
MyTreeNode child = null; MyTreeNode child = null;
@ -319,14 +321,16 @@ public class FileNavigationPane extends VisibleComponent implements
} }
} }
} }
}
for (final Entry<String, byte[]> entry : BytecodeViewer.loadedResources.entrySet()) { if(!container.files.isEmpty()) {
for (final Entry<String, byte[]> entry : container.files.entrySet()) {
String name = entry.getKey(); String name = entry.getKey();
final String[] spl = name.split("/"); final String[] spl = name.split("/");
if (spl.length < 2) { if (spl.length < 2) {
treeRoot.add(new MyTreeNode(name)); root.add(new MyTreeNode(name));
} else { } else {
MyTreeNode parent = treeRoot; MyTreeNode parent = root;
for (final String s : spl) { for (final String s : spl) {
MyTreeNode child = null; MyTreeNode child = null;
for (int i = 0; i < parent.getChildCount(); i++) { for (int i = 0; i < parent.getChildCount(); i++) {
@ -344,6 +348,9 @@ public class FileNavigationPane extends VisibleComponent implements
} }
} }
} }
}
}
treeRoot.sort(); treeRoot.sort();
tree.expandPath(new TreePath(tree.getModel().getRoot())); tree.expandPath(new TreePath(tree.getModel().getRoot()));

View file

@ -86,7 +86,6 @@ public class FileViewer extends Viewer {
JLabel label = new JLabel("", new ImageIcon(image), JLabel.CENTER); JLabel label = new JLabel("", new ImageIcon(image), JLabel.CENTER);
panel2.add( label, BorderLayout.CENTER ); panel2.add( label, BorderLayout.CENTER );
panel2.addMouseWheelListener(new MouseWheelListener() { panel2.addMouseWheelListener(new MouseWheelListener() {
@Override @Override
public void mouseWheelMoved(MouseWheelEvent e) { public void mouseWheelMoved(MouseWheelEvent e) {
int notches = e.getWheelRotation(); int notches = e.getWheelRotation();
@ -100,7 +99,6 @@ public class FileViewer extends Viewer {
panel2.add( label, BorderLayout.CENTER ); panel2.add( label, BorderLayout.CENTER );
panel2.updateUI(); panel2.updateUI();
} }
}); });
return; return;
} catch(Exception e) { } catch(Exception e) {
@ -134,7 +132,7 @@ public class FileViewer extends Viewer {
} else if(name.endsWith(".properties") || name.endsWith(".mf") || name.endsWith(".sf")) { } else if(name.endsWith(".properties") || name.endsWith(".mf") || name.endsWith(".sf")) {
panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PROPERTIES_FILE); panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PROPERTIES_FILE);
panelArea.setText(contentsS); panelArea.setText(contentsS);
} else if(name.endsWith(".php") || name.startsWith("<?php")) { } else if(name.endsWith(".php") || contentsS.startsWith("<?php")) {
panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PHP); panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PHP);
panelArea.setText(contentsS); panelArea.setText(contentsS);
} else if(name.endsWith(".js")) { } else if(name.endsWith(".js")) {

View file

@ -37,7 +37,6 @@ 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.Dex2Jar;
import the.bytecode.club.bytecodeviewer.Enjarify;
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.MiscUtils; import the.bytecode.club.bytecodeviewer.MiscUtils;
@ -1907,7 +1906,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
setSize(new Dimension(800, 400)); setSize(new Dimension(800, 400));
if(BytecodeViewer.previewCopy) if(BytecodeViewer.previewCopy)
setTitle("Bytecode Viewer "+BytecodeViewer.version+" preview - https://bytecodeviewer.com | https://the.bytecode.club - @Konloch"); setTitle("Bytecode Viewer "+BytecodeViewer.version+" Preview - https://bytecodeviewer.com | https://the.bytecode.club - @Konloch");
else else
setTitle("Bytecode Viewer "+BytecodeViewer.version+" - https://bytecodeviewer.com | https://the.bytecode.club - @Konloch"); setTitle("Bytecode Viewer "+BytecodeViewer.version+" - https://bytecodeviewer.com | https://the.bytecode.club - @Konloch");

View file

@ -42,9 +42,9 @@ public class Refactorer {
cr.accept(cn, 0); cr.accept(cn, 0);
refactored.put(oldName, cn); refactored.put(oldName, cn);
} }
for (Map.Entry<String, ClassNode> factor : refactored.entrySet()) { /*for (Map.Entry<String, ClassNode> factor : refactored.entrySet()) {
BytecodeViewer.relocate(factor.getKey(), factor.getValue()); BytecodeViewer.relocate(factor.getKey(), factor.getValue());
} }*/
mapper.printMap(); mapper.printMap();
} }