diff --git a/BytecodeViewer Beta 1.5.jar b/BytecodeViewer Beta 1.5.jar new file mode 100644 index 00000000..5cebc8a7 Binary files /dev/null and b/BytecodeViewer Beta 1.5.jar differ diff --git a/README.txt b/README.txt index fdf232cb..83c8c92d 100644 --- a/README.txt +++ b/README.txt @@ -118,3 +118,8 @@ Changelog: 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 ---: +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. +11/2/2014 - Updated Procyon to procyon-decompiler-0.5.27. \ No newline at end of file diff --git a/VERSION b/VERSION index 86d106c3..a9eaba36 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Beta 1.4 \ No newline at end of file +Beta 1.5 \ No newline at end of file diff --git a/libs/procyon-decompiler-0.5.26.jar b/libs/procyon-decompiler-0.5.27.jar similarity index 87% rename from libs/procyon-decompiler-0.5.26.jar rename to libs/procyon-decompiler-0.5.27.jar index af340304..623f1902 100644 Binary files a/libs/procyon-decompiler-0.5.26.jar and b/libs/procyon-decompiler-0.5.27.jar differ diff --git a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index 39da77ef..256cfa41 100644 --- a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -58,7 +58,7 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager; * 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 * Middle mouse click should close tabs - * http://i.imgur.com/yHaai9D.png + * Add more details on the search results. * * * ----Beta 1.0-----: @@ -147,6 +147,11 @@ import the.bytecode.club.bytecodeviewer.plugins.PluginManager; * 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-----: + * 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. + * 11/2/2014 - Updated Procyon to procyon-decompiler-0.5.27. * * @author Konloch * @@ -165,7 +170,7 @@ public class BytecodeViewer { public static String fs = System.getProperty("file.separator"); public static String nl = System.getProperty("line.separator"); public static String tempDirectory = "bcv_temp"; - public static String version = "Beta 1.4"; + public static String version = "Beta 1.5"; public static void main(String[] args) { cleanup(); @@ -385,7 +390,7 @@ public class BytecodeViewer { private static String quickConvert(ArrayList a) { String s = ""; for(String r : a) - s += r+"\r"; + s += r+nl; return s; } diff --git a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java index a817c0e7..78a778d8 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java @@ -1,7 +1,11 @@ package the.bytecode.club.bytecodeviewer.gui; import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.HierarchyEvent; @@ -10,15 +14,21 @@ import java.util.ArrayList; import static javax.swing.ScrollPaneConstants.*; +import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; +import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.text.AbstractDocument; import javax.swing.text.BoxView; import javax.swing.text.ComponentView; +import javax.swing.text.DefaultHighlighter; import javax.swing.text.Element; +import javax.swing.text.Highlighter; import javax.swing.text.IconView; +import javax.swing.text.JTextComponent; import javax.swing.text.LabelView; import javax.swing.text.StyleConstants; import javax.swing.text.StyledEditorKit; @@ -96,13 +106,100 @@ public class ClassViewer extends JPanel { ClassNode cn; JSplitPane sp; JSplitPane sp2; + public JCheckBox byteCheck = new JCheckBox("Exact"); + public JPanel bytePanelSearch = new JPanel(new BorderLayout()); + public JPanel decompPanelSearch = new JPanel(new BorderLayout()); + public JCheckBox decompCheck = new JCheckBox("Exact"); public JPanel bytePanel = new JPanel(new BorderLayout()); public JPanel decompPanel = new JPanel(new BorderLayout()); + public void search(int pane, String search) { + try { + if(pane == 0) { //bytecode + for(Component c : bytePanel.getComponents()) { + if(c instanceof RTextScrollPane) { + RSyntaxTextArea area = (RSyntaxTextArea) ((RTextScrollPane)c).getViewport().getComponent(0); + highlight(pane, area, search); + } + } + } else if(pane == 1) { //decomp + for(Component c : decompPanel.getComponents()) { + if(c instanceof RTextScrollPane) { + RSyntaxTextArea area = (RSyntaxTextArea) ((RTextScrollPane)c).getViewport().getComponent(0); + highlight(pane, area, search); + } + } + } + } catch(Exception e) { + e.printStackTrace(); + } + } + + private DefaultHighlighter.DefaultHighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(new Color(255,62,150)); + + public void highlight(int pane, 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((pane == 0 && !byteCheck.isSelected()) || pane == 1 && !decompCheck.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) { + e.printStackTrace(); + } + } + public ClassViewer(final String name, final ClassNode cn) { + JButton byteSearch = new JButton("Search"); + bytePanelSearch.add(byteSearch, BorderLayout.WEST); + final JTextField byteField = new JTextField(); + bytePanelSearch.add(byteField, BorderLayout.CENTER); + bytePanelSearch.add(byteCheck, BorderLayout.EAST); + byteSearch.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + search(0,byteField.getText()); + } + }); + + JButton decompSearch = new JButton("Search"); + decompPanelSearch.add(decompSearch, BorderLayout.WEST); + final JTextField decompField = new JTextField(); + decompPanelSearch.add(decompField, BorderLayout.CENTER); + decompPanelSearch.add(decompCheck, BorderLayout.EAST); + decompSearch.addActionListener(new ActionListener() { + @Override + public void actionPerformed(final ActionEvent arg0) { + search(1,decompField.getText()); + } + }); + sourcePane = BytecodeViewer.viewer.sourcePane.isSelected(); bytecodePane = BytecodeViewer.viewer.bytecodePane.isSelected(); hexPane = BytecodeViewer.viewer.hexPane.isSelected(); + + if(bytecodePane) + bytePanel.add(bytePanelSearch, BorderLayout.NORTH); + if(sourcePane) + decompPanel.add(decompPanelSearch, BorderLayout.NORTH); + this.name = name; this.cn = cn; this.setName(name); diff --git a/src/the/bytecode/club/bytecodeviewer/gui/SearchingPane.java b/src/the/bytecode/club/bytecodeviewer/gui/SearchingPane.java index a062a29f..d9888a95 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/SearchingPane.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/SearchingPane.java @@ -128,9 +128,8 @@ public class SearchingPane extends VisibleComponent { final SearchRadius radius = (SearchRadius) searchRadiusBox.getSelectedItem(); final SearchResultNotifier srn = new SearchResultNotifier() { @Override - public void notifyOfResult(final ClassNode clazz, - final MethodNode method, final AbstractInsnNode insn) { - treeRoot.add(new DefaultMutableTreeNode(clazz.name + "." + method.name)); + public void notifyOfResult(String debug) { + treeRoot.add(new DefaultMutableTreeNode(debug)); } }; if (radius == SearchRadius.All_Classes) { diff --git a/src/the/bytecode/club/bytecodeviewer/plugins/ReplaceStrings.java b/src/the/bytecode/club/bytecodeviewer/plugins/ReplaceStrings.java index dc633bcd..cc692c7a 100644 --- a/src/the/bytecode/club/bytecodeviewer/plugins/ReplaceStrings.java +++ b/src/the/bytecode/club/bytecodeviewer/plugins/ReplaceStrings.java @@ -93,13 +93,13 @@ public class ReplaceStrings extends Plugin { if(s.contains(originalLDC)) { ((LdcInsnNode)a).cst = ((String)((LdcInsnNode)a).cst).replaceAll(originalLDC, newLDC); String ugh = s.replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r"); - frame.appendText(classNode.name + "." +m.name+""+m.desc+" -> \"" + ugh + "\" replaced with \"" + s.replaceAll(originalLDC, newLDC) + "\""); + frame.appendText(classNode.name + "." +m.name+""+m.desc+" -> \"" + ugh + "\" replaced with \"" + s.replaceAll(originalLDC, newLDC).replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r") + "\""); } } else { if(s.equals(originalLDC)) { ((LdcInsnNode)a).cst = newLDC; String ugh = s.replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r"); - frame.appendText(classNode.name + "." +m.name+""+m.desc+" -> \"" + ugh + "\" replaced with \"" + newLDC + "\""); + frame.appendText(classNode.name + "." +m.name+""+m.desc+" -> \"" + ugh + "\" replaced with \"" + newLDC.replaceAll("\\n", "\\\\n").replaceAll("\\r", "\\\\r") + "\""); } } } diff --git a/src/the/bytecode/club/bytecodeviewer/searching/FieldCallSearch.java b/src/the/bytecode/club/bytecodeviewer/searching/FieldCallSearch.java index 6463ddd4..a2de432f 100644 --- a/src/the/bytecode/club/bytecodeviewer/searching/FieldCallSearch.java +++ b/src/the/bytecode/club/bytecodeviewer/searching/FieldCallSearch.java @@ -8,15 +8,19 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; +import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.MethodNode; +import eu.bibl.banalysis.asm.desc.OpcodeInfo; + /** * Field call searching * + * @author Konloch * @author Water Wolf * */ @@ -78,7 +82,7 @@ public class FieldCallSearch implements SearchTypeDetails { if (desc != null && !desc.equals(min.desc)) { continue; } - srn.notifyOfResult(node, method, insnNode); + srn.notifyOfResult(node.name + "." + method.name + Type.getType(method.desc) + " > " + OpcodeInfo.OPCODES.get(insnNode.getOpcode()).toLowerCase()); } else { if (name != null && !name.contains(min.name)) { @@ -90,7 +94,7 @@ public class FieldCallSearch implements SearchTypeDetails { if (desc != null && !desc.contains(min.desc)) { continue; } - srn.notifyOfResult(node, method, insnNode); + srn.notifyOfResult(node.name + "." + method.name + Type.getType(method.desc) + " > " + OpcodeInfo.OPCODES.get(insnNode.getOpcode()).toLowerCase()); } } } diff --git a/src/the/bytecode/club/bytecodeviewer/searching/LDCSearch.java b/src/the/bytecode/club/bytecodeviewer/searching/LDCSearch.java index bf62fac3..a3d7ac3b 100644 --- a/src/the/bytecode/club/bytecodeviewer/searching/LDCSearch.java +++ b/src/the/bytecode/club/bytecodeviewer/searching/LDCSearch.java @@ -1,5 +1,7 @@ package the.bytecode.club.bytecodeviewer.searching; +import groovyjarjarasm.asm.tree.FieldNode; + import java.awt.GridLayout; import java.util.Iterator; import java.util.ListIterator; @@ -8,6 +10,7 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; +import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.InsnList; @@ -17,6 +20,7 @@ import org.objectweb.asm.tree.MethodNode; /** * LDC Searching * + * @author Konloch * @author WaterWolf * */ @@ -51,16 +55,24 @@ public class LDCSearch implements SearchTypeDetails { while (instructions.hasNext()) { final AbstractInsnNode insnNode = instructions.next(); if (insnNode instanceof LdcInsnNode) { - final Object ldcObject = ((LdcInsnNode) insnNode).cst; - final String ldcString = ldcObject.toString(); + final LdcInsnNode ldcObject = ((LdcInsnNode) insnNode); + final String ldcString = ldcObject.cst.toString(); if ((exact && ldcString.equals(srchText)) || (!exact && ldcString.contains(srchText))) { - srn.notifyOfResult(node, method, insnNode); + srn.notifyOfResult(node.name + "." + method.name + Type.getType(method.desc).getInternalName() + " -> \""+ldcString + "\" > " + ldcObject.cst.getClass().getCanonicalName()); } } } } + final Iterator fields = node.fields.iterator(); + while (methods.hasNext()) { + final FieldNode field = fields.next(); + if(field.value instanceof String) { + srn.notifyOfResult(node.name + "." + field.name + field.desc + " -> \"" + field.value + "\" > field"); + } + } + } } \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/searching/MethodCallSearch.java b/src/the/bytecode/club/bytecodeviewer/searching/MethodCallSearch.java index b018f8e4..33f3ce52 100644 --- a/src/the/bytecode/club/bytecodeviewer/searching/MethodCallSearch.java +++ b/src/the/bytecode/club/bytecodeviewer/searching/MethodCallSearch.java @@ -8,15 +8,19 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; +import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; +import eu.bibl.banalysis.asm.desc.OpcodeInfo; + /** * Method call searching * + * @author Konloch * @author WaterWolf * */ @@ -78,7 +82,7 @@ public class MethodCallSearch implements SearchTypeDetails { if (desc != null && !desc.equals(min.desc)) { continue; } - srn.notifyOfResult(node, method, insnNode); + srn.notifyOfResult(node.name + "." + method.name + Type.getType(method.desc) + " > " + OpcodeInfo.OPCODES.get(insnNode.getOpcode()).toLowerCase()); } else { if (name != null && !name.contains(min.name)) { continue; @@ -89,7 +93,7 @@ public class MethodCallSearch implements SearchTypeDetails { if (desc != null && !desc.contains(min.desc)) { continue; } - srn.notifyOfResult(node, method, insnNode); + srn.notifyOfResult(node.name + "." + method.name + Type.getType(method.desc) + " > " + OpcodeInfo.OPCODES.get(insnNode.getOpcode()).toLowerCase()); } } } diff --git a/src/the/bytecode/club/bytecodeviewer/searching/RegexSearch.java b/src/the/bytecode/club/bytecodeviewer/searching/RegexSearch.java index 10529bbf..13c43ae1 100644 --- a/src/the/bytecode/club/bytecodeviewer/searching/RegexSearch.java +++ b/src/the/bytecode/club/bytecodeviewer/searching/RegexSearch.java @@ -13,6 +13,7 @@ import org.objectweb.asm.tree.MethodNode; /** * Regex Searching * + * @author Konloch * @author WaterWolf * */ @@ -53,7 +54,7 @@ public class RegexSearch implements SearchTypeDetails { } if (regexFinder.find(srchText).length > 0) { - srn.notifyOfResult(node, method, null); + srn.notifyOfResult(node.name + "." + method.name + method.desc); } } diff --git a/src/the/bytecode/club/bytecodeviewer/searching/SearchResultNotifier.java b/src/the/bytecode/club/bytecodeviewer/searching/SearchResultNotifier.java index dbd878eb..5da54590 100644 --- a/src/the/bytecode/club/bytecodeviewer/searching/SearchResultNotifier.java +++ b/src/the/bytecode/club/bytecodeviewer/searching/SearchResultNotifier.java @@ -1,17 +1,13 @@ package the.bytecode.club.bytecodeviewer.searching; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodNode; - /** * Used to update the search pane that there's been a result found. * + * @author Konloch * @author WaterWolf * */ public interface SearchResultNotifier { - public void notifyOfResult(ClassNode clazz, MethodNode method, - AbstractInsnNode insn); + public void notifyOfResult(String debug); }