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.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 a new issue