v2.9.18 fixes + JADX decompiler
This commit is contained in:
parent
fb4f2a1371
commit
7f227ca7e7
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)));
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
DecompilationOptions decompilationOptions = new DecompilationOptions();
|
||||
decompilationOptions.setSettings(DecompilerSettings.javaDefaults());
|
||||
decompilationOptions.setSettings(settings);
|
||||
decompilationOptions.setFullDecompilation(true);
|
||||
|
||||
TypeDefinition resolvedType = null;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue