v2.9.18 fixes + JADX decompiler

This commit is contained in:
Konloch 2019-04-25 15:27:35 -06:00
parent fb4f2a1371
commit 7f227ca7e7
26 changed files with 594 additions and 78 deletions

BIN
libs/android-5.1.jar Normal file

Binary file not shown.

BIN
libs/annotations-17.0.0.jar Normal file

Binary file not shown.

BIN
libs/cloning-1.9.12.jar Normal file

Binary file not shown.

BIN
libs/dx-1.16.jar Normal file

Binary file not shown.

BIN
libs/gson-2.8.5.jar Normal file

Binary file not shown.

BIN
libs/jadx-core.jar Normal file

Binary file not shown.

BIN
libs/objenesis-3.0.1.jar Normal file

Binary file not shown.

BIN
libs/slf4j-api-1.7.26.jar Normal file

Binary file not shown.

View File

@ -5,6 +5,9 @@ import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.io.IOException;
import javax.swing.JEditorPane;
@ -13,6 +16,7 @@ import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.text.html.HTMLEditorKit;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Resources;
/***************************************************************************
@ -44,7 +48,14 @@ public class InitialBootScreen extends JFrame {
private JProgressBar progressBar = new JProgressBar();
public InitialBootScreen() throws IOException {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
BytecodeViewer.canExit = true;
System.exit(0);
}
});
this.setIconImages(Resources.iconList);
int i = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();

View File

@ -16,8 +16,12 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
@ -26,12 +30,14 @@ import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;
import com.google.gson.reflect.TypeToken;
import me.konloch.kontainer.io.DiskReader;
import me.konloch.kontainer.io.DiskWriter;
import me.konloch.kontainer.io.HTTPRequest;
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.tree.ClassNode;
import com.google.gson.*;
import the.bytecode.club.bootloader.Boot;
import the.bytecode.club.bootloader.ILoader;
@ -68,6 +74,10 @@ import the.bytecode.club.bytecodeviewer.util.*;
***************************************************************************/
/**
* TODO:
* open as folder doesn't actually work
* smali compile
*
* A lightweight Java Reverse Engineering suite, developed by Konloch - http://konloch.me
*
* All you have to do is add a jar or class file into the workspace,
@ -109,7 +119,7 @@ import the.bytecode.club.bytecodeviewer.util.*;
public class BytecodeViewer
{
/*per version*/
public static final String VERSION = "2.9.17";
public static final String VERSION = "2.9.18";
public static String krakatauVersion = "12";
public static String enjarifyVersion = "4";
public static final boolean BLOCK_TAB_MENU = true;
@ -142,22 +152,46 @@ public class BytecodeViewer
public static String nl = System.getProperty("line.separator");
private static File BCVDir = new File(System.getProperty("user.home") + fs + ".Bytecode-Viewer");
public static File RJ_JAR = new File(System.getProperty("java.home") + fs + "lib" + fs + "rt.jar");
private static String filesName = getBCVDirectory() + fs + "recentfiles.bcv";
private static String pluginsName = getBCVDirectory() + fs + "recentplugins.bcv";
private static String filesName = getBCVDirectory() + fs + "recentfiles.json";
private static String pluginsName = getBCVDirectory() + fs + "recentplugins.json";
public static String settingsName = getBCVDirectory() + fs + "settings.bcv";
public static String tempDirectory = getBCVDirectory() + fs + "bcv_temp" + fs;
public static String libsDirectory = getBCVDirectory() + fs + "libs" + fs;
public static String krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + krakatauVersion;
public static String enjarifyWorkingDirectory = getBCVDirectory() + fs + "enjarify_" + enjarifyVersion;
private static ArrayList<String> recentFiles = DiskReader.loadArrayList(filesName, false);
private static ArrayList<String> recentPlugins = DiskReader.loadArrayList(pluginsName, false);
public static boolean runningObfuscation = false;
private static long start = System.currentTimeMillis();
public static String lastDirectory = "";
public static String lastDirectory = ".";
public static ArrayList<Process> createdProcesses = new ArrayList<Process>();
public static Refactorer refactorer = new Refactorer();
public static boolean pingback = false;
public static boolean deleteForeignLibraries = true;
public static boolean canExit = false;
public static Gson gson;
private static ArrayList<String> recentPlugins;
private static ArrayList<String> recentFiles;
static
{
try
{
gson = new GsonBuilder().setPrettyPrinting().create();
if(new File(filesName).exists())
recentFiles = gson.fromJson(DiskReader.loadAsString(filesName), new TypeToken<ArrayList<String>>() {}.getType());
else
recentFiles = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentfiles.bcv", false);
if(new File(pluginsName).exists())
recentPlugins = gson.fromJson(DiskReader.loadAsString(pluginsName), new TypeToken<ArrayList<String>>() {}.getType());
else
recentPlugins = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentplugins.bcv", false);
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* The version checker thread
@ -812,7 +846,7 @@ public class BytecodeViewer
} else {
if (f.isDirectory()) {
FileContainer container = new FileContainer(f);
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
HashMap<String, byte[]> files = new HashMap<>();
boolean finished = false;
ArrayList<File> totalFiles = new ArrayList<File>();
totalFiles.add(f);
@ -844,10 +878,10 @@ public class BytecodeViewer
container.files = files;
BytecodeViewer.files.add(container);
} else {
if (fn.endsWith(".jar") || fn.endsWith(".zip")) {
if (fn.endsWith(".jar") || fn.endsWith(".zip") || fn.endsWith(".war")) {
try {
JarUtils.put(f);
} catch (final java.util.zip.ZipException z) {
} catch (java.io.IOException z) {
try {
JarUtils.put2(f);
} catch (final Exception e) {
@ -938,7 +972,7 @@ public class BytecodeViewer
}
return;
} else {
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
HashMap<String, byte[]> files = new HashMap<>();
byte[] bytes = JarUtils.getBytes(new FileInputStream(f));
files.put(f.getName(), bytes);
@ -1201,10 +1235,7 @@ public class BytecodeViewer
* @return string with newline per array object
*/
private static String quickConvert(ArrayList<String> a) {
String s = "";
for (String r : a)
s += r + nl;
return s;
return gson.toJson(a);
}
private static long last = System.currentTimeMillis();

View File

@ -322,6 +322,7 @@ public class CommandLineInput {
System.out.println("Finished.");
System.out.println("Bytecode Viewer CLI v" + BytecodeViewer.VERSION + " by @Konloch - http://bytecodeviewer.com");
BytecodeViewer.canExit = true;
System.exit(0);
} catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);

View File

@ -121,6 +121,10 @@ public class SecurityMan extends SecurityManager {
@Override
public void checkExit(int status) {
if(!BytecodeViewer.canExit)
{
throw new SecurityException("BCV is awesome, blocking System.exit("+status+");");
}
}
@Override

View File

@ -329,6 +329,8 @@ public class Settings {
BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1KrakatauBytecode.getModel(), true);
else if (decompiler == 9)
BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1JDGUI.getModel(), true);
else if (decompiler == 10)
BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.jadxJ1.getModel(), true);
decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 82, false));
if (decompiler == 0)
@ -351,6 +353,8 @@ public class Settings {
BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2KrakatauBytecode.getModel(), true);
else if (decompiler == 9)
BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2JDGUI.getModel(), true);
else if (decompiler == 10)
BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.jadxJ2.getModel(), true);
decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 83, false));
if (decompiler == 0)
@ -373,6 +377,8 @@ public class Settings {
BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3KrakatauBytecode.getModel(), true);
else if (decompiler == 9)
BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3JDGUI.getModel(), true);
else if (decompiler == 10)
BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.jadxJ3.getModel(), true);
BytecodeViewer.viewer.refreshOnChange.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 84, false)));

