diff --git a/BytecodeViewer 2.1.1.jar b/BytecodeViewer 2.2.0.jar similarity index 94% rename from BytecodeViewer 2.1.1.jar rename to BytecodeViewer 2.2.0.jar index b1ca0088..ef5b669e 100644 Binary files a/BytecodeViewer 2.1.1.jar and b/BytecodeViewer 2.2.0.jar differ diff --git a/README.txt b/README.txt index 0c75a531..4efa7f19 100644 --- a/README.txt +++ b/README.txt @@ -169,4 +169,10 @@ Changelog: 11/19/2014 - Added annotatitons/local variables to the methodnode decompiler (Thanks Bibl). 11/21/2014 - Decided to release it with the obfuscator/reflection kit unfinished, they're currently disabled for future use. --- 2.1.1 ---: -12/09/2014 - Upated CFR to cfr_0_91. \ No newline at end of file +12/09/2014 - Upated CFR to cfr_0_91. +--- 2.2.0 ---: +12/09/2014 - Added a text search function to the plugin console. +12/09/2014 - When you press enter in the text search bar, it will now search. +12/13/2014 - The Bytecode Decompiler now shows the method's description in a comment. +12/13/2014 - Fixed an issue with the text search function. +12/13/2014 - Search results are now clickable. \ No newline at end of file diff --git a/VERSION b/VERSION index 7c327287..e3a4f193 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.1 \ No newline at end of file +2.2.0 \ No newline at end of file diff --git a/src/me/konloch/kontainer/io/DiskWriter.java b/src/me/konloch/kontainer/io/DiskWriter.java index cb0fb204..e84f15ae 100644 --- a/src/me/konloch/kontainer/io/DiskWriter.java +++ b/src/me/konloch/kontainer/io/DiskWriter.java @@ -6,8 +6,7 @@ import java.io.FileWriter; import java.io.PrintWriter; /** - * This method will save to disk, if it failed it will keep trying until - * it's saved to disk + * This method will save to disk * * @author Konloch * diff --git a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index 2456d6ce..c9013a67 100644 --- a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -59,18 +59,16 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager; * * TODO: * The import jar method eats up a lot of memory, look into some how reducing this. - * Make the search results clickable * Add a tool to build a flowchart of all the classes, and what methods execute what classes, and those method, read chatlog - * 2.1: * Add obfuscation * Add progress bars on saving all zips/java decompile jar * Add the jump/save mark system Ida Pro has. * Add a search function to the plugin console? - * Add integer boxing and other obfuscation methods contra thought of + * Add integer boxing and other obfuscation methods contra implemented * Insert unadded/debug opcodes to try to fuck up decompilers * ClassAnylyzterAdapter * - * ----Beta 1.0-----: + * ----Beta 1.0.0-----: * 10/4/2014 - Designed a POC GUI, still needs a lot of work. * 10/4/2014 - Started importing J-RET's backend. * 10/5/2014 - Finished importing J-RET's backend. @@ -129,12 +127,12 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager; * 10/16/2014 - Now if you try search with an empty string, it won't search. * 10/16/2014 - Added Replace Strings plugin. * 10/16/2014 - Added a loading icon that displays whenever a background task is being executed. - * ----Beta 1.1-----: + * ----Beta 1.1.0-----: * 10/19/2014 - Fixed harcoded \\. - * ----Beta 1.2-----: + * ----Beta 1.2.0-----: * 10/19/2014 - Started importing Procyon and CFR decompilers. * 10/19/2014 - Partially finished importing Procyon and CFR, just need to finish export java files as zip. - * ----Beta 1.3-----: + * ----Beta 1.3.0-----: * 10/22/2014 - Imported Bibl's Bytecode Decompiler from CFIDE. * 10/22/2014 - Did some changes to the Bytecode Decompiler. * 10/23/2014 - Added CFR settings. @@ -150,13 +148,13 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager; * 10/29/2014 - Replaced JSyntaxPane with RSyntaxArea, this sadly removes the search feature inside of source/bytecode files, I'll implement a search function soon. (This also fixes the JRE 1.8 issue) * 10/29/2014 - Added a new decompiler option to append brackets to labels. * 10/31/2014 - Fixed an issue with the decompiler still running when the source code pane isn't toggled. - * ----Beta 1.4-----: + * ----Beta 1.4.0-----: * 11/1/2014 - Fixed FernFlower save Java files on Unix. * 11/1/2014 - FernFlower now uses the settings for save Java files. * 11/1/2014 - Added Procyon save Java files (It uses the settings). * 11/1/2014 - Updated CFR to cfr_0_89. * 11/1/2014 - Added CFR save Java files (It uses the settings), however it relies on the file system, because of this if there is heavy name obfuscation, it could mess up for windows. - * -----Beta 1.5-----: + * -----Beta 1.5.0-----: * 11/1/2014 - Updated and improved the search function, it now prints out more useful information. * 11/1/2014 - Fixed a UI issue with the Replace All Strings plugin. * 11/2/2014 - Added search function to the Class Viewer. @@ -171,7 +169,7 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager; * 11/3/2014 - Removed the option to disable syntax highlighting (since it's lightweight now). * 11/3/2014 - About window now contains the version number and the BCV directory. * 11/3/2014 - Added an option to toggle to outdated status. - * -----2.0-----: + * -----2.0.0-----: * 11/4/2014 - Officially been 1 month of development. * 11/4/2014 - Replaced ""+ with String.valueOf (cheers bibl). * 11/4/2014 - Changed how the temp directory was created. @@ -185,9 +183,9 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager; * 11/5/2014 - Improved the Malicious Code Scanner, also made it instant. * 11/5/2014 - Added icons to the program (cheers Fluke). * -----2.0.1-----: - * 11/7/2014 - Fixed the search function. + * 11/7/2014 - Fixed the text search function. * 11/7/2014 - Removed an unused package containing some unused classes. - * -----2.1-----: + * -----2.1.0-----: * 11/5/2014 - Started working on the EZ-Inject plugin. * 11/6/2014 - Fixed the ClassNodeDecompiler creating unnessessary objects. (thanks bibl). * 11/6/2014 - Finished an alpha version of EZ-Inject. @@ -202,8 +200,14 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager; * 11/17/2014 - Fixed an issue with the out of date checking UI still activating when not selected. * 11/19/2014 - Added annotatitons/local variables to the methodnode decompiler (Thanks Bibl). * 11/21/2014 - Decided to release it with the obfuscator/reflection kit unfinished, they're currently disabled for future use. - * -----2.1-----: - * Updated CFR to cfr_0_91. + * -----2.1.1-----: + * 12/09/2014 - Updated CFR to cfr_0_91. + * -----2.2.0-----: + * 12/09/2014 - Added a text search function to the plugin console. + * 12/09/2014 - When you press enter in the text search bar, it will now search. + * 12/13/2014 - The Bytecode Decompiler now shows the method's description in a comment. + * 12/13/2014 - Fixed an issue with the text search function. + * 12/13/2014 - Search results are now clickable. * * @author Konloch * @@ -225,7 +229,7 @@ public class BytecodeViewer { private static ArrayList recentPlugins = DiskReader.loadArrayList(pluginsName, false); public static boolean runningObfuscation = false; - public static String version = "2.1.1"; + public static String version = "2.2.0"; public static void main(String[] args) { iconList = new ArrayList(); diff --git a/src/the/bytecode/club/bytecodeviewer/api/PluginConsole.java b/src/the/bytecode/club/bytecodeviewer/api/PluginConsole.java index fcbfa5dc..eae1e781 100644 --- a/src/the/bytecode/club/bytecodeviewer/api/PluginConsole.java +++ b/src/the/bytecode/club/bytecodeviewer/api/PluginConsole.java @@ -1,17 +1,31 @@ package the.bytecode.club.bytecodeviewer.api; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JFrame; +import javax.swing.JTextField; +import java.awt.Color; import java.awt.Dimension; import javax.swing.JScrollPane; import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; import javax.swing.JTextArea; import the.bytecode.club.bytecodeviewer.BytecodeViewer; +import javax.swing.JPanel; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; + /** * A simple console GUI. * @@ -22,18 +36,183 @@ import the.bytecode.club.bytecodeviewer.BytecodeViewer; public class PluginConsole extends JFrame { JTextArea textArea = new JTextArea(); + JPanel panel = new JPanel(new BorderLayout()); + JScrollPane scrollPane = new JScrollPane(); + public JCheckBox check = new JCheckBox("Exact"); public PluginConsole(String pluginName) { this.setIconImages(BytecodeViewer.iconList); setTitle("Bytecode Viewer - Plugin Console - " + pluginName); setSize(new Dimension(542, 316)); - JScrollPane scrollPane = new JScrollPane(); getContentPane().add(scrollPane, BorderLayout.CENTER); scrollPane.setViewportView(textArea); + + + JButton searchNext = new JButton(); + JButton searchPrev = new JButton(); + JPanel buttonPane = new JPanel(new BorderLayout()); + buttonPane.add(searchNext, BorderLayout.WEST); + buttonPane.add(searchPrev, BorderLayout.EAST); + searchNext.setIcon(new ImageIcon(BytecodeViewer.b642IMG("iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAABnRSTlMANzlYqPBJSG/ZAAAASUlEQVR42mNgwAbS0oAEE4yHyWBmYAzjYDC694OJ4f9+BoY3H0BSbz6A2MxA6VciFyDqGAWQTWVkYEkCUrcOsDD8OwtkvMViMwAb8xEUHlHcFAAAAABJRU5ErkJggg=="))); + searchPrev.setIcon(new ImageIcon(BytecodeViewer.b642IMG("iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAABnRSTlMANzlYgKhxpRi1AAAATElEQVR42mNgwAZYHIAEExA7qUAYLApMDmCGEwODCojByM/A8FEAyPi/moFh9QewYjCAM1iA+D2KqYwMrIlA6tUGFoa/Z4GMt1hsBgCe1wuKber+SwAAAABJRU5ErkJggg=="))); + panel.add(buttonPane, BorderLayout.WEST); + final JTextField field = new JTextField(); + panel.add(field, BorderLayout.CENTER); + panel.add(check, BorderLayout.EAST); + searchNext.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + search(field.getText(), true); + } + }); + searchPrev.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + search(field.getText(), false); + } + }); + field.addKeyListener(new KeyListener() { + @Override + public void keyReleased(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_ENTER) + search(field.getText(), true); + } + + @Override + public void keyPressed(KeyEvent arg0) {} + @Override + public void keyTyped(KeyEvent arg0) {} + }); + + scrollPane.setColumnHeaderView(panel); this.setLocationRelativeTo(null); } + + /** + * This was really interesting to write. + * + * @author Konloch + * + */ + public void search(String search, boolean next) { + try { + JTextArea area = textArea; + if(search.isEmpty()) { + highlight(area, ""); + return; + } + + int startLine = area.getDocument().getDefaultRootElement().getElementIndex(area.getCaretPosition())+1; + int currentLine = 1; + boolean canSearch = false; + String[] test = null; + if(area.getText().split("\n").length >= 2) + test = area.getText().split("\n"); + else + test = area.getText().split("\r"); + int lastGoodLine = -1; + int firstPos = -1; + boolean found = false; + + if(next) { + for(String s : test) { + if(!check.isSelected()) + { + s = s.toLowerCase(); + search = search.toLowerCase(); + } + + if(currentLine == startLine) { + canSearch = true; + } else if(s.contains(search)) { + if(canSearch) { + area.setCaretPosition(area.getDocument() + .getDefaultRootElement().getElement(currentLine-1) + .getStartOffset()); + canSearch = false; + found = true; + } + + if(firstPos == -1) + firstPos = currentLine; + } + + currentLine++; + } + + if(!found && firstPos != -1) { + area.setCaretPosition(area.getDocument() + .getDefaultRootElement().getElement(firstPos-1) + .getStartOffset()); + } + } else { + canSearch = true; + for(String s : test) { + if(!check.isSelected()) + { + s = s.toLowerCase(); + search = search.toLowerCase(); + } + + if(s.contains(search)) { + if(lastGoodLine != -1 && canSearch) + area.setCaretPosition(area.getDocument() + .getDefaultRootElement().getElement(lastGoodLine-1) + .getStartOffset()); + + lastGoodLine = currentLine; + + if(currentLine >= startLine) + canSearch = false; + } + currentLine++; + } + + if(lastGoodLine != -1 && area.getDocument().getDefaultRootElement().getElementIndex(area.getCaretPosition())+1 == startLine) { + area.setCaretPosition(area.getDocument() + .getDefaultRootElement().getElement(lastGoodLine-1) + .getStartOffset()); + } + } + highlight(area, search); + } catch(Exception e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + } + + private DefaultHighlighter.DefaultHighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(new Color(255,62,150)); + + public void highlight(JTextComponent textComp, String pattern) { + if(pattern.isEmpty()) { + textComp.getHighlighter().removeAllHighlights(); + return; + } + + try { + Highlighter hilite = textComp.getHighlighter(); + hilite.removeAllHighlights(); + javax.swing.text.Document doc = textComp.getDocument(); + String text = doc.getText(0, doc.getLength()); + int pos = 0; + + if(!check.isSelected()) { + pattern = pattern.toLowerCase(); + text = text.toLowerCase(); + } + + // Search for pattern + while ((pos = text.indexOf(pattern, pos)) >= 0) { + // Create highlighter using private painter and apply around pattern + hilite.addHighlight(pos, pos + pattern.length(), painter); + pos += pattern.length(); + } + } catch (Exception e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + } + /** * Appends \r\n to the end of your string, then it puts it on the top. * @param t the string you want to append diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/MethodNodeDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/MethodNodeDecompiler.java index 037ce597..daf47d65 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/MethodNodeDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/bytecode/MethodNodeDecompiler.java @@ -85,7 +85,10 @@ public class MethodNodeDecompiler { } if (s.contains("abstract")) { - sb.append(" {}"+BytecodeViewer.nl); + sb.append(" {}"); + sb.append(" //"); + sb.append(m.desc); + sb.append(BytecodeViewer.nl); } else { sb.append(" {"); @@ -96,6 +99,9 @@ public class MethodNodeDecompiler { else if(m.name.equals("")) sb.append(" // "); } + + sb.append(" //"); + sb.append(m.desc); sb.append(BytecodeViewer.nl); @@ -113,7 +119,6 @@ public class MethodNodeDecompiler { addAttrList(m.visibleAnnotations, "visAnno", sb, insnPrinter); addAttrList(m.visibleLocalVariableAnnotations, "visLocalVarAnno", sb, insnPrinter); addAttrList(m.visibleTypeAnnotations, "visTypeAnno", sb, insnPrinter); - for (Object o : m.tryCatchBlocks) { TryCatchBlockNode tcbn = (TryCatchBlockNode) o; diff --git a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java index d1abdd21..6bd865a6 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java @@ -10,6 +10,8 @@ import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; import java.util.ArrayList; import static javax.swing.ScrollPaneConstants.*; @@ -187,6 +189,13 @@ public class ClassViewer extends JPanel { } else { canSearch = true; for(String s : test) { + if(pane == 0 && !byteCheck.isSelected() || + pane == 1 && !decompCheck.isSelected()) + { + s = s.toLowerCase(); + search = search.toLowerCase(); + } + if(s.contains(search)) { if(lastGoodLine != -1 && canSearch) area.setCaretPosition(area.getDocument() @@ -270,6 +279,18 @@ public class ClassViewer extends JPanel { search(0,byteField.getText(), false); } }); + byteField.addKeyListener(new KeyListener() { + @Override + public void keyReleased(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_ENTER) + search(0,byteField.getText(), true); + } + + @Override + public void keyPressed(KeyEvent arg0) {} + @Override + public void keyTyped(KeyEvent arg0) {} + }); JButton decompSearchNext = new JButton(); JButton decompSearchPrev = new JButton(); @@ -294,6 +315,18 @@ public class ClassViewer extends JPanel { search(1,decompField.getText(), false); } }); + decompField.addKeyListener(new KeyListener() { + @Override + public void keyReleased(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_ENTER) + search(1,decompField.getText(), true); + } + + @Override + public void keyPressed(KeyEvent arg0) {} + @Override + public void keyTyped(KeyEvent arg0) {} + }); sourcePane = BytecodeViewer.viewer.sourcePane.isSelected(); bytecodePane = BytecodeViewer.viewer.bytecodePane.isSelected(); diff --git a/src/the/bytecode/club/bytecodeviewer/gui/SearchingPane.java b/src/the/bytecode/club/bytecodeviewer/gui/SearchingPane.java index ffe1ca5c..c54d52dd 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/SearchingPane.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/SearchingPane.java @@ -18,7 +18,6 @@ import javax.swing.JTree; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import org.objectweb.asm.tree.ClassNode; @@ -173,14 +172,15 @@ public class SearchingPane extends VisibleComponent { this.tree.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(final TreeSelectionEvent arg0) { - final TreePath path = arg0.getPath(); - if ( ((TreeNode)path.getLastPathComponent()).getChildCount() > 0) - return; - final String clazzName = path.getLastPathComponent().toString(); - final ClassNode fN = BytecodeViewer.getClassNode(clazzName); + String path = arg0.getPath().toString(); + + String className = path.split(", ")[1].split("\\.")[0]; + final ClassNode fN = BytecodeViewer.getClassNode(className); if (fN != null) { - MainViewerGUI.getComponent(FileNavigationPane.class).openClassFileToWorkSpace(clazzName, fN); + MainViewerGUI.getComponent(FileNavigationPane.class).openClassFileToWorkSpace(className, fN); } + + System.out.println(className); } }); diff --git a/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameClasses.java b/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameClasses.java index 858cdba2..3b72a112 100644 --- a/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameClasses.java +++ b/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameClasses.java @@ -11,14 +11,14 @@ public class RenameClasses extends JavaObfuscator { public void obfuscate() { int stringLength = getStringLength(); - System.out.println("Obfuscating"); + System.out.println("Obfuscating class names..."); for(ClassNode c : BytecodeViewer.getLoadedClasses()) { String newName = generateUniqueName(stringLength); ASMUtil_OLD.renameClassNode(c.name, newName); c.name = newName; } - System.out.println("Obfuscated"); + System.out.println("Obfuscated class names."); } } diff --git a/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameFields.java b/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameFields.java index d9fc6bca..27dbb791 100644 --- a/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameFields.java +++ b/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameFields.java @@ -12,7 +12,7 @@ public class RenameFields extends JavaObfuscator { public void obfuscate() { int stringLength = getStringLength(); - System.out.println("Obfuscating"); + System.out.println("Obfuscating fields names..."); for(ClassNode c : BytecodeViewer.getLoadedClasses()) { for(Object o : c.fields.toArray()) { FieldNode f = (FieldNode)o; @@ -22,7 +22,7 @@ public class RenameFields extends JavaObfuscator { } } - System.out.println("Obfuscated"); + System.out.println("Obfuscated field names."); } } diff --git a/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameMethods.java b/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameMethods.java index 118cbae3..2734439a 100644 --- a/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameMethods.java +++ b/src/the/bytecode/club/bytecodeviewer/obfuscators/RenameMethods.java @@ -13,7 +13,7 @@ public class RenameMethods extends JavaObfuscator { public void obfuscate() { int stringLength = getStringLength(); - System.out.println("Obfuscating"); + System.out.println("Obfuscating method names..."); for(ClassNode c : BytecodeViewer.getLoadedClasses()) { for(Object o : c.methods.toArray()) { MethodNode m = (MethodNode)o; @@ -37,7 +37,7 @@ public class RenameMethods extends JavaObfuscator { } } - System.out.println("Obfuscated"); + System.out.println("Obfuscated method names."); } } diff --git a/src/the/bytecode/club/bytecodeviewer/searching/MethodCallSearch.java b/src/the/bytecode/club/bytecodeviewer/searching/MethodCallSearch.java index 33f3ce52..64770729 100644 --- a/src/the/bytecode/club/bytecodeviewer/searching/MethodCallSearch.java +++ b/src/the/bytecode/club/bytecodeviewer/searching/MethodCallSearch.java @@ -44,6 +44,7 @@ public class MethodCallSearch implements SearchTypeDetails { return myPanel; } + @SuppressWarnings("unchecked") @Override public void search(final ClassNode node, final SearchResultNotifier srn, boolean exact) {