v2.9.18 fixes + JADX decompiler
This commit is contained in:
parent
fb4f2a1371
commit
7f227ca7e7
26 changed files with 594 additions and 78 deletions
BIN
libs/android-5.1.jar
Normal file
BIN
libs/android-5.1.jar
Normal file
Binary file not shown.
BIN
libs/annotations-17.0.0.jar
Normal file
BIN
libs/annotations-17.0.0.jar
Normal file
Binary file not shown.
BIN
libs/cloning-1.9.12.jar
Normal file
BIN
libs/cloning-1.9.12.jar
Normal file
Binary file not shown.
BIN
libs/dx-1.16.jar
Normal file
BIN
libs/dx-1.16.jar
Normal file
Binary file not shown.
BIN
libs/gson-2.8.5.jar
Normal file
BIN
libs/gson-2.8.5.jar
Normal file
Binary file not shown.
BIN
libs/jadx-core.jar
Normal file
BIN
libs/jadx-core.jar
Normal file
Binary file not shown.
BIN
libs/objenesis-3.0.1.jar
Normal file
BIN
libs/objenesis-3.0.1.jar
Normal file
Binary file not shown.
BIN
libs/slf4j-api-1.7.26.jar
Normal file
BIN
libs/slf4j-api-1.7.26.jar
Normal file
Binary file not shown.
|
@ -5,6 +5,9 @@ import java.awt.GridBagConstraints;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.awt.event.WindowStateListener;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.swing.JEditorPane;
|
import javax.swing.JEditorPane;
|
||||||
|
@ -13,6 +16,7 @@ import javax.swing.JProgressBar;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.text.html.HTMLEditorKit;
|
import javax.swing.text.html.HTMLEditorKit;
|
||||||
|
|
||||||
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.Resources;
|
import the.bytecode.club.bytecodeviewer.Resources;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -44,7 +48,14 @@ public class InitialBootScreen extends JFrame {
|
||||||
private JProgressBar progressBar = new JProgressBar();
|
private JProgressBar progressBar = new JProgressBar();
|
||||||
|
|
||||||
public InitialBootScreen() throws IOException {
|
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);
|
this.setIconImages(Resources.iconList);
|
||||||
|
|
||||||
int i = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
|
int i = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
|
||||||
|
|
|
@ -16,8 +16,12 @@ import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
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.JDialog;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
|
@ -26,12 +30,14 @@ import javax.swing.JOptionPane;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.filechooser.FileFilter;
|
import javax.swing.filechooser.FileFilter;
|
||||||
|
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
import me.konloch.kontainer.io.DiskReader;
|
import me.konloch.kontainer.io.DiskReader;
|
||||||
import me.konloch.kontainer.io.DiskWriter;
|
import me.konloch.kontainer.io.DiskWriter;
|
||||||
import me.konloch.kontainer.io.HTTPRequest;
|
import me.konloch.kontainer.io.HTTPRequest;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import com.google.gson.*;
|
||||||
|
|
||||||
import the.bytecode.club.bootloader.Boot;
|
import the.bytecode.club.bootloader.Boot;
|
||||||
import the.bytecode.club.bootloader.ILoader;
|
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
|
* 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,
|
* 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
|
public class BytecodeViewer
|
||||||
{
|
{
|
||||||
/*per version*/
|
/*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 krakatauVersion = "12";
|
||||||
public static String enjarifyVersion = "4";
|
public static String enjarifyVersion = "4";
|
||||||
public static final boolean BLOCK_TAB_MENU = true;
|
public static final boolean BLOCK_TAB_MENU = true;
|
||||||
|
@ -142,22 +152,46 @@ public class BytecodeViewer
|
||||||
public static String nl = System.getProperty("line.separator");
|
public static String nl = System.getProperty("line.separator");
|
||||||
private static File BCVDir = new File(System.getProperty("user.home") + fs + ".Bytecode-Viewer");
|
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");
|
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 filesName = getBCVDirectory() + fs + "recentfiles.json";
|
||||||
private static String pluginsName = getBCVDirectory() + fs + "recentplugins.bcv";
|
private static String pluginsName = getBCVDirectory() + fs + "recentplugins.json";
|
||||||
public static String settingsName = getBCVDirectory() + fs + "settings.bcv";
|
public static String settingsName = getBCVDirectory() + fs + "settings.bcv";
|
||||||
public static String tempDirectory = getBCVDirectory() + fs + "bcv_temp" + fs;
|
public static String tempDirectory = getBCVDirectory() + fs + "bcv_temp" + fs;
|
||||||
public static String libsDirectory = getBCVDirectory() + fs + "libs" + fs;
|
public static String libsDirectory = getBCVDirectory() + fs + "libs" + fs;
|
||||||
public static String krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + krakatauVersion;
|
public static String krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + krakatauVersion;
|
||||||
public static String enjarifyWorkingDirectory = getBCVDirectory() + fs + "enjarify_" + enjarifyVersion;
|
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;
|
public static boolean runningObfuscation = false;
|
||||||
private static long start = System.currentTimeMillis();
|
private static long start = System.currentTimeMillis();
|
||||||
public static String lastDirectory = "";
|
public static String lastDirectory = ".";
|
||||||
public static ArrayList<Process> createdProcesses = new ArrayList<Process>();
|
public static ArrayList<Process> createdProcesses = new ArrayList<Process>();
|
||||||
public static Refactorer refactorer = new Refactorer();
|
public static Refactorer refactorer = new Refactorer();
|
||||||
public static boolean pingback = false;
|
public static boolean pingback = false;
|
||||||
public static boolean deleteForeignLibraries = true;
|
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
|
* The version checker thread
|
||||||
|
@ -812,7 +846,7 @@ public class BytecodeViewer
|
||||||
} else {
|
} else {
|
||||||
if (f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
FileContainer container = new FileContainer(f);
|
FileContainer container = new FileContainer(f);
|
||||||
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
|
HashMap<String, byte[]> files = new HashMap<>();
|
||||||
boolean finished = false;
|
boolean finished = false;
|
||||||
ArrayList<File> totalFiles = new ArrayList<File>();
|
ArrayList<File> totalFiles = new ArrayList<File>();
|
||||||
totalFiles.add(f);
|
totalFiles.add(f);
|
||||||
|
@ -844,10 +878,10 @@ public class BytecodeViewer
|
||||||
container.files = files;
|
container.files = files;
|
||||||
BytecodeViewer.files.add(container);
|
BytecodeViewer.files.add(container);
|
||||||
} else {
|
} else {
|
||||||
if (fn.endsWith(".jar") || fn.endsWith(".zip")) {
|
if (fn.endsWith(".jar") || fn.endsWith(".zip") || fn.endsWith(".war")) {
|
||||||
try {
|
try {
|
||||||
JarUtils.put(f);
|
JarUtils.put(f);
|
||||||
} catch (final java.util.zip.ZipException z) {
|
} catch (java.io.IOException z) {
|
||||||
try {
|
try {
|
||||||
JarUtils.put2(f);
|
JarUtils.put2(f);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
|
@ -938,7 +972,7 @@ public class BytecodeViewer
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
|
HashMap<String, byte[]> files = new HashMap<>();
|
||||||
byte[] bytes = JarUtils.getBytes(new FileInputStream(f));
|
byte[] bytes = JarUtils.getBytes(new FileInputStream(f));
|
||||||
files.put(f.getName(), bytes);
|
files.put(f.getName(), bytes);
|
||||||
|
|
||||||
|
@ -1201,10 +1235,7 @@ public class BytecodeViewer
|
||||||
* @return string with newline per array object
|
* @return string with newline per array object
|
||||||
*/
|
*/
|
||||||
private static String quickConvert(ArrayList<String> a) {
|
private static String quickConvert(ArrayList<String> a) {
|
||||||
String s = "";
|
return gson.toJson(a);
|
||||||
for (String r : a)
|
|
||||||
s += r + nl;
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long last = System.currentTimeMillis();
|
private static long last = System.currentTimeMillis();
|
||||||
|
|
|
@ -322,6 +322,7 @@ public class CommandLineInput {
|
||||||
|
|
||||||
System.out.println("Finished.");
|
System.out.println("Finished.");
|
||||||
System.out.println("Bytecode Viewer CLI v" + BytecodeViewer.VERSION + " by @Konloch - http://bytecodeviewer.com");
|
System.out.println("Bytecode Viewer CLI v" + BytecodeViewer.VERSION + " by @Konloch - http://bytecodeviewer.com");
|
||||||
|
BytecodeViewer.canExit = true;
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
||||||
|
|
|
@ -121,6 +121,10 @@ public class SecurityMan extends SecurityManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkExit(int status) {
|
public void checkExit(int status) {
|
||||||
|
if(!BytecodeViewer.canExit)
|
||||||
|
{
|
||||||
|
throw new SecurityException("BCV is awesome, blocking System.exit("+status+");");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -329,6 +329,8 @@ public class Settings {
|
||||||
BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1KrakatauBytecode.getModel(), true);
|
BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1KrakatauBytecode.getModel(), true);
|
||||||
else if (decompiler == 9)
|
else if (decompiler == 9)
|
||||||
BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1JDGUI.getModel(), true);
|
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));
|
decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 82, false));
|
||||||
if (decompiler == 0)
|
if (decompiler == 0)
|
||||||
|
@ -351,6 +353,8 @@ public class Settings {
|
||||||
BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2KrakatauBytecode.getModel(), true);
|
BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2KrakatauBytecode.getModel(), true);
|
||||||
else if (decompiler == 9)
|
else if (decompiler == 9)
|
||||||
BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2JDGUI.getModel(), true);
|
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));
|
decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 83, false));
|
||||||
if (decompiler == 0)
|
if (decompiler == 0)
|
||||||
|
@ -373,6 +377,8 @@ public class Settings {
|
||||||
BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3KrakatauBytecode.getModel(), true);
|
BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3KrakatauBytecode.getModel(), true);
|
||||||
else if (decompiler == 9)
|
else if (decompiler == 9)
|
||||||
BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3JDGUI.getModel(), true);
|
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)));
|
BytecodeViewer.viewer.refreshOnChange.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 84, false)));
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,9 @@ public class SmaliAssembler extends Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,51 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
public class CFRDecompiler extends Decompiler {
|
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
|
@Override
|
||||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
public String decompileClassNode(ClassNode cn, byte[] b) {
|
||||||
String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs;
|
String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs.toLowerCase();
|
||||||
|
|
||||||
String exception = "";
|
String exception = "";
|
||||||
|
//final File tempClass = new File(windowsFun(MiscUtils.getUniqueName(fileStart, ".class") + ".class"));
|
||||||
final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class");
|
final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -66,6 +106,7 @@ public class CFRDecompiler extends Decompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
String fuckery = fuckery(fileStart);
|
String fuckery = fuckery(fileStart);
|
||||||
|
|
||||||
/*if (!BytecodeViewer.fatJar) {
|
/*if (!BytecodeViewer.fatJar) {
|
||||||
try {
|
try {
|
||||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
|
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
|
||||||
|
@ -84,6 +125,7 @@ public class CFRDecompiler extends Decompiler {
|
||||||
} else {
|
} else {
|
||||||
org.benf.cfr.reader.Main.main(generateMainMethod(tempClass.getAbsolutePath(), fuckery));
|
org.benf.cfr.reader.Main.main(generateMainMethod(tempClass.getAbsolutePath(), fuckery));
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
org.benf.cfr.reader.Main.main(generateMainMethod(tempClass.getAbsolutePath(), fuckery));
|
org.benf.cfr.reader.Main.main(generateMainMethod(tempClass.getAbsolutePath(), fuckery));
|
||||||
|
@ -104,8 +146,6 @@ public class CFRDecompiler extends Decompiler {
|
||||||
return findFile(file.listFiles());
|
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;
|
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();
|
Random r = new Random();
|
||||||
|
|
|
@ -36,8 +36,9 @@ public abstract class Decompiler {
|
||||||
public final static Decompiler cfr = new CFRDecompiler();
|
public final static Decompiler cfr = new CFRDecompiler();
|
||||||
public final static KrakatauDecompiler krakatau = new KrakatauDecompiler();
|
public final static KrakatauDecompiler krakatau = new KrakatauDecompiler();
|
||||||
public final static KrakatauDisassembler krakatauDA = new KrakatauDisassembler();
|
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 jdgui = new JDGUIDecompiler();
|
||||||
|
public final static Decompiler jadx = new JADXDecompiler();
|
||||||
|
|
||||||
public abstract String decompileClassNode(ClassNode cn, byte[] b);
|
public abstract String decompileClassNode(ClassNode cn, byte[] b);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -125,7 +125,7 @@ public class ProcyonDecompiler extends Decompiler {
|
||||||
.getCanonicalPath());
|
.getCanonicalPath());
|
||||||
|
|
||||||
DecompilationOptions decompilationOptions = new DecompilationOptions();
|
DecompilationOptions decompilationOptions = new DecompilationOptions();
|
||||||
decompilationOptions.setSettings(DecompilerSettings.javaDefaults());
|
decompilationOptions.setSettings(settings);
|
||||||
decompilationOptions.setFullDecompilation(true);
|
decompilationOptions.setFullDecompilation(true);
|
||||||
|
|
||||||
TypeDefinition resolvedType = null;
|
TypeDefinition resolvedType = null;
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package the.bytecode.club.bytecodeviewer.decompilers;
|
package the.bytecode.club.bytecodeviewer.decompilers;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import me.konloch.kontainer.io.DiskReader;
|
import me.konloch.kontainer.io.DiskReader;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.Dex2Jar;
|
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.MiscUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.ZipUtils;
|
import the.bytecode.club.bytecodeviewer.util.ZipUtils;
|
||||||
|
|
||||||
|
@ -39,14 +39,14 @@ import the.bytecode.club.bytecodeviewer.util.ZipUtils;
|
||||||
|
|
||||||
public class SmaliDisassembler extends Decompiler {
|
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
|
String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs
|
||||||
+ "temp";
|
+ "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 tempClass = new File(start + ".class");
|
||||||
final File tempZip = new File(start + ".jar");
|
|
||||||
final File tempDex = new File(start + ".dex");
|
final File tempDex = new File(start + ".dex");
|
||||||
final File tempSmali = new File(start + "-smali"); //output directory
|
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);
|
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 {
|
System.out.println("FOR SHOW: " + tempDex.getName().replaceFirst("\\.dex", "-out")); //tempSmali.getAbsolutePath()
|
||||||
com.googlecode.d2j.smali.SmaliCmd.main(new String[]{"-o", tempSmali.getAbsolutePath(), "-x", tempDex.getAbsolutePath()});
|
|
||||||
} catch (Exception e) {
|
try
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
{
|
||||||
|
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;
|
File outputSmali = null;
|
||||||
|
|
||||||
|
@ -87,9 +114,19 @@ public class SmaliDisassembler extends Decompiler {
|
||||||
try {
|
try {
|
||||||
return DiskReader.loadAsString(outputSmali.getAbsolutePath());
|
return DiskReader.loadAsString(outputSmali.getAbsolutePath());
|
||||||
} catch (Exception e) {
|
} 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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.text.*;
|
import javax.swing.text.*;
|
||||||
|
@ -685,7 +684,7 @@ public class ClassViewer extends Viewer
|
||||||
panelArea.setCodeFoldingEnabled(true);
|
panelArea.setCodeFoldingEnabled(true);
|
||||||
panelArea.setAntiAliasingEnabled(true);
|
panelArea.setAntiAliasingEnabled(true);
|
||||||
scrollPane = new RTextScrollPane(panelArea);
|
scrollPane = new RTextScrollPane(panelArea);
|
||||||
panelArea.setText(Decompiler.smali.decompileClassNode(cn, b));
|
panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b));
|
||||||
panelArea.setCaretPosition(0);
|
panelArea.setCaretPosition(0);
|
||||||
panelArea.setEditable(isPanel1Editable());
|
panelArea.setEditable(isPanel1Editable());
|
||||||
smali1 = panelArea;
|
smali1 = panelArea;
|
||||||
|
@ -857,6 +856,51 @@ public class ClassViewer extends Viewer
|
||||||
|
|
||||||
java1 = panelArea;
|
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) {
|
} catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) {
|
||||||
//ignore
|
//ignore
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -1050,7 +1094,7 @@ public class ClassViewer extends Viewer
|
||||||
panelArea.setCodeFoldingEnabled(true);
|
panelArea.setCodeFoldingEnabled(true);
|
||||||
panelArea.setAntiAliasingEnabled(true);
|
panelArea.setAntiAliasingEnabled(true);
|
||||||
scrollPane = new RTextScrollPane(panelArea);
|
scrollPane = new RTextScrollPane(panelArea);
|
||||||
panelArea.setText(Decompiler.smali.decompileClassNode(cn, b));
|
panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b));
|
||||||
panelArea.setCaretPosition(0);
|
panelArea.setCaretPosition(0);
|
||||||
panelArea.setEditable(isPanel2Editable());
|
panelArea.setEditable(isPanel2Editable());
|
||||||
smali2 = panelArea;
|
smali2 = panelArea;
|
||||||
|
@ -1195,6 +1239,51 @@ public class ClassViewer extends Viewer
|
||||||
|
|
||||||
java2 = panelArea;
|
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) {
|
} catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) {
|
||||||
//ignore
|
//ignore
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -1390,7 +1479,7 @@ public class ClassViewer extends Viewer
|
||||||
panelArea.setCodeFoldingEnabled(true);
|
panelArea.setCodeFoldingEnabled(true);
|
||||||
panelArea.setAntiAliasingEnabled(true);
|
panelArea.setAntiAliasingEnabled(true);
|
||||||
scrollPane = new RTextScrollPane(panelArea);
|
scrollPane = new RTextScrollPane(panelArea);
|
||||||
panelArea.setText(Decompiler.smali.decompileClassNode(cn, b));
|
panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b));
|
||||||
panelArea.setCaretPosition(0);
|
panelArea.setCaretPosition(0);
|
||||||
panelArea.setEditable(isPanel3Editable());
|
panelArea.setEditable(isPanel3Editable());
|
||||||
smali3 = panelArea;
|
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) {
|
} catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) {
|
||||||
//ignore
|
//ignore
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -1721,6 +1855,8 @@ public class ClassViewer extends Viewer
|
||||||
pane1 = 8;
|
pane1 = 8;
|
||||||
else if (BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1JDGUI.getModel()))
|
else if (BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1JDGUI.getModel()))
|
||||||
pane1 = 9;
|
pane1 = 9;
|
||||||
|
else if (BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.jadxJ1.getModel()))
|
||||||
|
pane1 = 10;
|
||||||
|
|
||||||
if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2None.getModel()))
|
if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2None.getModel()))
|
||||||
pane2 = 0;
|
pane2 = 0;
|
||||||
|
@ -1742,6 +1878,8 @@ public class ClassViewer extends Viewer
|
||||||
pane2 = 8;
|
pane2 = 8;
|
||||||
else if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2JDGUI.getModel()))
|
else if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2JDGUI.getModel()))
|
||||||
pane2 = 9;
|
pane2 = 9;
|
||||||
|
else if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.jadxJ2.getModel()))
|
||||||
|
pane2 = 10;
|
||||||
|
|
||||||
if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3None.getModel()))
|
if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3None.getModel()))
|
||||||
pane3 = 0;
|
pane3 = 0;
|
||||||
|
@ -1763,6 +1901,8 @@ public class ClassViewer extends Viewer
|
||||||
pane3 = 8;
|
pane3 = 8;
|
||||||
else if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3JDGUI.getModel()))
|
else if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3JDGUI.getModel()))
|
||||||
pane3 = 9;
|
pane3 = 9;
|
||||||
|
else if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.jadxJ3.getModel()))
|
||||||
|
pane3 = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPanel1Editable()
|
public boolean isPanel1Editable()
|
||||||
|
|
|
@ -250,6 +250,7 @@ public class FileNavigationPane extends VisibleComponent implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
|
System.out.println((int)e.getKeyChar());
|
||||||
if (e.getKeyCode() == KeyEvent.VK_ENTER)
|
if (e.getKeyCode() == KeyEvent.VK_ENTER)
|
||||||
{
|
{
|
||||||
if (e.getSource() instanceof MyTree)
|
if (e.getSource() instanceof MyTree)
|
||||||
|
@ -258,7 +259,7 @@ public class FileNavigationPane extends VisibleComponent implements
|
||||||
openPath(tree.getSelectionPath());
|
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.grabFocus();
|
||||||
quickSearch.setText("" + e.getKeyChar());
|
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;
|
the.bytecode.club.bytecodeviewer.gui.FileNavigationPane.MyTreeNode node = (the.bytecode.club.bytecodeviewer.gui.FileNavigationPane.MyTreeNode) value;
|
||||||
String name = node.toString().toLowerCase();
|
String name = node.toString().toLowerCase();
|
||||||
|
|
||||||
if (name.endsWith(".jar")) {
|
if (name.endsWith(".jar") || name.endsWith(".war")) {
|
||||||
setIcon(Resources.jarIcon);
|
setIcon(Resources.jarIcon);
|
||||||
} else if (name.endsWith(".zip")) {
|
} else if (name.endsWith(".zip")) {
|
||||||
setIcon(Resources.zipIcon);
|
setIcon(Resources.zipIcon);
|
||||||
|
|
|
@ -413,6 +413,17 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
public final JRadioButtonMenuItem panel1JDGUI = new JRadioButtonMenuItem("Java");
|
public final JRadioButtonMenuItem panel1JDGUI = new JRadioButtonMenuItem("Java");
|
||||||
private final JSeparator separator_35 = new JSeparator();
|
private final JSeparator separator_35 = new JSeparator();
|
||||||
public final JCheckBoxMenuItem panel1JDGUI_E = new JCheckBoxMenuItem("Editable");
|
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 mnFontSize = new JMenu("Font Size");
|
||||||
private final JMenu visualSettings = new JMenu("Visual Settings");
|
private final JMenu visualSettings = new JMenu("Visual Settings");
|
||||||
public final JSpinner fontSpinner = new JSpinner();
|
public final JSpinner fontSpinner = new JSpinner();
|
||||||
|
@ -488,7 +499,14 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
obfuscatorGroup.add(strongObf);
|
obfuscatorGroup.add(strongObf);
|
||||||
obfuscatorGroup.add(lightObf);
|
obfuscatorGroup.add(lightObf);
|
||||||
obfuscatorGroup.setSelected(strongObf.getModel(), true);
|
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
|
// procyon
|
||||||
/* none */
|
/* none */
|
||||||
|
|
||||||
|
@ -512,7 +530,9 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e)
|
public void actionPerformed(ActionEvent e)
|
||||||
{
|
{
|
||||||
JFileChooser fc = new JFileChooser();
|
|
||||||
|
final JFileChooser fc = new JFileChooser();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File f = new File(BytecodeViewer.lastDirectory);
|
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()
|
fc.setFileFilter(new FileFilter()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
@ -535,7 +559,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
if (extension != null)
|
if (extension != null)
|
||||||
if (extension.equals("jar") || extension.equals("zip")
|
if (extension.equals("jar") || extension.equals("zip")
|
||||||
|| extension.equals("class") || extension.equals("apk")
|
|| extension.equals("class") || extension.equals("apk")
|
||||||
|| extension.equals("dex"))
|
|| extension.equals("dex") || extension.equals("war") || extension.equals("jsp"))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -544,11 +568,10 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
@Override
|
@Override
|
||||||
public String getDescription()
|
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);
|
int returnVal = fc.showOpenDialog(BytecodeViewer.viewer);
|
||||||
|
|
||||||
if (returnVal == JFileChooser.APPROVE_OPTION)
|
if (returnVal == JFileChooser.APPROVE_OPTION)
|
||||||
|
@ -557,8 +580,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
BytecodeViewer.viewer.setIcon(true);
|
BytecodeViewer.viewer.setIcon(true);
|
||||||
BytecodeViewer.openFiles(new File[]{fc
|
BytecodeViewer.openFiles(new File[]{fc.getSelectedFile()}, true);
|
||||||
.getSelectedFile()}, true);
|
|
||||||
BytecodeViewer.viewer.setIcon(false);
|
BytecodeViewer.viewer.setIcon(false);
|
||||||
}
|
}
|
||||||
catch (Exception e1)
|
catch (Exception e1)
|
||||||
|
@ -568,6 +590,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mnNewMenu.add(mntmLoadJar);
|
mnNewMenu.add(mntmLoadJar);
|
||||||
|
|
||||||
mnNewMenu.add(separator_40);
|
mnNewMenu.add(separator_40);
|
||||||
|
@ -1566,6 +1589,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
|
BytecodeViewer.canExit = true;
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1590,6 +1614,22 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
panel1Proc.addActionListener(listener);
|
panel1Proc.addActionListener(listener);
|
||||||
|
|
||||||
mnNewMenu_7.add(mnCfr);
|
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);
|
mnCfr.add(panel1CFR);
|
||||||
panel1CFR.addActionListener(listener);
|
panel1CFR.addActionListener(listener);
|
||||||
|
|
||||||
|
@ -1656,6 +1696,8 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
|
|
||||||
mnPane.add(menu_2);
|
mnPane.add(menu_2);
|
||||||
|
|
||||||
|
mnPane.add(jadx2);
|
||||||
|
|
||||||
menu_2.add(panel2CFR);
|
menu_2.add(panel2CFR);
|
||||||
|
|
||||||
menu_2.add(separator_11);
|
menu_2.add(separator_11);
|
||||||
|
@ -1719,6 +1761,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
menu_7.add(panel3Proc_E);
|
menu_7.add(panel3Proc_E);
|
||||||
|
|
||||||
mnPane_1.add(menu_8);
|
mnPane_1.add(menu_8);
|
||||||
|
mnPane_1.add(jadx3);
|
||||||
|
|
||||||
menu_8.add(panel3CFR);
|
menu_8.add(panel3CFR);
|
||||||
|
|
||||||
|
@ -1889,6 +1932,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
|
|
||||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_4);
|
mnNewMenu_4.add(chckbxmntmNewCheckItem_4);
|
||||||
|
|
||||||
|
chckbxmntmNewCheckItem_7.setSelected(true);
|
||||||
mnNewMenu_4.add(chckbxmntmNewCheckItem_7);
|
mnNewMenu_4.add(chckbxmntmNewCheckItem_7);
|
||||||
|
|
||||||
mnNewMenu_4.add(chckbxmntmSimplifyMemberReferences);
|
mnNewMenu_4.add(chckbxmntmSimplifyMemberReferences);
|
||||||
|
@ -2338,6 +2382,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
panelGroup1.add(panel1None);
|
panelGroup1.add(panel1None);
|
||||||
panelGroup1.add(panel1Proc);
|
panelGroup1.add(panel1Proc);
|
||||||
panelGroup1.add(panel1CFR);
|
panelGroup1.add(panel1CFR);
|
||||||
|
panelGroup1.add(jadxJ1);
|
||||||
panelGroup1.add(panel1JDGUI);
|
panelGroup1.add(panel1JDGUI);
|
||||||
panelGroup1.add(panel1Fern);
|
panelGroup1.add(panel1Fern);
|
||||||
panelGroup1.add(panel1Krakatau);
|
panelGroup1.add(panel1Krakatau);
|
||||||
|
@ -2349,6 +2394,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
panelGroup2.add(panel2None);
|
panelGroup2.add(panel2None);
|
||||||
panelGroup2.add(panel2Proc);
|
panelGroup2.add(panel2Proc);
|
||||||
panelGroup2.add(panel2CFR);
|
panelGroup2.add(panel2CFR);
|
||||||
|
panelGroup2.add(jadxJ2);
|
||||||
panelGroup2.add(panel2JDGUI);
|
panelGroup2.add(panel2JDGUI);
|
||||||
panelGroup2.add(panel2Fern);
|
panelGroup2.add(panel2Fern);
|
||||||
panelGroup2.add(panel2Krakatau);
|
panelGroup2.add(panel2Krakatau);
|
||||||
|
@ -2360,6 +2406,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier
|
||||||
panelGroup3.add(panel3None);
|
panelGroup3.add(panel3None);
|
||||||
panelGroup3.add(panel3Proc);
|
panelGroup3.add(panel3Proc);
|
||||||
panelGroup3.add(panel3CFR);
|
panelGroup3.add(panel3CFR);
|
||||||
|
panelGroup3.add(jadxJ3);
|
||||||
panelGroup3.add(panel3JDGUI);
|
panelGroup3.add(panel3JDGUI);
|
||||||
panelGroup3.add(panel3Fern);
|
panelGroup3.add(panel3Fern);
|
||||||
panelGroup3.add(panel3Krakatau);
|
panelGroup3.add(panel3Krakatau);
|
||||||
|
|
|
@ -29,8 +29,7 @@ import javax.swing.event.CaretListener;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.*;
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.gui.TabbedPane.BLANK;
|
import static the.bytecode.club.bytecodeviewer.gui.TabbedPane.BLANK;
|
||||||
|
@ -57,6 +56,38 @@ public abstract class PaneUpdaterThread extends Thread
|
||||||
public void run() {
|
public void run() {
|
||||||
doShit();
|
doShit();
|
||||||
synchronizePane();
|
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()
|
public final CaretListener caretListener = new CaretListener()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package the.bytecode.club.bytecodeviewer.util;
|
package the.bytecode.club.bytecodeviewer.util;
|
||||||
|
|
||||||
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -55,14 +57,35 @@ public class Dex2Jar {
|
||||||
* @param output the output .dex file
|
* @param output the output .dex file
|
||||||
*/
|
*/
|
||||||
public static synchronized void saveAsDex(File input, File output) {
|
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 {
|
try {
|
||||||
com.googlecode.dex2jar.tools.Dex2jarCmd.main(new String[]{input.getAbsolutePath()});
|
com.googlecode.dex2jar.tools.Jar2Dex.main(new String[]{input.getAbsolutePath()});
|
||||||
String realOutput = input.getName().replaceAll("\\.jar", "-jar2dex.dex");
|
File currentDexLocation = new File("./"+input.getName());
|
||||||
File realOutputF = new File(realOutput);
|
|
||||||
realOutputF.renameTo(output);
|
if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".jar"))
|
||||||
File realOutputF2 = new File(realOutput);
|
{
|
||||||
while (realOutputF2.exists())
|
currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.jar", "-jar2dex.dex"));
|
||||||
realOutputF2.delete();
|
}
|
||||||
|
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) {
|
} catch (Exception e) {
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,8 @@ public class FileContainer {
|
||||||
public File file;
|
public File file;
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
public HashMap<String, byte[]> files = new HashMap<String, byte[]>();
|
public HashMap<String, byte[]> files = new HashMap<>();
|
||||||
public ArrayList<ClassNode> classes = new ArrayList<ClassNode>();
|
public ArrayList<ClassNode> classes = new ArrayList<>();
|
||||||
|
|
||||||
public ClassNode getClassNode(String name) {
|
public ClassNode getClassNode(String name) {
|
||||||
for (ClassNode c : classes)
|
for (ClassNode c : classes)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package the.bytecode.club.bytecodeviewer.util;
|
package the.bytecode.club.bytecodeviewer.util;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
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.ZipArchiveEntry;
|
||||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||||
import org.apache.commons.compress.utils.IOUtils;
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
@ -59,7 +57,7 @@ public class JarUtils {
|
||||||
*/
|
*/
|
||||||
public static void put(final File jarFile) throws IOException {
|
public static void put(final File jarFile) throws IOException {
|
||||||
FileContainer container = new FileContainer(jarFile);
|
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));
|
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
|
||||||
ZipEntry entry;
|
ZipEntry entry;
|
||||||
|
@ -86,7 +84,7 @@ public class JarUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (ZipException e) {
|
} catch (java.io.EOFException | ZipException e) {
|
||||||
//ignore cause apache unzip
|
//ignore cause apache unzip
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
||||||
|
@ -99,12 +97,12 @@ public class JarUtils {
|
||||||
BytecodeViewer.files.add(container);
|
BytecodeViewer.files.add(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void put2(final File jarFile) throws IOException {
|
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
|
{
|
||||||
|
//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);
|
FileContainer container = new FileContainer(jarFile);
|
||||||
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
|
HashMap<String, byte[]> files = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
Path path = jarFile.toPath();
|
Path path = jarFile.toPath();
|
||||||
|
|
||||||
|
@ -114,29 +112,42 @@ public class JarUtils {
|
||||||
try (ZipFile zipFile = new ZipFile(jarFile))
|
try (ZipFile zipFile = new ZipFile(jarFile))
|
||||||
{
|
{
|
||||||
Enumeration<? extends ZipArchiveEntry> entries = zipFile.getEntries();
|
Enumeration<? extends ZipArchiveEntry> entries = zipFile.getEntries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements())
|
||||||
|
{
|
||||||
ZipArchiveEntry entry = entries.nextElement();
|
ZipArchiveEntry entry = entries.nextElement();
|
||||||
Path entryPath = destFolderPath.resolve(entry.getName());
|
Path entryPath = destFolderPath.resolve(entry.getName());
|
||||||
String name = entry.getName();
|
String name = entry.getName();
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory())
|
||||||
|
{
|
||||||
//directory
|
//directory
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
try (InputStream in = zipFile.getInputStream(entry))
|
try (InputStream in = zipFile.getInputStream(entry))
|
||||||
{
|
{
|
||||||
|
|
||||||
final byte[] bytes = getBytes(in);
|
final byte[] bytes = getBytes(in);
|
||||||
if (!name.endsWith(".class")) {
|
|
||||||
|
if(!name.endsWith(".class"))
|
||||||
|
{
|
||||||
files.put(name, bytes);
|
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]);
|
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")) {
|
if (cafebabe.toLowerCase().equals("cafebabe"))
|
||||||
try {
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
final ClassNode cn = getNode(bytes);
|
final ClassNode cn = getNode(bytes);
|
||||||
container.classes.add(cn);
|
container.classes.add(cn);
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
files.put(name, bytes);
|
files.put(name, bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +204,7 @@ public class JarUtils {
|
||||||
if (!zipFile.exists())
|
if (!zipFile.exists())
|
||||||
return null; //just ignore
|
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));
|
ZipInputStream jis = new ZipInputStream(new FileInputStream(zipFile));
|
||||||
ZipEntry entry;
|
ZipEntry entry;
|
||||||
|
|
Loading…
Reference in a new issue