diff --git a/BytecodeViewer 2.7.1.jar b/BytecodeViewer 2.7.1.jar deleted file mode 100644 index 29035202c..000000000 Binary files a/BytecodeViewer 2.7.1.jar and /dev/null differ diff --git a/libs/jython-standalone-2.5.3.jar b/BytecodeViewer 2.8.0.jar similarity index 58% rename from libs/jython-standalone-2.5.3.jar rename to BytecodeViewer 2.8.0.jar index 9e01e5caa..04831d4fd 100644 Binary files a/libs/jython-standalone-2.5.3.jar and b/BytecodeViewer 2.8.0.jar differ diff --git a/README.txt b/README.txt index c448d002b..a6456dc32 100644 --- a/README.txt +++ b/README.txt @@ -1,8 +1,8 @@ -Bytecode Viewer is an Advanced Lightweight Java Bytecode Viewer, GUI Smali, GUI Baksmali, GUI APK Editor, GUI Dex Editor, GUI APK Decompiler, GUI DEX Decompiler, GUI Procyon Java Decompiler, GUI CFR Java Decompiler, GUI FernFlower Java Decompiler, GUI DEX2Jar, GUI Jar2DEX, GUI Jar-Jar, Hex Viewer, Code Searcher, Debugger and more. +Bytecode Viewer is an Advanced Lightweight Java Bytecode Viewer, GUI Smali, GUI Baksmali, GUI APK Editor, GUI Dex Editor, GUI APK Decompiler, GUI DEX Decompiler, GUI Procyon Java Decompiler, GUI Krakatau, GUI CFR Java Decompiler, GUI FernFlower Java Decompiler, GUI DEX2Jar, GUI Jar2DEX, 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. 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. -You can either use one of the pre-written plugins, or write your own. It supports groovy, python and ruby scripting. Once a plugin is activated, it will execute the plugin with a ClassNode ArrayList of every single class loaded in BCV, this allows the user to handle it completely using ASM. +You can either use one of the pre-written plugins, or write your own. It supports groovy scripting. Once a plugin is activated, it will execute the plugin with a ClassNode ArrayList of every single class loaded in BCV, this allows the user to handle it completely using ASM. Code from various projects has been used, including but not limited to: J-RET by WaterWolf @@ -16,6 +16,7 @@ Code from various projects has been used, including but not limited to: CFIDE by Bibl Smali by JesusFreke Dex2Jar by pxb1..? + Krakatau by Storyyeller Contributors: Konloch @@ -31,7 +32,7 @@ Contribution Guide Lines: Packages must start with the.bytecode.club.bytecodeviewer If code you write can throw an exception, handle it using new the.bytecode.club.bytecodeviewer.ExceptionUI(exception) -Video: http://the.bytecode.club/bytecodeviewer-video/ +Website: https://bytecodeviewer.com Source Code: https://github.com/konloch/bytecode-viewer Bin/Archive: https://github.com/konloch/bytecode-viewer/releases Java Docs: https://the.bytecode.club/docs/bytecode-viewer/ @@ -40,7 +41,8 @@ Report Bugs (or below): https://github.com/Konloch/bytecode-viewer/issues Discussion Forum: https://the.bytecode.club/forumdisplay.php?fid=69 Key Features: - Smali/BakSmali Intergration - You can now edit class files/dex files via smali! + Krakatau Integration for Bytecode assembly/disassembly. + Smali/BakSmali Integration - You can now edit class files/dex files via smali! APK/DEX Support - Using Dex2Jar and Jar2Dex it's able to load and save APKs with ease! Java Decompiler - It utilizes FernFlower, Procyon and CFR for decompilation. Bytecode Decompiler - A modified version of CFIDE's. @@ -48,7 +50,7 @@ Key Features: Each Decompiler/Viewer is toggleable, you can also select what will display on each pane. 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) - Fully Featured Scripting System That Supports Groovy, Python And Ruby. + Fully Featured Scripting System That Supports Groovy. 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! @@ -276,4 +278,13 @@ Changelog: 01/27/2015 - Decided to scrap the JVM Sandbox POC and use the Security Manager. 01/27/2015 - BCV now blocks exec and won't allow any ports to be bound. --- 2.7.1 ---: -01/27/2015 - Fixed hide file. \ No newline at end of file +01/27/2015 - Fixed hide file. +--- 2.8.0 ---: +02/01/2015 - Updated CFR and Proycon to latest versions. +02/01/2015 - Started working on implementing Krakatau. +02/01/2015 - Sexifixed the security manager a little bit. +02/03/2015 - Fully added Krakatau Java decompiler, just disassembly/assembly left. +02/03/2015 - Updated the about window. +02/03/2015 - Dropped JRuby and Jython support (BCV is now roughly 16mb, was 45mb). +02/04/2015 - Added Krakatau Disassembly. +02/04/2015 - Added Krakatau Assembly. \ No newline at end of file diff --git a/libs/cfr_0_94.jar b/libs/cfr_0_95.jar similarity index 79% rename from libs/cfr_0_94.jar rename to libs/cfr_0_95.jar index 641ce1e75..65dfe2dec 100644 Binary files a/libs/cfr_0_94.jar and b/libs/cfr_0_95.jar differ diff --git a/libs/jruby.jar b/libs/jruby.jar deleted file mode 100644 index 0c0ed7337..000000000 Binary files a/libs/jruby.jar and /dev/null differ diff --git a/libs/procyon-decompiler-0.5.27.jar b/libs/procyon-decompiler-0.5.28.jar similarity index 86% rename from libs/procyon-decompiler-0.5.27.jar rename to libs/procyon-decompiler-0.5.28.jar index 623f19022..9d6391902 100644 Binary files a/libs/procyon-decompiler-0.5.27.jar and b/libs/procyon-decompiler-0.5.28.jar differ diff --git a/src/krakatau.zip b/src/krakatau.zip new file mode 100644 index 000000000..652f292ee Binary files /dev/null and b/src/krakatau.zip differ diff --git a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index 25914e231..ea15589c5 100644 --- a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -7,16 +7,13 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.net.InetAddress; import java.net.URI; import java.net.URL; -import java.security.Permission; import java.util.ArrayList; import java.util.HashMap; import java.util.Map.Entry; @@ -37,7 +34,7 @@ import org.imgscalr.Scalr; import org.objectweb.asm.tree.ClassNode; -import the.bytecode.club.bytecodeviewer.decompilers.Smali; +import the.bytecode.club.bytecodeviewer.api.ClassNodeLoader; import the.bytecode.club.bytecodeviewer.gui.ClassViewer; import the.bytecode.club.bytecodeviewer.gui.FileNavigationPane; import the.bytecode.club.bytecodeviewer.gui.MainViewerGUI; @@ -63,7 +60,7 @@ * 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. You can either use one of the - * pre-written plugins, or write your own. It supports groovy, python and ruby + * pre-written plugins, or write your own. It supports groovy * scripting. Once a plugin is activated, it will send a ClassNode ArrayList of * every single class loaded in the file system to the execute function, this * allows the user to handle it completely using ASM. @@ -303,6 +300,15 @@ * 01/27/2015 - Added java.awt.Robot to the malicious code scanner. * -----2.7.1-----: * 01/27/2015 - Fixed hide file. + * -----2.8.0-----: + * 02/01/2015 - Updated CFR and Proycon to latest versions. + * 02/01/2015 - Started working on implementing Krakatau. + * 02/01/2015 - Sexifixed the security manager a little bit. + * 02/03/2015 - Fully added Krakatau Java decompiler, just disassembly/assembly left. + * 02/03/2015 - Updated the about window. + * 02/03/2015 - Dropped JRuby and Jython support (BCV is now roughly 16mb, was 45mb). + * 02/04/2015 - Added Krakatau Disassembly. + * 02/04/2015 - Added Krakatau Assembly. * * @author Konloch * @@ -310,20 +316,29 @@ public class BytecodeViewer { + /*per version*/ + public static String version = "2.8.0"; + public static String krakatauVersion = "2"; + /*the rest*/ 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 String python = ""; + public static String rt = ""; + public static SecurityMan sm = new SecurityMan(); public static HashMap loadedClasses = new HashMap(); public static HashMap loadedResources = new HashMap(); private static int maxRecentFiles = 25; public static String fs = System.getProperty("file.separator"); public static String nl = System.getProperty("line.separator"); + private static File BCVDir = new File(System.getProperty("user.home") + fs + ".Bytecode-Viewer"); private static String filesName = getBCVDirectory() + fs + "recentfiles.bcv"; private static String pluginsName = getBCVDirectory() + fs + "recentplugins.bcv"; public static String settingsName = getBCVDirectory() + fs + "settings.bcv"; public static String tempDirectory = getBCVDirectory() + fs + "bcv_temp" + fs; + public static String krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + krakatauVersion + fs + "Krakatau-master"; private static ArrayList recentFiles = DiskReader.loadArrayList(filesName, false); private static ArrayList recentPlugins = DiskReader.loadArrayList(pluginsName, false); public static boolean runningObfuscation = false; - public static String version = "2.7.1"; private static long start = System.currentTimeMillis(); public static String lastDirectory = ""; private static Thread versionChecker = new Thread() { @@ -502,51 +517,8 @@ public static byte[] getClassFile(Class clazz) throws IOException { } public static void main(String[] args) { - getBCVDirectory(); - SecurityManager sm = new SecurityManager() { - @Override - public void checkExec(String cmd) { - throw new SecurityException("BCV is awesome."); - } - @Override - public void checkListen(int port) { - throw new SecurityException("BCV is awesome."); - } - @Override - public void checkPermission(Permission perm) { //expand eventually - } - @Override - public void checkPermission(Permission perm, Object context) {//expand eventually - } - @Override public void checkAccess(Thread t) {} - @Override public void checkAccept(String host, int port) {} - @Override public void checkAccess(ThreadGroup g) {} - @Override public void checkAwtEventQueueAccess() {} - @Override public void checkConnect(String host, int port) {} - @Override public void checkConnect(String host, int port, Object context) {} - @Override public void checkCreateClassLoader() {} - @Override public void checkDelete(String file) {} - @Override public void checkExit(int status) {} - @Override public void checkLink(String lib) {} - @Override public void checkMemberAccess(Class clazz, int which) {} - @Override public void checkMulticast(InetAddress maddr) {} - @Override public void checkMulticast(InetAddress maddr, byte ttl) {} - @Override public void checkPackageAccess(String pkg) {} - @Override public void checkPackageDefinition(String pkg) {} - @Override public void checkPrintJobAccess() {} - @Override public void checkPropertiesAccess() {} - @Override public void checkPropertyAccess(String key) {} - @Override public void checkRead(FileDescriptor fd) {} - @Override public void checkRead(String file) {} - @Override public void checkRead(String file, Object context) {} - @Override public void checkSecurityAccess(String target) {} - @Override public void checkSetFactory() {} - @Override public void checkSystemClipboardAccess() {} - @Override public void checkWrite(FileDescriptor fd) {} - @Override public void checkWrite(String file) {} - }; System.setSecurityManager(sm); - + checkKrakatau(); System.out.println("https://the.bytecode.club - Created by @Konloch - Bytecode Viewer " + version); iconList = new ArrayList(); int size = 16; @@ -616,7 +588,7 @@ public static ArrayList getLoadedClasses() { } //called whenever a save function is executed - public static boolean compileSmali(boolean message) { + public static boolean compile(boolean message) { if(getLoadedClasses().isEmpty()) return false; @@ -624,10 +596,10 @@ public static boolean compileSmali(boolean message) { if(c instanceof ClassViewer) { ClassViewer cv = (ClassViewer) c; Object smali[] = cv.getSmali(); - ClassNode origNode = (ClassNode) smali[0]; - String smaliText = (String) smali[1]; if(smali != null) { - byte[] smaliCompiled = Smali.compile(smaliText); + ClassNode origNode = (ClassNode) smali[0]; + String smaliText = (String) smali[1]; + byte[] smaliCompiled = the.bytecode.club.bytecodeviewer.compilers.SmaliAssembler.compile(smaliText); if(smaliCompiled != null) { ClassNode newNode = JarUtils.getNode(smaliCompiled); System.out.println(origNode.name+":"+newNode.name); @@ -637,6 +609,22 @@ public static boolean compileSmali(boolean message) { return false; } } + + + Object krakatau[] = cv.getKrakatau(); + if(krakatau != null) { + ClassNode origNodeK = (ClassNode) krakatau[0]; + String krakatauText = (String) krakatau[1]; + byte[] krakatauCompiled = the.bytecode.club.bytecodeviewer.compilers.KrakatauAssembler.compile(krakatauText, origNodeK.name); + if(krakatauCompiled != null) { + ClassNode newNode = JarUtils.getNode(krakatauCompiled); + System.out.println(origNodeK.name+":"+newNode.name); + BytecodeViewer.updateNode(origNodeK, newNode); + } else { + BytecodeViewer.showMessage("There has been an error with assembling your Krakatau Bytecode, please check this. Class: " + origNodeK.name); + return false; + } + } } } @@ -646,6 +634,30 @@ public static boolean compileSmali(boolean message) { return true; } + public static void checkKrakatau() { + File krakatauDirectory = new File(getBCVDirectory() + fs + "krakatau_" + krakatauVersion); + if(!krakatauDirectory.exists()) { + try { + File temp = new File(getBCVDirectory() + fs + "krakatau_" + krakatauVersion + ".zip"); + while(temp.exists()) + temp.delete(); + InputStream is = BytecodeViewer.class.getClassLoader().getResourceAsStream("krakatau.zip"); + FileOutputStream baos = new FileOutputStream(temp); + int r = 0; + byte[] buffer = new byte[8192]; + while((r=is.read(buffer))>=0) { + baos.write(buffer, 0, r); + } + baos.close(); + ZipUtils.unzipFilesToPath(temp.getAbsolutePath(), krakatauDirectory.getAbsolutePath()); + temp.delete(); + } catch(Exception e) { + showMessage("ERROR: There was an issue unzipping Krakatau decompiler, please contact @Konloch with your stacktrace."); + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + } + } + private static boolean update = true; public static void openFiles(final File[] files, boolean recentFiles) { if(recentFiles) @@ -741,7 +753,6 @@ public static void showMessage(String message) { JOptionPane.showMessageDialog(viewer, message); } - @SuppressWarnings("deprecation") public static void resetWorkSpace(boolean ask) { if(!ask) { loadedResources.clear(); @@ -759,7 +770,7 @@ public static void resetWorkSpace(boolean ask) { pane.setOptions(options); JDialog dialog = pane.createDialog(viewer, "Bytecode Viewer - Reset Workspace"); - dialog.show(); + dialog.setVisible(true); Object obj = pane.getValue(); int result = -1; for (int k = 0; k < options.length; k++) @@ -793,8 +804,7 @@ public static void addRecentFile(File f) { killList.clear(); } - if (recentFiles.contains(f.getAbsolutePath())) // already added on the - // list + if (recentFiles.contains(f.getAbsolutePath())) // already added on the list recentFiles.remove(f.getAbsolutePath()); if (recentFiles.size() >= maxRecentFiles) recentFiles.remove(maxRecentFiles - 1); // zero indexing @@ -818,8 +828,7 @@ public static void addRecentPlugin(File f) { killList2.clear(); } - if (recentPlugins.contains(f.getAbsolutePath())) // already added on the - // list + if (recentPlugins.contains(f.getAbsolutePath())) // already added on the list recentPlugins.remove(f.getAbsolutePath()); if (recentPlugins.size() >= maxRecentFiles) recentPlugins.remove(maxRecentFiles - 1); // zero indexing @@ -887,15 +896,13 @@ public static String getRandomizedName() { } public static String getBCVDirectory() { - File f = new File(System.getProperty("user.home") + fs - + ".Bytecode-Viewer"); - while (!f.exists()) - f.mkdirs(); + while (!BCVDir.exists()) + BCVDir.mkdirs(); - if (!f.isHidden() && isWindows()) - hideFile(f); + if (!BCVDir.isHidden() && isWindows()) + hideFile(BCVDir); - return f.getAbsolutePath(); + return BCVDir.getAbsolutePath(); } private static boolean isWindows() { @@ -903,13 +910,14 @@ private static boolean isWindows() { } private static void hideFile(File f) { - System.out.println("hiding file"); + sm.blocking = false; try { // Hide file by running attrib system command (on Windows) Runtime.getRuntime().exec("attrib +H " + f.getAbsolutePath()); } catch (Exception e) { new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); } + sm.blocking = true; } private static String quickConvert(ArrayList a) { diff --git a/src/the/bytecode/club/bytecodeviewer/MiscUtils.java b/src/the/bytecode/club/bytecodeviewer/MiscUtils.java index 42c96d476..f1b0bd1bf 100644 --- a/src/the/bytecode/club/bytecodeviewer/MiscUtils.java +++ b/src/the/bytecode/club/bytecodeviewer/MiscUtils.java @@ -1,5 +1,6 @@ package the.bytecode.club.bytecodeviewer; +import java.io.File; import java.util.Random; public class MiscUtils { @@ -20,4 +21,35 @@ public static String randomStringNum(int len) { sb.append(AN.charAt(rnd.nextInt(AN.length()))); return sb.toString(); } + + + + public static String getUniqueName(String start, String ext) { + String s = null; + boolean b = true; + File f = null; + String m = null; + while (b) { + m = MiscUtils.randomString(32); + f = new File(start + m + ext); + if (!f.exists()) { + s = start + m; + b = false; + } + } + return s; + } + + public static int getClassNumber(String start, String ext) { + boolean b = true; + int i = 0; + while (b) { + File tempF = new File(start + i + ext); + if (!tempF.exists()) + b = false; + else + i++; + } + return i; + } } diff --git a/src/the/bytecode/club/bytecodeviewer/SecurityMan.java b/src/the/bytecode/club/bytecodeviewer/SecurityMan.java new file mode 100644 index 000000000..636f98c06 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/SecurityMan.java @@ -0,0 +1,53 @@ +package the.bytecode.club.bytecodeviewer; + +import java.io.FileDescriptor; +import java.net.InetAddress; +import java.security.Permission; + +public class SecurityMan extends SecurityManager { + + public boolean blocking = true; + @Override + public void checkExec(String cmd) { + if(blocking) + throw new SecurityException("BCV is awesome."); + } + @Override + public void checkListen(int port) { + if(blocking) + throw new SecurityException("BCV is awesome."); + } + @Override + public void checkPermission(Permission perm) { //expand eventually + } + @Override + public void checkPermission(Permission perm, Object context) {//expand eventually + } + @Override public void checkAccess(Thread t) {} + @Override public void checkAccept(String host, int port) {} + @Override public void checkAccess(ThreadGroup g) {} + @Override public void checkAwtEventQueueAccess() {} + @Override public void checkConnect(String host, int port) {} + @Override public void checkConnect(String host, int port, Object context) {} + @Override public void checkCreateClassLoader() {} + @Override public void checkDelete(String file) {} + @Override public void checkExit(int status) {} + @Override public void checkLink(String lib) {} + @Override public void checkMemberAccess(Class clazz, int which) {} + @Override public void checkMulticast(InetAddress maddr) {} + @Override public void checkMulticast(InetAddress maddr, byte ttl) {} + @Override public void checkPackageAccess(String pkg) {} + @Override public void checkPackageDefinition(String pkg) {} + @Override public void checkPrintJobAccess() {} + @Override public void checkPropertiesAccess() {} + @Override public void checkPropertyAccess(String key) {} + @Override public void checkRead(FileDescriptor fd) {} + @Override public void checkRead(String file) {} + @Override public void checkRead(String file, Object context) {} + @Override public void checkSecurityAccess(String target) {} + @Override public void checkSetFactory() {} + @Override public void checkSystemClipboardAccess() {} + @Override public void checkWrite(FileDescriptor fd) {} + @Override public void checkWrite(String file) {} + +} diff --git a/src/the/bytecode/club/bytecodeviewer/Settings.java b/src/the/bytecode/club/bytecodeviewer/Settings.java index 199417361..ff1112997 100644 --- a/src/the/bytecode/club/bytecodeviewer/Settings.java +++ b/src/the/bytecode/club/bytecodeviewer/Settings.java @@ -111,6 +111,10 @@ else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false); else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1Smali.getModel())) DiskWriter.writeNewLine(BytecodeViewer.settingsName, "6", false); + else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1Krakatau.getModel())) + DiskWriter.writeNewLine(BytecodeViewer.settingsName, "7", false); + else if(BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1KrakatauEditable.getModel())) + DiskWriter.writeNewLine(BytecodeViewer.settingsName, "8", false); if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2None.getModel())) DiskWriter.writeNewLine(BytecodeViewer.settingsName, "0", false); @@ -126,6 +130,10 @@ else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false); else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2Smali.getModel())) DiskWriter.writeNewLine(BytecodeViewer.settingsName, "6", false); + else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2Krakatau.getModel())) + DiskWriter.writeNewLine(BytecodeViewer.settingsName, "7", false); + else if(BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2KrakatauEditable.getModel())) + DiskWriter.writeNewLine(BytecodeViewer.settingsName, "8", false); if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3None.getModel())) DiskWriter.writeNewLine(BytecodeViewer.settingsName, "0", false); @@ -141,12 +149,18 @@ else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel DiskWriter.writeNewLine(BytecodeViewer.settingsName, "5", false); else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3Smali.getModel())) DiskWriter.writeNewLine(BytecodeViewer.settingsName, "6", false); + else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3Krakatau.getModel())) + DiskWriter.writeNewLine(BytecodeViewer.settingsName, "7", false); + else if(BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3KrakatauEditable.getModel())) + DiskWriter.writeNewLine(BytecodeViewer.settingsName, "8", false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.refreshOnChange.isSelected()), false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.isMaximized), false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.autoCompileSmali.isSelected()), false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, String.valueOf(BytecodeViewer.viewer.autoCompileOnRefresh.isSelected()), false); DiskWriter.writeNewLine(BytecodeViewer.settingsName, BytecodeViewer.lastDirectory, false); + DiskWriter.writeNewLine(BytecodeViewer.settingsName, BytecodeViewer.python, false); + DiskWriter.writeNewLine(BytecodeViewer.settingsName, BytecodeViewer.rt, false); } catch(Exception e) { new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); } @@ -249,6 +263,10 @@ else if(decompiler == 5) BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1Hexcode.getModel(), true); else if(decompiler == 6) BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1Smali.getModel(), true); + else if(decompiler == 7) + BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1Krakatau.getModel(), true); + else if(decompiler == 8) + BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1KrakatauEditable.getModel(), true); decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 82, false)); if(decompiler == 0) @@ -265,6 +283,10 @@ else if(decompiler == 5) BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2Hexcode.getModel(), true); else if(decompiler == 6) BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2Smali.getModel(), true); + else if(decompiler == 7) + BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2Krakatau.getModel(), true); + else if(decompiler == 8) + BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2KrakatauEditable.getModel(), true); decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 83, false)); if(decompiler == 0) @@ -281,6 +303,10 @@ else if(decompiler == 5) BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3Hexcode.getModel(), true); else if(decompiler == 6) BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3Smali.getModel(), true); + else if(decompiler == 7) + BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3Krakatau.getModel(), true); + else if(decompiler == 8) + BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3KrakatauEditable.getModel(), true); BytecodeViewer.viewer.refreshOnChange.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 84, false))); @@ -292,6 +318,8 @@ else if(decompiler == 6) BytecodeViewer.viewer.autoCompileSmali.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 86, false))); BytecodeViewer.viewer.autoCompileOnRefresh.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 87, false))); BytecodeViewer.lastDirectory = DiskReader.loadString(BytecodeViewer.settingsName, 88, false); + BytecodeViewer.python = DiskReader.loadString(BytecodeViewer.settingsName, 89, false); + BytecodeViewer.rt = DiskReader.loadString(BytecodeViewer.settingsName, 90, false); } catch(Exception e) { //ignore because errors are expected, first start up and outdated settings. } diff --git a/src/the/bytecode/club/bytecodeviewer/ZipUtils.java b/src/the/bytecode/club/bytecodeviewer/ZipUtils.java index e8d692fe2..778b998ab 100644 --- a/src/the/bytecode/club/bytecodeviewer/ZipUtils.java +++ b/src/the/bytecode/club/bytecodeviewer/ZipUtils.java @@ -279,4 +279,47 @@ public static void zipFile(File inputFile, File outputZip) { e.printStackTrace(); } } + + public static void zipFolder(String srcFolder, String destZipFile, String ignore) throws Exception { + ZipOutputStream zip = null; + FileOutputStream fileWriter = null; + + fileWriter = new FileOutputStream(destZipFile); + zip = new ZipOutputStream(fileWriter); + + addFolderToZip("", srcFolder, zip, ignore); + zip.flush(); + zip.close(); + } + + public static void addFileToZip(String path, String srcFile, ZipOutputStream zip, String ignore) + throws Exception { + + File folder = new File(srcFile); + if (folder.isDirectory()) { + addFolderToZip(path, srcFile, zip, ignore); + } else { + byte[] buf = new byte[1024]; + int len; + FileInputStream in = new FileInputStream(srcFile); + zip.putNextEntry(new ZipEntry(path.replace(ignore, "BCV_Krakatau") + "/" + folder.getName())); + while ((len = in.read(buf)) > 0) { + zip.write(buf, 0, len); + } + in.close(); + } + } + + public static void addFolderToZip(String path, String srcFolder, ZipOutputStream zip, String ignore) + throws Exception { + File folder = new File(srcFolder); + + for (String fileName : folder.list()) { + if (path.equals("")) { + addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip, ignore); + } else { + addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip, ignore); + } + } + } } \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/api/BytecodeViewer.java b/src/the/bytecode/club/bytecodeviewer/api/BytecodeViewer.java index 8d41e0191..f0ad427b9 100644 --- a/src/the/bytecode/club/bytecodeviewer/api/BytecodeViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/api/BytecodeViewer.java @@ -17,26 +17,21 @@ public class BytecodeViewer { - /** - * This is used to define a global loader. - */ - private static ClassNodeLoader loader = new ClassNodeLoader(); - /** * Grab the loader instance * * @return */ public static ClassNodeLoader getClassNodeLoader() { - return loader; + return the.bytecode.club.bytecodeviewer.BytecodeViewer.loader; } /** * Creates a new instance of the ClassNode loader. */ public static void createNewClassNodeLoaderInstance() { - loader.clear(); - loader = new ClassNodeLoader(); + the.bytecode.club.bytecodeviewer.BytecodeViewer.loader.clear(); + the.bytecode.club.bytecodeviewer.BytecodeViewer.loader = new ClassNodeLoader(); } /** diff --git a/src/the/bytecode/club/bytecodeviewer/api/ExceptionUI.java b/src/the/bytecode/club/bytecodeviewer/api/ExceptionUI.java index 94cb47889..d8e6859f4 100644 --- a/src/the/bytecode/club/bytecodeviewer/api/ExceptionUI.java +++ b/src/the/bytecode/club/bytecodeviewer/api/ExceptionUI.java @@ -30,6 +30,14 @@ public class ExceptionUI extends JFrame { public ExceptionUI(Exception e) { setup(e, "@Konloch - konloch@gmail.com"); } + + /** + * @param e + * The exception to be shown + */ + public ExceptionUI(String e) { + setup(e, "@Konloch - konloch@gmail.com"); + } /** * @param e @@ -41,6 +49,16 @@ public ExceptionUI(Exception e, String author) { setup(e, author); } + /** + * @param e + * The exception to be shown + * @param author + * the author of the plugin throwing this exception. + */ + public ExceptionUI(String e, String author) { + setup(e, author); + } + private void setup(Exception e, String author) { this.setIconImages(BytecodeViewer.iconList); @@ -62,6 +80,23 @@ private void setup(Exception e, String author) { this.setLocationRelativeTo(null); this.setVisible(true); } + + private void setup(String e, String author) { + this.setIconImages(BytecodeViewer.iconList); + setSize(new Dimension(600, 400)); + setTitle("Bytecode Viewer " + BytecodeViewer.version + + " - Stack Trace - Send this to " + author); + getContentPane().setLayout(new CardLayout(0, 0)); + + JTextArea txtrBytecodeViewerIs = new JTextArea(); + txtrBytecodeViewerIs.setDisabledTextColor(Color.BLACK); + txtrBytecodeViewerIs.setWrapStyleWord(true); + getContentPane().add(new JScrollPane(txtrBytecodeViewerIs), + "name_140466576080695"); + txtrBytecodeViewerIs.setText(e); + this.setLocationRelativeTo(null); + this.setVisible(true); + } private static final long serialVersionUID = -5230501978224926296L; diff --git a/src/the/bytecode/club/bytecodeviewer/compilers/KrakatauAssembler.java b/src/the/bytecode/club/bytecodeviewer/compilers/KrakatauAssembler.java new file mode 100644 index 000000000..40d4f3941 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/compilers/KrakatauAssembler.java @@ -0,0 +1,91 @@ +package the.bytecode.club.bytecodeviewer.compilers; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; + +import me.konloch.kontainer.io.DiskWriter; +import the.bytecode.club.bytecodeviewer.BytecodeViewer; +import the.bytecode.club.bytecodeviewer.JarUtils; +import the.bytecode.club.bytecodeviewer.MiscUtils; + +/** + * Krakatau Java assembler, requires Python 2.7 + * + * @author Konloch + * + */ +public class KrakatauAssembler { + + public static byte[] compile(String contents, String name) { + if(BytecodeViewer.python.equals("")) { + BytecodeViewer.showMessage("You need to set your Python 2.7 executable path."); + BytecodeViewer.viewer.pythonC(); + } + + String origName = name; + name = MiscUtils.randomString(20); + + System.out.println("run"); + File tempD = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + MiscUtils.randomString(32) + BytecodeViewer.fs); + tempD.mkdir(); + + File tempJ = new File(tempD.getAbsolutePath() + BytecodeViewer.fs+name+".j"); + DiskWriter.replaceFile(tempJ.getAbsolutePath(), contents, true); + System.out.println("ran"); + + final File tempDirectory = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + MiscUtils.randomString(32) + BytecodeViewer.fs); + tempDirectory.mkdir(); + final File tempJar = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp"+MiscUtils.randomString(32)+".jar"); + JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath()); + + BytecodeViewer.sm.blocking = false; + String log = ""; + try { + ProcessBuilder pb = new ProcessBuilder( + BytecodeViewer.python, + BytecodeViewer.krakatauWorkingDirectory + BytecodeViewer.fs + "assemble.py", + "-out", + tempDirectory.getAbsolutePath(), + tempJ.getAbsolutePath() + ); + + Process process = pb.start(); + + //Read out dir output + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + while ((line = br.readLine()) != null) { + log += BytecodeViewer.nl + line; + } + + log += BytecodeViewer.nl+BytecodeViewer.nl+"Error:"+BytecodeViewer.nl+BytecodeViewer.nl; + is = process.getErrorStream(); + isr = new InputStreamReader(is); + br = new BufferedReader(isr); + while ((line = br.readLine()) != null) { + log += BytecodeViewer.nl + line; + } + + int exitValue = process.waitFor(); + log += BytecodeViewer.nl+BytecodeViewer.nl+"Exit Value is " + exitValue; + System.out.println(log); + + byte[] b = org.apache.commons.io.FileUtils.readFileToByteArray(new File(tempDirectory.getAbsolutePath() + BytecodeViewer.fs + origName + ".class")); + tempDirectory.delete(); + tempJar.delete(); + return b; + } catch(Exception e) { + e.printStackTrace(); + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(log); + } + + BytecodeViewer.sm.blocking = true; + + return null; + } + +} diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/Smali.java b/src/the/bytecode/club/bytecodeviewer/compilers/SmaliAssembler.java similarity index 51% rename from src/the/bytecode/club/bytecodeviewer/decompilers/Smali.java rename to src/the/bytecode/club/bytecodeviewer/compilers/SmaliAssembler.java index 8ab1a3f04..d7cb5ee87 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/Smali.java +++ b/src/the/bytecode/club/bytecodeviewer/compilers/SmaliAssembler.java @@ -1,80 +1,19 @@ -package the.bytecode.club.bytecodeviewer.decompilers; +package the.bytecode.club.bytecodeviewer.compilers; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import me.konloch.kontainer.io.DiskReader; import me.konloch.kontainer.io.DiskWriter; - -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.ClassNode; - import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.Dex2Jar; +import the.bytecode.club.bytecodeviewer.MiscUtils; import the.bytecode.club.bytecodeviewer.ZipUtils; -public class Smali { - - public static String decompileClassNode(ClassNode cn) { - final ClassWriter cw = new ClassWriter(0); - cn.accept(cw); - - String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs - + "temp"; - - String start = JavaDecompiler.getUniqueName(fileStart, ".class"); - - final File tempClass = new File(start + ".class"); - final File tempZip = new File(start + ".jar"); - final File tempDex = new File(start + ".dex"); - final File tempSmali = new File(start + "-smali"); //output directory - - try { - final FileOutputStream fos = new FileOutputStream(tempClass); - - fos.write(cw.toByteArray()); - - fos.close(); - } catch (final IOException e) { - new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); - } - - ZipUtils.zipFile(tempClass, tempZip); - Dex2Jar.saveAsDex(tempZip, tempDex); - try { - org.jf.baksmali.main.main(new String[]{"-o", tempSmali.getAbsolutePath(), "-x", tempDex.getAbsolutePath()}); - } catch (Exception e) { - new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); - } - - File outputSmali = null; - - boolean found = false; - File current = tempSmali; - while(!found) { - File f = current.listFiles()[0]; - if(f.isDirectory()) - current = f; - else { - outputSmali = f; - found = true; - } - - } - try { - return DiskReader.loadAsString(outputSmali.getAbsolutePath()); - } catch (Exception e) { - new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); - } - - return null; - } +public class SmaliAssembler { public static byte[] compile(String contents) { String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp"; - int fileNumber = JavaDecompiler.getClassNumber(fileStart, ".dex"); + int fileNumber = MiscUtils.getClassNumber(fileStart, ".dex"); final File tempSmaliFolder = new File(fileStart + fileNumber + "-smalifolder"+BytecodeViewer.fs); tempSmaliFolder.mkdir(); diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/CFRDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/CFRDecompiler.java index ce7ecf6d9..7ee3e65e1 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/CFRDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/CFRDecompiler.java @@ -23,6 +23,7 @@ import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.JarUtils; +import the.bytecode.club.bytecodeviewer.MiscUtils; /** * @@ -43,10 +44,9 @@ public String decompileClassNode(ClassNode cn) { final ClassWriter cw = new ClassWriter(0); cn.accept(cw); - String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs - + "temp"; - - final File tempClass = new File(getUniqueName(fileStart, ".class") + ".class"); + String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs; + + final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class"); try { final FileOutputStream fos = new FileOutputStream(tempClass); @@ -96,12 +96,12 @@ public String findFile(File[] fA) { e.printStackTrace(); String exception = "Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); - return "CFR error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com"+BytecodeViewer.nl+BytecodeViewer.nl+"Suggestest Fix: Click refresh class, if it fails again try another decompiler."+BytecodeViewer.nl+BytecodeViewer.nl+exception; + return "CFR error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com"+BytecodeViewer.nl+BytecodeViewer.nl+"Suggested Fix: Click refresh class, if it fails again try another decompiler."+BytecodeViewer.nl+BytecodeViewer.nl+exception; } return s; } } - return "CFR error!"+BytecodeViewer.nl+BytecodeViewer.nl+"Suggestest Fix: Click refresh class, if it fails again try another decompiler."; + return "CFR error!"+BytecodeViewer.nl+BytecodeViewer.nl+"Suggested Fix: Click refresh class, if it fails again try another decompiler."; } public String[] generateMainMethod(String filePath, String outputPath) { @@ -230,8 +230,7 @@ public void decompileToZip(String zipName) { JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), tempZip.getAbsolutePath()); - String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs - + "temp"; + String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs; String fuckery = fuckery(fileStart); diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/FernFlowerDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/FernFlowerDecompiler.java index de4e3115e..28abf21bc 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/FernFlowerDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/FernFlowerDecompiler.java @@ -14,6 +14,7 @@ import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.JarUtils; +import the.bytecode.club.bytecodeviewer.MiscUtils; /** * A complete FernFlower launcher with all the options (except 2) @@ -63,7 +64,7 @@ public String decompileClassNode(final ClassNode cn) { final ClassWriter cw = new ClassWriter(0); cn.accept(cw); - String start = getUniqueName("", ".class"); + String start = MiscUtils.getUniqueName("", ".class"); final File tempClass = new File(start + ".class"); @@ -104,7 +105,7 @@ public String decompileClassNode(final ClassNode cn) { exception += BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); } } - return "FernFlower error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com"+BytecodeViewer.nl+BytecodeViewer.nl+"Suggestest Fix: Click refresh class, if it fails again try another decompiler."+BytecodeViewer.nl+BytecodeViewer.nl+exception; + return "FernFlower error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com"+BytecodeViewer.nl+BytecodeViewer.nl+"Suggested Fix: Click refresh class, if it fails again try another decompiler."+BytecodeViewer.nl+BytecodeViewer.nl+exception; } private String[] generateMainMethod(String className, String folder) { diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/JavaDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/JavaDecompiler.java index f7ab15413..9b9c5d68e 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/JavaDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/JavaDecompiler.java @@ -1,11 +1,7 @@ package the.bytecode.club.bytecodeviewer.decompilers; -import java.io.File; - import org.objectweb.asm.tree.ClassNode; -import the.bytecode.club.bytecodeviewer.MiscUtils; - /** * * @author Konloch @@ -19,33 +15,4 @@ public abstract class JavaDecompiler { public abstract void decompileToZip(String zipName); public abstract void decompileToClass(String className, String classNameSaved); - - public static String getUniqueName(String start, String ext) { - String s = null; - boolean b = true; - File f = null; - String m = null; - while (b) { - m = MiscUtils.randomString(32); - f = new File(start + m + ext); - if (!f.exists()) { - s = start + m; - b = false; - } - } - return s; - } - - public static int getClassNumber(String start, String ext) { - boolean b = true; - int i = 0; - while (b) { - File tempF = new File(start + i + ext); - if (!tempF.exists()) - b = false; - else - i++; - } - return i; - } } diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/KrakatauDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/KrakatauDecompiler.java new file mode 100644 index 000000000..b5774694a --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/KrakatauDecompiler.java @@ -0,0 +1,219 @@ +package the.bytecode.club.bytecodeviewer.decompilers; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; + +import me.konloch.kontainer.io.DiskReader; + +import org.objectweb.asm.tree.ClassNode; + +import the.bytecode.club.bytecodeviewer.BytecodeViewer; +import the.bytecode.club.bytecodeviewer.JarUtils; +import the.bytecode.club.bytecodeviewer.MiscUtils; +import the.bytecode.club.bytecodeviewer.ZipUtils; + +/** + * Krakatau Java Decompiler, requires Python 2.7 + * + * @author Konloch + * + */ + +public class KrakatauDecompiler extends JavaDecompiler { + + public String decompileClassNode(ClassNode cn) { + if(BytecodeViewer.python.equals("")) { + BytecodeViewer.showMessage("You need to set your Python 2.7 executable path."); + BytecodeViewer.viewer.pythonC(); + } + if(BytecodeViewer.rt.equals("")) { + BytecodeViewer.showMessage("You need to set your JRE RT Library.\r\n(C:\\Program Files (x86)\\Java\\jre7\\lib\\rt.jar)"); + BytecodeViewer.viewer.rtC(); + } + String s = "Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + "Please send this to konloch@gmail.com. " + BytecodeViewer.nl + BytecodeViewer.nl; + + final File tempDirectory = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + MiscUtils.randomString(32) + BytecodeViewer.fs); + tempDirectory.mkdir(); + final File tempJar = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp"+MiscUtils.randomString(32)+".jar"); + while(tempJar.exists()) + tempJar.delete(); + JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath()); + + BytecodeViewer.sm.blocking = false; + try { + ProcessBuilder pb = new ProcessBuilder( + BytecodeViewer.python, + BytecodeViewer.krakatauWorkingDirectory + BytecodeViewer.fs + "decompile.py", + "-nauto", + "-path", + BytecodeViewer.rt+";"+tempJar.getAbsolutePath(), + "-out", + tempDirectory.getAbsolutePath(), + cn.name+".class" + ); + + Process process = pb.start(); + + //Read out dir output + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String log = "Process:"+BytecodeViewer.nl+BytecodeViewer.nl; + String line; + while ((line = br.readLine()) != null) { + log += BytecodeViewer.nl + line; + } + + log += BytecodeViewer.nl+BytecodeViewer.nl+"Error:"+BytecodeViewer.nl+BytecodeViewer.nl; + is = process.getErrorStream(); + isr = new InputStreamReader(is); + br = new BufferedReader(isr); + while ((line = br.readLine()) != null) { + log += BytecodeViewer.nl + line; + } + + int exitValue = process.waitFor(); + log += BytecodeViewer.nl+BytecodeViewer.nl+"Exit Value is " + exitValue; + s = log; + + //if the motherfucker failed this'll fail, aka wont set. + s = DiskReader.loadAsString(tempDirectory.getAbsolutePath() + BytecodeViewer.fs + cn.name + ".java"); + tempDirectory.delete(); + tempJar.delete(); + } catch(Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + e.printStackTrace(); + s += BytecodeViewer.nl+"Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); + } + + BytecodeViewer.sm.blocking = true; + + return s; + } + + public void decompileToZip(String zipName) { + if(BytecodeViewer.python.equals("")) { + BytecodeViewer.showMessage("You need to set your Python 2.7 executable path."); + BytecodeViewer.viewer.pythonC(); + } + if(BytecodeViewer.rt.equals("")) { + BytecodeViewer.showMessage("You need to set your JRE RT Library.\r\n(C:\\Program Files (x86)\\Java\\jre7\\lib\\rt.jar)"); + BytecodeViewer.viewer.rtC(); + } + + String ran = MiscUtils.randomString(32); + final File tempDirectory = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + ran + BytecodeViewer.fs); + tempDirectory.mkdir(); + final File tempJar = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp.jar"); + JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath()); + + BytecodeViewer.sm.blocking = false; + try { + ProcessBuilder pb = new ProcessBuilder( + BytecodeViewer.python, + BytecodeViewer.krakatauWorkingDirectory + BytecodeViewer.fs + "decompile.py", + "-nauto", + "-path", + BytecodeViewer.rt+";"+tempJar.getAbsolutePath(), + "-out", + tempDirectory.getAbsolutePath(), + tempJar.getAbsolutePath() + ); + + Process process = pb.start(); + + //Read out dir output + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + while ((line = br.readLine()) != null) { + System.out.println(line); + } + + is = process.getErrorStream(); + isr = new InputStreamReader(is); + br = new BufferedReader(isr); + while ((line = br.readLine()) != null) { + System.out.println(line); + } + + int exitValue = process.waitFor(); + System.out.println("Exit Value is " + exitValue); + + // ZipUtils.zipDirectory(tempDirectory, new File(zipName)); + ZipUtils.zipFolder(tempDirectory.getAbsolutePath(), zipName, ran); + + //tempDirectory.delete(); + tempJar.delete(); + } catch(Exception e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + + BytecodeViewer.sm.blocking = true; + } + + public void decompileToClass(String className, String classNameSaved) { + if(BytecodeViewer.python.equals("")) { + BytecodeViewer.showMessage("You need to set your Python 2.7 executable path."); + BytecodeViewer.viewer.pythonC(); + } + if(BytecodeViewer.rt.equals("")) { + BytecodeViewer.showMessage("You need to set your JRE RT Library.\r\n(C:\\Program Files (x86)\\Java\\jre7\\lib\\rt.jar)"); + BytecodeViewer.viewer.rtC(); + } + + final File tempDirectory = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + MiscUtils.randomString(32) + BytecodeViewer.fs); + tempDirectory.mkdir(); + final File tempJar = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp.jar"); + JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath()); + + BytecodeViewer.sm.blocking = false; + try { + ProcessBuilder pb = new ProcessBuilder( + BytecodeViewer.python, + BytecodeViewer.krakatauWorkingDirectory + BytecodeViewer.fs + "decompile.py", + "-nauto", + "-path", + BytecodeViewer.rt+";"+tempJar.getAbsolutePath(), + "-out", + tempDirectory.getAbsolutePath(), + className+".class" + ); + + Process process = pb.start(); + + //Read out dir output + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + while ((line = br.readLine()) != null) { + System.out.println(line); + } + + is = process.getErrorStream(); + isr = new InputStreamReader(is); + br = new BufferedReader(isr); + while ((line = br.readLine()) != null) { + System.out.println(line); + } + + int exitValue = process.waitFor(); + System.out.println("Exit Value is " + exitValue); + + File f = new File(tempDirectory.getAbsolutePath() + BytecodeViewer.fs + className + ".java"); + f.renameTo(new File(classNameSaved)); + tempDirectory.delete(); + tempJar.delete(); + } catch(Exception e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + } + +} diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/KrakatauDisassembler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/KrakatauDisassembler.java new file mode 100644 index 000000000..e8af4e361 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/KrakatauDisassembler.java @@ -0,0 +1,91 @@ +package the.bytecode.club.bytecodeviewer.decompilers; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; + +import me.konloch.kontainer.io.DiskReader; + +import org.objectweb.asm.tree.ClassNode; + +import the.bytecode.club.bytecodeviewer.BytecodeViewer; +import the.bytecode.club.bytecodeviewer.JarUtils; +import the.bytecode.club.bytecodeviewer.MiscUtils; + +/** + * Krakatau Java Disassembler, requires Python 2.7 + * + * @author Konloch + * + */ + +public class KrakatauDisassembler { + + public static String decompileClassNode(ClassNode cn) { + if(BytecodeViewer.python.equals("")) { + BytecodeViewer.showMessage("You need to set your Python 2.7 executable path."); + BytecodeViewer.viewer.pythonC(); + } + String s = "Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + "Please send this to konloch@gmail.com. " + BytecodeViewer.nl + BytecodeViewer.nl; + + final File tempDirectory = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + MiscUtils.randomString(32) + BytecodeViewer.fs); + tempDirectory.mkdir(); + final File tempJar = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp"+MiscUtils.randomString(32)+".jar"); + JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath()); + + BytecodeViewer.sm.blocking = false; + try { + ProcessBuilder pb = new ProcessBuilder( + BytecodeViewer.python, + BytecodeViewer.krakatauWorkingDirectory + BytecodeViewer.fs + "disassemble.py", + "-path", + tempJar.getAbsolutePath(), + "-out", + tempDirectory.getAbsolutePath(), + cn.name+".class" + ); + + Process process = pb.start(); + + //Read out dir output + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String log = "Process:"+BytecodeViewer.nl+BytecodeViewer.nl; + String line; + while ((line = br.readLine()) != null) { + log += BytecodeViewer.nl + line; + } + + log += BytecodeViewer.nl+BytecodeViewer.nl+"Error:"+BytecodeViewer.nl+BytecodeViewer.nl; + is = process.getErrorStream(); + isr = new InputStreamReader(is); + br = new BufferedReader(isr); + while ((line = br.readLine()) != null) { + log += BytecodeViewer.nl + line; + } + + int exitValue = process.waitFor(); + log += BytecodeViewer.nl+BytecodeViewer.nl+"Exit Value is " + exitValue; + s = log; + + //if the motherfucker failed this'll fail, aka wont set. + s = DiskReader.loadAsString(tempDirectory.getAbsolutePath() + BytecodeViewer.fs + cn.name + ".j"); + tempDirectory.delete(); + tempJar.delete(); + } catch(Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + e.printStackTrace(); + s += BytecodeViewer.nl+"Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); + } + + BytecodeViewer.sm.blocking = true; + + return s; + } + +} diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/ProcyonDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/ProcyonDecompiler.java index 0a308dc2c..151822af6 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/ProcyonDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/ProcyonDecompiler.java @@ -39,6 +39,7 @@ import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.JarUtils; +import the.bytecode.club.bytecodeviewer.MiscUtils; /** * @@ -99,7 +100,7 @@ public String decompileClassNode(ClassNode cn) { String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp"; - final File tempClass = new File(getUniqueName(fileStart, ".class") + ".class"); + final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class"); try { final FileOutputStream fos = new FileOutputStream(tempClass); @@ -139,7 +140,7 @@ public String decompileClassNode(ClassNode cn) { exception = "Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); } - return "Procyon error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com"+BytecodeViewer.nl+BytecodeViewer.nl+"Suggestest Fix: Click refresh class, if it fails again try another decompiler."+BytecodeViewer.nl+BytecodeViewer.nl+exception; + return "Procyon error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com"+BytecodeViewer.nl+BytecodeViewer.nl+"Suggested Fix: Click refresh class, if it fails again try another decompiler."+BytecodeViewer.nl+BytecodeViewer.nl+exception; } @Override diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/SmaliDisassembler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/SmaliDisassembler.java new file mode 100644 index 000000000..8966cbc59 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/SmaliDisassembler.java @@ -0,0 +1,74 @@ +package the.bytecode.club.bytecodeviewer.decompilers; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import me.konloch.kontainer.io.DiskReader; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.tree.ClassNode; + +import the.bytecode.club.bytecodeviewer.BytecodeViewer; +import the.bytecode.club.bytecodeviewer.Dex2Jar; +import the.bytecode.club.bytecodeviewer.MiscUtils; +import the.bytecode.club.bytecodeviewer.ZipUtils; + +public class SmaliDisassembler { + + public static String decompileClassNode(ClassNode cn) { + final ClassWriter cw = new ClassWriter(0); + cn.accept(cw); + + String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs + + "temp"; + + String start = MiscUtils.getUniqueName(fileStart, ".class"); + + final File tempClass = new File(start + ".class"); + final File tempZip = new File(start + ".jar"); + final File tempDex = new File(start + ".dex"); + final File tempSmali = new File(start + "-smali"); //output directory + + try { + final FileOutputStream fos = new FileOutputStream(tempClass); + + fos.write(cw.toByteArray()); + + fos.close(); + } catch (final IOException e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + + ZipUtils.zipFile(tempClass, tempZip); + Dex2Jar.saveAsDex(tempZip, tempDex); + try { + org.jf.baksmali.main.main(new String[]{"-o", tempSmali.getAbsolutePath(), "-x", tempDex.getAbsolutePath()}); + } catch (Exception e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + + File outputSmali = null; + + boolean found = false; + File current = tempSmali; + while(!found) { + File f = current.listFiles()[0]; + if(f.isDirectory()) + current = f; + else { + outputSmali = f; + found = true; + } + + } + try { + return DiskReader.loadAsString(outputSmali.getAbsolutePath()); + } catch (Exception e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + + return null; + } + +} diff --git a/src/the/bytecode/club/bytecodeviewer/gui/AboutWindow.java b/src/the/bytecode/club/bytecodeviewer/gui/AboutWindow.java index 2da4fd09a..93bc1ce36 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/AboutWindow.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/AboutWindow.java @@ -14,7 +14,7 @@ public class AboutWindow extends JFrame { public AboutWindow() { this.setIconImages(BytecodeViewer.iconList); - setSize(new Dimension(446, 374)); + setSize(new Dimension(446, 434)); setType(Type.UTILITY); setTitle("Bytecode Viewer - About"); getContentPane().setLayout(new CardLayout(0, 0)); @@ -24,9 +24,7 @@ public AboutWindow() { txtrBytecodeViewerIs.setWrapStyleWord(true); getContentPane().add(txtrBytecodeViewerIs, "name_140466526081695"); txtrBytecodeViewerIs - .setText("Bytecode Viewer "+BytecodeViewer.version+" is an open source program\r\ndeveloped by Konloch (konloch@gmail.com)\r\nDir: " - + BytecodeViewer.getBCVDirectory() - + "\r\n\r\nIt uses code from the following:\r\n J-RET by WaterWolf\r\n JHexPane by Sam Koivu\r\n RSyntaxTextArea by Bobbylight\r\n Commons IO by Apache\r\n ASM by OW2\r\n CFIDE by Bibl\r\n FernFlower by Stiver\r\n Procyon by Mstrobel\r\n CFR by Lee Benfield\r\n\r\nIf you're interested in Java Reverse\r\nEngineering, join The Bytecode Club\r\nhttps://the.bytecode.club"); + .setText("Bytecode Viewer "+BytecodeViewer.version+" is an open source program\r\ndeveloped by Konloch (konloch@gmail.com)\r\nDir: C:\\Users\\null\\.Bytecode-Viewer\r\n\r\nIt uses code from the following:\r\n J-RET by WaterWolf\r\n JHexPane by Sam Koivu\r\n RSynaxPane by Robert Futrell\r\n Commons IO by Apache\r\n ASM by OW2\r\n FernFlower by Stiver\r\n Procyon by Mstrobel\r\n CFR by Lee Benfield\r\n CFIDE by Bibl\r\n Smali by JesusFreke\r\n Dex2Jar by pxb1..?\r\n Krakatau by Storyyeller\r\n\r\nIf you're interested in Java Reverse\r\nEngineering, join The Bytecode Club\r\nhttps://the.bytecode.club"); txtrBytecodeViewerIs.setEnabled(false); this.setResizable(false); this.setLocationRelativeTo(null); diff --git a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java index b4ff90bb7..235d46295 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java @@ -47,8 +47,11 @@ import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.decompilers.CFRDecompiler; import the.bytecode.club.bytecodeviewer.decompilers.FernFlowerDecompiler; +import the.bytecode.club.bytecodeviewer.decompilers.JavaDecompiler; +import the.bytecode.club.bytecodeviewer.decompilers.KrakatauDisassembler; +import the.bytecode.club.bytecodeviewer.decompilers.KrakatauDecompiler; import the.bytecode.club.bytecodeviewer.decompilers.ProcyonDecompiler; -import the.bytecode.club.bytecodeviewer.decompilers.Smali; +import the.bytecode.club.bytecodeviewer.decompilers.SmaliDisassembler; import the.bytecode.club.bytecodeviewer.decompilers.bytecode.ClassNodeDecompiler; /** @@ -118,6 +121,9 @@ public void hierarchyChanged(HierarchyEvent e) { public RSyntaxTextArea smali1 = null; public RSyntaxTextArea smali2 = null; public RSyntaxTextArea smali3 = null; + public RSyntaxTextArea krakatau1 = null; + public RSyntaxTextArea krakatau2 = null; + public RSyntaxTextArea krakatau3 = null; /** * This was really interesting to write. @@ -453,9 +459,10 @@ else if (pane1 == 0 && pane2 == 0) } } - static FernFlowerDecompiler ff_dc = new FernFlowerDecompiler(); - static ProcyonDecompiler proc_dc = new ProcyonDecompiler(); - static CFRDecompiler cfr_dc = new CFRDecompiler(); + static JavaDecompiler ff_dc = new FernFlowerDecompiler(); + static JavaDecompiler proc_dc = new ProcyonDecompiler(); + static JavaDecompiler cfr_dc = new CFRDecompiler(); + static JavaDecompiler krak_dc = new KrakatauDecompiler(); PaneUpdaterThread t; public void startPaneUpdater(final JButton button) { @@ -481,6 +488,12 @@ else if (BytecodeViewer.viewer.panelGroup1 else if (BytecodeViewer.viewer.panelGroup1 .isSelected(BytecodeViewer.viewer.panel1Smali.getModel())) pane1 = 6; + else if (BytecodeViewer.viewer.panelGroup1 + .isSelected(BytecodeViewer.viewer.panel1Krakatau.getModel())) + pane1 = 7; + else if (BytecodeViewer.viewer.panelGroup1 + .isSelected(BytecodeViewer.viewer.panel1KrakatauEditable.getModel())) + pane1 = 8; if (BytecodeViewer.viewer.panelGroup2 .isSelected(BytecodeViewer.viewer.panel2None.getModel())) @@ -503,6 +516,12 @@ else if (BytecodeViewer.viewer.panelGroup2 else if (BytecodeViewer.viewer.panelGroup2 .isSelected(BytecodeViewer.viewer.panel2Smali.getModel())) pane2 = 6; + else if (BytecodeViewer.viewer.panelGroup2 + .isSelected(BytecodeViewer.viewer.panel2Krakatau.getModel())) + pane2 = 7; + else if (BytecodeViewer.viewer.panelGroup2 + .isSelected(BytecodeViewer.viewer.panel2KrakatauEditable.getModel())) + pane2 = 8; if (BytecodeViewer.viewer.panelGroup3 .isSelected(BytecodeViewer.viewer.panel3None.getModel())) @@ -525,6 +544,12 @@ else if (BytecodeViewer.viewer.panelGroup3 else if (BytecodeViewer.viewer.panelGroup3 .isSelected(BytecodeViewer.viewer.panel3Smali.getModel())) pane3 = 6; + else if (BytecodeViewer.viewer.panelGroup3 + .isSelected(BytecodeViewer.viewer.panel3Krakatau.getModel())) + pane3 = 7; + else if (BytecodeViewer.viewer.panelGroup3 + .isSelected(BytecodeViewer.viewer.panel3KrakatauEditable.getModel())) + pane3 = 8; t = new PaneUpdaterThread() { @Override @@ -612,12 +637,41 @@ public void doShit() { bytecodeArea.setAntiAliasingEnabled(true); RTextScrollPane bytecodeSPane = new RTextScrollPane( bytecodeArea); - bytecodeArea.setText(Smali.decompileClassNode(cn)); + bytecodeArea.setText(SmaliDisassembler.decompileClassNode(cn)); bytecodeArea.setCaretPosition(0); smali1 = bytecodeArea; panel1.add(bytecodeSPane); } + if (pane1 == 7) {// krakatau + RSyntaxTextArea bytecodeArea = new RSyntaxTextArea(); + bytecodeArea + .setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + bytecodeArea.setCodeFoldingEnabled(true); + bytecodeArea.setAntiAliasingEnabled(true); + RTextScrollPane bytecodeSPane = new RTextScrollPane( + bytecodeArea); + bytecodeArea.setText(krak_dc.decompileClassNode(cn)); + bytecodeArea.setCaretPosition(0); + panel1.add(bytecodeSPane); + } + + + + if (pane1 == 8) {// kraktau editable + RSyntaxTextArea bytecodeArea = new RSyntaxTextArea(); + bytecodeArea + .setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + bytecodeArea.setCodeFoldingEnabled(true); + bytecodeArea.setAntiAliasingEnabled(true); + RTextScrollPane bytecodeSPane = new RTextScrollPane( + bytecodeArea); + bytecodeArea.setText(KrakatauDisassembler.decompileClassNode(cn)); + bytecodeArea.setCaretPosition(0); + krakatau1 = bytecodeArea; + panel1.add(bytecodeSPane); + } + if (pane2 == 1) { RSyntaxTextArea panelArea = new RSyntaxTextArea(); panelArea @@ -682,12 +736,41 @@ public void doShit() { paneArea.setCodeFoldingEnabled(true); paneArea.setAntiAliasingEnabled(true); RTextScrollPane scrollPane = new RTextScrollPane(paneArea); - paneArea.setText(Smali.decompileClassNode(cn)); + paneArea.setText(SmaliDisassembler.decompileClassNode(cn)); paneArea.setCaretPosition(0); smali2 = paneArea; panel2.add(scrollPane); } + if (pane2 == 7) {// krakatau + RSyntaxTextArea bytecodeArea = new RSyntaxTextArea(); + bytecodeArea + .setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + bytecodeArea.setCodeFoldingEnabled(true); + bytecodeArea.setAntiAliasingEnabled(true); + RTextScrollPane bytecodeSPane = new RTextScrollPane( + bytecodeArea); + bytecodeArea.setText(krak_dc.decompileClassNode(cn)); + bytecodeArea.setCaretPosition(0); + panel2.add(bytecodeSPane); + } + + + + if (pane2 == 8) {// kraktau editable + RSyntaxTextArea bytecodeArea = new RSyntaxTextArea(); + bytecodeArea + .setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + bytecodeArea.setCodeFoldingEnabled(true); + bytecodeArea.setAntiAliasingEnabled(true); + RTextScrollPane bytecodeSPane = new RTextScrollPane( + bytecodeArea); + bytecodeArea.setText(KrakatauDisassembler.decompileClassNode(cn)); + bytecodeArea.setCaretPosition(0); + krakatau2 = bytecodeArea; + panel2.add(bytecodeSPane); + } + if (pane3 == 1) { RSyntaxTextArea panelArea = new RSyntaxTextArea(); panelArea @@ -752,12 +835,41 @@ public void doShit() { paneArea.setCodeFoldingEnabled(true); paneArea.setAntiAliasingEnabled(true); RTextScrollPane scrollPane = new RTextScrollPane(paneArea); - paneArea.setText(Smali.decompileClassNode(cn)); + paneArea.setText(SmaliDisassembler.decompileClassNode(cn)); paneArea.setCaretPosition(0); smali3 = paneArea; panel3.add(scrollPane); } + if (pane3 == 7) {// krakatau + RSyntaxTextArea bytecodeArea = new RSyntaxTextArea(); + bytecodeArea + .setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + bytecodeArea.setCodeFoldingEnabled(true); + bytecodeArea.setAntiAliasingEnabled(true); + RTextScrollPane bytecodeSPane = new RTextScrollPane( + bytecodeArea); + bytecodeArea.setText(krak_dc.decompileClassNode(cn)); + bytecodeArea.setCaretPosition(0); + panel3.add(bytecodeSPane); + } + + + + if (pane3 == 8) {// kraktau editable + RSyntaxTextArea bytecodeArea = new RSyntaxTextArea(); + bytecodeArea + .setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + bytecodeArea.setCodeFoldingEnabled(true); + bytecodeArea.setAntiAliasingEnabled(true); + RTextScrollPane bytecodeSPane = new RTextScrollPane( + bytecodeArea); + bytecodeArea.setText(KrakatauDisassembler.decompileClassNode(cn)); + bytecodeArea.setCaretPosition(0); + krakatau3 = bytecodeArea; + panel3.add(bytecodeSPane); + } + resetDivider(); BytecodeViewer.viewer.setIcon(false); } catch(Exception e) { @@ -771,7 +883,7 @@ public void doShit() { }; t.start(); } - + public Object[] getSmali() { if(smali1 != null) return new Object[]{cn, smali1.getText()}; @@ -782,6 +894,17 @@ public Object[] getSmali() { return null; } + + public Object[] getKrakatau() { + if(krakatau1 != null) + return new Object[]{cn, krakatau1.getText()}; + if(krakatau2 != null) + return new Object[]{cn, krakatau2.getText()}; + if(krakatau3 != null) + return new Object[]{cn, krakatau3.getText()}; + + return null; + } public static class MethodData { public String name, desc; diff --git a/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java b/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java index 763df239f..bf6076edf 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java @@ -35,6 +35,8 @@ import the.bytecode.club.bytecodeviewer.JarUtils; import the.bytecode.club.bytecodeviewer.decompilers.CFRDecompiler; import the.bytecode.club.bytecodeviewer.decompilers.FernFlowerDecompiler; +import the.bytecode.club.bytecodeviewer.decompilers.JavaDecompiler; +import the.bytecode.club.bytecodeviewer.decompilers.KrakatauDecompiler; import the.bytecode.club.bytecodeviewer.decompilers.ProcyonDecompiler; import the.bytecode.club.bytecodeviewer.obfuscators.RenameClasses; import the.bytecode.club.bytecodeviewer.obfuscators.RenameFields; @@ -49,10 +51,41 @@ import javax.swing.JRadioButtonMenuItem; public class MainViewerGUI extends JFrame implements FileChangeNotifier { + + public void pythonC() { + JFileChooser fc = new JFileChooser(); + fc.setFileFilter(new PythonCFileFilter()); + fc.setFileHidingEnabled(false); + fc.setAcceptAllFileFilterUsed(false); + int returnVal = fc.showOpenDialog(BytecodeViewer.viewer); + + if (returnVal == JFileChooser.APPROVE_OPTION) + try { + BytecodeViewer.python = fc.getSelectedFile().getAbsolutePath(); + } catch (Exception e1) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e1); + } + } + + public void rtC() { + JFileChooser fc = new JFileChooser(); + fc.setFileFilter(new RTCFileFilter()); + fc.setFileHidingEnabled(false); + fc.setAcceptAllFileFilterUsed(false); + int returnVal = fc.showOpenDialog(BytecodeViewer.viewer); + + if (returnVal == JFileChooser.APPROVE_OPTION) + try { + BytecodeViewer.rt = fc.getSelectedFile().getAbsolutePath(); + } catch (Exception e1) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e1); + } + } - final FernFlowerDecompiler ff_dc = new FernFlowerDecompiler(); - final ProcyonDecompiler proc_dc = new ProcyonDecompiler(); - final CFRDecompiler cfr_dc = new CFRDecompiler(); + final JavaDecompiler ff_dc = new FernFlowerDecompiler(); + final JavaDecompiler proc_dc = new ProcyonDecompiler(); + final JavaDecompiler cfr_dc = new CFRDecompiler(); + final JavaDecompiler krak_dc = new KrakatauDecompiler(); private static final long serialVersionUID = 1851409230530948543L; public JCheckBoxMenuItem debugHelpers = new JCheckBoxMenuItem( @@ -391,9 +424,18 @@ public boolean dispatchKeyEvent(KeyEvent e) { public final JRadioButtonMenuItem panel1Smali = new JRadioButtonMenuItem("Smali Editable"); public final JRadioButtonMenuItem panel2Smali = new JRadioButtonMenuItem("Smali Editable"); public final JRadioButtonMenuItem panel3Smali = new JRadioButtonMenuItem("Smali Editable"); - public final JCheckBoxMenuItem autoCompileSmali = new JCheckBoxMenuItem("Compile Smali On Save"); - private final JMenuItem mntmNewMenuItem_13 = new JMenuItem("Compile Smali"); - public final JCheckBoxMenuItem autoCompileOnRefresh = new JCheckBoxMenuItem("Compile Smali On Refresh"); + public final JCheckBoxMenuItem autoCompileSmali = new JCheckBoxMenuItem("Compile On Save"); + private final JMenuItem mntmNewMenuItem_13 = new JMenuItem("Compile"); + public final JCheckBoxMenuItem autoCompileOnRefresh = new JCheckBoxMenuItem("Compile On Refresh"); + private final JMenuItem mntmSetPythonDirectory = new JMenuItem("Set Python 2.7 Executable"); + private final JSeparator separator_13 = new JSeparator(); + public final JRadioButtonMenuItem panel1Krakatau = new JRadioButtonMenuItem("Krakatau"); + public final JRadioButtonMenuItem panel1KrakatauEditable = new JRadioButtonMenuItem("Krakatau Editable"); + public final JRadioButtonMenuItem panel2Krakatau = new JRadioButtonMenuItem("Krakatau"); + public final JRadioButtonMenuItem panel2KrakatauEditable = new JRadioButtonMenuItem("Krakatau Editable"); + public final JRadioButtonMenuItem panel3Krakatau = new JRadioButtonMenuItem("Krakatau"); + public final JRadioButtonMenuItem panel3KrakatauEditable = new JRadioButtonMenuItem("Krakatau Editable"); + private final JMenuItem mntmSetJreRt = new JMenuItem("Set JRE RT Library"); public void setIcon(final boolean busy) { SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -439,6 +481,8 @@ public void windowStateChanged(WindowEvent evt) { panelGroup1.add(panel1Bytecode); panelGroup1.add(panel1Smali); panelGroup1.add(panel1Hexcode); + panelGroup1.add(panel1Krakatau); + panelGroup1.add(panel1KrakatauEditable); panelGroup1.setSelected(panel1Proc.getModel(), true);//my one true love panelGroup2.add(panel2None); panelGroup2.add(panel2Fern); @@ -447,6 +491,8 @@ public void windowStateChanged(WindowEvent evt) { panelGroup2.add(panel2Bytecode); panelGroup2.add(panel2Smali); panelGroup2.add(panel2Hexcode); + panelGroup2.add(panel2Krakatau); + panelGroup2.add(panel2KrakatauEditable); panelGroup2.setSelected(panel2Bytecode.getModel(), true); panelGroup3.add(panel3None); panelGroup3.add(panel3Fern); @@ -455,6 +501,8 @@ public void windowStateChanged(WindowEvent evt) { panelGroup3.add(panel3Bytecode); panelGroup3.add(panel3Smali); panelGroup3.add(panel3Hexcode); + panelGroup3.add(panel3Krakatau); + panelGroup3.add(panel3KrakatauEditable); panelGroup3.setSelected(panel3None.getModel(), true); ActionListener listener = new ActionListener() { @@ -547,7 +595,7 @@ public void actionPerformed(ActionEvent arg0) { BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file."); return; } - if(autoCompileSmali.isSelected() && !BytecodeViewer.compileSmali(false)) + if(autoCompileSmali.isSelected() && !BytecodeViewer.compile(false)) return; JFileChooser fc = new JFileChooser(); fc.setFileFilter(new ZipFileFilter()); @@ -603,7 +651,7 @@ public void actionPerformed(ActionEvent e) { BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file."); return; } - if(autoCompileSmali.isSelected() && !BytecodeViewer.compileSmali(false)) + if(autoCompileSmali.isSelected() && !BytecodeViewer.compile(false)) return; JFileChooser fc = new JFileChooser(); fc.setFileFilter(new JarFileFilter()); @@ -643,7 +691,7 @@ public void actionPerformed(ActionEvent e) { }); mntmNewMenuItem_13.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { - BytecodeViewer.compileSmali(true); + BytecodeViewer.compile(true); } }); @@ -656,7 +704,7 @@ public void actionPerformed(ActionEvent arg0) { BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file."); return; } - if(autoCompileSmali.isSelected() && !BytecodeViewer.compileSmali(false)) + if(autoCompileSmali.isSelected() && !BytecodeViewer.compile(false)) return; JFileChooser fc = new JFileChooser(); fc.setFileFilter(new DexFileFilter()); @@ -722,7 +770,7 @@ public void actionPerformed(ActionEvent arg0) { BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file."); return; } - if(autoCompileSmali.isSelected() && !BytecodeViewer.compileSmali(false)) + if(autoCompileSmali.isSelected() && !BytecodeViewer.compile(false)) return; JFileChooser fc = new JFileChooser(); fc.setFileFilter(new ZipFileFilter()); @@ -762,7 +810,7 @@ public void actionPerformed(ActionEvent arg0) { JOptionPane pane = new JOptionPane( "What decompiler will you use?"); Object[] options = new String[] { "Procyon", "CFR", - "Fernflower", "Cancel" }; + "Fernflower", "Krakatau", "Cancel" }; pane.setOptions(options); JDialog dialog = pane.createDialog(BytecodeViewer.viewer, "Bytecode Viewer - Select Decompiler"); @@ -781,8 +829,7 @@ public void run() { proc_dc.decompileToZip(path); BytecodeViewer.viewer.setIcon(false); } catch (Exception e) { - new the.bytecode.club.bytecodeviewer.api.ExceptionUI( - e); + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); } } }; @@ -796,8 +843,7 @@ public void run() { cfr_dc.decompileToZip(path); BytecodeViewer.viewer.setIcon(false); } catch (Exception e) { - new the.bytecode.club.bytecodeviewer.api.ExceptionUI( - e); + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); } } }; @@ -811,13 +857,31 @@ public void run() { ff_dc.decompileToZip(path); BytecodeViewer.viewer.setIcon(false); } catch (Exception e) { - new the.bytecode.club.bytecodeviewer.api.ExceptionUI( - e); + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); } } }; t.start(); } + + if (result == 3) { + Thread t = new Thread() { + @Override + public void run() { + try { + krak_dc.decompileToZip(path); + BytecodeViewer.viewer.setIcon(false); + } catch (Exception e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + } + }; + t.start(); + } + + if(result == 4) { + BytecodeViewer.viewer.setIcon(false); + } } } }); @@ -827,7 +891,7 @@ public void actionPerformed(ActionEvent arg0) { BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file."); return; } - if(autoCompileSmali.isSelected() && !BytecodeViewer.compileSmali(false)) + if(autoCompileSmali.isSelected() && !BytecodeViewer.compile(false)) return; final String s = workPane.getCurrentClass().name; @@ -867,7 +931,7 @@ public void actionPerformed(ActionEvent arg0) { JOptionPane pane = new JOptionPane( "What decompiler will you use?"); Object[] options = new String[] { "Procyon", "CFR", - "Fernflower", "Cancel" }; + "Fernflower", "Krakatau", "Cancel" }; pane.setOptions(options); JDialog dialog = pane.createDialog(BytecodeViewer.viewer, "Bytecode Viewer - Select Decompiler"); @@ -923,6 +987,25 @@ public void run() { }; t.start(); } + if (result == 3) { + Thread t = new Thread() { + @Override + public void run() { + try { + krak_dc.decompileToClass(s,path); + BytecodeViewer.viewer.setIcon(false); + } catch (Exception e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI( + e); + } + } + }; + t.start(); + } + + if(result == 4) { + BytecodeViewer.viewer.setIcon(false); + } } } }); @@ -983,10 +1066,14 @@ public void actionPerformed(ActionEvent arg0) { mnNewMenu_7.add(panel1Fern); + mnNewMenu_7.add(panel1Krakatau); + mnNewMenu_7.add(separator_8); mnNewMenu_7.add(panel1Bytecode); + mnNewMenu_7.add(panel1KrakatauEditable); + mnNewMenu_7.add(panel1Smali); mnNewMenu_7.add(panel1Hexcode); @@ -1003,10 +1090,14 @@ public void actionPerformed(ActionEvent arg0) { mnNewMenu_8.add(panel2Fern); + mnNewMenu_8.add(panel2Krakatau); + mnNewMenu_8.add(separator_10); mnNewMenu_8.add(panel2Bytecode); + mnNewMenu_8.add(panel2KrakatauEditable); + mnNewMenu_8.add(panel2Smali); mnNewMenu_8.add(panel2Hexcode); @@ -1023,7 +1114,11 @@ public void actionPerformed(ActionEvent arg0) { mnNewMenu_9.add(panel3Fern); + mnNewMenu_9.add(panel3Krakatau); + mnNewMenu_9.add(separator_12); + + mnNewMenu_9.add(panel3KrakatauEditable); mnNewMenu_9.add(panel3Bytecode); @@ -1041,6 +1136,22 @@ public void actionPerformed(ActionEvent arg0) { mnSettings.add(refreshOnChange); + mnSettings.add(separator_13); + mntmSetPythonDirectory.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + pythonC(); + } + }); + + mnSettings.add(mntmSetPythonDirectory); + mntmSetJreRt.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + rtC(); + } + }); + + mnSettings.add(mntmSetJreRt); + mnSettings.add(separator_6); mnSettings.add(mnNewMenu_4); @@ -1260,8 +1371,7 @@ public void actionPerformed(ActionEvent arg0) { mntmNewMenuItem_6.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { if (BytecodeViewer.runningObfuscation) { - BytecodeViewer - .showMessage("You're currently running an obfuscation task, wait for this to finish."); + BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish."); return; } new RenameFields().start(); @@ -1281,8 +1391,7 @@ public void actionPerformed(ActionEvent arg0) { mntmNewMenuItem_7.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { if (BytecodeViewer.runningObfuscation) { - BytecodeViewer - .showMessage("You're currently running an obfuscation task, wait for this to finish."); + BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish."); return; } new RenameMethods().start(); @@ -1293,8 +1402,7 @@ public void actionPerformed(ActionEvent arg0) { mntmNewMenuItem_11.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { if (BytecodeViewer.runningObfuscation) { - BytecodeViewer - .showMessage("You're currently running an obfuscation task, wait for this to finish."); + BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish."); return; } new RenameClasses().start(); @@ -1319,10 +1427,8 @@ public void actionPerformed(ActionEvent arg0) { if (!BytecodeViewer.loadedClasses.isEmpty()) PluginManager.runPlugin(new CodeSequenceDiagram()); else { - System.out - .println("Plugin not ran, put some classes in first."); - BytecodeViewer - .showMessage("Plugin not ran, put some classes in first."); + System.out.println("Plugin not ran, put some classes in first."); + BytecodeViewer.showMessage("Plugin not ran, put some classes in first."); } } }); @@ -1336,10 +1442,8 @@ public void actionPerformed(ActionEvent arg0) { if (!BytecodeViewer.loadedClasses.isEmpty()) new ReplaceStringsOptions().setVisible(true); else { - System.out - .println("Plugin not ran, put some classes in first."); - BytecodeViewer - .showMessage("Plugin not ran, put some classes in first."); + System.out.println("Plugin not ran, put some classes in first."); + BytecodeViewer.showMessage("Plugin not ran, put some classes in first."); } } }); @@ -1352,10 +1456,8 @@ public void actionPerformed(ActionEvent arg0) { if (!BytecodeViewer.loadedClasses.isEmpty()) new EZInjectionOptions().setVisible(true); else { - System.out - .println("Plugin not ran, put some classes in first."); - BytecodeViewer - .showMessage("Plugin not ran, put some classes in first."); + System.out.println("Plugin not ran, put some classes in first."); + BytecodeViewer.showMessage("Plugin not ran, put some classes in first."); } } }); @@ -1367,7 +1469,7 @@ public void actionPerformed(ActionEvent arg0) { mntmStartExternalPlugin.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { JFileChooser fc = new JFileChooser(); - fc.setFileFilter(new GroovyPythonRubyFileFilter()); + fc.setFileFilter(new GroovyFileFilter()); fc.setFileHidingEnabled(false); fc.setAcceptAllFileFilterUsed(false); int returnVal = fc.showOpenDialog(BytecodeViewer.viewer); @@ -1397,10 +1499,8 @@ public void actionPerformed(ActionEvent e) { if (!BytecodeViewer.loadedClasses.isEmpty()) new MaliciousCodeScannerOptions().setVisible(true); else { - System.out - .println("Plugin not ran, put some classes in first."); - BytecodeViewer - .showMessage("Plugin not ran, put some classes in first."); + System.out.println("Plugin not ran, put some classes in first."); + BytecodeViewer.showMessage("Plugin not ran, put some classes in first."); } } }); @@ -1417,7 +1517,7 @@ public void actionPerformed(ActionEvent e) { }); setSize(new Dimension(800, 400)); - setTitle("Bytecode Viewer "+BytecodeViewer.version+" - https://the.bytecode.club - @Konloch"); + setTitle("Bytecode Viewer "+BytecodeViewer.version+" - https://bytecodeviewer.com | https://the.bytecode.club - @Konloch"); getContentPane().setLayout( new BoxLayout(getContentPane(), BoxLayout.X_AXIS)); @@ -1514,6 +1614,36 @@ public String getExtension(File f) { } } + + public class GroovyFileFilter extends FileFilter { + @Override + public boolean accept(File f) { + if (f.isDirectory()) + return true; + + String extension = getExtension(f); + if (extension != null) + return (extension.equals("gy") || extension.equals("groovy")); + + return false; + } + + @Override + public String getDescription() { + return "Groovy plugins."; + } + + 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; + } + } public class APKDEXJarZipClassFileFilter extends FileFilter { @Override public boolean accept(File f) { @@ -1665,4 +1795,28 @@ public String getExtension(File f) { return ext; } } + + public class PythonCFileFilter extends FileFilter { + @Override + public boolean accept(File f) { + return true; + } + + @Override + public String getDescription() { + return "Python 2.7 Executable"; + } + } + + public class RTCFileFilter extends FileFilter { + @Override + public boolean accept(File f) { + return true; + } + + @Override + public String getDescription() { + return "JRE RT Library"; + } + } } \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/gui/WorkPane.java b/src/the/bytecode/club/bytecodeviewer/gui/WorkPane.java index 784d09c9e..b3545ac01 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/WorkPane.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/WorkPane.java @@ -121,7 +121,7 @@ public java.awt.Component[] getLoadedViewers() { public void actionPerformed(final ActionEvent arg0) { if(BytecodeViewer.viewer.autoCompileOnRefresh.isSelected()) try { - if(!BytecodeViewer.compileSmali(false)) + if(!BytecodeViewer.compile(false)) return; } catch(java.lang.NullPointerException e) { diff --git a/src/the/bytecode/club/bytecodeviewer/plugins/EZInjection.java b/src/the/bytecode/club/bytecodeviewer/plugins/EZInjection.java index 3d003e35b..008182cc8 100644 --- a/src/the/bytecode/club/bytecodeviewer/plugins/EZInjection.java +++ b/src/the/bytecode/club/bytecodeviewer/plugins/EZInjection.java @@ -13,7 +13,6 @@ import org.objectweb.asm.tree.MethodNode; import the.bytecode.club.bytecodeviewer.BytecodeViewer; -import the.bytecode.club.bytecodeviewer.api.ASMUtil_OLD; import the.bytecode.club.bytecodeviewer.api.BytecodeHook; import the.bytecode.club.bytecodeviewer.api.Plugin; import the.bytecode.club.bytecodeviewer.api.PluginConsole; @@ -28,9 +27,6 @@ * * @author Konloch * - * TODO: figure out a way to block runtime.exec without java agents, - * maybe by replacing the method call? - * */ public class EZInjection extends Plugin { @@ -114,21 +110,6 @@ public static void print(String message) { gui.appendText(message); } - public static void exit(int i) { - print("[SANDBOX] Tried to call on System.exit(" + i - + "), it's been blocked."); - } - - public static void exitR(int i) { - print("[SANDBOX] Tried to call on Runtime.exit(" + i - + "), it's been blocked."); - } - - public static void announceSystem(String s) { - print("[SANDBOX] Tried to call on Runtime.exec(" + s - + "), it's been blocked."); - } - @Override public void execute(ArrayList classNodeList) { BytecodeViewer.viewer.setIcon(true); @@ -252,18 +233,6 @@ else if (injectHooks) } } - if (sandboxRuntime) { - ASMUtil_OLD.renameClassNode("java/lang/Runtime", - "the/bytecode/club/bytecodeviewer/RuntimeOverride"); - } - - if (sandboxSystem) { - ASMUtil_OLD.renameMethodNode("java/lang/System", "exit", - "(Ljava/lang/String;)V", - "the/bytecode/club/bytecodeviewer/plugins/EZInjection", - null, null); - } - if (useProxy) { try { String[] split = proxy.split(":");