View File

@ -55,8 +55,9 @@ public class SmaliAssembler extends Compiler {
}
try {
com.googlecode.d2j.smali.SmaliCmd.main(new String[]{tempSmaliFolder.getAbsolutePath(), "-o", tempDex.getAbsolutePath()});
com.googlecode.d2j.smali.SmaliCmd.main(new String[]{tempSmaliFolder.getAbsolutePath()});//, "-o", tempDex.getAbsolutePath()});
} catch (Exception e) {
e.printStackTrace();
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}

View File

@ -48,11 +48,51 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
public class CFRDecompiler extends Decompiler {
private static final String[] WINDOWS_IS_GREAT = new String[]
{
"CON",
"PRN",
"AUX",
"NUL",
"COM1",
"COM2",
"COM3",
"COM4",
"COM5",
"COM6",
"COM7",
"COM8",
"COM9",
"LPT1",
"LPT2",
"LPT3",
"LPT4",
"LPT5",
"LPT6",
"LPT7",
"LPT8",
"LPT9"
};
public static String windowsFun(String base)
{
for(String s : WINDOWS_IS_GREAT)
{
if(base.contains(s.toLowerCase()))
{
base = base.replace(s.toLowerCase(), "BCV");
}
}
return base;
}
@Override
public String decompileClassNode(ClassNode cn, byte[] b) {
String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs;
String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs.toLowerCase();
String exception = "";
//final File tempClass = new File(windowsFun(MiscUtils.getUniqueName(fileStart, ".class") + ".class"));
final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class");
try {
@ -66,6 +106,7 @@ public class CFRDecompiler extends Decompiler {
}
String fuckery = fuckery(fileStart);
/*if (!BytecodeViewer.fatJar) {
try {
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
@ -84,6 +125,7 @@ public class CFRDecompiler extends Decompiler {
} else {
org.benf.cfr.reader.Main.main(generateMainMethod(tempClass.getAbsolutePath(), fuckery));
}*/
try
{
org.benf.cfr.reader.Main.main(generateMainMethod(tempClass.getAbsolutePath(), fuckery));
@ -104,8 +146,6 @@ public class CFRDecompiler extends Decompiler {
return findFile(file.listFiles());
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;
}
Random r = new Random();

View File

@ -36,8 +36,9 @@ public abstract class Decompiler {
public final static Decompiler cfr = new CFRDecompiler();
public final static KrakatauDecompiler krakatau = new KrakatauDecompiler();
public final static KrakatauDisassembler krakatauDA = new KrakatauDisassembler();
public final static Decompiler smali = new SmaliDisassembler();
public final static SmaliDisassembler smali = new SmaliDisassembler();
public final static Decompiler jdgui = new JDGUIDecompiler();
public final static Decompiler jadx = new JADXDecompiler();
public abstract String decompileClassNode(ClassNode cn, byte[] b);

View File

@ -0,0 +1,131 @@
package the.bytecode.club.bytecodeviewer.decompilers;
import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import me.konloch.kontainer.io.DiskReader;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
import java.io.*;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
/**
* JADX Java Wrapper
*
* @author Konloch
*/
public class JADXDecompiler extends Decompiler
{
@Override
public String decompileClassNode(ClassNode cn, byte[] b) {
String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs;
String exception = "";
final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class");
try {
final FileOutputStream fos = new FileOutputStream(tempClass);
fos.write(b);
fos.close();
} catch (final IOException e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
File fuckery = new File(fuckery(fileStart));
try
{
JadxArgs args = new JadxArgs();
args.getInputFiles().add(tempClass);
args.setOutDir(fuckery);
JadxDecompiler jadx = new JadxDecompiler(args);
jadx.load();
jadx.save();
}
catch(StackOverflowError | Exception e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
e.printStackTrace();
exception = "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString();
}
tempClass.delete();
if(fuckery.exists())
return findFile(fuckery.listFiles());
return "JADX 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;
}
Random r = new Random();
File f;
public String fuckery(String start) {
boolean b = false;
while (!b) {
f = new File(start + r.nextInt(Integer.MAX_VALUE));
if (!f.exists())
return f.toString();
}
return null;
}
public String findFile(File[] fA) {
for (File f : fA) {
if (f.isDirectory())
return findFile(f.listFiles());
else {
String s = "";
try {
s = DiskReader.loadAsString(f.getAbsolutePath());
} catch (Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
e.printStackTrace();
String exception = "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString();
return "JADX 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 + "Suggested Fix: Click refresh class, if it fails again try another decompiler.";
}
@Override
public void decompileToZip(String sourceJar, String zipName)
{
}
}

View File

@ -125,7 +125,7 @@ public class ProcyonDecompiler extends Decompiler {
.getCanonicalPath());
DecompilationOptions decompilationOptions = new DecompilationOptions();
decompilationOptions.setSettings(DecompilerSettings.javaDefaults());
decompilationOptions.setSettings(settings);
decompilationOptions.setFullDecompilation(true);
TypeDefinition resolvedType = null;

View File

@ -1,15 +1,15 @@
package the.bytecode.club.bytecodeviewer.decompilers;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.*;
import me.konloch.kontainer.io.DiskReader;
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.util.Dex2Jar;
import the.bytecode.club.bytecodeviewer.util.FileContainer;
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
import the.bytecode.club.bytecodeviewer.util.ZipUtils;
@ -39,14 +39,14 @@ import the.bytecode.club.bytecodeviewer.util.ZipUtils;
public class SmaliDisassembler extends Decompiler {
public String decompileClassNode(ClassNode cn, byte[] b) {
public String decompileClassNode(FileContainer container, ClassNode cn, byte[] b) {
String exception = "";
String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs
+ "temp";
String start = BytecodeViewer.tempDirectory + BytecodeViewer.fs+MiscUtils.getUniqueName(fileStart, ".class");
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
@ -60,15 +60,42 @@ public class SmaliDisassembler extends Decompiler {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
ZipUtils.zipFile(tempClass, tempZip);
//ZipUtils.zipFile(tempClass, tempZip);
Dex2Jar.saveAsDex(tempZip, tempDex);
Dex2Jar.saveAsDex(container.file, tempDex, false);
try {
com.googlecode.d2j.smali.SmaliCmd.main(new String[]{"-o", tempSmali.getAbsolutePath(), "-x", tempDex.getAbsolutePath()});
} catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
System.out.println("FOR SHOW: " + tempDex.getName().replaceFirst("\\.dex", "-out")); //tempSmali.getAbsolutePath()
try
{
com.googlecode.d2j.smali.BaksmaliCmd.main(new String[]{tempDex.getAbsolutePath()});
}
catch(Exception e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
e.printStackTrace();
exception += "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString();
}
File rename = new File(tempDex.getName().replaceFirst("\\.dex", "-out"));
try
{
FileUtils.moveDirectory(rename, tempSmali);
}
catch (IOException e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
e.printStackTrace();
exception += "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString();
}
System.out.println("FOR SHOW1: " + rename.getAbsolutePath());
System.out.println("FOR SHOW2: " + tempSmali.getAbsolutePath());
File outputSmali = null;
@ -87,9 +114,19 @@ public class SmaliDisassembler extends Decompiler {
try {
return DiskReader.loadAsString(outputSmali.getAbsolutePath());
} catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
e.printStackTrace();
exception += "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString();
}
return "Smali Disassembler 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
public String decompileClassNode(ClassNode cn, byte[] b)
{
return null;
}

View File

@ -13,7 +13,6 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import javax.swing.*;
import javax.swing.text.*;
@ -685,7 +684,7 @@ public class ClassViewer extends Viewer
panelArea.setCodeFoldingEnabled(true);
panelArea.setAntiAliasingEnabled(true);
scrollPane = new RTextScrollPane(panelArea);
panelArea.setText(Decompiler.smali.decompileClassNode(cn, b));
panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b));
panelArea.setCaretPosition(0);
panelArea.setEditable(isPanel1Editable());
smali1 = panelArea;
@ -857,6 +856,51 @@ public class ClassViewer extends Viewer
java1 = panelArea;
}
if (pane1 == 10) {// JADX
panelArea = new RSyntaxTextArea();
panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
panelArea.setCodeFoldingEnabled(true);
panelArea.setAntiAliasingEnabled(true);
scrollPane = new RTextScrollPane(panelArea);
panelArea.setText(Decompiler.jadx.decompileClassNode(cn, b));
panelArea.setCaretPosition(0);
panelArea.setEditable(isPanel1Editable());
panelArea.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent e)
{
if ((e.getKeyCode() == KeyEvent.VK_F) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0))
{
field1.requestFocus();
}
BytecodeViewer.checkHotKey(e);
}
@Override
public void keyReleased(KeyEvent arg0)
{
}
@Override
public void keyTyped(KeyEvent arg0)
{
}
});
scrollPane.setColumnHeaderView(new JLabel("JADX Decompiler - Editable: " + panelArea.isEditable()));
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue()));
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
panel1.add(scrollPane);
}
});
java1 = panelArea;
}
} catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) {
//ignore
} catch (Exception e) {
@ -1050,7 +1094,7 @@ public class ClassViewer extends Viewer
panelArea.setCodeFoldingEnabled(true);
panelArea.setAntiAliasingEnabled(true);
scrollPane = new RTextScrollPane(panelArea);
panelArea.setText(Decompiler.smali.decompileClassNode(cn, b));
panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b));
panelArea.setCaretPosition(0);
panelArea.setEditable(isPanel2Editable());
smali2 = panelArea;
@ -1195,6 +1239,51 @@ public class ClassViewer extends Viewer
java2 = panelArea;
}
if (pane2 == 10) {// JADX
panelArea = new RSyntaxTextArea();
panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
panelArea.setCodeFoldingEnabled(true);
panelArea.setAntiAliasingEnabled(true);
scrollPane = new RTextScrollPane(panelArea);
panelArea.setText(Decompiler.jadx.decompileClassNode(cn, b));
panelArea.setCaretPosition(0);
panelArea.setEditable(isPanel2Editable());
panelArea.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent e)
{
if ((e.getKeyCode() == KeyEvent.VK_F) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0))
{
field1.requestFocus();
}
BytecodeViewer.checkHotKey(e);
}
@Override
public void keyReleased(KeyEvent arg0)
{
}
@Override
public void keyTyped(KeyEvent arg0)
{
}
});
scrollPane.setColumnHeaderView(new JLabel("JADX Decompiler - Editable: " + panelArea.isEditable()));
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue()));
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
panel2.add(scrollPane);
}
});
java2 = panelArea;
}
} catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) {
//ignore
} catch (Exception e) {
@ -1390,7 +1479,7 @@ public class ClassViewer extends Viewer
panelArea.setCodeFoldingEnabled(true);
panelArea.setAntiAliasingEnabled(true);
scrollPane = new RTextScrollPane(panelArea);
panelArea.setText(Decompiler.smali.decompileClassNode(cn, b));
panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b));
panelArea.setCaretPosition(0);
panelArea.setEditable(isPanel3Editable());
smali3 = panelArea;
@ -1533,6 +1622,51 @@ public class ClassViewer extends Viewer
}
});
}
if (pane3 == 10) {// JADX
panelArea = new RSyntaxTextArea();
panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
panelArea.setCodeFoldingEnabled(true);
panelArea.setAntiAliasingEnabled(true);
scrollPane = new RTextScrollPane(panelArea);
panelArea.setText(Decompiler.jadx.decompileClassNode(cn, b));
panelArea.setCaretPosition(0);
panelArea.setEditable(isPanel3Editable());
panelArea.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent e)
{
if ((e.getKeyCode() == KeyEvent.VK_F) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0))
{
field1.requestFocus();
}
BytecodeViewer.checkHotKey(e);
}
@Override
public void keyReleased(KeyEvent arg0)
{
}
@Override
public void keyTyped(KeyEvent arg0)
{
}
});
scrollPane.setColumnHeaderView(new JLabel("JADX Decompiler - Editable: " + panelArea.isEditable()));
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue()));
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
panel3.add(scrollPane);
}
});
java3 = panelArea;
}
} catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) {
//ignore
} catch (Exception e) {
@ -1721,6 +1855,8 @@ public class ClassViewer extends Viewer
pane1 = 8;
else if (BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1JDGUI.getModel()))
pane1 = 9;
else if (BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.jadxJ1.getModel()))
pane1 = 10;
if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2None.getModel()))
pane2 = 0;
@ -1742,6 +1878,8 @@ public class ClassViewer extends Viewer
pane2 = 8;
else if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2JDGUI.getModel()))
pane2 = 9;
else if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.jadxJ2.getModel()))
pane2 = 10;
if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3None.getModel()))
pane3 = 0;
@ -1763,6 +1901,8 @@ public class ClassViewer extends Viewer
pane3 = 8;
else if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3JDGUI.getModel()))
pane3 = 9;
else if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.jadxJ3.getModel()))
pane3 = 10;
}
public boolean isPanel1Editable()

View File

@ -250,6 +250,7 @@ public class FileNavigationPane extends VisibleComponent implements
@Override
public void keyPressed(KeyEvent e) {
System.out.println((int)e.getKeyChar());
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
if (e.getSource() instanceof MyTree)
@ -258,7 +259,7 @@ public class FileNavigationPane extends VisibleComponent implements
openPath(tree.getSelectionPath());
}
}
else if((int)e.getKeyChar() != 0 && (int)e.getKeyChar() != 65535 && !e.isControlDown() && !e.isAltDown())
else if((int)e.getKeyChar() != 0 &&(int)e.getKeyChar() != 8 &&(int)e.getKeyChar() != 127 && (int)e.getKeyChar() != 65535 && !e.isControlDown() && !e.isAltDown())
{
quickSearch.grabFocus();
quickSearch.setText("" + e.getKeyChar());
@ -614,7 +615,7 @@ public class FileNavigationPane extends VisibleComponent implements
the.bytecode.club.bytecodeviewer.gui.FileNavigationPane.MyTreeNode node = (the.bytecode.club.bytecodeviewer.gui.FileNavigationPane.MyTreeNode) value;
String name = node.toString().toLowerCase();
if (name.endsWith(".jar")) {
if (name.endsWith(".jar") || name.endsWith(".war")) {
setIcon(Resources.jarIcon);
} else if (name.endsWith(".zip")) {
setIcon(Resources.zipIcon);

View File

@ -413,6 +413,17 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
public final JRadioButtonMenuItem panel1JDGUI = new JRadioButtonMenuItem("Java");
private final JSeparator separator_35 = new JSeparator();
public final JCheckBoxMenuItem panel1JDGUI_E = new JCheckBoxMenuItem("Editable");
private final JMenu jadx1 = new JMenu("JADX");
public final JRadioButtonMenuItem jadxJ1 = new JRadioButtonMenuItem("Java");
public final JCheckBoxMenuItem jadxE1 = new JCheckBoxMenuItem("Editable");
private final JMenu jadx2 = new JMenu("JADX");
public final JRadioButtonMenuItem jadxJ2 = new JRadioButtonMenuItem("Java");
public final JCheckBoxMenuItem jadxE2 = new JCheckBoxMenuItem("Editable");
private final JMenu jadx3 = new JMenu("JADX");
public final JRadioButtonMenuItem jadxJ3 = new JRadioButtonMenuItem("Java");
public final JCheckBoxMenuItem jadxE3 = new JCheckBoxMenuItem("Editable");
private final JMenu mnFontSize = new JMenu("Font Size");
private final JMenu visualSettings = new JMenu("Visual Settings");
public final JSpinner fontSpinner = new JSpinner();
@ -488,7 +499,14 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
obfuscatorGroup.add(strongObf);
obfuscatorGroup.add(lightObf);
obfuscatorGroup.setSelected(strongObf.getModel(), true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
BytecodeViewer.canExit = true;
System.exit(0);
}
});
// procyon
/* none */
@ -512,7 +530,9 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
@Override
public void actionPerformed(ActionEvent e)
{
JFileChooser fc = new JFileChooser();
final JFileChooser fc = new JFileChooser();
try
{
File f = new File(BytecodeViewer.lastDirectory);
@ -523,6 +543,10 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
{
}
fc.setDialogTitle("Select File or Folder to open in BCV");
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
fc.setAcceptAllFileFilterUsed(true);
fc.setFileFilter(new FileFilter()
{
@Override
@ -535,7 +559,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
if (extension != null)
if (extension.equals("jar") || extension.equals("zip")
|| extension.equals("class") || extension.equals("apk")
|| extension.equals("dex"))
|| extension.equals("dex") || extension.equals("war") || extension.equals("jsp"))
return true;
return false;
@ -544,11 +568,10 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
@Override
public String getDescription()
{
return "APKs, DEX, Class Files or Zip/Jar Archives";
return "APKs, DEX, Class Files or Zip/Jar/War Archives";
}
});
fc.setFileHidingEnabled(false);
fc.setAcceptAllFileFilterUsed(false);
int returnVal = fc.showOpenDialog(BytecodeViewer.viewer);
if (returnVal == JFileChooser.APPROVE_OPTION)
@ -557,8 +580,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
try
{
BytecodeViewer.viewer.setIcon(true);
BytecodeViewer.openFiles(new File[]{fc
.getSelectedFile()}, true);
BytecodeViewer.openFiles(new File[]{fc.getSelectedFile()}, true);
BytecodeViewer.viewer.setIcon(false);
}
catch (Exception e1)
@ -568,6 +590,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
}
}
});
mnNewMenu.add(mntmLoadJar);
mnNewMenu.add(separator_40);
@ -1566,6 +1589,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
if (result == 0)
{
BytecodeViewer.canExit = true;
System.exit(0);
}
}
@ -1590,6 +1614,22 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
panel1Proc.addActionListener(listener);
mnNewMenu_7.add(mnCfr);
jadx1.add(jadxJ1);
jadx1.add(separator_19);
jadx1.add(jadxE1);
jadx2.add(jadxJ2);
jadx2.add(separator_19);
jadx2.add(jadxE2);
jadx3.add(jadxJ3);
jadx3.add(separator_19);
jadx3.add(jadxE3);
mnNewMenu_7.add(jadx1);
mnCfr.add(panel1CFR);
panel1CFR.addActionListener(listener);
@ -1656,6 +1696,8 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
mnPane.add(menu_2);
mnPane.add(jadx2);
menu_2.add(panel2CFR);
menu_2.add(separator_11);
@ -1719,6 +1761,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
menu_7.add(panel3Proc_E);
mnPane_1.add(menu_8);
mnPane_1.add(jadx3);
menu_8.add(panel3CFR);
@ -1889,6 +1932,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
mnNewMenu_4.add(chckbxmntmNewCheckItem_4);
chckbxmntmNewCheckItem_7.setSelected(true);
mnNewMenu_4.add(chckbxmntmNewCheckItem_7);
mnNewMenu_4.add(chckbxmntmSimplifyMemberReferences);
@ -2338,6 +2382,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
panelGroup1.add(panel1None);
panelGroup1.add(panel1Proc);
panelGroup1.add(panel1CFR);
panelGroup1.add(jadxJ1);
panelGroup1.add(panel1JDGUI);
panelGroup1.add(panel1Fern);
panelGroup1.add(panel1Krakatau);
@ -2349,6 +2394,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
panelGroup2.add(panel2None);
panelGroup2.add(panel2Proc);
panelGroup2.add(panel2CFR);
panelGroup2.add(jadxJ2);
panelGroup2.add(panel2JDGUI);
panelGroup2.add(panel2Fern);
panelGroup2.add(panel2Krakatau);
@ -2360,6 +2406,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
panelGroup3.add(panel3None);
panelGroup3.add(panel3Proc);
panelGroup3.add(panel3CFR);
panelGroup3.add(jadxJ3);
panelGroup3.add(panel3JDGUI);
panelGroup3.add(panel3Fern);
panelGroup3.add(panel3Krakatau);

