Merge remote-tracking branch 'origin/master'

This commit is contained in:
Nico Mexis 2022-01-23 21:50:01 +01:00
commit ece284c95b
No known key found for this signature in database
GPG key ID: 27D6E17CE092AB78
19 changed files with 210 additions and 302 deletions

View file

@ -3,6 +3,7 @@
Bytecode Viewer - a lightweight user-friendly Java/Android Bytecode Viewer, Decompiler & More. Bytecode Viewer - a lightweight user-friendly Java/Android Bytecode Viewer, Decompiler & More.
#### New Features #### New Features
* Patched [CVE-2022-21675](https://github.com/Konloch/bytecode-viewer/security/advisories/GHSA-3wq9-j4fc-4wmc) (Make sure to upgrade to v2.11.X)
* Dark mode with multiple themes * Dark mode with multiple themes
* Translated into over 30 languages including: Arabic, German, Japanese, Mandarin, Russian, Spanish * Translated into over 30 languages including: Arabic, German, Japanese, Mandarin, Russian, Spanish
* Plugin Writer - create and edit external plugins from within BCV * Plugin Writer - create and edit external plugins from within BCV
@ -16,10 +17,6 @@ Bytecode Viewer - a lightweight user-friendly Java/Android Bytecode Viewer, Deco
* Added support to Java files compiled using JDK > 13 * Added support to Java files compiled using JDK > 13
* Migrated to Maven * Migrated to Maven
#### v2.10.x Notes
* The rewrite/refactoring process is currently ongoing so please report any bugs you find
* If you're encountering any issues try using [v2.9.22](https://github.com/Konloch/bytecode-viewer/releases/tag/v2.9.22)
#### Links #### Links
* [BCV Discord](https://discord.gg/aexsYpfMEf) * [BCV Discord](https://discord.gg/aexsYpfMEf)
* [Website](https://bytecodeviewer.com) * [Website](https://bytecodeviewer.com)

View file

@ -1,13 +0,0 @@
import org.objectweb.asm.tree.ClassNode
import the.bytecode.club.bytecodeviewer.api.*
class Skeleton extends Plugin {
@Override
void execute(List<ClassNode> classNodesList) {
PluginConsole gui = new PluginConsole("Skeleton")
gui.setVisible(true)
gui.appendText("executed skeleton")
}
}

View file

@ -1,6 +0,0 @@
function execute(classNodeList) {
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
var gui = new PluginConsole("Skeleton");
gui.setVisible(true);
gui.appendText("executed skeleton");
}

View file

@ -1,48 +0,0 @@
import java.lang.reflect.Field;
import java.util.List;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import the.bytecode.club.bytecodeviewer.api.*;
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
import static the.bytecode.club.bytecodeviewer.Constants.nl;
/**
* This is an example of a string decrypter plugin
*/
public class ExampleStringDecrypter extends Plugin {
@Override
public void execute(List<ClassNode> classNodesList) {
PluginConsole gui = new PluginConsole("Example String Decrypter");
MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
"WARNING: This will load the classes into the JVM and execute the initialize function"
+ nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
new String[]{"Continue", "Cancel"});
if (dialog.promptChoice() == 0) {
for (ClassNode cn : classNodesList) {
BCV.getClassNodeLoader().addClass(cn);
for (Object o : cn.fields.toArray()) {
FieldNode f = (FieldNode) o;
if (f.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) {
try {
for (Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields()) {
String s = (String) f2.get(null);
if (s != null && !s.isEmpty())
gui.appendText(cn + ":" + s);
}
} catch (Exception ignored) {
}
}
}
}
gui.setVisible(true);
}
}
}

View file

@ -10,13 +10,15 @@ import java.lang.reflect.Field
import static the.bytecode.club.bytecodeviewer.Constants.nl import static the.bytecode.club.bytecodeviewer.Constants.nl
/** /**
* This is an example of a string decrypter plugin ** This is an example of a String Decrypter Groovy Plugin for BCV.
*/ **
** @author [Your-Name-Goes-Here]
**/
class ExampleStringDecrypter extends Plugin { class ExampleStringDecrypter extends Plugin {
@Override @Override
void execute(List<ClassNode> classNodesList) { void execute(List<ClassNode> classNodesList) {
PluginConsole gui = new PluginConsole("Example String Decrypter") PluginConsole gui = new PluginConsole("Example String Decrypter Groovy Edition")
MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING", MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
"WARNING: This will load the classes into the JVM and execute the initialize function" "WARNING: This will load the classes into the JVM and execute the initialize function"

View file

@ -0,0 +1,18 @@
import org.objectweb.asm.tree.ClassNode
import the.bytecode.club.bytecodeviewer.api.*
/**
** This is a skeleton template for BCV's Groovy Plugin System
**
** @author [Your Name Goes Here]
**/
class Skeleton extends Plugin {
@Override
void execute(List<ClassNode> classNodesList) {
PluginConsole gui = new PluginConsole("Skeleton Title")
gui.setVisible(true)
gui.appendText("executed skeleton example")
}
}

View file

@ -0,0 +1,68 @@
import java.lang.reflect.Field;
import java.util.List;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import the.bytecode.club.bytecodeviewer.api.*;
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
import static the.bytecode.club.bytecodeviewer.Constants.nl;
/**
** This is an example of a String Decrypter Java Plugin for BCV.
**
** @author [Your-Name-Goes-Here]
**/
public class ExampleStringDecrypter extends Plugin {
@Override
public void execute(List<ClassNode> classNodesList) {
PluginConsole gui = new PluginConsole("Example String Decrypter Java Edition");
MultipleChoiceDialog dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
"WARNING: This will load the classes into the JVM and execute the initialize function"
+ nl + "for each class. IF THE FILE YOU'RE LOADING IS MALICIOUS, DO NOT CONTINUE.",
new String[]{"Continue", "Cancel"});
if (dialog.promptChoice() == 0) {
boolean needsWarning = false;
for (ClassNode cn : classNodesList) {
try {
//load the class node into the classloader
BCV.getClassNodeLoader().addClass(cn);
for (Object o : cn.fields.toArray()) {
FieldNode f = (FieldNode) o;
//if the class contains the field z, get the class object from the class node
//then print out the value of the fields inside the class
//if the strings get decrypted on init, this allows you to dump the current values
if (f.name.equals("z")) {
try {
for (Field f2 : BCV.getClassNodeLoader().nodeToClass(cn).getFields()) {
String s = (String) f2.get(null);
if (s != null && !s.isEmpty())
gui.appendText(cn + ":" + s);
}
} catch (Exception ignored) {
}
}
}
} catch (Exception e) {
gui.appendText("Failed loading class " + cn.name);
e.printStackTrace();
needsWarning = true;
}
}
if (needsWarning) {
BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them\n"
+ "makes sure you include ALL the libraries it requires.");
}
gui.setVisible(true);
}
}
}

View file

@ -2,13 +2,18 @@ import java.util.List;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.api.*; import the.bytecode.club.bytecodeviewer.api.*;
/**
** This is a skeleton template for BCV's Java Plugin System
**
** @author [Your Name Goes Here]
**/
public class Skeleton extends Plugin { public class Skeleton extends Plugin {
@Override @Override
public void execute(List<ClassNode> classNodesList) { public void execute(List<ClassNode> classNodesList) {
PluginConsole gui = new PluginConsole("Skeleton"); PluginConsole gui = new PluginConsole("Skeleton Title");
gui.setVisible(true); gui.setVisible(true);
gui.appendText("executed skeleton"); gui.appendText("executed skeleton example");
} }
}
}

View file

@ -18,10 +18,13 @@ import the.bytecode.club.bytecodeviewer.decompilers.impl.FernFlowerDecompiler;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer; import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
/** /**
* @author jowasp ** This is an Xposed Generator Plugin, used to aid Reverse-Engineering.
*/ **
** @author jowasp
**/
public class XposedGenerator extends Plugin { public class XposedGenerator extends Plugin {
//PRIVATE
private static final List<String> methodsNames = new ArrayList<>(); private static final List<String> methodsNames = new ArrayList<>();
private static final List<String> cleanMethodsNames = new ArrayList<>(); private static final List<String> cleanMethodsNames = new ArrayList<>();
private static String foundPckg; private static String foundPckg;
@ -40,7 +43,6 @@ public class XposedGenerator extends Plugin {
} }
String className = viewer.getName(); String className = viewer.getName();
//String containerName = viewer.getName();
ClassNode classnode = BytecodeViewer.getCurrentlyOpenedClassNode(); ClassNode classnode = BytecodeViewer.getCurrentlyOpenedClassNode();
//Call XposedGenerator class //Call XposedGenerator class
@ -64,7 +66,6 @@ public class XposedGenerator extends Plugin {
//Set results of parsed methods into a list //Set results of parsed methods into a list
List<String> methodsExtracted = ProcessContentExtractedClass(decomp); List<String> methodsExtracted = ProcessContentExtractedClass(decomp);
String packgExtracted = ProcessContentExtractedPackage(decomp); String packgExtracted = ProcessContentExtractedPackage(decomp);
System.out.println("PACKAGE NAME: " + packgExtracted);
//Get a clean list //Get a clean list
List<String> cleanMethods; List<String> cleanMethods;
@ -114,16 +115,16 @@ public class XposedGenerator extends Plugin {
public static void WriteXposedModule(String functionToHook, String packageName, String classToHook, public static void WriteXposedModule(String functionToHook, String packageName, String classToHook,
String template) { String template) {
System.out.println("TEMPLATE: " + template);
if (template != null && !template.equals("Empty")) { if (template != null && !template.equals("Empty")) {
try { try {
//TODO: Prompt save dialog //TODO: Prompt save dialog
File file = new File("./XposedClassTest.java"); File file = new File("./XposedClassTest.java");
// if file doesn't exist, then create it // if file doesn't exist, then create it
if (!file.exists()) { if (!file.exists())
file.createNewFile(); file.createNewFile();
}
//Extract the package name only //Extract the package name only
String packageNameOnly = packageName.substring(8, packageName.length() - 2).trim(); String packageNameOnly = packageName.substring(8, packageName.length() - 2).trim();
String classToHookNameOnly = classToHook; String classToHookNameOnly = classToHook;
@ -132,18 +133,14 @@ public class XposedGenerator extends Plugin {
String[] classClean = classToHookNameOnly.split("/"); String[] classClean = classToHookNameOnly.split("/");
String[] functionSplitValues = functionToHook.split("\\s+"); String[] functionSplitValues = functionToHook.split("\\s+");
//select //select
String onlyClass = classClean[classClean.length - 1]; String onlyClass = classClean[classClean.length - 1];
//String onlyFunctionParateses = functionSplitValues[functionSplitValues.length-2];
String onlyFunction = CleanUpFunction(functionSplitValues); String onlyFunction = CleanUpFunction(functionSplitValues);
//String functionToHookOnly = "dummy function";
System.out.println(onlyClass);
System.out.println(packageNameOnly);
//Write Xposed Class //Write Xposed Class
String XposedClassText = String XposedClassText = "package androidpentesting.com.xposedmodule;" + "\r\n" +
"package androidpentesting.com.xposedmodule;" + "\r\n" +
"import de.robv.android.xposed.IXposedHookLoadPackage;" + "\r\n" + "import de.robv.android.xposed.IXposedHookLoadPackage;" + "\r\n" +
"\r\n" + "\r\n" +
"import de.robv.android.xposed.XC_MethodHook;" + "\r\n" + "import de.robv.android.xposed.XC_MethodHook;" + "\r\n" +
@ -177,7 +174,6 @@ public class XposedGenerator extends Plugin {
bw.write("\r\n"); bw.write("\r\n");
bw.close(); bw.close();
System.out.println("Done");
JOptionPane.showMessageDialog(null, "Xposed Module Generated"); JOptionPane.showMessageDialog(null, "Xposed Module Generated");
} catch (IOException e) { } catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error" + e); JOptionPane.showMessageDialog(null, "Error" + e);
@ -193,19 +189,16 @@ public class XposedGenerator extends Plugin {
try { try {
scanner = new Scanner(contentFile); scanner = new Scanner(contentFile);
//@TODO : Improve patterns to match other excepts 'public' //@TODO : Improve patterns to match other excepts 'public'
String regexclass = "public"; String regexclass = "public";
//String regexPkg = "package";
Pattern pattern = Pattern.compile(regexclass, Pattern.CASE_INSENSITIVE); Pattern pattern = Pattern.compile(regexclass, Pattern.CASE_INSENSITIVE);
//Pattern patternVoid = Pattern.compile(regexVoid , Pattern.CASE_INSENSITIVE);
// Pattern patternPkg = Pattern.compile(regexPkg , Pattern.CASE_INSENSITIVE);
//scanner.useDelimiter(";");
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();
// process the line // process the line
Matcher matcher = pattern.matcher(line); Matcher matcher = pattern.matcher(line);
while (matcher.find()) { while (matcher.find()) {
if (matcher.group() != null) { if (matcher.group() != null) {
System.out.println("find() found the pattern \"" + quote(line.trim())); System.out.println("find() found the pattern \"" + quote(line.trim()));
System.out.println("Function: " + CleanUpFunction(line.trim().split("\\s+"))); System.out.println("Function: " + CleanUpFunction(line.trim().split("\\s+")));
@ -213,9 +206,7 @@ public class XposedGenerator extends Plugin {
} else { } else {
methodsNames.add("No methods found"); methodsNames.add("No methods found");
} }
} }
} }
if (methodsNames.isEmpty()) { if (methodsNames.isEmpty()) {
@ -237,11 +228,9 @@ public class XposedGenerator extends Plugin {
if (!m.contains("extends") && (!m.contains("implements") && (m.contains("(")))) { if (!m.contains("extends") && (!m.contains("implements") && (m.contains("(")))) {
cleanMethodsNames.add(m); cleanMethodsNames.add(m);
} }
} }
return cleanMethodsNames; return cleanMethodsNames;
} }
private static String CleanUpFunction(String[] rawFunction) { private static String CleanUpFunction(String[] rawFunction) {
@ -254,7 +243,6 @@ public class XposedGenerator extends Plugin {
} }
return onlyFunc; return onlyFunc;
} }
private static String ProcessContentExtractedPackage(String contentFile) { private static String ProcessContentExtractedPackage(String contentFile) {
@ -264,20 +252,19 @@ public class XposedGenerator extends Plugin {
String regexPkg = "package"; String regexPkg = "package";
Pattern patternPkg = Pattern.compile(regexPkg, Pattern.CASE_INSENSITIVE); Pattern patternPkg = Pattern.compile(regexPkg, Pattern.CASE_INSENSITIVE);
String line = scanner.nextLine(); String line = scanner.nextLine();
// process the line // process the line
Matcher matcher = patternPkg.matcher(line); Matcher matcher = patternPkg.matcher(line);
while (matcher.find()) { while (matcher.find()) {
if (matcher.group() != null) { if (matcher.group() != null) {
System.out.println("find() found the pattern \"" + quote(line.trim())); System.out.println("find() found the pattern \"" + quote(line.trim()));
foundPckg = quote(line.trim()); foundPckg = quote(line.trim());
} else { } else {
foundPckg = ""; foundPckg = "";
} }
} }
try try
//
{ {
if (foundPckg == null || foundPckg.isEmpty()) if (foundPckg == null || foundPckg.isEmpty())
foundPckg = "No Package Found"; foundPckg = "No Package Found";
@ -296,8 +283,8 @@ public class XposedGenerator extends Plugin {
if (scanner != null) if (scanner != null)
scanner.close(); scanner.close();
} }
return foundPckg; return foundPckg;
} }
private static String quote(String aText) { private static String quote(String aText) {

View file

@ -1,10 +1,14 @@
/** /**
* This is an example plugin ** An example BCV Javascript Plugin.
*/ ** This is used to display all of loaded classnodes that have been imported into BCV.
**
** @author [Your-Name-Goes-Here]
**/
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole"); var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
var gui = new PluginConsole("Example Plugin Print Loaded Classes"); var gui = new PluginConsole("Example Plugin Print Loaded Classes Javascript Edition");
function execute(classNodeList) { function execute(classNodeList) {
for (index = 0; index < classNodeList.length; index++) { for (index = 0; index < classNodeList.length; index++) {
@ -13,4 +17,4 @@ function execute(classNodeList) {
} }
gui.setVisible(true); gui.setVisible(true);
} }

View file

@ -1,6 +1,9 @@
/** /**
* This is an example of a string decrypter plugin ** This is an example of a String Decrypter Javascript Plugin for BCV.
*/ **
** @author [Your-Name-Goes-Here]
**/
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole"); var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
var MultipleChoiceDialog = Java.type("the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog") var MultipleChoiceDialog = Java.type("the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog")
@ -13,7 +16,7 @@ var dialog = new MultipleChoiceDialog("Bytecode Viewer - WARNING",
var gui; var gui;
function execute(classNodeList) { function execute(classNodeList) {
gui = new PluginConsole("Skeleton"); gui = new PluginConsole("Example String Decrypter Javascript Edition");
if (dialog.promptChoice() == 0) { if (dialog.promptChoice() == 0) {
var needsWarning = false; var needsWarning = false;
@ -33,7 +36,7 @@ function execute(classNodeList) {
//then print out the value of the fields inside the class //then print out the value of the fields inside the class
//if the strings get decrypted on init, this allows you to dump the current values //if the strings get decrypted on init, this allows you to dump the current values
if (field.name.equals("z")) {// && f.desc.equals("([Ljava/lang/String;)V")) { if (field.name.equals("z")) {
try { try {
var loadedClass = BytecodeViewer.getClassNodeLoader().nodeToClass(cn); var loadedClass = BytecodeViewer.getClassNodeLoader().nodeToClass(cn);
var reflectedFields = loadedClass.getFields(); var reflectedFields = loadedClass.getFields();
@ -45,7 +48,7 @@ function execute(classNodeList) {
if (s != null && !s.empty()) if (s != null && !s.empty())
gui.appendText(cn + "->" + s); gui.appendText(cn + "->" + s);
} }
} catch (e) { } catch (ignored) {
} }
} }
} }

View file

@ -0,0 +1,13 @@
/**
** This is a skeleton template for BCV's Javascript Plugin System
**
** @author [Your Name Goes Here]
**/
function execute(classNodeList) {
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
var gui = new PluginConsole("Skeleton Title");
gui.setVisible(true);
gui.appendText("executed skeleton example");
}

View file

@ -5,9 +5,14 @@ from java.lang import Boolean
from java.util import ArrayList from java.util import ArrayList
from org.objectweb.asm.tree import ClassNode from org.objectweb.asm.tree import ClassNode
class skeleton(Plugin): #
# This is a skeleton template for BCV's Ruby Plugin System
#
# @author [Your Name Goes Here]
#
def execute(classNodeList, poop): #for some reason it requires a second arg class skeleton(Plugin):
gui = PluginConsole("Skeleton") def execute(classNodeList, notUsed): #for some reason it requires a second arg
gui = PluginConsole("Skeleton Title")
gui.setVisible(Boolean.TRUE) gui.setVisible(Boolean.TRUE)
gui.appendText("exceuted skeleton") gui.appendText("executed skeleton example")

View file

@ -6,10 +6,16 @@ java_import 'java.lang.System'
java_import 'java.util.ArrayList' java_import 'java.util.ArrayList'
java_import 'org.objectweb.asm.tree.ClassNode' java_import 'org.objectweb.asm.tree.ClassNode'
#
# This is a skeleton template for BCV's Ruby Plugin System
#
# @author [Your Name Goes Here]
#
class Skeleton < Plugin class Skeleton < Plugin
def execute(classNodeList) def execute(classNodeList)
gui = PluginConsole.new "Skeleton" gui = PluginConsole.new "Skeleton Title"
gui.setVisible(true) gui.setVisible(true)
gui.appendText("executed skeleton") gui.appendText("executed skeleton example")
end end
end end

View file

@ -36,7 +36,7 @@
<gson.version>2.8.9</gson.version> <gson.version>2.8.9</gson.version>
<guava.version>31.0.1-jre</guava.version> <guava.version>31.0.1-jre</guava.version>
<imgscalr-lib.version>4.2</imgscalr-lib.version> <imgscalr-lib.version>4.2</imgscalr-lib.version>
<jadx.version>1.3.1</jadx.version> <jadx.version>1.3.2</jadx.version>
<janino.version>3.1.6</janino.version> <janino.version>3.1.6</janino.version>
<jd-gui.version>1.6.6bcv</jd-gui.version> <jd-gui.version>1.6.6bcv</jd-gui.version>
<jgraphx.version>3.4.1.3</jgraphx.version> <jgraphx.version>3.4.1.3</jgraphx.version>

View file

@ -37,7 +37,8 @@ public class PluginConsole extends SystemConsole
public PluginConsole(String pluginName) public PluginConsole(String pluginName)
{ {
super(Configuration.pluginConsoleAsNewTab ? (pluginName + " Output") : (TranslatedStrings.PLUGIN_CONSOLE_TITLE + " - " + pluginName)); super(Configuration.pluginConsoleAsNewTab ? (pluginName + " Output")
: (TranslatedStrings.PLUGIN_CONSOLE_TITLE + " - " + pluginName));
} }
@Override @Override

View file

@ -156,7 +156,8 @@ public final class PluginManager
} }
final String name = activePlugin.activeContainer == null final String name = activePlugin.activeContainer == null
? "#" + (activeTabbedException.getTabbedPane().getTabCount() + 1) : activePlugin.activeContainer.name; ? "#" + (activeTabbedException.getTabbedPane().getTabCount() + 1)
: activePlugin.activeContainer.name;
ExceptionUI existingUI = exceptionTabs.get(name); ExceptionUI existingUI = exceptionTabs.get(name);
@ -201,7 +202,8 @@ public final class PluginManager
console.setConsoleID(id); console.setConsoleID(id);
final String name = (activePlugin == null || activePlugin.activeContainer == null) final String name = (activePlugin == null || activePlugin.activeContainer == null)
? ("#" + (activeTabbedConsole.getTabbedPane().getTabCount() + 1)) : activePlugin.activeContainer.name; ? ("#" + (activeTabbedConsole.getTabbedPane().getTabCount() + 1))
: activePlugin.activeContainer.name;
activeTabbedConsole.addConsole(console.getComponent(0), name); activeTabbedConsole.addConsole(console.getComponent(0), name);
} }

View file

@ -1,166 +0,0 @@
<html lang="en">
<h2>About</h2>
Bytecode Viewer (BCV) is an easy to use Java & Android Reverse Engineering Suite!<br>
BCV is designed to be extremely user and beginner friendly, because of this almost everything is accessible through an interface, settings, tools, etc.
<br><br>To start drag your Jar/APK/Class file into the resource list.
<h2>How To - Java Importing</h2>
<pre>
Java resources have no special preprocessing before you open them.
Import your Jar/Class/WAR/EAR file via the File>Open menu in Bytecode Viewer. (CTRL + O)
</pre>
<h2>How To - Android Importing</h2>
<pre>
Android resources have three options for preprocessing:
1). Decode Resources
2). Enjarify
3). Dex2Jar (d2j)
1). Decode Resources will run APKTool to decode any packed android-specific resources
2). Enjarify will convert the dalvik specific bytecode to java bytecode
3). Dex2Jar will convert the dalvik specific bytecode to java bytecode
Import your APK/WAPK/DEX file via the File>Open menu in Bytecode Viewer. (CTRL + O)
</pre>
<h2>How To - File Navigation</h2>
<pre>
Using the resource list (it should say "Files" on the title bar) you can select all of the resources added into BCV.
Any archive will opened, to select a resource click + button for each folder.
Using the search pane inside of the resource list you can search by file name and extension.
For case-sensitivity enable the checkbox labeled "Exact".
</pre>
<h2>Settings</h2>
<ul>
<li>Fat Jar: {fatJar}</li>
<li>Java: {java}</li>
<li>Javac: {javac}</li>
<li>Python 2.7 (or PyPy): {python}</li>
<li>Python 3.X (or PyPy): {python3}</li>
<li>RT.jar: {rt}</li>
<li>Optional Lib: {lib}</li>
<li>BCV Dir: {bcvDir}</li>
<li>Temp Dir: {tempDir}</li>
<li>Krakatau Dir: {krakatauDir}</li>
<li>Enjarify Dir: {enjarifyDir}</li>
<li>BCV Krakatau version: v{krakatauVersion}</li>
<li>BCV Enjarify version: v{enjarifyVersion}</li>
</ul>
<h2>Command Line Interface (CLI)</h2>
<ul>
<li> -help Displays the help menu</li>
<li> -list Displays the available decompilers</li>
<li> -decompiler [decompiler] Selects the decompiler, procyon by default</li>
<li> -i [input file] Selects the input file (Jar, Class, APK, ZIP, DEX all work automatically)</li>
<li> -o [output file] Selects the output file (Java or Java-Bytecode)</li>
<li> -t [target classname] Must either be the fully qualified classname or "all" to decompile all as zip</li>
<li> -nowait Doesn't wait for the user to read the CLI messages</li>
</ul>
<h2>File</h2>
<ul>
<li>Add (Ctrl + O) - If you add a jar/zip BCV will unzip it, if you add an APK or DEX file, BCV will run dex2jar
then run the jar input process.
</li>
<li>Reopen Recent File (Ctrl + L) - Reopens your last recent opened file.</li>
<li>New Workspace (Ctrl + N) - It clears the opened jars/resources.</li>
<li>Run (Ctrl + R) - Runs the classfiles you've loaded into BCV in a secure sandboxed JVM instance that you can
fully debug.
</li>
<li>Compile (Ctrl + T) - Tries to compile all of the editable panes you've selected, if it's Java it'll compile with
Ranino. Krakatau and *Smali use their own assemblers.
</li>
<li>Save As Jar - Export the class files and loaded resources as a runnable Jar file.</li>
<li>Save As DEX - Run jar2dex and export the Classfiles as DEX.</li>
<li>Save Files As - Save all the Classfiles and resources as a zip.</li>
<li>Save Java File As - Save the currently opened decompiled Classfile.</li>
<li>Save Java Files As - Save all of the decompiled Classfiles as a zip.</li>
<li>Recent Files - Last 25 files/directories you've opened with BCV.</li>
<li>About - A small information window about BCV.</li>
<li>Exit - Closes BCV.</li>
</ul>
<h2>View Panes</h2>
<ul>
<li>Editable - Defines if that viewing pane will be editable.</li>
<li>None - Nothing will be displayed.</li>
<li>Procyon - Decompiles with Procyon decompiler.</li>
<li>CFR - Decompilers with CFR decompiler.</li>
<li>FernFlower - Decompiles with FernFlower decompiler.</li>
<li>JD-GUI - Decompiles with JD-GUI decompiler.</li>
<li>Krakatau Java - Decompiles with Krakatau decompiler.</li>
<li>Krakatau Bytecode - Disassembles with Krakatau disassembler.</li>
<li>Smali - Disassembles with Smali.</li>
<li>Bytecode - Decompiles the Bytecode via CFIDE. Not Editable.</li>
<li>Hexcode - Shows the classfile in a hex viewer. Not Editable.</li>
</ul>
<h2>Settings</h2>
<ul>
<li>Compile On Save - If selected whenever you do one of the File>Save * functions it will try to compile before it
saves.
</li>
<li>Compile On Refresh - If selected whenever you press refresh it compile before it reloads the resource/class.
</li>
<li>Update Check - If selected it queries https://github.com/Konloch/bytecode-viewer to ensure you've got the latest
version.
</li>
<li>Refresh On View Change - If selected whenever you change an option in the View Panes it will refresh the
currently opened resources/class.
</li>
<li>Decode APK Resources - If selected whenever you add an APK, it will first run APKTool.jar to decode the
resources.
</li>
<li>Set Python 2.7 Executable - Set the Python 2.7 executable if you want Krakatau decompiler/disassembler/assembler
to work.
</li>
<li>Set JRE RT Library - Set the JRE RT library for Krakatau decompiler.</li>
</ul>
<h2>Plugins</h2>
<ul>
<li>Open Plugin - Open a .java plugin created for BCV.</li>
<li>Recent Plugins - Last 25 plugins you've opened with BCV.</li>
<li>Code Sequence Diagram - Builds a crude code sequence diagram for the classfile that's currently opened.</li>
<li>Malicious Code Scanner - Allows you to define what to search for, and outputs what it found.</li>
<li>Show Main Methods - Detects and outputs all of the public static void main(String[]) functions.</li>
<li>Show All Strings - Grabs then outputs all of the strings in every classfile.</li>
<li>Replace Strings - Allows you to do a simple permanent .replace on the classfile strings, very useful for URL swapping.</li>
<li>Allatori String Decrypter - Decrypts the Allatori obfuscated/encrypted strings.</li>
<li>ZKM String Decrypter - Decrypts the ZKM obfuscated/encrypted strings.</li>
<li>ZStringArray String Decrypter - Decrypts the ZStringArray obfuscated/encrypted strings.</li>
</ul>
<h2>Code from various projects has been used, including but not limited to</h2>
<ul>
<li>J-RET by WaterWolf</li>
<li>JHexPane by Sam Koivu</li>
<li>RSynaxPane by Robert Futrell</li>
<li>Commons IO by Apache</li>
<li>ASM by OW2</li>
<li>FernFlower by Stiver</li>
<li>Procyon by Mstrobel</li>
<li>CFR by Lee Benfield</li>
<li>CFIDE by Bibl</li>
<li>Smali by JesusFreke</li>
<li>Dex2Jar by pxb1988</li>
<li>Krakatau by Storyyeller</li>
<li>JD-GUI + JD-Core by The Java-Decompiler Team</li>
<li>Enjarify by Storyyeller</li>
</ul>
<h2>Notes</h2>
<ul>
<li>If BCV fails to boot simply append -clean as an argument to clean the lib directory.</li>
<li>Relax and take notes</li>
<li>BCV was created out of love for Java Reverse engineering.</li>
<li>You can join our Discord server at <a href="https://discord.gg/aexsYpfMEf">https://discord.gg/aexsYpfMEf</a>!</li>
<li>Bytecode Viewer's Homepage is <a href="https://bytecodeviewer.com">https://bytecodeviewer.com</a></li>
</ul>
</html>

View file

@ -1,25 +1,55 @@
<html lang="en"> <html lang="en">
<h2>About</h2> <h2>About</h2>
Bytecode Viewer (BCV) was designed to be extremely user and beginner friendly, because of this almost everything Bytecode Viewer (BCV) is an easy-to-use Java & Android Reverse Engineering Suite!<br>
is accessible through an interface, settings, tools, etc. BCV is designed to be extremely user and beginner-friendly, this means everything is accessible through an interface such as settings, tools, etc.
<br><br>To start drag your Jar/APK/Class file into the resource list. <br><br>To start, simply drag your Jar/APK/Class file into the resource list.
<h2>How To - Java Importing</h2>
<pre>
Java resources have no special preprocessing before you open them.
Import your Jar/Class/WAR/EAR file via the File>Open menu in Bytecode Viewer. (CTRL + O)
</pre>
<h2>How To - Android Importing</h2>
<pre>
Android resources have three options for preprocessing:
1). Decode Resources
2). Enjarify
3). Dex2Jar (d2j)
1). Decode Resources will run APKTool to decode any packed android-specific resources
2). Enjarify will convert the Android Dalvik Bytecode to Java Bytecode
3). Dex2Jar will convert the Android Dalvik Bytecode to Java Bytecode
Import your APK/WAPK/DEX file via the File>Open menu in Bytecode Viewer. (CTRL + O)
</pre>
<h2>How To - File Navigation</h2>
<pre>
To use the resource list - (Note: it will say "Files" on the title bar) - you can select all of the resources added into BCV.
Any archive (Zip, Jar, ETC.) will opened.
To select a resource click + button for each folder.
Using the search pane inside of the resource list you can search by file name and extension.
For case-sensitivity enable the checkbox labeled "Exact".
</pre>
<h2>Settings</h2> <h2>Settings</h2>
<ul> <ul>
<li>Fat Jar: {fatJar}</li> <li>Fat Jar: {fatJar}</li>
<li>Java: {java}</li> <li>Java: {java}</li>
<li>Javac: {javac}</li> <li>Javac: {javac}</li>
<li>BCV Dir: {bcvDir}</li>
<li>Python 2.7 (or PyPy): {python}</li> <li>Python 2.7 (or PyPy): {python}</li>
<li>Python 3.X (or PyPy): {python3}</li> <li>Python 3.X (or PyPy): {python3}</li>
<li>RT.jar: {rt}</li> <li>RT.jar: {rt}</li>
<li>Optional Lib: {lib}</li> <li>Optional Lib: {lib}</li>
<li>BCV Krakatau: v{krakatauVersion}</li> <li>BCV Dir: {bcvDir}</li>
<li>Temp Dir: {tempDir}</li>
<li>Krakatau Dir: {krakatauDir}</li> <li>Krakatau Dir: {krakatauDir}</li>
<li>BCV Enjarify: v{enjarifyVersion}</li>
<li>Enjarify Dir: {enjarifyDir}</li> <li>Enjarify Dir: {enjarifyDir}</li>
<li>BCV Krakatau version: v{krakatauVersion}</li>
<li>BCV Enjarify version: v{enjarifyVersion}</li>
</ul> </ul>
<h2>Command Line Interface (CLI)</h2> <h2>Command Line Interface (CLI)</h2>
@ -134,4 +164,4 @@ is accessible through an interface, settings, tools, etc.
<li>Bytecode Viewer's Homepage is <a href="https://bytecodeviewer.com">https://bytecodeviewer.com</a></li> <li>Bytecode Viewer's Homepage is <a href="https://bytecodeviewer.com">https://bytecodeviewer.com</a></li>
</ul> </ul>
</html> </html>