Skip to content

Commit

Permalink
2.8.0
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Konloch committed Feb 4, 2015
1 parent 58020b0 commit 1cd3bfa
Show file tree
Hide file tree
Showing 28 changed files with 1,111 additions and 280 deletions.
Binary file removed BytecodeViewer 2.7.1.jar
Binary file not shown.
Binary file not shown.
23 changes: 17 additions & 6 deletions README.txt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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/
Expand All @@ -40,15 +41,16 @@ 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.
Hex Viewer - Powered by JHexPane.
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!
Expand Down Expand Up @@ -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.
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.
Binary file renamed libs/cfr_0_94.jar → libs/cfr_0_95.jar
Binary file not shown.
Binary file removed libs/jruby.jar
Binary file not shown.
Binary file not shown.
Binary file added src/krakatau.zip
Binary file not shown.
144 changes: 76 additions & 68 deletions src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -303,27 +300,45 @@
* 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
*
*/

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<String, ClassNode> loadedClasses = new HashMap<String, ClassNode>();
public static HashMap<String, byte[]> loadedResources = new HashMap<String, byte[]>();
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<String> recentFiles = DiskReader.loadArrayList(filesName, false);
private static ArrayList<String> 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() {
Expand Down Expand Up @@ -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<BufferedImage>();
int size = 16;
Expand Down Expand Up @@ -616,18 +588,18 @@ public static ArrayList<ClassNode> 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;

for(java.awt.Component c : BytecodeViewer.viewer.workPane.getLoadedViewers()) {
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);
Expand All @@ -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;
}
}
}
}

Expand All @@ -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)
Expand Down Expand Up @@ -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();
Expand All @@ -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++)
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -887,29 +896,28 @@ 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() {
return System.getProperty("os.name").toLowerCase().contains("win");
}

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<String> a) {
Expand Down
32 changes: 32 additions & 0 deletions src/the/bytecode/club/bytecodeviewer/MiscUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package the.bytecode.club.bytecodeviewer;

import java.io.File;
import java.util.Random;

public class MiscUtils {
Expand All @@ -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;
}
}
Loading

0 comments on commit 1cd3bfa

Please sign in to comment.