View File

@ -29,8 +29,7 @@ import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.*;
import java.util.regex.Matcher;
import static the.bytecode.club.bytecodeviewer.gui.TabbedPane.BLANK;
@ -57,6 +56,38 @@ public abstract class PaneUpdaterThread extends Thread
public void run() {
doShit();
synchronizePane();
//attachCtrlMouseWheelZoom(scrollPane, panelArea); //freezes the UI for some reason, probably cause BCV is doing dumb shit with the swing thread
}
public void attachCtrlMouseWheelZoom(RTextScrollPane scrollPane, RSyntaxTextArea panelArea)
{
if(scrollPane == null)
return;
scrollPane.addMouseWheelListener(new MouseWheelListener()
{
@Override
public void mouseWheelMoved(MouseWheelEvent e)
{
if(panelArea == null || panelArea.getText().isEmpty())
return;
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0)
{
Font font = panelArea.getFont();
int size = font.getSize();
if(e.getWheelRotation() > 0)
{ //Up
panelArea.setFont(new Font(font.getName(), font.getStyle(), --size >= 2 ? --size : 2));
}
else
{ //Down
panelArea.setFont(new Font(font.getName(), font.getStyle(), ++size));
}
}
e.consume();
}
});
}
public final CaretListener caretListener = new CaretListener()

View File

@ -1,5 +1,7 @@
package the.bytecode.club.bytecodeviewer.util;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import java.io.File;
/***************************************************************************
@ -55,14 +57,35 @@ public class Dex2Jar {
* @param output the output .dex file
*/
public static synchronized void saveAsDex(File input, File output) {
saveAsDex(input, output, true);
}
public static synchronized void saveAsDex(File input, File output, boolean delete) {
try {
com.googlecode.dex2jar.tools.Dex2jarCmd.main(new String[]{input.getAbsolutePath()});
String realOutput = input.getName().replaceAll("\\.jar", "-jar2dex.dex");
File realOutputF = new File(realOutput);
realOutputF.renameTo(output);
File realOutputF2 = new File(realOutput);
while (realOutputF2.exists())
realOutputF2.delete();
com.googlecode.dex2jar.tools.Jar2Dex.main(new String[]{input.getAbsolutePath()});
File currentDexLocation = new File("./"+input.getName());
if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".jar"))
{
currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.jar", "-jar2dex.dex"));
}
else if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".apk"))
{
currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.apk", "-jar2dex.dex"));
}
else if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".dex"))
{
currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.dex", "-jar2dex.dex"));
}
else if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".zip"))
{
currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.zip", "-jar2dex.dex"));
}
currentDexLocation.renameTo(output);
if(delete)
input.delete();
} catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}

View File

@ -45,8 +45,8 @@ public class FileContainer {
public File file;
public String name;
public HashMap<String, byte[]> files = new HashMap<String, byte[]>();
public ArrayList<ClassNode> classes = new ArrayList<ClassNode>();
public HashMap<String, byte[]> files = new HashMap<>();
public ArrayList<ClassNode> classes = new ArrayList<>();
public ClassNode getClassNode(String name) {
for (ClassNode c : classes)

View File

@ -1,7 +1,6 @@
package the.bytecode.club.bytecodeviewer.util;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@ -17,7 +16,6 @@ import me.konloch.kontainer.io.DiskWriter;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FilenameUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
@ -59,7 +57,7 @@ public class JarUtils {
*/
public static void put(final File jarFile) throws IOException {
FileContainer container = new FileContainer(jarFile);
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
HashMap<String, byte[]> files = new HashMap<>();
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
ZipEntry entry;
@ -86,7 +84,7 @@ public class JarUtils {
}
}
} catch (ZipException e) {
} catch (java.io.EOFException | ZipException e) {
//ignore cause apache unzip
} catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
@ -99,12 +97,12 @@ public class JarUtils {
BytecodeViewer.files.add(container);
}
public static void put2(final File jarFile) throws IOException {
//TODO try zip libraries till one works, worst case import Sun's jarsigner code from JDK 7 re-sign the jar to rebuilt the CRC, should also rebuild the archive byte offsets
public static void put2(final File jarFile) throws IOException
{
//if this ever fails, worst case import Sun's jarsigner code from JDK 7 re-sign the jar to rebuild the CRC, should also rebuild the archive byte offsets
FileContainer container = new FileContainer(jarFile);
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
HashMap<String, byte[]> files = new HashMap<>();
Path path = jarFile.toPath();
@ -114,29 +112,42 @@ public class JarUtils {
try (ZipFile zipFile = new ZipFile(jarFile))
{
Enumeration<? extends ZipArchiveEntry> entries = zipFile.getEntries();
while (entries.hasMoreElements()) {
while (entries.hasMoreElements())
{
ZipArchiveEntry entry = entries.nextElement();
Path entryPath = destFolderPath.resolve(entry.getName());
String name = entry.getName();
if (entry.isDirectory()) {
if (entry.isDirectory())
{
//directory
} else {
}
else
{
try (InputStream in = zipFile.getInputStream(entry))
{
final byte[] bytes = getBytes(in);
if (!name.endsWith(".class")) {
if(!name.endsWith(".class"))
{
files.put(name, bytes);
} else {
}
else
{
String cafebabe = String.format("%02X", bytes[0]) + String.format("%02X", bytes[1]) + String.format("%02X", bytes[2]) + String.format("%02X", bytes[3]);
if (cafebabe.toLowerCase().equals("cafebabe")) {
try {
if (cafebabe.toLowerCase().equals("cafebabe"))
{
try
{
final ClassNode cn = getNode(bytes);
container.classes.add(cn);
} catch (Exception e) {
}
catch (Exception e)
{
e.printStackTrace();
}
} else {
}
else
{
files.put(name, bytes);
}
}
@ -193,7 +204,7 @@ public class JarUtils {
if (!zipFile.exists())
return null; //just ignore
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
HashMap<String, byte[]> files = new HashMap<>();
ZipInputStream jis = new ZipInputStream(new FileInputStream(zipFile));
ZipEntry entry;