From 52adc8851062776be8f18978d289090b0dd3078e Mon Sep 17 00:00:00 2001 From: Corey-Dean Arthur <1339555+CoreyD97@users.noreply.github.com> Date: Wed, 31 Mar 2021 16:23:56 +0100 Subject: [PATCH 01/25] Panel listener only executes convert once --- src/main/java/burp/Convertors.java | 14 +++++--- src/main/java/burp/ui/HackvertorPanel.java | 38 ++++++++++++++++------ 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/main/java/burp/Convertors.java b/src/main/java/burp/Convertors.java index 6886e3d..c7cc5b6 100644 --- a/src/main/java/burp/Convertors.java +++ b/src/main/java/burp/Convertors.java @@ -518,6 +518,13 @@ public static String callTag(HashMap variableMap, JSONArray cust return loop_letters_upper(variableMap, customTags, output, getString(arguments, 0)); case "loop_numbers": return loop_letters_numbers(variableMap, customTags, output, getString(arguments, 0)); + case "sleep": + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return ""; } } @@ -2247,13 +2254,10 @@ static String substring(String str, int start, int end) { } static String repeat(String str, int amount) { - String output = ""; if (amount > 0 && amount < 10000) { - for (int i = 0; i < amount; i++) { - output += str; - } + return str.repeat(amount); } - return output; + return ""; } static String split_join(String str, String splitChar, String joinChar) { diff --git a/src/main/java/burp/ui/HackvertorPanel.java b/src/main/java/burp/ui/HackvertorPanel.java index c126b95..eb223a2 100644 --- a/src/main/java/burp/ui/HackvertorPanel.java +++ b/src/main/java/burp/ui/HackvertorPanel.java @@ -11,6 +11,7 @@ import javax.swing.*; import javax.swing.event.*; +import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; @@ -22,6 +23,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.LinkedList; +import java.util.concurrent.*; import java.util.stream.Collectors; import static burp.BurpExtender.*; @@ -135,26 +137,42 @@ public void actionPerformed(ActionEvent evt) { } final JTextArea outputArea = new JTextArea(); outputArea.setFont(new Font("Courier New", Font.PLAIN, 12)); + DocumentListener documentListener = new DocumentListener() { + LinkedBlockingQueue queue = new LinkedBlockingQueue<>(1); + ExecutorService executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, + queue, new ThreadPoolExecutor.DiscardOldestPolicy()); + + public void scheduleUpdate(){ + executorService.submit(() -> { + String output = hackvertor.convert(inputArea.getText()); + try { + outputArea.getDocument().remove(0, outputArea.getDocument().getLength()); + outputArea.getDocument().insertString(0, output, null); + } catch (BadLocationException e) { + e.printStackTrace(); + } + outputArea.setCaretPosition(0); + }); + } + + public void changedUpdate(DocumentEvent documentEvent) { - updateLen(documentEvent); - outputArea.setText(hackvertor.convert(inputArea.getText())); - outputArea.setCaretPosition(0); + updateLen(); + scheduleUpdate(); } public void insertUpdate(DocumentEvent documentEvent) { - updateLen(documentEvent); - outputArea.setText(hackvertor.convert(inputArea.getText())); - outputArea.setCaretPosition(0); + updateLen(); + scheduleUpdate(); } public void removeUpdate(DocumentEvent documentEvent) { - updateLen(documentEvent); - outputArea.setText(hackvertor.convert(inputArea.getText())); - outputArea.setCaretPosition(0); + updateLen(); + scheduleUpdate(); } - private void updateLen(DocumentEvent documentEvent) { + private void updateLen() { int len = inputArea.getText().length(); int realLen = calculateRealLen(inputArea.getText()); inputLenLabel.setText("" + len); From 1808730c51e39781de07f30caf57a6e0ce0a9b38 Mon Sep 17 00:00:00 2001 From: Corey <1339555+CoreyD97@users.noreply.github.com> Date: Thu, 11 May 2023 10:55:22 +0100 Subject: [PATCH 02/25] Update Java version. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index fde3ffe..478666f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java' -targetCompatibility = 1.8 -sourceCompatibility = 1.8 +targetCompatibility = JavaVersion.VERSION_17 +sourceCompatibility = JavaVersion.VERSION_17 compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' From d0174c3af172254aa25469f95a0b3940ab67eec1 Mon Sep 17 00:00:00 2001 From: Corey <1339555+CoreyD97@users.noreply.github.com> Date: Thu, 11 May 2023 10:56:11 +0100 Subject: [PATCH 03/25] Small improvements. Use scheduler to prevent lag when converting large documents. --- hackvertor.iml | 37 +--------------- src/main/java/burp/Convertors.java | 50 +++++++++++++--------- src/main/java/burp/ui/HackvertorInput.java | 2 +- src/main/java/burp/ui/HackvertorPanel.java | 5 +-- 4 files changed, 32 insertions(+), 62 deletions(-) diff --git a/hackvertor.iml b/hackvertor.iml index ec337e0..0aa8195 100644 --- a/hackvertor.iml +++ b/hackvertor.iml @@ -1,43 +1,8 @@ - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/java/burp/Convertors.java b/src/main/java/burp/Convertors.java index ac074c3..576108a 100644 --- a/src/main/java/burp/Convertors.java +++ b/src/main/java/burp/Convertors.java @@ -135,7 +135,7 @@ public static String callTag(HashMap variableMap, JSONArray cust tagCount.put(tag, count + 1); } for(int i=0;i variables, JSONArray customTags, String input){ + public static String strictConvert(HashMap variables, JSONArray customTags, String input, Hackvertor hackvertor){ Queue tagElements; try { tagElements = HackvertorParser.parse(input); - return convert(variables, customTags, "", new Stack<>(), tagElements); + return strictConvert(variables, customTags, "", new Stack<>(), tagElements, hackvertor); }catch (Exception e){ StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); @@ -655,7 +655,7 @@ public static String weakConvert(HashMap variables, JSONArray cu Queue tagElements; try { tagElements = HackvertorParser.parse(input); - tagElements = weakConvertProcessSetTags(variables, customTags, tagElements); + tagElements = weakConvertPreProcessSetTags(variables, customTags, tagElements); return weakConvert(variables, customTags, new Stack<>(), tagElements, hackvertor); }catch (Exception e){ StringWriter sw = new StringWriter(); @@ -666,7 +666,7 @@ public static String weakConvert(HashMap variables, JSONArray cu /** * Recursive conversion, ensuring tags are properly matched. - * Does not treat mismatched tags as text. + * Does not treat mismatched tags as text. Will throw an error instead. * @param variables * @param customTags * @param textBuffer @@ -675,11 +675,11 @@ public static String weakConvert(HashMap variables, JSONArray cu * @return * @throws ParseException */ - private static String convert(HashMap variables, - JSONArray customTags, - String textBuffer, - Stack stack, - Queue elements) throws ParseException{ + private static String strictConvert(HashMap variables, + JSONArray customTags, + String textBuffer, + Stack stack, + Queue elements, Hackvertor hackvertor) throws ParseException{ if(elements.size() == 0) { if(stack.size() > 0){ String error = String.format("Unclosed tag%s - %s",stack.size()>1?"s":"", @@ -695,11 +695,11 @@ private static String convert(HashMap variables, textBuffer+= ((Element.TextElement) element).getContent(); }else if(element instanceof Element.SelfClosingTag){ //Self closing tag. Just add its output to textbuffer. Element.SelfClosingTag selfClosingTag = (Element.SelfClosingTag) element; - String tagOutput = callTag(variables, customTags, selfClosingTag.getIdentifier(), "", selfClosingTag.getArguments(), null); + String tagOutput = callTag(variables, customTags, selfClosingTag.getIdentifier(), "", selfClosingTag.getArguments(), hackvertor); textBuffer+= tagOutput; }else if(element instanceof Element.StartTag){ //Start of a conversion. stack.push((Element.StartTag) element); - textBuffer+= convert(variables, customTags, "", stack, elements); + textBuffer+= strictConvert(variables, customTags, "", stack, elements, hackvertor); }else if(element instanceof Element.EndTag){ //End of a conversion. Convert and update textbuffer. Element.StartTag startTag; Element.EndTag endTag = (Element.EndTag) element; @@ -712,15 +712,23 @@ private static String convert(HashMap variables, throw new ParseException(String.format("Mismatched opening and closing tags, %s and %s.", startTag.getIdentifier(), endTag.getIdentifier())); } - return callTag(variables, customTags, startTag.getIdentifier(), textBuffer, startTag.getArguments(), null); + return callTag(variables, customTags, startTag.getIdentifier(), textBuffer, startTag.getArguments(), hackvertor); } - return convert(variables, customTags, textBuffer, stack, elements); + return strictConvert(variables, customTags, textBuffer, stack, elements, hackvertor); } - private static Queue weakConvertProcessSetTags(HashMap variables, - JSONArray customTags, - Queue elements) throws ParseException{ + /** + * Process all variable setting tags in a list of tokens, and update the variables map with their values + * @param variables The map of variables and their values + * @param customTags Any custom tags to be processed + * @param elements A list of lexical tokens + * @return + * @throws ParseException + */ + private static Queue weakConvertPreProcessSetTags(HashMap variables, + JSONArray customTags, + Queue elements) throws ParseException{ Queue elementQueue = new LinkedList<>(); Iterator iter = elements.iterator(); while(iter.hasNext()) { @@ -3391,7 +3399,7 @@ static String loop_for(HashMap variableMap, JSONArray customTags String output = ""; for (int i = start; i < end; i += increment) { variableMap.put(variable, Integer.toString(i)); - output += convert(variableMap, customTags, input); + output += weakConvert(variableMap, customTags, input, null); } return output; } @@ -3400,7 +3408,7 @@ static String loop_letters_lower(HashMap variableMap, JSONArray String output = ""; for (char letter = 'a'; letter <= 'z'; letter++) { variableMap.put(variable, Character.toString(letter)); - output += convert(variableMap, customTags, input);; + output += weakConvert(variableMap, customTags, input, null); } return output; } @@ -3409,7 +3417,7 @@ static String loop_letters_upper(HashMap variableMap, JSONArray String output = ""; for (char letter = 'A'; letter <= 'Z'; letter++) { variableMap.put(variable, Character.toString(letter)); - output += convert(variableMap, customTags, input); + output += weakConvert(variableMap, customTags, input, null); } return output; } @@ -3418,7 +3426,7 @@ static String loop_letters_numbers(HashMap variableMap, JSONArra String output = ""; for (char num = '0'; num <= '9'; num++) { variableMap.put(variable, Character.toString(num)); - output += convert(variableMap, customTags, input); + output += weakConvert(variableMap, customTags, input, null); } return output; } diff --git a/src/main/java/burp/ui/HackvertorInput.java b/src/main/java/burp/ui/HackvertorInput.java index b795912..3a74f6e 100644 --- a/src/main/java/burp/ui/HackvertorInput.java +++ b/src/main/java/burp/ui/HackvertorInput.java @@ -30,6 +30,6 @@ public void updateUI() { this.updateFont(); } public void updateFont() { - this.setFont(new Font("Courier New", Font.PLAIN, this.getFont().getSize())); + this.setFont(new Font("Courier New", Font.PLAIN, this.getFont() != null ? this.getFont().getSize() : 11)); } } diff --git a/src/main/java/burp/ui/HackvertorPanel.java b/src/main/java/burp/ui/HackvertorPanel.java index ba4a17f..22bca47 100644 --- a/src/main/java/burp/ui/HackvertorPanel.java +++ b/src/main/java/burp/ui/HackvertorPanel.java @@ -161,9 +161,6 @@ public void actionPerformed(ActionEvent evt) { inputLenLabel.setBackground(Color.decode("#FFF5BF")); inputLenLabel.setBorder(BorderFactory.createLineBorder(Color.decode("#FF9900"), 1)); } - final JTextArea outputArea = new JTextArea(); - outputArea.setFont(new Font("Courier New", Font.PLAIN, 12)); - DocumentListener documentListener = new DocumentListener() { LinkedBlockingQueue queue = new LinkedBlockingQueue<>(1); ExecutorService executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, @@ -171,7 +168,7 @@ public void actionPerformed(ActionEvent evt) { public void scheduleUpdate(){ executorService.submit(() -> { - String output = hackvertor.convert(inputArea.getText()); + String output = hackvertor.convert(inputArea.getText(), null); try { outputArea.getDocument().remove(0, outputArea.getDocument().getLength()); outputArea.getDocument().insertString(0, output, null); From 3fbd1a2379e6509a744967781c4bbbf3711ac0af Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Fri, 15 Dec 2023 12:58:59 +0000 Subject: [PATCH 04/25] Implemented tag store and fixed UI issues with custom tags. --- README.md | 21 ++ src/main/java/burp/BurpExtender.java | 418 +++++++++++++++++---- src/main/java/burp/Convertors.java | 38 ++ src/main/java/burp/Hackvertor.java | 14 + src/main/java/burp/Utils.java | 65 +++- src/main/java/burp/ui/HackvertorPanel.java | 33 +- tag-store/README.md | 27 ++ tag-store/base62_decode/base62_decode.py | 32 ++ tag-store/base62_encode/base62_encode.py | 35 ++ tag-store/hello_world/hello_world.py | 1 + tag-store/tag-store.json | 29 ++ 11 files changed, 612 insertions(+), 101 deletions(-) create mode 100644 tag-store/README.md create mode 100644 tag-store/base62_decode/base62_decode.py create mode 100644 tag-store/base62_encode/base62_encode.py create mode 100644 tag-store/hello_world/hello_world.py create mode 100644 tag-store/tag-store.json diff --git a/README.md b/README.md index b21650e..937cab4 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,27 @@ Hackvertor is a tag based conversion tool written in Java implemented as a Burp Tags also support arguments. The find tag allows you to find a string by regex and has parenthesis after the unique tag number: <@find_0("\\w")>abc<@/find_0> this indicates it supports arguments. The argument in this case is the regex string to find on the text inbetween the tags. Hackvertor allows you to use two types of arguments either strings (double, single) or numbers (including hex). +# Changelog + +**1.8.4 2023-11-1** + +- Continued improvements on create tag window. + +**1.8.3 2023-11-1** + +- Disabled install button when tag is installed +- Started work on create new tag to make more room + +**1.8.2 2023-10-31** +- Fixed editing tags without producing duplicates +- Added export to tag store + +**1.8.1 2023-10-30** +- Fixed bug when installing a tag from the tag store with the same name. + +**1.8 2023-10-26** +- Implemented tag store. Installable tags from Github. + # Installation - In order to use Hackvertor you need to open Burp Suite. diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index 8e6d8bf..ca3dba5 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -11,7 +11,9 @@ import org.json.JSONObject; import javax.swing.*; +import javax.swing.border.EmptyBorder; import javax.swing.event.*; +import javax.swing.table.DefaultTableModel; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.datatransfer.Clipboard; @@ -19,10 +21,8 @@ import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.*; +import java.io.*; import java.net.*; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintWriter; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -80,16 +80,16 @@ public class BurpExtender implements IBurpExtender, ITab, IContextMenuFactory, I public static int MAX_POPULAR_TAGS = 10; - public static GridBagConstraints createConstraints(int x, int y, int gridWidth) { + public static GridBagConstraints createConstraints(int x, int y, int gridWidth, int fill, double weightx, double weighty, int ipadx, int ipady) { GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 0; - c.weighty = 0; + c.fill = fill; c.gridx = x; c.gridy = y; - c.ipadx = 0; - c.ipady = 0; + c.ipadx = ipadx; + c.ipady = ipady; c.gridwidth = gridWidth; + c.weightx = weightx; + c.weighty = weighty; return c; } @@ -201,7 +201,7 @@ public void run() { } try { hackvertor = new Hackvertor(); - stdout.println("Hackvertor v1.7.49"); + stdout.println("Hackvertor v1.8.4"); loadCustomTags(); loadGlobalVariables(); registerPayloadProcessors(); @@ -341,19 +341,20 @@ public void actionPerformed(ActionEvent e) { showListTagsDialog(); } }); + JMenuItem tagStoreMenu = new JMenuItem("View tag store"); + tagStoreMenu.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showTagStore(); + } + }); hvMenuBar.add(globalVariablesMenu); hvMenuBar.add(createCustomTagsMenu); hvMenuBar.add(listCustomTagsMenu); + hvMenuBar.add(tagStoreMenu); JMenuItem reportBugMenu = new JMenuItem("Report bug/request feature"); reportBugMenu.addActionListener(e -> { - if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { - try { - Desktop.getDesktop().browse(new URI("https://github.com/hackvertor/hackvertor/issues/new")); - } catch (IOException ioException) { - } catch (URISyntaxException uriSyntaxException) { - - } - } + Utils.openUrl("https://github.com/hackvertor/hackvertor/issues/new"); }); hvMenuBar.add(reportBugMenu); burpMenuBar.add(hvMenuBar); @@ -505,7 +506,8 @@ public void actionPerformed(ActionEvent e) { createVariableWindow.setVisible(true); } public void showCreateEditTagDialog(boolean edit, String editTagName) { - JPanel createTagPanel = new JPanel(); + JPanel createTagPanel = new JPanel(new GridBagLayout()); + createTagPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); JFrame createTagWindow; JSONObject customTag = null; if (edit) { @@ -522,21 +524,18 @@ public void showCreateEditTagDialog(boolean edit, String editTagName) { } } } - - createTagWindow.setResizable(false); - createTagWindow.setPreferredSize(new Dimension(500, 600)); + createTagWindow.setResizable(true); + createTagWindow.setPreferredSize(new Dimension(800, 600)); + createTagPanel.setPreferredSize(new Dimension(800, 600)); JLabel tagLabel = new JLabel("Tag name"); - tagLabel.setPreferredSize(new Dimension(220, 25)); JTextField tagNameField = new JTextField(); if (edit && customTag != null && customTag.has("tagName")) { tagNameField.setText(customTag.getString("tagName")); tagNameField.setEditable(false); } - tagNameField.setPreferredSize(new Dimension(220, 30)); - createTagPanel.add(tagLabel); - createTagPanel.add(tagNameField); + createTagPanel.add(tagLabel, createConstraints(0, 0, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + createTagPanel.add(tagNameField, createConstraints(1, 0, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); JLabel languageLabel = new JLabel("Select language"); - languageLabel.setPreferredSize(new Dimension(220, 25)); JTextComponent.removeKeymap("RTextAreaKeymap"); HackvertorInput codeArea = new HackvertorInput(); Utils.fixRSyntaxAreaBurp(); @@ -569,11 +568,12 @@ public void actionPerformed(ActionEvent e) { if (changes[0] > 0) { return; } - String code = "output = convert(\"<@base64>\"+input+\"<@/base64>\")\n"; String comment = "//"; if(index == 1) { comment = "#"; } + String code = "output = input\n"; + code += comment + "output = convert(\"<@base64>\"+input+\"<@/base64>\")\n"; code += comment + "output = convert(\"<@customTag('\"+executionKey+\"')>\"+input+\"<@/customTag>\")"; codeArea.setText(code); changes[0] = 0; @@ -594,7 +594,6 @@ public void actionPerformed(ActionEvent e) { } } }); - languageCombo.setPreferredSize(new Dimension(220, 25)); languageCombo.addItem("JavaScript"); languageCombo.addItem("Python"); languageCombo.addItem("Java"); @@ -607,7 +606,7 @@ public void actionPerformed(ActionEvent e) { languageCombo.setSelectedIndex(1); } else if (customTag.getString("language").equals("Java")) { languageCombo.setSelectedIndex(2); - } else if (customTag.getString("language").equals("groovy")) { + } else if (customTag.getString("language").equals("Groovy")) { languageCombo.setSelectedIndex(3); } } @@ -615,10 +614,9 @@ public void actionPerformed(ActionEvent e) { codeArea.setText(customTag.getString("code")); } Container pane = createTagWindow.getContentPane(); - createTagPanel.add(languageLabel); - createTagPanel.add(languageCombo); + createTagPanel.add(languageLabel, createConstraints(0, 1, 1, GridBagConstraints.BOTH, 0, 0, 5, 5)); + createTagPanel.add(languageCombo, createConstraints(1, 1, 1, GridBagConstraints.BOTH, 0, 0, 5, 5)); JLabel argument1Label = new JLabel("Argument1"); - argument1Label.setPreferredSize(new Dimension(100, 25)); JComboBox argument1Combo = new JComboBox(); argument1Combo.addItem("None"); argument1Combo.addItem("String"); @@ -635,27 +633,25 @@ public void actionPerformed(ActionEvent e) { if (edit && customTag != null && customTag.has("argument1")) { argument1NameField.setText(customTag.getString("argument1")); } - argument1NameField.setPreferredSize(new Dimension(100, 25)); JLabel argument1DefaultLabel = new JLabel("Default value"); - argument1DefaultLabel.setPreferredSize(new Dimension(100, 25)); JTextField argument1DefaultValueField = new JTextField(); if (edit && customTag != null && customTag.has("argument1Default")) { argument1DefaultValueField.setText(customTag.getString("argument1Default")); } - argument1DefaultValueField.setPreferredSize(new Dimension(100, 25)); JPanel argument1Panel = new JPanel(); - argument1Panel.setLayout(new GridLayout(0, 2)); - argument1Panel.add(argument1Label); - argument1Panel.add(argument1Combo); - argument1Panel.add(argument1NameLabel); - argument1Panel.add(argument1NameField); - argument1Panel.add(argument1DefaultLabel); - argument1Panel.add(argument1DefaultValueField); - createTagPanel.add(argument1Panel); + argument1Panel.setBorder(new EmptyBorder(0, 0, 0, 10)); + argument1Panel.setPreferredSize(new Dimension(400, 300)); + argument1Panel.setLayout(new GridBagLayout()); + argument1Panel.add(argument1Label, createConstraints(0, 0, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument1Panel.add(argument1Combo, createConstraints(1, 0, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument1Panel.add(argument1NameLabel, createConstraints(0, 1, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument1Panel.add(argument1NameField, createConstraints(1, 1, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument1Panel.add(argument1DefaultLabel, createConstraints(0, 2, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument1Panel.add(argument1DefaultValueField, createConstraints(1, 2, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + createTagPanel.add(argument1Panel, createConstraints(0, 2, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); JLabel argument2NameLabel = new JLabel("Param Name"); JLabel argument2Label = new JLabel("Argument2"); - argument2Label.setPreferredSize(new Dimension(100, 25)); JComboBox argument2Combo = new JComboBox(); argument2Combo.addItem("None"); argument2Combo.addItem("String"); @@ -671,30 +667,26 @@ public void actionPerformed(ActionEvent e) { if (edit && customTag != null && customTag.has("argument2")) { argument2NameField.setText(customTag.getString("argument2")); } - argument2NameField.setPreferredSize(new Dimension(100, 25)); JLabel argument2DefaultLabel = new JLabel("Default value"); - argument2DefaultLabel.setPreferredSize(new Dimension(100, 25)); JTextField argument2DefaultValueField = new JTextField(); if (edit && customTag != null && customTag.has("argument2Default")) { argument2DefaultValueField.setText(customTag.getString("argument2Default")); } - argument2DefaultValueField.setPreferredSize(new Dimension(100, 25)); JPanel argument2Panel = new JPanel(); - argument2Panel.setLayout(new GridLayout(0, 2)); - argument2Panel.add(argument2Label); - argument2Panel.add(argument2Combo); - argument2Panel.add(argument2NameLabel); - argument2Panel.add(argument2NameField); - argument2Panel.add(argument2DefaultLabel); - argument2Panel.add(argument2DefaultValueField); - createTagPanel.add(argument2Panel); + argument2Panel.setPreferredSize(new Dimension(400, 300)); + argument2Panel.setLayout(new GridBagLayout()); + argument2Panel.add(argument2Label, createConstraints(0, 0, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument2Panel.add(argument2Combo, createConstraints(1, 0, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument2Panel.add(argument2NameLabel, createConstraints(0, 1, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument2Panel.add(argument2NameField, createConstraints(1, 1, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument2Panel.add(argument2DefaultLabel, createConstraints(0, 2, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + argument2Panel.add(argument2DefaultValueField, createConstraints(1, 2, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); + createTagPanel.add(argument2Panel, createConstraints(1, 2, 1, GridBagConstraints.BOTH, 1, 0, 5, 5)); JLabel convertLabel = new JLabel("You can now convert Hackvertor tags inside customTags!"); JLabel codeLabel = new JLabel("Code (if you end the code with .js/.py/.java/.groovy it will read a file)"); - codeLabel.setPreferredSize(new Dimension(450, 25)); - codeScroll.setPreferredSize(new Dimension(450, 300)); - createTagPanel.add(convertLabel); - createTagPanel.add(codeLabel); - createTagPanel.add(codeScroll); + createTagPanel.add(convertLabel, createConstraints(0, 3, 2, GridBagConstraints.BOTH, 0, 0, 5, 5)); + createTagPanel.add(codeLabel, createConstraints(0, 4, 2, GridBagConstraints.BOTH, 0, 0, 5, 5)); + createTagPanel.add(codeScroll, createConstraints(0, 5, 2, GridBagConstraints.BOTH, 1, 1, 5, 5)); JButton cancelButton = new JButton("Cancel"); if (!isNativeTheme && !isDarkTheme) { cancelButton.setBackground(Color.decode("#005a70")); @@ -707,9 +699,38 @@ public void actionPerformed(ActionEvent e) { } }); JLabel errorMessage = new JLabel(); - errorMessage.setPreferredSize(new Dimension(450, 25)); errorMessage.setForeground(Color.red); JButton createButton = new JButton("Create tag"); + JButton exportButton = new JButton("Export to tag store"); + JSONObject finalCustomTag = customTag; + exportButton.addActionListener(e -> { + loadCustomTags(); + for (int i = 0; i < hackvertor.getCustomTags().length(); i++) { + JSONObject savedCustomTag = (JSONObject) hackvertor.getCustomTags().get(i); + if (finalCustomTag.getString("tagName").equals(savedCustomTag.getString("tagName"))) { + JSONObject customTagCopy = new JSONObject(savedCustomTag, JSONObject.getNames(savedCustomTag)); + customTagCopy.remove("code"); + customTagCopy.put("tagName", customTagCopy.get("tagName").toString().replaceFirst("^_","")); + String author = JOptionPane.showInputDialog(null, "Enter your github username", ""); + if(author == null || author.isEmpty()) { + return; + } + String description = JOptionPane.showInputDialog(null, "Enter a description of your tag", ""); + if(description.isEmpty()) { + return; + } + customTagCopy.put("author",author); + customTagCopy.put("description",description); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + StringSelection customTagCopyJSON = new StringSelection(customTagCopy.toString(3)); + clipboard.setContents(customTagCopyJSON, null); + alert("Copied JSON data to clipboard."); + Utils.openUrl("https://github.com/hackvertor/hackvertor/tag-store/README.md"); + return; + } + } + alert("Unable to find tag"); + }); if (edit) { createButton.setText("Update tag"); } @@ -717,7 +738,7 @@ public void actionPerformed(ActionEvent e) { testButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - String tagName = tagNameField.getText().replaceAll("[^\\w+]", ""); + String tagName = Utils.sanitizeTagName(tagNameField.getText()); String language = languageCombo.getSelectedItem().toString(); String code = codeArea.getText(); String argument1 = argument1NameField.getText(); @@ -766,7 +787,6 @@ public void actionPerformed(ActionEvent e) { args.add(argument1DefaultValue); customTagOptions.put("param1", getInt(args, 0)); } - } else if (numberOfArgs == 2) { int pos = 0; if (argument1Type.equals("String")) { @@ -803,42 +823,41 @@ public void actionPerformed(ActionEvent e) { createButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - String tagName = tagNameField.getText().replaceAll("[^\\w+]", ""); + String tagName = Utils.sanitizeTagName(tagNameField.getText()); String language = languageCombo.getSelectedItem().toString(); String code = codeArea.getText(); String argument1 = argument1NameField.getText(); String argument1DefaultValue = argument1DefaultValueField.getText(); String argument2 = argument2NameField.getText(); String argument2DefaultValue = argument2DefaultValueField.getText(); - String paramRegex = "^[a-zA-Z_]\\w{0,10}$"; - String numberRegex = "^(?:0x[a-fA-F0-9]+|\\d+)$"; + int numberOfArgs = 0; - if (tagName.length() < 1) { + if (!Utils.validateTagName(tagName)) { errorMessage.setText("Invalid tag name. Use a-zA-Z_0-9 for tag names"); return; } - if (code.length() < 1) { - errorMessage.setText("Please enter some code"); + if (!Utils.validateCode(code)) { + errorMessage.setText("Please enter some code. Code cannot be blank or exceed " + Utils.MAX_TAG_CODE_LEN + " bytes"); return; } - if (argument1Combo.getSelectedIndex() > 0 && !argument1.matches(paramRegex)) { - errorMessage.setText("Invalid param name. For argument1. Use " + paramRegex); + if (argument1Combo.getSelectedIndex() > 0 && !Utils.validateParam(argument1)) { + errorMessage.setText("Invalid param name. For argument1. Use " + Utils.paramRegex); return; } - if (argument1Combo.getSelectedItem().toString().equals("Number") && !argument1DefaultValue.matches(numberRegex)) { - errorMessage.setText("Invalid default value for argument1. Use " + numberRegex); + if (argument1Combo.getSelectedItem().equals("Number") && !Utils.validateTagParamNumber(argument1DefaultValue)) { + errorMessage.setText("Invalid default value for argument1. Use " + Utils.numberRegex); return; } - if (argument2Combo.getSelectedIndex() > 0 && !argument2.matches(paramRegex)) { - errorMessage.setText("Invalid param name for argument2. Use " + paramRegex); + if (argument2Combo.getSelectedIndex() > 0 && !Utils.validateParam(argument2)) { + errorMessage.setText("Invalid param name for argument2. Use " + Utils.paramRegex); return; } if (argument2Combo.getSelectedIndex() > 0 && argument1Combo.getSelectedIndex() == 0) { errorMessage.setText("You have selected two arguments but not defined the first."); return; } - if (argument2Combo.getSelectedItem().toString().equals("Number") && !argument2DefaultValue.matches(numberRegex)) { - errorMessage.setText("Invalid default value for argument2. Use " + numberRegex); + if (argument2Combo.getSelectedItem().toString().equals("Number") && !Utils.validateTagParamNumber(argument2DefaultValue)) { + errorMessage.setText("Invalid default value for argument2. Use " + Utils.numberRegex); return; } if (argument1Combo.getSelectedIndex() > 0) { @@ -861,17 +880,252 @@ public void actionPerformed(ActionEvent e) { createButton.setForeground(Color.white); testButton.setBackground(Color.decode("#005a70")); testButton.setForeground(Color.white); + exportButton.setBackground(Color.decode("#005a70")); + exportButton.setForeground(Color.white); + } + JPanel buttonsPanel = new JPanel(new GridBagLayout()); + buttonsPanel.add(cancelButton, createConstraints(0, 0, 1, GridBagConstraints.NONE, 0, 0, 5, 5)); + if(edit) { + buttonsPanel.add(exportButton, createConstraints(1, 0, 1, GridBagConstraints.NONE, 0, 0, 5, 5)); } - createTagPanel.add(cancelButton); - createTagPanel.add(testButton); - createTagPanel.add(createButton); - createTagPanel.add(errorMessage); + buttonsPanel.add(testButton, createConstraints(2, 0, 1, GridBagConstraints.NONE, 0, 0, 5, 5)); + buttonsPanel.add(createButton, createConstraints(3, 0, 1, GridBagConstraints.NONE, 0, 0, 5, 5)); + buttonsPanel.add(errorMessage, createConstraints(4, 0, 1, GridBagConstraints.NONE, 0, 0, 5, 5)); + createTagPanel.add(buttonsPanel,createConstraints(0, 6, 2, GridBagConstraints.NONE, 1, 0, 5, 5)) ; pane.add(createTagPanel); createTagWindow.pack(); createTagWindow.setLocationRelativeTo(null); createTagWindow.setVisible(true); } + public void showTagStore() { + final String TAG_STORE_URL = "https://raw.githubusercontent.com/hackvertor/hackvertor/master/tag-store/"; + //final String TAG_STORE_URL = "http://127.0.0.1:4000/"; + String jsonResponse = makeHttpRequest(TAG_STORE_URL + "tag-store.json", "GET"); + if(jsonResponse == null) { + callbacks.printError("Unable to load tag store JSON"); + alert("Unable to load the tag store. Store may be down."); + return; + } + JSONArray tagStore; + try { + tagStore = new JSONArray(jsonResponse); + } catch (JSONException ex) { + alert("Unable to load the tag store. Store may be down."); + callbacks.printError("Invalid JSON"); + return; + } + + if(tagStore.isEmpty()) { + alert("Unable to load the tag store. Tag store JSON not found."); + callbacks.printError("Unable to retrieve JSON"); + return; + } + HashMap storeCode = new HashMap<>(); + JFrame tagStoreWindow = new JFrame("Hackvertor tag store"); + JPanel optionsPanel = new JPanel(new BorderLayout()); + Utils.setMarginAndPadding(optionsPanel, 10); + optionsPanel.setVisible(false); + JLabel title = new JLabel("Title here"); + Utils.setMarginAndPadding(title, 10); + title.setFont(new Font("Arial",Font.BOLD,30)); + title.putClientProperty("html.disable", Boolean.TRUE); + JPanel buttonsPanel = new JPanel(new BorderLayout()); + Utils.setMarginAndPadding(buttonsPanel, 10); + JButton installButton = new JButton("Install tag"); + JButton closeButton = new JButton("Close"); + buttonsPanel.add(closeButton, BorderLayout.WEST); + buttonsPanel.add(installButton, BorderLayout.EAST); + closeButton.addActionListener(e -> { + tagStoreWindow.dispose(); + }); + Utils.setMarginAndPadding(closeButton, 10); + Utils.setMarginAndPadding(installButton, 10); + optionsPanel.add(title, BorderLayout.NORTH); + JTextComponent.removeKeymap("RTextAreaKeymap"); + HackvertorInput codeArea = new HackvertorInput(); + codeArea.setEditable(false); + codeArea.setText("Code goes here"); + Utils.fixRSyntaxAreaBurp(); + Utils.configureRSyntaxArea(codeArea); + codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); + JScrollPane codeScroller = new JScrollPane(codeArea); + Utils.setMarginAndPadding(codeScroller, 10); + JTextArea description = new JTextArea("Description goes here"); + description.setEditable(false); + description.putClientProperty("html.disable", Boolean.TRUE); + JScrollPane descScroller = new JScrollPane(description, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + Utils.setMarginAndPadding(descScroller, 10); + JPanel centerPanel = new JPanel(new BorderLayout()); + centerPanel.add(descScroller, BorderLayout.NORTH); + centerPanel.add(codeScroller, BorderLayout.CENTER); + optionsPanel.add(centerPanel, BorderLayout.CENTER); + optionsPanel.add(buttonsPanel, BorderLayout.SOUTH); + JPanel tagStorePanel = new JPanel(new BorderLayout()); + String[] columnNames = {"Tag name", "Author", "Language"}; + DefaultTableModel tagStoreModel = new DefaultTableModel(columnNames, 0); + HashMap storeTags = new HashMap(); + for(int i=0;i { + alert("Custom tags can compromise your system. Please ensure you've evaluated the code before you install it."); + int confirm = JOptionPane.showConfirmDialog(null, "Are you sure you want to install this custom tag?"); + if(confirm == 0) { + int selectedRow = storeTable.getSelectedRow(); + String tagName = (String) storeTable.getValueAt(selectedRow, 0); + if (!Utils.validateTagName(tagName)) { + alert("Invalid tag name. Use a-zA-Z_0-9 for tag names"); + return; + } + String code = storeCode.get(tagName); + JSONObject tag = storeTags.get(tagName); + int numberOfArgs = tag.getInt("numberOfArgs"); + String language = tag.getString("language"); + if (!Utils.validateCode(code)) { + alert("Invalid code unable to install tag. Code cannot be blank or exceed " + Utils.MAX_TAG_CODE_LEN + " bytes"); + return; + } + String argument1 = null; + String argument1Type = null; + String argument1Default = null; + String argument2 = null; + String argument2Type = null; + String argument2Default = null; + if(numberOfArgs > 0) { + argument1 = tag.getString("argument1"); + argument1Type = tag.getString("argument1Type"); + argument1Default = tag.getString("argument1Default"); + argument2 = tag.getString("argument2"); + argument2Type = tag.getString("argument2Type"); + argument2Default = tag.getString("argument2Default"); + if (!Utils.validateParam(argument1)) { + alert("Invalid param name. For argument1. Use " + Utils.paramRegex); + return; + } + if (argument1Type.equals("Number") && !Utils.validateTagParamNumber(argument1Default)) { + alert("Invalid default value for argument1. Use " + Utils.numberRegex); + return; + } + if (!Utils.validateParam(argument2)) { + alert("Invalid param name for argument2. Use " + Utils.paramRegex); + return; + } + if (argument2Type.equals("Number") && !Utils.validateTagParamNumber(argument2Default)) { + alert("Invalid default value for argument2. Use " + Utils.numberRegex); + return; + } + } + loadCustomTags(); + if(hackvertor.hasCustomTag(tagName)) { + updateCustomTag("_" + tagName, language, code, argument1, argument1Type, argument1Default, argument2, argument2Type, argument2Default, numberOfArgs); + } else { + createCustomTag(tagName, language, code, argument1, argument1Type, argument1Default, argument2, argument2Type, argument2Default, numberOfArgs); + } + loadCustomTags(); + alert("Successfully installed the tag"); + } + }); + selectionModel.addListSelectionListener(e -> { + if(e.getValueIsAdjusting()) { + return; + } + int selectedRow = storeTable.getSelectedRow(); + String tagName = (String) storeTable.getValueAt(selectedRow, 0); + tagName = Utils.sanitizeTagName(tagName); + String code = null; + loadCustomTags(); + if(hackvertor.hasCustomTag(tagName)) { + installButton.setEnabled(false); + } else { + installButton.setEnabled(true); + } + + if(storeCode.containsKey(tagName)) { + code = storeCode.get(tagName); + } else { + code = makeHttpRequest(TAG_STORE_URL+tagName+"/"+tagName+Utils.getExtensionFromLanguage(storeTags.get(tagName).getString("language")), "GET"); + if(code == null) { + callbacks.printError("Unable get retrieve code for tag:"+tagName); + return; + } + storeCode.put(tagName, code); + } + title.setText(tagName); + description.setText(storeTags.get(tagName).getString("description")); + String language = storeTags.get(tagName).getString("language"); + + switch(language) { + case "JavaScript": + codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); + break; + case "Python": + codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PYTHON); + break; + case "Java": + codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + break; + case "Groovy": + codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_GROOVY); + break; + } + codeArea.setTabSize(3); + codeArea.setText(code); + codeArea.setCaretPosition(0); + optionsPanel.setVisible(true); + }); + JScrollPane scrollPane = new JScrollPane(storeTable); + tagStorePanel.add(scrollPane, BorderLayout.WEST); + tagStorePanel.add(optionsPanel, BorderLayout.CENTER); + tagStoreWindow.add(tagStorePanel); + tagStoreWindow.setResizable(true); + tagStoreWindow.setPreferredSize(new Dimension(1000, 700)); + tagStoreWindow.pack(); + tagStoreWindow.setLocationRelativeTo(null); + tagStoreWindow.setVisible(true); + } + + public String makeHttpRequest(String requestUrl, String method) { + HttpURLConnection connection = null; + + try { + URL url = new URI(requestUrl).toURL(); + connection = (HttpURLConnection) url.openConnection(); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setUseCaches(false); + connection.setDoOutput(true); + connection.setRequestMethod(method); + InputStream is = connection.getInputStream(); + BufferedReader rd = new BufferedReader(new InputStreamReader(is)); + StringBuilder response = new StringBuilder(); + String line; + while ((line = rd.readLine()) != null) { + response.append(line); + response.append(System.lineSeparator()); + } + rd.close(); + return response.toString(); + } catch (Exception e) { + callbacks.printError("Error making HTTP request:" + e); + e.printStackTrace(); + return null; + } finally { + if (connection != null) { + connection.disconnect(); + } + } + } + public void showListTagsDialog() { JPanel listTagsPanel = new JPanel(); JFrame listTagsWindow = new JFrame("List custom tags"); diff --git a/src/main/java/burp/Convertors.java b/src/main/java/burp/Convertors.java index fbc568d..392abdc 100644 --- a/src/main/java/burp/Convertors.java +++ b/src/main/java/burp/Convertors.java @@ -61,6 +61,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.text.Normalizer; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; @@ -334,6 +335,8 @@ public static String callTag(HashMap variableMap, JSONArray cust return powershell(output); case "js_string": return js_string(output); + case "unicode_alternatives": + return unicode_alternatives(output); case "d_quoted_printable": return d_quoted_printable(output); case "auto_decode": @@ -1487,7 +1490,42 @@ static String js_string(String str) { return JsonEscape.escapeJson(str); } + static String unicode_alternatives(String input) { + StringBuilder output = new StringBuilder(); + HashMap cache = new HashMap<>(); + int len = input.length(); + for (int i = 0; i < len; i++) { + char originalChr = input.charAt(i); + if(input.codePointAt(i) > 0x7f) { + output.append(originalChr); + continue; + } + boolean foundVariant = false; + StringBuilder unicodeCharacters = new StringBuilder(); + if(cache.containsKey(originalChr)) { + output.append(cache.get(originalChr)); + continue; + } + for(int j=0x7f;j<0xffff;j++) { + String chr = new StringBuilder().appendCodePoint(j).toString(); + String normalized = Normalizer.normalize(chr, Normalizer.Form.NFKC); + if(normalized.equals(String.valueOf(originalChr))) { + unicodeCharacters.append(chr); + foundVariant = true; + } + } + if(!foundVariant) { + output.append(originalChr); + } else { + output.append(unicodeCharacters); + cache.put(originalChr, unicodeCharacters); + } + } + return output.toString(); + } + static String d_quoted_printable(String str) { + str = str.replace("=\n",""); QuotedPrintableCodec codec = new QuotedPrintableCodec(); try { return codec.decode(str); diff --git a/src/main/java/burp/Hackvertor.java b/src/main/java/burp/Hackvertor.java index 7ab8e5c..2298313 100644 --- a/src/main/java/burp/Hackvertor.java +++ b/src/main/java/burp/Hackvertor.java @@ -37,6 +37,19 @@ public void setRequest(byte[] request) { this.request = request; } + public boolean hasCustomTag(String tagName) { + tagName = "_" + tagName; + JSONArray customTags = this.getCustomTags(); + int len = customTags.length(); + for (int i = 0; i < len; i++) { + JSONObject customTag = (JSONObject) customTags.get(i); + if (tagName.equals(customTag.getString("tagName"))) { + return true; + } + } + return false; + } + public static String removeHackvertorTags(String input) { try { input = HackvertorParser.parse(input).stream() @@ -175,6 +188,7 @@ void init() { tags.add(new Tag(Tag.Category.Encode, "powershell", true, "powershell(String cmd)")); tags.add(new Tag(Tag.Category.Encode, "quoted_printable", true, "quoted_printable(String str)")); tags.add(new Tag(Tag.Category.Encode, "js_string", true, "js_string(String str)")); + tags.add(new Tag(Tag.Category.Encode, "unicode_alternatives", true, "unicode_alteratives(String str)")); tags.add(new Tag(Tag.Category.Decode, "d_saml", true, "d_saml(String str)")); tags.add(new Tag(Tag.Category.Decode, "auto_decode", true, "auto_decode(String str)")); tags.add(new Tag(Tag.Category.Decode, "auto_decode_no_decrypt", true, "auto_decode_no_decrypt(String str)")); diff --git a/src/main/java/burp/Utils.java b/src/main/java/burp/Utils.java index 7cd2efb..80f4eff 100644 --- a/src/main/java/burp/Utils.java +++ b/src/main/java/burp/Utils.java @@ -3,17 +3,23 @@ import burp.parser.Element; import burp.ui.HackvertorInput; import burp.ui.MenuScroller; +import com.github.javafaker.Bool; import org.apache.commons.lang3.StringUtils; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.Theme; import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; import javax.swing.text.Highlighter; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -23,7 +29,10 @@ import static burp.BurpExtender.*; public class Utils { - + public static String paramRegex = "^[a-zA-Z_]\\w{0,10}$"; + public static String numberRegex = "^(?:0x[a-fA-F0-9]+|\\d+)$"; + public static String tagNameRegex = "[^\\w]"; + public static final int MAX_TAG_CODE_LEN = 1337; public static JScrollPane createButtons(List tags, final JTextArea inputArea, Tag.Category displayCategory, String searchTag, Boolean regex) { JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); JScrollPane scrollFrame = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); @@ -194,4 +203,58 @@ public static void configureRSyntaxArea(HackvertorInput area) { } callbacks.customizeUiComponent(area); } + + public static void setMarginAndPadding(JComponent comp, int amount) { + Border margin = new EmptyBorder(amount,amount,amount,amount); + comp.setBorder(margin); + } + + public static String sanitizeTagName(String tagName) { + return tagName.replaceAll(tagNameRegex, ""); + } + + public static Boolean validateParam(String param) { + return param.matches(paramRegex); + } + + public static Boolean validateCode(String code) { + return !code.isEmpty() && code.length() <= MAX_TAG_CODE_LEN; + } + + public static Boolean validateTagName(String code) { + code = sanitizeTagName(code); + return !code.isEmpty(); + } + + public static Boolean validateTagParamNumber(String tagParamNumber) { + return tagParamNumber.matches(numberRegex); + } + + public static String getExtensionFromLanguage(String language) { + switch (language) { + case "Python": + return ".py"; + case "JavaScript": + return ".js"; + case "Java": + return ".java"; + case "Groovy": + return ".groovy"; + default: + return null; + } + } + + public static void openUrl(String url) { + if(url.startsWith("https://")) { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException ioException) { + } catch (URISyntaxException uriSyntaxException) { + + } + } + } + } } diff --git a/src/main/java/burp/ui/HackvertorPanel.java b/src/main/java/burp/ui/HackvertorPanel.java index 5b55ff2..3a6546c 100644 --- a/src/main/java/burp/ui/HackvertorPanel.java +++ b/src/main/java/burp/ui/HackvertorPanel.java @@ -8,8 +8,6 @@ import org.fife.ui.autocomplete.*; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; -import org.json.JSONArray; -import org.json.JSONObject; import javax.swing.*; import javax.swing.event.*; @@ -26,7 +24,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; -import java.util.stream.Collectors; import static burp.BurpExtender.*; import static burp.Convertors.*; @@ -407,65 +404,65 @@ public void actionPerformed(ActionEvent e) { buttonsPanel.add(selectOutputButton); buttonsPanel.add(pasteInsideButton); buttonsPanel.add(convertButton); - GridBagConstraints c = createConstraints(1, 0, 1); + GridBagConstraints c = createConstraints(1, 0, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.anchor = FIRST_LINE_END; c.ipadx = 20; c.ipady = 20; topBar.add(logoLabel, c); - c = createConstraints(0, 0, 1); + c = createConstraints(0, 0, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.anchor = FIRST_LINE_START; c.fill = BOTH; c.weightx = 1.0; c.weighty = 1; topBar.add(tabs, c); - c = createConstraints(0, 0, 2); + c = createConstraints(0, 0, 2, GridBagConstraints.NONE, 0, 0, 0, 0); c.anchor = FIRST_LINE_START; c.fill = BOTH; c.weightx = 1.0; this.add(topBar, c); JPanel inputLabelsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); - c = createConstraints(0, 0, 1); + c = createConstraints(0, 0, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.WEST; inputLabelsPanel.add(inputLabel, c); - c = createConstraints(1, 1, 1); + c = createConstraints(1, 1, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.WEST; inputLabelsPanel.add(inputLenLabel, c); - c = createConstraints(2, 1, 1); + c = createConstraints(2, 1, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.WEST; inputLabelsPanel.add(inputRealLenLabel, c); - this.add(inputLabelsPanel, createConstraints(0, 2, 1)); - c = createConstraints(0, 3, 1); + this.add(inputLabelsPanel, createConstraints(0, 2, 1, GridBagConstraints.NONE, 0, 0, 0, 0)); + c = createConstraints(0, 3, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.anchor = FIRST_LINE_START; c.fill = BOTH; c.weightx = 0.5; c.weighty = 1.0; this.add(inputScroll, c); JPanel outputLabelsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); - c = createConstraints(0, 1, 1); + c = createConstraints(0, 1, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.insets = new Insets(5, 5, 5, 5); outputLabelsPanel.add(outputLabel, c); - c = createConstraints(1, 1, 1); + c = createConstraints(1, 1, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.insets = new Insets(5, 5, 5, 5); outputLabelsPanel.add(outputLenLabel, c); - c = createConstraints(2, 1, 1); + c = createConstraints(2, 1, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.insets = new Insets(5, 5, 5, 5); outputLabelsPanel.add(outputRealLenLabel, c); - this.add(outputLabelsPanel, createConstraints(1, 2, 1)); - c = createConstraints(1, 3, 1); + this.add(outputLabelsPanel, createConstraints(1, 2, 1, GridBagConstraints.NONE, 0, 0, 0, 0)); + c = createConstraints(1, 3, 1, GridBagConstraints.NONE, 0, 0, 0, 0); c.anchor = FIRST_LINE_START; c.fill = BOTH; c.weightx = 0.5; c.weighty = 1.0; this.add(outputScroll, c); - c = createConstraints(0, 4, 2); + c = createConstraints(0, 4, 2, GridBagConstraints.NONE, 0, 0, 0, 0); c.anchor = GridBagConstraints.SOUTH; c.fill = BOTH; c.weightx = 1.0; this.add(buttonsPanel, c); - c = createConstraints(0, 5, 2); + c = createConstraints(0, 5, 2, GridBagConstraints.NONE, 0, 0, 0, 0); c.insets = new Insets(5, 5, 5, 5); c.anchor = LAST_LINE_START; c.fill = BOTH; diff --git a/tag-store/README.md b/tag-store/README.md new file mode 100644 index 0000000..52d8e18 --- /dev/null +++ b/tag-store/README.md @@ -0,0 +1,27 @@ +# Hackvertor tag store + +Welcome to the Hackvertor tag store. This repository allows Hackvertor users to submit their custom tags to be shared with other users. The store can be viewed in the Hackvertor menu->View tag store. + +## Rules of submission + +1. Only one tag per pull request is allowed. +2. There should only be one file with your code you cannot import multiple files. +3. The maximum size of your code is 1337 bytes. +4. You should create a folder with your tag name and the file should also have the same name. +5. The author property should reflect your github username. +6. Any form of obfuscation will be rejected. +7. Any form of malicious code is obviously not allowed. +8. You must test your tag before submission + +## How to submit your custom tag + +1. Create a custom tag in the usual way. +2. Test and make sure it works in the Hackvertor interface. +3. Edit the custom tag and click "Export to tag store" +4. Fork the Hackvertor github repo. +5. Paste the JSON into the tag-store.json file +6. Create a folder with your tag name in the tag-store folder +7. Create your file inside the folder with the same tag name with the extension +8. Create a pull request. +9. As long as you've followed the rules above the submission will be reviewed and merged +10. Submission approval may take some time as I have a day job :) \ No newline at end of file diff --git a/tag-store/base62_decode/base62_decode.py b/tag-store/base62_decode/base62_decode.py new file mode 100644 index 0000000..5e735fe --- /dev/null +++ b/tag-store/base62_decode/base62_decode.py @@ -0,0 +1,32 @@ +charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +base = 62 + +def _value(ch, charset): + try: + return charset.index(ch) + except ValueError: + raise ValueError("base62: Invalid character (%s)" % ch) + +def decode(encoded): + l, i, v = len(encoded), 0, 0 + for x in encoded: + v += _value(x, charset=charset) * (base ** (l - (i + 1))) + i += 1 + return v + +def decodebytes(encoded): + + leading_null_bytes = b"" + while encoded.startswith("0") and len(encoded) >= 2: + leading_null_bytes += b"\x00" * _value(encoded[1], charset) + encoded = encoded[2:] + decoded = decode(encoded) + buf = bytearray() + while decoded > 0: + buf.append(decoded & 0xFF) + decoded //= 256 + buf.reverse() + + return leading_null_bytes + bytes(buf) + +output = decodebytes(input) \ No newline at end of file diff --git a/tag-store/base62_encode/base62_encode.py b/tag-store/base62_encode/base62_encode.py new file mode 100644 index 0000000..8963e58 --- /dev/null +++ b/tag-store/base62_encode/base62_encode.py @@ -0,0 +1,35 @@ +charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +base = 62 + +def _value(ch, charset): + try: + return charset.index(ch) + except ValueError: + raise ValueError("base62: Invalid character (%s)" % ch) + +def b62_encode(n): + chs = [] + while n > 0: + n, r = divmod(n, base) + chs.insert(0, charset[r]) + if not chs: + return "0" + return "".join(chs) + +def encodebytes(barray): + barray = bytes(barray) + leading_zeros_count = 0 + for i in range(len(barray)): + if barray[i] != 0: + break + leading_zeros_count += 1 + n, r = divmod(leading_zeros_count, len(charset) - 1) + zero_padding = "0{}".format(charset[-1]) * n + if r: + zero_padding += "0{}".format(charset[r]) + if leading_zeros_count == len(barray): + return zero_padding + value = b62_encode(int(barray.encode('hex'), 16)) + return zero_padding + value + +output = encodebytes(input) \ No newline at end of file diff --git a/tag-store/hello_world/hello_world.py b/tag-store/hello_world/hello_world.py new file mode 100644 index 0000000..3b42a76 --- /dev/null +++ b/tag-store/hello_world/hello_world.py @@ -0,0 +1 @@ +output = input + strHello + str(intTest) \ No newline at end of file diff --git a/tag-store/tag-store.json b/tag-store/tag-store.json new file mode 100644 index 0000000..5ac5bde --- /dev/null +++ b/tag-store/tag-store.json @@ -0,0 +1,29 @@ +[ + { + "tagName": "base62_encode", + "description": "Performs a base62 encode.", + "author": "H1v0lt4g3", + "numberOfArgs": 0, + "language": "Python" + }, + { + "tagName": "base62_decode", + "description": "Performs a base62 decode.", + "author": "H1v0lt4g3", + "numberOfArgs": 0, + "language": "Python" + }, + { + "tagName": "hello_world", + "description": "An example tag that shows the JSON structure.", + "author": "hackvertor", + "numberOfArgs": 2, + "argument1": "strHello", + "argument1Type": "String", + "argument1Default": "Hello world", + "argument2": "intTest", + "argument2Type": "Number", + "argument2Default": "1337", + "language": "Python" + } +] \ No newline at end of file From 8ef70bcb5021c47542e3a7d5d5395fc3c2cf42cc Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Mon, 18 Dec 2023 12:15:32 +0000 Subject: [PATCH 05/25] Fixed bug where hex default value for custom tag would be quoted --- README.md | 4 ++++ src/main/java/burp/BurpExtender.java | 2 +- src/main/java/burp/parser/Element.java | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 937cab4..d5aae71 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ Tags also support arguments. The find tag allows you to find a string by regex a # Changelog +**1.8.5 2023-11-1** + +- Fixed bug where hex default value for custom tag would be quoted + **1.8.4 2023-11-1** - Continued improvements on create tag window. diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index ca3dba5..41e34b5 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -201,7 +201,7 @@ public void run() { } try { hackvertor = new Hackvertor(); - stdout.println("Hackvertor v1.8.4"); + stdout.println("Hackvertor v1.8.5"); loadCustomTags(); loadGlobalVariables(); registerPayloadProcessors(); diff --git a/src/main/java/burp/parser/Element.java b/src/main/java/burp/parser/Element.java index 9dcdd13..a0b52bf 100644 --- a/src/main/java/burp/parser/Element.java +++ b/src/main/java/burp/parser/Element.java @@ -32,7 +32,7 @@ public String toString() { for (int i = 0; i < arguments.size(); i++) { if(i != 0) sb.append(","); String argument = arguments.get(i); - if((argument.startsWith("-") && StringUtils.isNumeric(argument.substring(1))) || StringUtils.isNumeric(argument) || argument.equals("true") || argument.equals("false")) + if((argument.startsWith("0x") && argument.matches("^0x[0-9a-fA-F]+$")) || (argument.startsWith("-") && StringUtils.isNumeric(argument.substring(1))) || StringUtils.isNumeric(argument) || argument.equals("true") || argument.equals("false")) sb.append(argument); else sb.append("'" + JavaEscape.escapeJava(argument) + "'"); From b472d8c879a81dfda633a5148b0993265f2d2a14 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Tue, 19 Dec 2023 13:11:22 +0000 Subject: [PATCH 06/25] Added full JavaScript support!!! --- README.md | 6 +- build.gradle | 3 +- src/main/java/burp/BurpExtender.java | 2 +- src/main/java/burp/Convertors.java | 126 ++++++++++++--------------- 4 files changed, 63 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index d5aae71..2530c36 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,11 @@ Tags also support arguments. The find tag allows you to find a string by regex a # Changelog -**1.8.5 2023-11-1** +**1.8.6 2023-12-19** + +- Added full support for JavaScript in custom tags + +**1.8.5 2023-12-18** - Fixed bug where hex default value for custom tag would be quoted diff --git a/build.gradle b/build.gradle index 930a3e9..ce9e4f7 100644 --- a/build.gradle +++ b/build.gradle @@ -25,12 +25,13 @@ dependencies { implementation 'bsf:bsf:2.4.0' implementation 'org.apache-extras.beanshell:bsh:2.0b6' implementation 'org.codehaus.groovy:groovy-all:3.0.16' - implementation 'com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0' implementation 'com.github.javafaker:javafaker:1.0.2' implementation 'com.fifesoft:rsyntaxtextarea:3.3.1' implementation 'com.fifesoft:autocomplete:3.3.1' testImplementation 'junit:junit:4.13.2' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + implementation 'org.graalvm.js:js:23.0.2' + implementation 'org.graalvm.js:js-scriptengine:23.1.1' } sourceSets { diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index 41e34b5..a8daa3a 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -201,7 +201,7 @@ public void run() { } try { hackvertor = new Hackvertor(); - stdout.println("Hackvertor v1.8.5"); + stdout.println("Hackvertor v1.8.6"); loadCustomTags(); loadGlobalVariables(); registerPayloadProcessors(); diff --git a/src/main/java/burp/Convertors.java b/src/main/java/burp/Convertors.java index 392abdc..0c455a3 100644 --- a/src/main/java/burp/Convertors.java +++ b/src/main/java/burp/Convertors.java @@ -10,7 +10,6 @@ import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; -import com.eclipsesource.v8.*; import com.github.javafaker.Faker; import groovy.lang.Binding; import groovy.lang.GroovyShell; @@ -33,6 +32,8 @@ import org.bouncycastle.util.encoders.Hex; import org.brotli.dec.BrotliInputStream; import org.codehaus.groovy.control.CompilationFailedException; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.HostAccess; import org.json.JSONArray; import org.json.JSONObject; import org.python.core.PyException; @@ -3293,87 +3294,64 @@ static String javascript(HashMap variableMap, String input, Stri if (!tagCodeExecutionKey.equals(executionKey)) { return "Incorrect tag code execution key"; } - V8 v8 = V8.createV8Runtime(null, String.valueOf(j2v8TempDirectory)); - String declarations = "var input, output, argument1, argument2"; - Set keySet = variableMap.keySet(); - if(keySet.size() > 0) { - declarations += "," + keySet.stream().collect(Collectors.joining(",")); - } - v8.executeScript(declarations); - v8.add("input", input); - v8.add("executionKey", executionKey); - JavaCallback callback = new JavaCallback() { - public String invoke(final V8Object receiver, final V8Array parameters) { - if (parameters.length() > 0) { - Object input = parameters.get(0); - String output = Convertors.weakConvert(variableMap, customTags, input.toString(), hackvertor); - if (input instanceof Releasable) { - ((Releasable) input).release(); + try { + Context context = Context.newBuilder("js").allowIO(true).allowHostAccess(HostAccess.ALL).build(); + context.getBindings("js").putMember("input", input); + context.getBindings("js").putMember("executionKey", executionKey); + context.getBindings("js").putMember("convert", (EmitReturn) (tagInput) -> Convertors.weakConvert(variableMap, customTags, tagInput, hackvertor)); + + for (Map.Entry entry : variableMap.entrySet()) { + String name = entry.getKey(); + String value = entry.getValue(); + if (name.length() > 0) { + if (value.matches("^\\d+$") || value.matches("^0x[0-9a-fA-F]+$")) { + context.getBindings("js").putMember(name, Integer.parseInt(value)); + } else { + context.getBindings("js").putMember(name, value); } - return output; - } - return ""; - } - }; - v8.registerJavaMethod(callback, "convert"); - for (Map.Entry entry : variableMap.entrySet()) { - String name = entry.getKey(); - String value = entry.getValue(); - if (name.length() > 0) { - if(value.matches("^\\d+$")) { - v8.add(name, Integer.parseInt(value)); - } else { - v8.add(name, value); } } - } - if (customTagOptions != null) { - JSONObject customTag = (JSONObject) customTagOptions.get("customTag"); - int numberOfArgs = customTag.getInt("numberOfArgs"); - if (numberOfArgs == 1) { - String name = customTag.getString("argument1"); - String value = customTagOptions.get("param1").toString(); - if(value.matches("^\\d+$")) { - v8.add(name, Integer.parseInt(value)); - } else { - v8.add(name, value); - } - } - if (numberOfArgs == 2) { - String argument1Name = customTag.getString("argument1"); - String param1Value = customTagOptions.get("param1").toString(); - if(param1Value.matches("^\\d+$")) { - v8.add(argument1Name, Integer.parseInt(param1Value)); - } else { - v8.add(argument1Name, param1Value); + + if (customTagOptions != null) { + JSONObject customTag = (JSONObject) customTagOptions.get("customTag"); + int numberOfArgs = customTag.getInt("numberOfArgs"); + if (numberOfArgs == 1) { + String name = customTag.getString("argument1"); + String value = customTagOptions.get("param1").toString(); + if (value.matches("^\\d+$") || value.matches("^0x[0-9a-fA-F]+$")) { + context.getBindings("js").putMember(name, Integer.parseInt(value)); + } else { + context.getBindings("js").putMember(name, value); + } } - String argument2Name = customTag.getString("argument2"); - String param2Value = customTagOptions.get("param2").toString(); - if(param2Value.matches("^\\d+$")) { - v8.add(argument2Name, Integer.parseInt(param2Value)); - } else { - v8.add(argument2Name, param2Value); + if (numberOfArgs == 2) { + String argument1Name = customTag.getString("argument1"); + String param1Value = customTagOptions.get("param1").toString(); + if (param1Value.matches("^\\d+$") || param1Value.matches("^0x[0-9a-fA-F]+$")) { + context.getBindings("js").putMember(argument1Name, Integer.parseInt(param1Value)); + } else { + context.getBindings("js").putMember(argument1Name, param1Value); + } + String argument2Name = customTag.getString("argument2"); + String param2Value = customTagOptions.get("param2").toString(); + if (param2Value.matches("^\\d+$") || param2Value.matches("^0x[0-9a-fA-F]+$")) { + context.getBindings("js").putMember(argument2Name, Integer.parseInt(param2Value)); + } else { + context.getBindings("js").putMember(argument2Name, param2Value); + } } } - } - try { + if (code.endsWith(".js")) { - v8.executeScript(new String(Files.readAllBytes(Paths.get(code)), StandardCharsets.UTF_8)); + return context.eval("js", new String(Files.readAllBytes(Paths.get(code)), StandardCharsets.UTF_8)).toString(); } else { - v8.executeScript(code); + return context.eval("js", code).toString(); } - return v8.get("output").toString(); - } catch (FileNotFoundException e) { - return "Unable to find JavaScript file:" + e; - } catch (NullPointerException e) { - return "Unable to get output. Make sure you have defined an output variable:" + e.toString(); - } catch (AssertionError | Exception e) { - return "Unable to parse JavaScript:" + e; - } finally { - v8.shutdownExecutors(true); + + } catch (Exception e) { + return "Exception:" + e; } } - static String system(String cmd, Boolean enabled, String executionKey) { if (!codeExecutionTagsEnabled) { return "Code execution tags are disabled by default. Use the menu bar to enable them."; @@ -3426,6 +3404,12 @@ static String system(String cmd, Boolean enabled, String executionKey) { return output.toString(); } + @FunctionalInterface + public interface EmitReturn { + @HostAccess.Export + String emit(T type); + } + static String read_url(String input, String charset, Boolean enabled, String executionKey) { if(!charset.equalsIgnoreCase("UTF-8")) { input = convertCharset(input, charset); From 68e0a528dc2046a6c3937dff42059a7a1d1173cb Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Wed, 20 Dec 2023 12:39:20 +0000 Subject: [PATCH 07/25] Added line numbers to custom tag editor --- README.md | 4 ++++ build.gradle | 2 +- src/main/java/burp/BurpExtender.java | 6 ++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2530c36..35c38aa 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ Tags also support arguments. The find tag allows you to find a string by regex a # Changelog +**1.8.6 2023-12-20** + +- Added line numbers to custom tag editor + **1.8.6 2023-12-19** - Added full support for JavaScript in custom tags diff --git a/build.gradle b/build.gradle index ce9e4f7..a642630 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ dependencies { implementation 'org.apache-extras.beanshell:bsh:2.0b6' implementation 'org.codehaus.groovy:groovy-all:3.0.16' implementation 'com.github.javafaker:javafaker:1.0.2' - implementation 'com.fifesoft:rsyntaxtextarea:3.3.1' + implementation 'com.fifesoft:rsyntaxtextarea:3.3.4' implementation 'com.fifesoft:autocomplete:3.3.1' testImplementation 'junit:junit:4.13.2' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index a8daa3a..cddcc61 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -6,6 +6,7 @@ import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; +import org.fife.ui.rtextarea.RTextScrollPane; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -201,7 +202,7 @@ public void run() { } try { hackvertor = new Hackvertor(); - stdout.println("Hackvertor v1.8.6"); + stdout.println("Hackvertor v1.8.7"); loadCustomTags(); loadGlobalVariables(); registerPayloadProcessors(); @@ -541,7 +542,8 @@ public void showCreateEditTagDialog(boolean edit, String editTagName) { Utils.fixRSyntaxAreaBurp(); Utils.configureRSyntaxArea(codeArea); codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); - JScrollPane codeScroll = new JScrollPane(codeArea); + RTextScrollPane codeScroll = new RTextScrollPane(codeArea); + codeScroll.setLineNumbersEnabled(true); final int[] changes = {0}; codeArea.getDocument().addDocumentListener(new DocumentListener() { From f780c3d6575759e1b8ac2ec3ea3fe3bf0c7fce82 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Thu, 21 Dec 2023 12:18:28 +0000 Subject: [PATCH 08/25] Added remove output tag --- README.md | 4 ++++ src/main/java/burp/BurpExtender.java | 2 +- src/main/java/burp/Convertors.java | 5 +++++ src/main/java/burp/Hackvertor.java | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 35c38aa..f13b2af 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ Tags also support arguments. The find tag allows you to find a string by regex a # Changelog +**1.8.8 2023-12-20** + +- Added remove output tag + **1.8.6 2023-12-20** - Added line numbers to custom tag editor diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index cddcc61..81ba81f 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -202,7 +202,7 @@ public void run() { } try { hackvertor = new Hackvertor(); - stdout.println("Hackvertor v1.8.7"); + stdout.println("Hackvertor v1.8.8"); loadCustomTags(); loadGlobalVariables(); registerPayloadProcessors(); diff --git a/src/main/java/burp/Convertors.java b/src/main/java/burp/Convertors.java index 0c455a3..5f18a30 100644 --- a/src/main/java/burp/Convertors.java +++ b/src/main/java/burp/Convertors.java @@ -404,6 +404,8 @@ public static String callTag(HashMap variableMap, JSONArray cust return lowercase(output); case "unique": return unique(output); + case "remove_output": + return remove_output(output); case "capitalise": return capitalise(output); case "uncapitalise": @@ -1335,6 +1337,9 @@ static String unique(String str) { return String.join(" ", result); } + static String remove_output(String input) { + return ""; + } static String capitalise(String str) { return StringUtils.capitalize(str); } diff --git a/src/main/java/burp/Hackvertor.java b/src/main/java/burp/Hackvertor.java index 2298313..d5db3ce 100644 --- a/src/main/java/burp/Hackvertor.java +++ b/src/main/java/burp/Hackvertor.java @@ -279,6 +279,7 @@ void init() { tag.argument1 = new TagArgument("string", "split char"); tag.argument2 = new TagArgument("string", "join char"); tags.add(tag); + tags.add(new Tag(Tag.Category.String, "remove_output", true, "remove_output(String str)")); Faker faker = new Faker(); generateFakeTags(new Object[]{ From 6ee5b934c4e9b633d1366afa5a90b0c65e38d5ec Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Fri, 22 Dec 2023 12:15:57 +0000 Subject: [PATCH 09/25] Added JSON export/load to file for custom tags --- README.md | 2 + src/main/java/burp/BurpExtender.java | 131 ++++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f13b2af..4ed9bf1 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ Tags also support arguments. The find tag allows you to find a string by regex a **1.8.8 2023-12-20** - Added remove output tag +- Added load from json file +- Added save to json file **1.8.6 2023-12-20** diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index 81ba81f..de9c59d 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -4,6 +4,7 @@ import burp.ui.HackvertorInput; import burp.ui.HackvertorMessageTab; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.FileUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.fife.ui.rtextarea.RTextScrollPane; @@ -14,6 +15,7 @@ import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.event.*; +import javax.swing.filechooser.FileFilter; import javax.swing.table.DefaultTableModel; import javax.swing.text.JTextComponent; import java.awt.*; @@ -25,8 +27,10 @@ import java.io.*; import java.net.*; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.Security; @@ -1156,6 +1160,128 @@ public void actionPerformed(ActionEvent e) { JButton deleteButton = new JButton("Delete tag"); JButton loadButton = new JButton("Load tags from clipboard"); JButton exportButton = new JButton("Export all my tags to clipboard"); + JButton loadFromJsonButton = new JButton("Load from JSON file"); + JButton exportToJsonButton = new JButton("Export all my tags to JSON file"); + exportToJsonButton.addActionListener(e -> { + String customTagsJSON = hackvertor.getCustomTags().toString(); + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileFilter(new FileFilter() { + @Override + public boolean accept(File f) { + return f.getPath().endsWith(".json") || f.isDirectory(); + } + + @Override + public String getDescription() { + return "JSON only"; + } + }); + fileChooser.setDialogTitle("Specify a JSON file to save"); + int userSelection = fileChooser.showSaveDialog(listTagsWindow); + if (userSelection == JFileChooser.APPROVE_OPTION) { + File fileToSave = fileChooser.getSelectedFile(); + if(fileToSave != null && fileToSave.getAbsolutePath().endsWith(".json")) { + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new FileWriter(fileToSave.getAbsolutePath())); + } catch (IOException ex) { + alert("Unable to open file to write:" + ex); + return; + } + try { + writer.write(customTagsJSON); + } catch (IOException ex) { + alert("Failed to write file:" + ex); + return; + } + try { + writer.close(); + } catch (IOException ex) { + alert("Failed to close file:" + ex); + } + } + } + }); + loadFromJsonButton.addActionListener(e -> { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileFilter(new FileFilter() { + @Override + public boolean accept(File f) { + return f.getPath().endsWith(".json") || f.isDirectory(); + } + + @Override + public String getDescription() { + return "JSON only"; + } + }); + fileChooser.setCurrentDirectory(new File(System.getProperty("user.home"))); + int result = fileChooser.showOpenDialog(listTagsWindow); + if (result == JFileChooser.APPROVE_OPTION) { + File selectedFile = fileChooser.getSelectedFile(); + if(selectedFile != null && selectedFile.getAbsolutePath().endsWith(".json")) { + try { + String json = FileUtils.readFileToString(selectedFile, "UTF-8"); + if (json != null && !json.isEmpty()) { + try { + JSONArray tags = new JSONArray(json); + for(int i=0;i 0) { + argument1 = tag.getString("argument1"); + argument1Type = tag.getString("argument1Type"); + argument1Default = tag.getString("argument1Default"); + if (!Utils.validateParam(argument1)) { + alert("Invalid param name. For argument1. Use " + Utils.paramRegex); + return; + } + if (argument1Type.equals("Number") && !Utils.validateTagParamNumber(argument1Default)) { + alert("Invalid default value for argument1. Use " + Utils.numberRegex); + return; + } + if(numberOfArgs == 2) { + argument2 = tag.getString("argument2"); + argument2Type = tag.getString("argument2Type"); + argument2Default = tag.getString("argument2Default"); + + if (!Utils.validateParam(argument2)) { + alert("Invalid param name for argument2. Use " + Utils.paramRegex); + return; + } + if (argument2Type.equals("Number") && !Utils.validateTagParamNumber(argument2Default)) { + alert("Invalid default value for argument2. Use " + Utils.numberRegex); + return; + } + } + } + } + hackvertor.setCustomTags(tags); + alert("All your tags have been replaced from the file"); + saveCustomTags(); + listTagsWindow.dispose(); + showListTagsDialog(); + } catch (JSONException ex) { + alert("Invalid JSON: " + ex); + } + } + } catch (IOException ex) { + alert("Unable to load JSON: " + ex); + } + + } + } + }); exportButton.addActionListener(e -> { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); StringSelection customTagsJSON = new StringSelection(hackvertor.getCustomTags().toString()); @@ -1168,7 +1294,7 @@ public void actionPerformed(ActionEvent e) { } try { String tagsJSON = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); - if (tagsJSON != null && tagsJSON.length() > 0) { + if (tagsJSON != null && !tagsJSON.isEmpty()) { try { JSONArray tags = new JSONArray(tagsJSON); hackvertor.setCustomTags(tags); @@ -1181,7 +1307,6 @@ public void actionPerformed(ActionEvent e) { } } } catch (UnsupportedFlavorException unsupportedFlavorException) { - unsupportedFlavorException.printStackTrace(); alert("Invalid JSON"); } catch (IOException ioException) { ioException.printStackTrace(); @@ -1221,6 +1346,8 @@ public void actionPerformed(ActionEvent e) { listTagsPanel.add(deleteButton); listTagsPanel.add(loadButton); listTagsPanel.add(exportButton); + listTagsPanel.add(loadFromJsonButton); + listTagsPanel.add(exportToJsonButton); listTagsWindow.add(listTagsPanel); listTagsWindow.pack(); listTagsWindow.setLocationRelativeTo(null); From 816c93fac38ffab6d6484981cf6a978a08c1d889 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Fri, 22 Dec 2023 12:32:14 +0000 Subject: [PATCH 10/25] Fixed #79 No contextual menu entries for requests in Proxy History and Sitemap --- src/main/java/burp/BurpExtender.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index de9c59d..c6c77dd 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -206,7 +206,7 @@ public void run() { } try { hackvertor = new Hackvertor(); - stdout.println("Hackvertor v1.8.8"); + stdout.println("Hackvertor v1.8.9"); loadCustomTags(); loadGlobalVariables(); registerPayloadProcessors(); @@ -1612,7 +1612,11 @@ public List createMenuItems(IContextMenuInvocation invocation) { switch (invocation.getInvocationContext()) { case IContextMenuInvocation.CONTEXT_INTRUDER_PAYLOAD_POSITIONS: case IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST: + case IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_REQUEST: case IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_RESPONSE: + case IContextMenuInvocation.CONTEXT_TARGET_SITE_MAP_TREE: + case IContextMenuInvocation.CONTEXT_TARGET_SITE_MAP_TABLE: + case IContextMenuInvocation.CONTEXT_PROXY_HISTORY: break; default: return null; @@ -1628,9 +1632,14 @@ public List createMenuItems(IContextMenuInvocation invocation) { JMenuItem sendToHackvertor = new JMenuItem(hackvertorAction); submenu.add(sendToHackvertor); - if (invocation.getInvocationContext() == IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_RESPONSE) { - menu.add(submenu); - return menu; + switch(invocation.getInvocationContext()) { + case IContextMenuInvocation.CONTEXT_TARGET_SITE_MAP_TREE: + case IContextMenuInvocation.CONTEXT_TARGET_SITE_MAP_TABLE: + case IContextMenuInvocation.CONTEXT_PROXY_HISTORY: + case IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_REQUEST: + case IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_RESPONSE: + menu.add(submenu); + return menu; } JMenuItem copyUrl = new JMenuItem("Copy URL"); From d99d356b0b7d6c636dcb7b4d8c3002767ac02314 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Fri, 22 Dec 2023 12:33:21 +0000 Subject: [PATCH 11/25] Updated changelog --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 4ed9bf1..a48f8a5 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ Tags also support arguments. The find tag allows you to find a string by regex a # Changelog +**1.8.9 2023-12-22** + +- Fixed #79 No contextual menu entries for requests in Proxy History and Sitemap + **1.8.8 2023-12-20** - Added remove output tag From dcc9e007b560ad0c6d4db2da2eec138bf0b56896 Mon Sep 17 00:00:00 2001 From: Corey <1339555+CoreyD97@users.noreply.github.com> Date: Sat, 23 Dec 2023 17:04:41 +0000 Subject: [PATCH 12/25] Automatic JavaCC generation on build --- build.gradle | 15 +- .../java/burp/parser/HackvertorParser.java | 722 ------------- .../parser/HackvertorParserConstants.java | 94 -- .../parser/HackvertorParserTokenManager.java | 955 ------------------ src/main/java/burp/parser/ParseException.java | 193 ---- .../java/burp/parser/SimpleCharStream.java | 474 --------- src/main/java/burp/parser/Token.java | 131 --- src/main/java/burp/parser/TokenMgrError.java | 146 --- .../{java => javacc}/burp/parser/Element.java | 0 .../{java => javacc}/burp/parser/parser.jj | 0 10 files changed, 10 insertions(+), 2720 deletions(-) delete mode 100644 src/main/java/burp/parser/HackvertorParser.java delete mode 100644 src/main/java/burp/parser/HackvertorParserConstants.java delete mode 100644 src/main/java/burp/parser/HackvertorParserTokenManager.java delete mode 100644 src/main/java/burp/parser/ParseException.java delete mode 100644 src/main/java/burp/parser/SimpleCharStream.java delete mode 100644 src/main/java/burp/parser/Token.java delete mode 100644 src/main/java/burp/parser/TokenMgrError.java rename src/main/{java => javacc}/burp/parser/Element.java (100%) rename src/main/{java => javacc}/burp/parser/parser.jj (100%) diff --git a/build.gradle b/build.gradle index 51168b6..965c68c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,7 @@ -apply plugin: 'java' +plugins { + id 'java' + id "org.javacc.javacc" version "3.0.2" +} targetCompatibility = JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_17 @@ -37,14 +40,16 @@ dependencies { sourceSets { main { java { - srcDir 'src' - } - resources { - srcDir 'src' + srcDir compileJavacc.outputDirectory } } } +compileJavacc { + inputDirectory = file('src/main/javacc') + include '**/*.java' +} + jar{ duplicatesStrategy = DuplicatesStrategy.EXCLUDE archivesBaseName = project.name + '-all' diff --git a/src/main/java/burp/parser/HackvertorParser.java b/src/main/java/burp/parser/HackvertorParser.java deleted file mode 100644 index 3b27e53..0000000 --- a/src/main/java/burp/parser/HackvertorParser.java +++ /dev/null @@ -1,722 +0,0 @@ -/* HackvertorParser.java */ -/* Generated By:JavaCC: Do not edit this line. HackvertorParser.java */ -package burp.parser; - -import java.io.StringReader; -import java.util.LinkedList; -import java.util.ArrayList; -import org.unbescape.java.JavaEscape; - -public class HackvertorParser implements HackvertorParserConstants { - - private static String getTokenText(Token first, Token cur) { - Token t; - StringBuffer sb = new StringBuffer(); - - for (t=first; t != cur.next; t = t.next) { - if (t.specialToken != null) { - Token tt=t.specialToken; - while (tt.specialToken != null) - tt = tt.specialToken; - for (; tt != null; tt = tt.next) - sb.append(tt.image); - }; - sb.append(t.image); - }; - return sb.toString(); - } - - public static LinkedList parse(String string) throws ParseException { - HackvertorParser parser = new HackvertorParser(new StringReader(string)); - LinkedList elementList = parser.Input(); -// for (Element e : elementList) { -// System.out.println(e.getClass() + " - " + e.toString()); -// } - return elementList; - } - - final public LinkedList Input() throws ParseException {LinkedList s = new LinkedList(); - LinkedList e; - label_1: - while (true) { - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case TAG_START: - case ENDTAG_START: - case TEXT: - case LESSTHAN: - case ST_ERR: - case SELF_CLOSE_TAG_END: - case TAG_END: - case IT_ERR: - case QUOTED_STRING_VAL: - case LITERAL_VAL: - case COMMA: - case ARGS_END: - case ARG_ERR:{ - ; - break; - } - default: - jj_la1[0] = jj_gen; - break label_1; - } - e = ElementSequence(); -s.addAll(e); - } - jj_consume_token(0); -{if ("" != null) return s;} - throw new Error("Missing return statement in function"); -} - - final public LinkedList ElementSequence() throws ParseException {LinkedList elements = new LinkedList(); - Element e; - Token text; - Token firstToken = getToken(1); - try { - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case TAG_START:{ - elements = StartTag(); -{if ("" != null) return elements;} - break; - } - case ENDTAG_START:{ - elements = CloseTag(); -{if ("" != null) return elements;} - break; - } - case LESSTHAN:{ - jj_consume_token(LESSTHAN); -elements.add(new Element.TextElement("<")); {if ("" != null) return elements;} - break; - } - case TEXT: - case ST_ERR: - case SELF_CLOSE_TAG_END: - case TAG_END: - case IT_ERR: - case QUOTED_STRING_VAL: - case LITERAL_VAL: - case COMMA: - case ARGS_END: - case ARG_ERR:{ - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case TEXT:{ - text = jj_consume_token(TEXT); - break; - } - case ST_ERR:{ - text = jj_consume_token(ST_ERR); - break; - } - case IT_ERR:{ - text = jj_consume_token(IT_ERR); - break; - } - case ARG_ERR:{ - text = jj_consume_token(ARG_ERR); - break; - } - case QUOTED_STRING_VAL:{ - text = jj_consume_token(QUOTED_STRING_VAL); - break; - } - case LITERAL_VAL:{ - text = jj_consume_token(LITERAL_VAL); - break; - } - case COMMA:{ - text = jj_consume_token(COMMA); - break; - } - case ARGS_END:{ - text = jj_consume_token(ARGS_END); - break; - } - case TAG_END:{ - text = jj_consume_token(TAG_END); - break; - } - case SELF_CLOSE_TAG_END:{ - text = jj_consume_token(SELF_CLOSE_TAG_END); - break; - } - default: - jj_la1[1] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } -elements.add(new Element.TextElement(text.image)); {if ("" != null) return elements;} - break; - } - default: - jj_la1[2] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } catch (ParseException ex) { -//Catch any unexpected inputs including EOF and try to recover - token_source.SwitchTo(DEFAULT); - elements.addFirst(new Element.TextElement(getTokenText(firstToken, getToken(0)))); - elements.addAll(ElementSequence()); - {if ("" != null) return elements;} - } - throw new Error("Missing return statement in function"); -} - - final public LinkedList StartTag() throws ParseException {LinkedList elements = new LinkedList(); - ArrayList args = new ArrayList(); - LinkedList rest = null; - Token t; - Token identifier = null; - String arg; - Token firstToken = getToken(1); - try { - t = jj_consume_token(TAG_START); - identifier = jj_consume_token(FUNCTION_NAME); - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case ARGS_START:{ - jj_consume_token(ARGS_START); - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case QUOTED_STRING_VAL: - case LITERAL_VAL:{ - arg = Argument(); -args.add(arg); - label_2: - while (true) { - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case COMMA:{ - ; - break; - } - default: - jj_la1[3] = jj_gen; - break label_2; - } - jj_consume_token(COMMA); - arg = Argument(); -args.add(arg); - } - break; - } - default: - jj_la1[4] = jj_gen; - ; - } - jj_consume_token(ARGS_END); - break; - } - default: - jj_la1[5] = jj_gen; - ; - } - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case TAG_END:{ - jj_consume_token(TAG_END); -elements.add(new Element.StartTag(identifier.image, args)); {if ("" != null) return elements;} - break; - } - case SELF_CLOSE_TAG_END: - case SELF_CLOSE_TAG_END_AT:{ - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case SELF_CLOSE_TAG_END:{ - jj_consume_token(SELF_CLOSE_TAG_END); - break; - } - case SELF_CLOSE_TAG_END_AT:{ - jj_consume_token(SELF_CLOSE_TAG_END_AT); - break; - } - default: - jj_la1[6] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } -elements.add(new Element.SelfClosingTag(identifier.image, args)); {if ("" != null) return elements;} - break; - } - default: - jj_la1[7] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } catch (ParseException e) { -// System.out.println("Failed Start tag. Treating as text"); - elements.addFirst(new Element.TextElement(getTokenText(firstToken, getToken(0)))); - } - if (jj_2_1(2)) { - rest = ElementSequence(); - } else { - ; - } -if(rest != null) elements.addAll(rest); {if ("" != null) return elements;} - throw new Error("Missing return statement in function"); -} - - final public String Argument() throws ParseException {Token t; - switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { - case QUOTED_STRING_VAL:{ - t = jj_consume_token(QUOTED_STRING_VAL); -{if ("" != null) return JavaEscape.unescapeJava(t.image.substring(1, t.image.length() - 1));} - break; - } - case LITERAL_VAL:{ - t = jj_consume_token(LITERAL_VAL); -{if ("" != null) return t.image;} - break; - } - default: - jj_la1[8] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - throw new Error("Missing return statement in function"); -} - - final public LinkedList CloseTag() throws ParseException {LinkedList elements = new LinkedList(); - LinkedList rest = null; - Token t; - Token firstToken = getToken(1); - try { - jj_consume_token(ENDTAG_START); - t = jj_consume_token(FUNCTION_NAME); - jj_consume_token(TAG_END); -elements.add(new Element.EndTag(t.image)); {if ("" != null) return elements;} - } catch (ParseException e) { -// System.out.println("Failed End tag. Treating as text"); - elements.addFirst(new Element.TextElement(getTokenText(firstToken, getToken(0)))); - } - if (jj_2_2(2)) { - rest = ElementSequence(); - } else { - ; - } -if(rest != null) elements.addAll(rest); {if ("" != null) return elements;} - throw new Error("Missing return statement in function"); -} - - private boolean jj_2_1(int xla) - { - jj_la = xla; jj_lastpos = jj_scanpos = token; - try { return (!jj_3_1()); } - catch(LookaheadSuccess ls) { return true; } - finally { jj_save(0, xla); } - } - - private boolean jj_2_2(int xla) - { - jj_la = xla; jj_lastpos = jj_scanpos = token; - try { return (!jj_3_2()); } - catch(LookaheadSuccess ls) { return true; } - finally { jj_save(1, xla); } - } - - private boolean jj_3R_7() - { - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(10)) { - jj_scanpos = xsp; - if (jj_scan_token(13)) { - jj_scanpos = xsp; - if (jj_scan_token(18)) { - jj_scanpos = xsp; - if (jj_scan_token(23)) { - jj_scanpos = xsp; - if (jj_scan_token(19)) { - jj_scanpos = xsp; - if (jj_scan_token(20)) { - jj_scanpos = xsp; - if (jj_scan_token(21)) { - jj_scanpos = xsp; - if (jj_scan_token(22)) { - jj_scanpos = xsp; - if (jj_scan_token(17)) { - jj_scanpos = xsp; - if (jj_scan_token(15)) return true; - } - } - } - } - } - } - } - } - } - return false; - } - - private boolean jj_3R_6() - { - if (jj_scan_token(LESSTHAN)) return true; - return false; - } - - private boolean jj_3_2() - { - if (jj_3R_3()) return true; - return false; - } - - private boolean jj_3R_5() - { - if (jj_3R_9()) return true; - return false; - } - - private boolean jj_3R_8() - { - if (jj_scan_token(TAG_START)) return true; - if (jj_scan_token(FUNCTION_NAME)) return true; - return false; - } - - private boolean jj_3_1() - { - if (jj_3R_3()) return true; - return false; - } - - private boolean jj_3R_4() - { - if (jj_3R_8()) return true; - return false; - } - - private boolean jj_3R_3() - { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_4()) { - jj_scanpos = xsp; - if (jj_3R_5()) { - jj_scanpos = xsp; - if (jj_3R_6()) { - jj_scanpos = xsp; - if (jj_3R_7()) return true; - } - } - } - return false; - } - - private boolean jj_3R_9() - { - if (jj_scan_token(ENDTAG_START)) return true; - if (jj_scan_token(FUNCTION_NAME)) return true; - return false; - } - - /** Generated Token Manager. */ - public HackvertorParserTokenManager token_source; - SimpleCharStream jj_input_stream; - /** Current token. */ - public Token token; - /** Next token. */ - public Token jj_nt; - private int jj_ntk; - private Token jj_scanpos, jj_lastpos; - private int jj_la; - private int jj_gen; - final private int[] jj_la1 = new int[9]; - static private int[] jj_la1_0; - static { - jj_la1_init_0(); - } - private static void jj_la1_init_0() { - jj_la1_0 = new int[] {0xfeaf00,0xfea400,0xfeaf00,0x200000,0x180000,0x4000,0x18000,0x38000,0x180000,}; - } - final private JJCalls[] jj_2_rtns = new JJCalls[2]; - private boolean jj_rescan = false; - private int jj_gc = 0; - - /** Constructor with InputStream. */ - public HackvertorParser(java.io.InputStream stream) { - this(stream, null); - } - /** Constructor with InputStream and supplied encoding */ - public HackvertorParser(java.io.InputStream stream, String encoding) { - try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source = new HackvertorParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 9; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - /** Reinitialise. */ - public void ReInit(java.io.InputStream stream) { - ReInit(stream, null); - } - /** Reinitialise. */ - public void ReInit(java.io.InputStream stream, String encoding) { - try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 9; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - /** Constructor. */ - public HackvertorParser(java.io.Reader stream) { - jj_input_stream = new SimpleCharStream(stream, 1, 1); - token_source = new HackvertorParserTokenManager(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 9; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - /** Reinitialise. */ - public void ReInit(java.io.Reader stream) { - if (jj_input_stream == null) { - jj_input_stream = new SimpleCharStream(stream, 1, 1); - } else { - jj_input_stream.ReInit(stream, 1, 1); - } - if (token_source == null) { - token_source = new HackvertorParserTokenManager(jj_input_stream); - } - - token_source.ReInit(jj_input_stream); - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 9; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - /** Constructor with generated Token Manager. */ - public HackvertorParser(HackvertorParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 9; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - /** Reinitialise. */ - public void ReInit(HackvertorParserTokenManager tm) { - token_source = tm; - token = new Token(); - jj_ntk = -1; - jj_gen = 0; - for (int i = 0; i < 9; i++) jj_la1[i] = -1; - for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); - } - - private Token jj_consume_token(int kind) throws ParseException { - Token oldToken; - if ((oldToken = token).next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - if (token.kind == kind) { - jj_gen++; - if (++jj_gc > 100) { - jj_gc = 0; - for (int i = 0; i < jj_2_rtns.length; i++) { - JJCalls c = jj_2_rtns[i]; - while (c != null) { - if (c.gen < jj_gen) c.first = null; - c = c.next; - } - } - } - return token; - } - token = oldToken; - jj_kind = kind; - throw generateParseException(); - } - - @SuppressWarnings("serial") - static private final class LookaheadSuccess extends java.lang.Error { } - final private LookaheadSuccess jj_ls = new LookaheadSuccess(); - private boolean jj_scan_token(int kind) { - if (jj_scanpos == jj_lastpos) { - jj_la--; - if (jj_scanpos.next == null) { - jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); - } else { - jj_lastpos = jj_scanpos = jj_scanpos.next; - } - } else { - jj_scanpos = jj_scanpos.next; - } - if (jj_rescan) { - int i = 0; Token tok = token; - while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } - if (tok != null) jj_add_error_token(kind, i); - } - if (jj_scanpos.kind != kind) return true; - if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; - return false; - } - - -/** Get the next Token. */ - final public Token getNextToken() { - if (token.next != null) token = token.next; - else token = token.next = token_source.getNextToken(); - jj_ntk = -1; - jj_gen++; - return token; - } - -/** Get the specific Token. */ - final public Token getToken(int index) { - Token t = token; - for (int i = 0; i < index; i++) { - if (t.next != null) t = t.next; - else t = t.next = token_source.getNextToken(); - } - return t; - } - - private int jj_ntk_f() { - if ((jj_nt=token.next) == null) - return (jj_ntk = (token.next=token_source.getNextToken()).kind); - else - return (jj_ntk = jj_nt.kind); - } - - private java.util.List jj_expentries = new java.util.ArrayList(); - private int[] jj_expentry; - private int jj_kind = -1; - private int[] jj_lasttokens = new int[100]; - private int jj_endpos; - - private void jj_add_error_token(int kind, int pos) { - if (pos >= 100) { - return; - } - - if (pos == jj_endpos + 1) { - jj_lasttokens[jj_endpos++] = kind; - } else if (jj_endpos != 0) { - jj_expentry = new int[jj_endpos]; - - for (int i = 0; i < jj_endpos; i++) { - jj_expentry[i] = jj_lasttokens[i]; - } - - for (int[] oldentry : jj_expentries) { - if (oldentry.length == jj_expentry.length) { - boolean isMatched = true; - - for (int i = 0; i < jj_expentry.length; i++) { - if (oldentry[i] != jj_expentry[i]) { - isMatched = false; - break; - } - - } - if (isMatched) { - jj_expentries.add(jj_expentry); - break; - } - } - } - - if (pos != 0) { - jj_lasttokens[(jj_endpos = pos) - 1] = kind; - } - } - } - - /** Generate ParseException. */ - public ParseException generateParseException() { - jj_expentries.clear(); - boolean[] la1tokens = new boolean[25]; - if (jj_kind >= 0) { - la1tokens[jj_kind] = true; - jj_kind = -1; - } - for (int i = 0; i < 9; i++) { - if (jj_la1[i] == jj_gen) { - for (int j = 0; j < 32; j++) { - if ((jj_la1_0[i] & (1< jj_gen) { - jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; - switch (i) { - case 0: jj_3_1(); break; - case 1: jj_3_2(); break; - } - } - p = p.next; - } while (p != null); - - } catch(LookaheadSuccess ls) { } - } - jj_rescan = false; - } - - private void jj_save(int index, int xla) { - JJCalls p = jj_2_rtns[index]; - while (p.gen > jj_gen) { - if (p.next == null) { p = p.next = new JJCalls(); break; } - p = p.next; - } - - p.gen = jj_gen + xla - jj_la; - p.first = token; - p.arg = xla; - } - - static final class JJCalls { - int gen; - Token first; - int arg; - JJCalls next; - } - -} diff --git a/src/main/java/burp/parser/HackvertorParserConstants.java b/src/main/java/burp/parser/HackvertorParserConstants.java deleted file mode 100644 index 22ac2a7..0000000 --- a/src/main/java/burp/parser/HackvertorParserConstants.java +++ /dev/null @@ -1,94 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. HackvertorParserConstants.java */ -package burp.parser; - - -/** - * Token literal values and constants. - * Generated by org.javacc.parser.OtherFilesGen#start() - */ -public interface HackvertorParserConstants { - - /** End of File. */ - int EOF = 0; - /** RegularExpression Id. */ - int IDENTIFIER = 4; - /** RegularExpression Id. */ - int QUOTED_STRING = 5; - /** RegularExpression Id. */ - int LITERAL = 6; - /** RegularExpression Id. */ - int WHITESPACE = 7; - /** RegularExpression Id. */ - int TAG_START = 8; - /** RegularExpression Id. */ - int ENDTAG_START = 9; - /** RegularExpression Id. */ - int TEXT = 10; - /** RegularExpression Id. */ - int LESSTHAN = 11; - /** RegularExpression Id. */ - int FUNCTION_NAME = 12; - /** RegularExpression Id. */ - int ST_ERR = 13; - /** RegularExpression Id. */ - int ARGS_START = 14; - /** RegularExpression Id. */ - int SELF_CLOSE_TAG_END = 15; - /** RegularExpression Id. */ - int SELF_CLOSE_TAG_END_AT = 16; - /** RegularExpression Id. */ - int TAG_END = 17; - /** RegularExpression Id. */ - int IT_ERR = 18; - /** RegularExpression Id. */ - int QUOTED_STRING_VAL = 19; - /** RegularExpression Id. */ - int LITERAL_VAL = 20; - /** RegularExpression Id. */ - int COMMA = 21; - /** RegularExpression Id. */ - int ARGS_END = 22; - /** RegularExpression Id. */ - int ARG_ERR = 23; - /** RegularExpression Id. */ - int UNKNOWN = 24; - - /** Lexical state. */ - int Args = 0; - /** Lexical state. */ - int InsideTag = 1; - /** Lexical state. */ - int StartTag = 2; - /** Lexical state. */ - int DEFAULT = 3; - - /** Literal token values. */ - String[] tokenImage = { - "", - "\" \"", - "\"=\\r\"", - "\"=\\r\\n\"", - "", - "", - "", - "", - "\"<@\"", - "\"<@/\"", - "", - "\"<\"", - "", - "", - "\"(\"", - "\"/>\"", - "\"@/>\"", - "\">\"", - "", - "", - "", - "\",\"", - "\")\"", - "", - "", - }; - -} diff --git a/src/main/java/burp/parser/HackvertorParserTokenManager.java b/src/main/java/burp/parser/HackvertorParserTokenManager.java deleted file mode 100644 index 61c91f1..0000000 --- a/src/main/java/burp/parser/HackvertorParserTokenManager.java +++ /dev/null @@ -1,955 +0,0 @@ -/* HackvertorParserTokenManager.java */ -/* Generated By:JavaCC: Do not edit this line. HackvertorParserTokenManager.java */ -package burp.parser; -import java.io.StringReader; -import java.util.LinkedList; -import java.util.ArrayList; -import org.unbescape.java.JavaEscape; - -/** Token Manager. */ -public class HackvertorParserTokenManager implements HackvertorParserConstants { - // required by SetState - void backup(int n) { - input_stream.backup(n); - } - - /** Debug output. */ - public java.io.PrintStream debugStream = System.out; - /** Set debug output. */ - public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } -private final int jjStopStringLiteralDfa_3(int pos, long active0){ - switch (pos) - { - case 0: - if ((active0 & 0x2L) != 0L) - return 0; - if ((active0 & 0xcL) != 0L) - { - jjmatchedKind = 10; - return 0; - } - return -1; - case 1: - if ((active0 & 0xcL) != 0L) - return 0; - return -1; - default : - return -1; - } -} -private final int jjStartNfa_3(int pos, long active0){ - return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1); -} -private int jjStopAtPos(int pos, int kind) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - return pos + 1; -} -private int jjMoveStringLiteralDfa0_3(){ - switch(curChar) - { - case 32: - return jjStartNfaWithStates_3(0, 1, 0); - case 60: - jjmatchedKind = 11; - return jjMoveStringLiteralDfa1_3(0x300L); - case 61: - return jjMoveStringLiteralDfa1_3(0xcL); - default : - return jjMoveNfa_3(0, 0); - } -} -private int jjMoveStringLiteralDfa1_3(long active0){ - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_3(0, active0); - return 1; - } - switch(curChar) - { - case 13: - if ((active0 & 0x4L) != 0L) - { - jjmatchedKind = 2; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_3(active0, 0x8L); - case 64: - if ((active0 & 0x100L) != 0L) - { - jjmatchedKind = 8; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_3(active0, 0x200L); - default : - break; - } - return jjStartNfa_3(0, active0); -} -private int jjMoveStringLiteralDfa2_3(long old0, long active0){ - if (((active0 &= old0)) == 0L) - return jjStartNfa_3(0, old0); - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_3(1, active0); - return 2; - } - switch(curChar) - { - case 10: - if ((active0 & 0x8L) != 0L) - return jjStartNfaWithStates_3(2, 3, 0); - break; - case 47: - if ((active0 & 0x200L) != 0L) - return jjStopAtPos(2, 9); - break; - default : - break; - } - return jjStartNfa_3(1, active0); -} -private int jjStartNfaWithStates_3(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_3(state, pos + 1); -} -static final long[] jjbitVec0 = { - 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL -}; -static final long[] jjbitVec2 = { - 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL -}; -private int jjMoveNfa_3(int startState, int curPos) -{ - int startsAt = 0; - jjnewStateCnt = 1; - int i = 1; - jjstateSet[0] = startState; - int kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0xefffffffffffffffL & l) == 0L) - break; - kind = 10; - jjstateSet[jjnewStateCnt++] = 0; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - do - { - switch(jjstateSet[--i]) - { - case 0: - kind = 10; - jjstateSet[jjnewStateCnt++] = 0; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int hiByte = (curChar >> 8); - int i1 = hiByte >> 6; - long l1 = 1L << (hiByte & 077); - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - do - { - switch(jjstateSet[--i]) - { - case 0: - if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) - break; - if (kind > 10) - kind = 10; - jjstateSet[jjnewStateCnt++] = 0; - break; - default : if (i1 == 0 || l1 == 0 || i2 == 0 || l2 == 0) break; else break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 1 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_0(int pos, long active0){ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_0(int pos, long active0){ - return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); -} -private int jjMoveStringLiteralDfa0_0(){ - switch(curChar) - { - case 41: - return jjStopAtPos(0, 22); - case 44: - return jjStopAtPos(0, 21); - case 60: - return jjMoveStringLiteralDfa1_0(0x300L); - case 61: - return jjMoveStringLiteralDfa1_0(0xcL); - default : - return jjMoveNfa_0(0, 0); - } -} -private int jjMoveStringLiteralDfa1_0(long active0){ - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_0(0, active0); - return 1; - } - switch(curChar) - { - case 13: - if ((active0 & 0x4L) != 0L) - { - jjmatchedKind = 2; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_0(active0, 0x8L); - case 64: - if ((active0 & 0x100L) != 0L) - { - jjmatchedKind = 8; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_0(active0, 0x200L); - default : - break; - } - return jjStartNfa_0(0, active0); -} -private int jjMoveStringLiteralDfa2_0(long old0, long active0){ - if (((active0 &= old0)) == 0L) - return jjStartNfa_0(0, old0); - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_0(1, active0); - return 2; - } - switch(curChar) - { - case 10: - if ((active0 & 0x8L) != 0L) - return jjStopAtPos(2, 3); - break; - case 47: - if ((active0 & 0x200L) != 0L) - return jjStopAtPos(2, 9); - break; - default : - break; - } - return jjStartNfa_0(1, active0); -} -private int jjMoveNfa_0(int startState, int curPos) -{ - int startsAt = 0; - jjnewStateCnt = 11; - int i = 1; - jjstateSet[0] = startState; - int kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0x3ff680000000000L & l) != 0L) - { - if (kind > 20) - kind = 20; - { jjCheckNAdd(10); } - } - else if (curChar == 34) - { jjCheckNAddStates(0, 2); } - else if (curChar == 39) - { jjCheckNAddStates(3, 5); } - break; - case 2: - { jjCheckNAddStates(3, 5); } - break; - case 3: - if ((0xffffff7fffffffffL & l) != 0L) - { jjCheckNAddStates(3, 5); } - break; - case 4: - if (curChar == 39 && kind > 19) - kind = 19; - break; - case 5: - if (curChar == 34) - { jjCheckNAddStates(0, 2); } - break; - case 7: - { jjCheckNAddStates(0, 2); } - break; - case 8: - if ((0xfffffffbffffffffL & l) != 0L) - { jjCheckNAddStates(0, 2); } - break; - case 9: - if (curChar == 34 && kind > 19) - kind = 19; - break; - case 10: - if ((0x3ff680000000000L & l) == 0L) - break; - if (kind > 20) - kind = 20; - { jjCheckNAdd(10); } - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - do - { - switch(jjstateSet[--i]) - { - case 0: - case 10: - if ((0x7fffffe07fffffeL & l) == 0L) - break; - if (kind > 20) - kind = 20; - { jjCheckNAdd(10); } - break; - case 1: - if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 2; - break; - case 2: - { jjCheckNAddStates(3, 5); } - break; - case 3: - if ((0xffffffffefffffffL & l) != 0L) - { jjCheckNAddStates(3, 5); } - break; - case 6: - if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 7; - break; - case 7: - { jjCheckNAddStates(0, 2); } - break; - case 8: - if ((0xffffffffefffffffL & l) != 0L) - { jjCheckNAddStates(0, 2); } - break; - default : break; - } - } while(i != startsAt); - } - else - { - int hiByte = (curChar >> 8); - int i1 = hiByte >> 6; - long l1 = 1L << (hiByte & 077); - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - do - { - switch(jjstateSet[--i]) - { - case 2: - case 3: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - { jjCheckNAddStates(3, 5); } - break; - case 7: - case 8: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - { jjCheckNAddStates(0, 2); } - break; - default : if (i1 == 0 || l1 == 0 || i2 == 0 || l2 == 0) break; else break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 11 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private final int jjStopStringLiteralDfa_2(int pos, long active0){ - switch (pos) - { - default : - return -1; - } -} -private final int jjStartNfa_2(int pos, long active0){ - return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1); -} -private int jjMoveStringLiteralDfa0_2(){ - switch(curChar) - { - case 60: - return jjMoveStringLiteralDfa1_2(0x300L); - case 61: - return jjMoveStringLiteralDfa1_2(0xcL); - default : - return jjMoveNfa_2(0, 0); - } -} -private int jjMoveStringLiteralDfa1_2(long active0){ - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_2(0, active0); - return 1; - } - switch(curChar) - { - case 13: - if ((active0 & 0x4L) != 0L) - { - jjmatchedKind = 2; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_2(active0, 0x8L); - case 64: - if ((active0 & 0x100L) != 0L) - { - jjmatchedKind = 8; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_2(active0, 0x200L); - default : - break; - } - return jjStartNfa_2(0, active0); -} -private int jjMoveStringLiteralDfa2_2(long old0, long active0){ - if (((active0 &= old0)) == 0L) - return jjStartNfa_2(0, old0); - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_2(1, active0); - return 2; - } - switch(curChar) - { - case 10: - if ((active0 & 0x8L) != 0L) - return jjStopAtPos(2, 3); - break; - case 47: - if ((active0 & 0x200L) != 0L) - return jjStopAtPos(2, 9); - break; - default : - break; - } - return jjStartNfa_2(1, active0); -} -private int jjMoveNfa_2(int startState, int curPos) -{ - int startsAt = 0; - jjnewStateCnt = 1; - int i = 1; - jjstateSet[0] = startState; - int kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64) - { - long l = 1L << curChar; - do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0x3ff200000000000L & l) == 0L) - break; - kind = 12; - jjstateSet[jjnewStateCnt++] = 0; - break; - default : break; - } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0x7fffffe87fffffeL & l) == 0L) - break; - kind = 12; - jjstateSet[jjnewStateCnt++] = 0; - break; - default : break; - } - } while(i != startsAt); - } - else - { - int hiByte = (curChar >> 8); - int i1 = hiByte >> 6; - long l1 = 1L << (hiByte & 077); - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - do - { - switch(jjstateSet[--i]) - { - default : if (i1 == 0 || l1 == 0 || i2 == 0 || l2 == 0) break; else break; - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 1 - (jjnewStateCnt = startsAt))) - return curPos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} -private int jjMoveStringLiteralDfa0_1(){ - switch(curChar) - { - case 40: - return jjStopAtPos(0, 14); - case 47: - return jjMoveStringLiteralDfa1_1(0x8000L); - case 60: - return jjMoveStringLiteralDfa1_1(0x300L); - case 61: - return jjMoveStringLiteralDfa1_1(0xcL); - case 62: - return jjStopAtPos(0, 17); - case 64: - return jjMoveStringLiteralDfa1_1(0x10000L); - default : - return 1; - } -} -private int jjMoveStringLiteralDfa1_1(long active0){ - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - return 1; - } - switch(curChar) - { - case 13: - if ((active0 & 0x4L) != 0L) - { - jjmatchedKind = 2; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_1(active0, 0x8L); - case 47: - return jjMoveStringLiteralDfa2_1(active0, 0x10000L); - case 62: - if ((active0 & 0x8000L) != 0L) - return jjStopAtPos(1, 15); - break; - case 64: - if ((active0 & 0x100L) != 0L) - { - jjmatchedKind = 8; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_1(active0, 0x200L); - default : - return 2; - } - return 2; -} -private int jjMoveStringLiteralDfa2_1(long old0, long active0){ - if (((active0 &= old0)) == 0L) - return 2; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - return 2; - } - switch(curChar) - { - case 10: - if ((active0 & 0x8L) != 0L) - return jjStopAtPos(2, 3); - break; - case 47: - if ((active0 & 0x200L) != 0L) - return jjStopAtPos(2, 9); - break; - case 62: - if ((active0 & 0x10000L) != 0L) - return jjStopAtPos(2, 16); - break; - default : - return 3; - } - return 3; -} - -/** Token literal values. */ -public static final String[] jjstrLiteralImages = { -"", null, null, null, null, null, null, null, "\74\100", "\74\100\57", null, -"\74", null, null, "\50", "\57\76", "\100\57\76", "\76", null, null, null, "\54", -"\51", null, null, }; -protected Token jjFillToken() -{ - final Token t; - final String curTokenImage; - final int beginLine; - final int endLine; - final int beginColumn; - final int endColumn; - String im = jjstrLiteralImages[jjmatchedKind]; - curTokenImage = (im == null) ? input_stream.GetImage() : im; - beginLine = input_stream.getBeginLine(); - beginColumn = input_stream.getBeginColumn(); - endLine = input_stream.getEndLine(); - endColumn = input_stream.getEndColumn(); - t = Token.newToken(jjmatchedKind, curTokenImage); - - t.beginLine = beginLine; - t.endLine = endLine; - t.beginColumn = beginColumn; - t.endColumn = endColumn; - - return t; -} -static final int[] jjnextStates = { - 6, 8, 9, 1, 3, 4, -}; -private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) -{ - switch(hiByte) - { - case 0: - return ((jjbitVec2[i2] & l2) != 0L); - default : - if ((jjbitVec0[i1] & l1) != 0L) - return true; - return false; - } -} - -int curLexState = 3; -int defaultLexState = 3; -int jjnewStateCnt; -int jjround; -int jjmatchedPos; -int jjmatchedKind; - -/** Get the next Token. */ -public Token getNextToken() -{ - Token matchedToken; - int curPos = 0; - - EOFLoop : - for (;;) - { - try - { - curChar = input_stream.BeginToken(); - } - catch(Exception e) - { - jjmatchedKind = 0; - jjmatchedPos = -1; - matchedToken = jjFillToken(); - return matchedToken; - } - - switch(curLexState) - { - case 0: - try { input_stream.backup(0); - while (curChar <= 32 && (0x100000000L & (1L << curChar)) != 0L) - curChar = input_stream.BeginToken(); - } - catch (java.io.IOException e1) { continue EOFLoop; } - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_0(); - if (jjmatchedPos == 0 && jjmatchedKind > 23) - { - jjmatchedKind = 23; - } - break; - case 1: - try { input_stream.backup(0); - while (curChar <= 32 && (0x100000000L & (1L << curChar)) != 0L) - curChar = input_stream.BeginToken(); - } - catch (java.io.IOException e1) { continue EOFLoop; } - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_1(); - if (jjmatchedPos == 0 && jjmatchedKind > 18) - { - jjmatchedKind = 18; - } - break; - case 2: - try { input_stream.backup(0); - while (curChar <= 32 && (0x100000000L & (1L << curChar)) != 0L) - curChar = input_stream.BeginToken(); - } - catch (java.io.IOException e1) { continue EOFLoop; } - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_2(); - if (jjmatchedPos == 0 && jjmatchedKind > 13) - { - jjmatchedKind = 13; - } - break; - case 3: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_3(); - if (jjmatchedPos == 0 && jjmatchedKind > 24) - { - jjmatchedKind = 24; - } - break; - } - if (jjmatchedKind != 0x7fffffff) - { - if (jjmatchedPos + 1 < curPos) - input_stream.backup(curPos - jjmatchedPos - 1); - if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - matchedToken = jjFillToken(); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - return matchedToken; - } - else - { - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - continue EOFLoop; - } - } - int error_line = input_stream.getEndLine(); - int error_column = input_stream.getEndColumn(); - String error_after = null; - boolean EOFSeen = false; - try { input_stream.readChar(); input_stream.backup(1); } - catch (java.io.IOException e1) { - EOFSeen = true; - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - if (curChar == '\n' || curChar == '\r') { - error_line++; - error_column = 0; - } - else - error_column++; - } - if (!EOFSeen) { - input_stream.backup(1); - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - } - throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); - } -} - -void SkipLexicalActions(Token matchedToken) -{ - switch(jjmatchedKind) - { - default : - break; - } -} -void MoreLexicalActions() -{ - jjimageLen += (lengthOfMatch = jjmatchedPos + 1); - switch(jjmatchedKind) - { - default : - break; - } -} -void TokenLexicalActions(Token matchedToken) -{ - switch(jjmatchedKind) - { - default : - break; - } -} -private void jjCheckNAdd(int state) -{ - if (jjrounds[state] != jjround) - { - jjstateSet[jjnewStateCnt++] = state; - jjrounds[state] = jjround; - } -} -private void jjAddStates(int start, int end) -{ - do { - jjstateSet[jjnewStateCnt++] = jjnextStates[start]; - } while (start++ != end); -} -private void jjCheckNAddTwoStates(int state1, int state2) -{ - jjCheckNAdd(state1); - jjCheckNAdd(state2); -} - -private void jjCheckNAddStates(int start, int end) -{ - do { - jjCheckNAdd(jjnextStates[start]); - } while (start++ != end); -} - - /** Constructor. */ - public HackvertorParserTokenManager(SimpleCharStream stream){ - - if (SimpleCharStream.staticFlag) - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); - - input_stream = stream; - } - - /** Constructor. */ - public HackvertorParserTokenManager (SimpleCharStream stream, int lexState){ - ReInit(stream); - SwitchTo(lexState); - } - - /** Reinitialise parser. */ - - public void ReInit(SimpleCharStream stream) - { - - - jjmatchedPos = - jjnewStateCnt = - 0; - curLexState = defaultLexState; - input_stream = stream; - ReInitRounds(); - } - - private void ReInitRounds() - { - int i; - jjround = 0x80000001; - for (i = 11; i-- > 0;) - jjrounds[i] = 0x80000000; - } - - /** Reinitialise parser. */ - public void ReInit(SimpleCharStream stream, int lexState) - - { - ReInit(stream); - SwitchTo(lexState); - } - - /** Switch to specified lex state. */ - public void SwitchTo(int lexState) - { - if (lexState >= 4 || lexState < 0) - throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); - else - curLexState = lexState; - } - - -/** Lexer state names. */ -public static final String[] lexStateNames = { - "Args", - "InsideTag", - "StartTag", - "DEFAULT", -}; - -/** Lex State array. */ -public static final int[] jjnewLexState = { - -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, -1, -1, 1, 3, 0, 3, 3, 3, 3, -1, -1, -1, 1, 3, -1, -}; -static final long[] jjtoToken = { - 0x1ffff01L, -}; -static final long[] jjtoSkip = { - 0xeL, -}; -static final long[] jjtoSpecial = { - 0x0L, -}; -static final long[] jjtoMore = { - 0x0L, -}; - protected SimpleCharStream input_stream; - - private final int[] jjrounds = new int[11]; - private final int[] jjstateSet = new int[2 * 11]; - private final StringBuilder jjimage = new StringBuilder(); - private StringBuilder image = jjimage; - private int jjimageLen; - private int lengthOfMatch; - protected int curChar; -} diff --git a/src/main/java/burp/parser/ParseException.java b/src/main/java/burp/parser/ParseException.java deleted file mode 100644 index 791f6d7..0000000 --- a/src/main/java/burp/parser/ParseException.java +++ /dev/null @@ -1,193 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 7.0 */ -/* JavaCCOptions:KEEP_LINE_COLUMN=true */ -package burp.parser; - -/** - * This exception is thrown when parse errors are encountered. - * You can explicitly create objects of this exception type by - * calling the method generateParseException in the generated - * parser. - * - * You can modify this class to customize your error reporting - * mechanisms so long as you retain the public fields. - */ -public class ParseException extends Exception { - - /** - * The version identifier for this Serializable class. - * Increment only if the serialized form of the - * class changes. - */ - private static final long serialVersionUID = 1L; - - /** - * The end of line string for this machine. - */ - protected static String EOL = System.getProperty("line.separator", "\n"); - - /** - * This constructor is used by the method "generateParseException" - * in the generated parser. Calling this constructor generates - * a new object of this type with the fields "currentToken", - * "expectedTokenSequences", and "tokenImage" set. - */ - public ParseException(Token currentTokenVal, - int[][] expectedTokenSequencesVal, - String[] tokenImageVal - ) - { - super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal)); - currentToken = currentTokenVal; - expectedTokenSequences = expectedTokenSequencesVal; - tokenImage = tokenImageVal; - } - - /** - * The following constructors are for use by you for whatever - * purpose you can think of. Constructing the exception in this - * manner makes the exception behave in the normal way - i.e., as - * documented in the class "Throwable". The fields "errorToken", - * "expectedTokenSequences", and "tokenImage" do not contain - * relevant information. The JavaCC generated code does not use - * these constructors. - */ - - public ParseException() { - super(); - } - - /** Constructor with message. */ - public ParseException(String message) { - super(message); - } - - - /** - * This is the last token that has been consumed successfully. If - * this object has been created due to a parse error, the token - * followng this token will (therefore) be the first error token. - */ - public Token currentToken; - - /** - * Each entry in this array is an array of integers. Each array - * of integers represents a sequence of tokens (by their ordinal - * values) that is expected at this point of the parse. - */ - public int[][] expectedTokenSequences; - - /** - * This is a reference to the "tokenImage" array of the generated - * parser within which the parse error occurred. This array is - * defined in the generated ...Constants interface. - */ - public String[] tokenImage; - - /** - * It uses "currentToken" and "expectedTokenSequences" to generate a parse - * error message and returns it. If this object has been created - * due to a parse error, and you do not catch it (it gets thrown - * from the parser) the correct error message - * gets displayed. - */ - private static String initialise(Token currentToken, - int[][] expectedTokenSequences, - String[] tokenImage) { - - StringBuffer expected = new StringBuffer(); - int maxSize = 0; - for (int i = 0; i < expectedTokenSequences.length; i++) { - if (maxSize < expectedTokenSequences[i].length) { - maxSize = expectedTokenSequences[i].length; - } - for (int j = 0; j < expectedTokenSequences[i].length; j++) { - expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' '); - } - if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { - expected.append("..."); - } - expected.append(EOL).append(" "); - } - String retval = "Encountered \""; - Token tok = currentToken.next; - for (int i = 0; i < maxSize; i++) { - if (i != 0) retval += " "; - if (tok.kind == 0) { - retval += tokenImage[0]; - break; - } - retval += " " + tokenImage[tok.kind]; - retval += " \""; - retval += add_escapes(tok.image); - retval += " \""; - tok = tok.next; - } - retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; - retval += "." + EOL; - - - if (expectedTokenSequences.length == 0) { - // Nothing to add here - } else { - if (expectedTokenSequences.length == 1) { - retval += "Was expecting:" + EOL + " "; - } else { - retval += "Was expecting one of:" + EOL + " "; - } - retval += expected.toString(); - } - - return retval; - } - - - /** - * Used to convert raw characters to their escaped version - * when these raw version cannot be used as part of an ASCII - * string literal. - */ - static String add_escapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - -} -/* JavaCC - OriginalChecksum=e8615de02235cdcf87eafa3d19f881cc (do not edit this line) */ diff --git a/src/main/java/burp/parser/SimpleCharStream.java b/src/main/java/burp/parser/SimpleCharStream.java deleted file mode 100644 index 172f93a..0000000 --- a/src/main/java/burp/parser/SimpleCharStream.java +++ /dev/null @@ -1,474 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 7.0 */ -/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ -package burp.parser; - -/** - * An implementation of interface CharStream, where the stream is assumed to - * contain only ASCII characters (without unicode processing). - */ - -public class SimpleCharStream -{ -/** Whether parser is static. */ - public static final boolean staticFlag = false; - int bufsize; - int available; - int tokenBegin; -/** Position in buffer. */ - public int bufpos = -1; - protected int bufline[]; - protected int bufcolumn[]; - - protected int column = 0; - protected int line = 1; - - protected boolean prevCharIsCR = false; - protected boolean prevCharIsLF = false; - - protected java.io.Reader inputStream; - - protected char[] buffer; - protected int maxNextCharInd = 0; - protected int inBuf = 0; - protected int tabSize = 1; - protected boolean trackLineColumn = true; - - public void setTabSize(int i) { tabSize = i; } - public int getTabSize() { return tabSize; } - - - - protected void ExpandBuff(boolean wrapAround) - { - char[] newbuffer = new char[bufsize + 2048]; - int newbufline[] = new int[bufsize + 2048]; - int newbufcolumn[] = new int[bufsize + 2048]; - - try - { - if (wrapAround) - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos += (bufsize - tokenBegin)); - } - else - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - bufcolumn = newbufcolumn; - - maxNextCharInd = (bufpos -= tokenBegin); - } - } - catch (Throwable t) - { - throw new Error(t.getMessage()); - } - - - bufsize += 2048; - available = bufsize; - tokenBegin = 0; - } - - protected void FillBuff() throws java.io.IOException - { - if (maxNextCharInd == available) - { - if (available == bufsize) - { - if (tokenBegin > 2048) - { - bufpos = maxNextCharInd = 0; - available = tokenBegin; - } - else if (tokenBegin < 0) - bufpos = maxNextCharInd = 0; - else - ExpandBuff(false); - } - else if (available > tokenBegin) - available = bufsize; - else if ((tokenBegin - available) < 2048) - ExpandBuff(true); - else - available = tokenBegin; - } - - int i; - try { - if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1) - { - inputStream.close(); - throw new java.io.IOException(); - } - else - maxNextCharInd += i; - return; - } - catch(java.io.IOException e) { - --bufpos; - backup(0); - if (tokenBegin == -1) - tokenBegin = bufpos; - throw e; - } - } - -/** Start. */ - public char BeginToken() throws java.io.IOException - { - tokenBegin = -1; - char c = readChar(); - tokenBegin = bufpos; - - return c; - } - - protected void UpdateLineColumn(char c) - { - column++; - - if (prevCharIsLF) - { - prevCharIsLF = false; - line += (column = 1); - } - else if (prevCharIsCR) - { - prevCharIsCR = false; - if (c == '\n') - { - prevCharIsLF = true; - } - else - line += (column = 1); - } - - switch (c) - { - case '\r' : - prevCharIsCR = true; - break; - case '\n' : - prevCharIsLF = true; - break; - case '\t' : - column--; - column += (tabSize - (column % tabSize)); - break; - default : - break; - } - - bufline[bufpos] = line; - bufcolumn[bufpos] = column; - } - -/** Read a character. */ - public char readChar() throws java.io.IOException - { - if (inBuf > 0) - { - --inBuf; - - if (++bufpos == bufsize) - bufpos = 0; - - return buffer[bufpos]; - } - - if (++bufpos >= maxNextCharInd) - FillBuff(); - - char c = buffer[bufpos]; - - UpdateLineColumn(c); - return c; - } - - @Deprecated - /** - * @deprecated - * @see #getEndColumn - */ - - public int getColumn() { - return bufcolumn[bufpos]; - } - - @Deprecated - /** - * @deprecated - * @see #getEndLine - */ - - public int getLine() { - return bufline[bufpos]; - } - - /** Get token end column number. */ - public int getEndColumn() { - return bufcolumn[bufpos]; - } - - /** Get token end line number. */ - public int getEndLine() { - return bufline[bufpos]; - } - - /** Get token beginning column number. */ - public int getBeginColumn() { - return bufcolumn[tokenBegin]; - } - - /** Get token beginning line number. */ - public int getBeginLine() { - return bufline[tokenBegin]; - } - -/** Backup a number of characters. */ - public void backup(int amount) { - - inBuf += amount; - if ((bufpos -= amount) < 0) - bufpos += bufsize; - } - - /** Constructor. */ - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - - /** Constructor. */ - public SimpleCharStream(java.io.Reader dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - - /** Constructor. */ - public SimpleCharStream(java.io.Reader dstream) - { - this(dstream, 1, 1, 4096); - } - - /** Reinitialise. */ - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - if (buffer == null || buffersize != buffer.length) - { - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - } - prevCharIsLF = prevCharIsCR = false; - tokenBegin = inBuf = maxNextCharInd = 0; - bufpos = -1; - } - - /** Reinitialise. */ - public void ReInit(java.io.Reader dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - - /** Reinitialise. */ - public void ReInit(java.io.Reader dstream) - { - ReInit(dstream, 1, 1, 4096); - } - /** Constructor. */ - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - /** Constructor. */ - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - /** Constructor. */ - public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, startline, startcolumn, 4096); - } - - /** Constructor. */ - public SimpleCharStream(java.io.InputStream dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - - /** Constructor. */ - public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, 1, 1, 4096); - } - - /** Constructor. */ - public SimpleCharStream(java.io.InputStream dstream) - { - this(dstream, 1, 1, 4096); - } - - /** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - - /** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } - - /** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, 1, 1, 4096); - } - - /** Reinitialise. */ - public void ReInit(java.io.InputStream dstream) - { - ReInit(dstream, 1, 1, 4096); - } - /** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, startline, startcolumn, 4096); - } - /** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - /** Get token literal value. */ - public String GetImage() - { - if (bufpos >= tokenBegin) - return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); - else - return new String(buffer, tokenBegin, bufsize - tokenBegin) + - new String(buffer, 0, bufpos + 1); - } - - /** Get the suffix. */ - public char[] GetSuffix(int len) - { - char[] ret = new char[len]; - - if ((bufpos + 1) >= len) - System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); - else - { - System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, - len - bufpos - 1); - System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); - } - - return ret; - } - - /** Reset buffer when finished. */ - public void Done() - { - buffer = null; - bufline = null; - bufcolumn = null; - } - - /** - * Method to adjust line and column numbers for the start of a token. - */ - public void adjustBeginLineColumn(int newLine, int newCol) - { - int start = tokenBegin; - int len; - - if (bufpos >= tokenBegin) - { - len = bufpos - tokenBegin + inBuf + 1; - } - else - { - len = bufsize - tokenBegin + bufpos + 1 + inBuf; - } - - int i = 0, j = 0, k = 0; - int nextColDiff = 0, columnDiff = 0; - - while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) - { - bufline[j] = newLine; - nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; - bufcolumn[j] = newCol + columnDiff; - columnDiff = nextColDiff; - i++; - } - - if (i < len) - { - bufline[j] = newLine++; - bufcolumn[j] = newCol + columnDiff; - - while (i++ < len) - { - if (bufline[j = start % bufsize] != bufline[++start % bufsize]) - bufline[j] = newLine++; - else - bufline[j] = newLine; - } - } - - line = bufline[j]; - column = bufcolumn[j]; - } - boolean getTrackLineColumn() { return trackLineColumn; } - void setTrackLineColumn(boolean tlc) { trackLineColumn = tlc; } -} -/* JavaCC - OriginalChecksum=e9a4c63c6a32529181bc8c734bcdc46d (do not edit this line) */ diff --git a/src/main/java/burp/parser/Token.java b/src/main/java/burp/parser/Token.java deleted file mode 100644 index bb92c13..0000000 --- a/src/main/java/burp/parser/Token.java +++ /dev/null @@ -1,131 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. Token.java Version 7.0 */ -/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COLUMN=true,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ -package burp.parser; - -/** - * Describes the input token stream. - */ - -public class Token implements java.io.Serializable { - - /** - * The version identifier for this Serializable class. - * Increment only if the serialized form of the - * class changes. - */ - private static final long serialVersionUID = 1L; - - /** - * An integer that describes the kind of this token. This numbering - * system is determined by JavaCCParser, and a table of these numbers is - * stored in the file ...Constants.java. - */ - public int kind; - - /** The line number of the first character of this Token. */ - public int beginLine; - /** The column number of the first character of this Token. */ - public int beginColumn; - /** The line number of the last character of this Token. */ - public int endLine; - /** The column number of the last character of this Token. */ - public int endColumn; - - /** - * The string image of the token. - */ - public String image; - - /** - * A reference to the next regular (non-special) token from the input - * stream. If this is the last token from the input stream, or if the - * token manager has not read tokens beyond this one, this field is - * set to null. This is true only if this token is also a regular - * token. Otherwise, see below for a description of the contents of - * this field. - */ - public Token next; - - /** - * This field is used to access special tokens that occur prior to this - * token, but after the immediately preceding regular (non-special) token. - * If there are no such special tokens, this field is set to null. - * When there are more than one such special token, this field refers - * to the last of these special tokens, which in turn refers to the next - * previous special token through its specialToken field, and so on - * until the first special token (whose specialToken field is null). - * The next fields of special tokens refer to other special tokens that - * immediately follow it (without an intervening regular token). If there - * is no such token, this field is null. - */ - public Token specialToken; - - /** - * An optional attribute value of the Token. - * Tokens which are not used as syntactic sugar will often contain - * meaningful values that will be used later on by the compiler or - * interpreter. This attribute value is often different from the image. - * Any subclass of Token that actually wants to return a non-null value can - * override this method as appropriate. - */ - public Object getValue() { - return null; - } - - /** - * No-argument constructor - */ - public Token() {} - - /** - * Constructs a new token for the specified Image. - */ - public Token(int kind) - { - this(kind, null); - } - - /** - * Constructs a new token for the specified Image and Kind. - */ - public Token(int kind, String image) - { - this.kind = kind; - this.image = image; - } - - /** - * Returns the image. - */ - public String toString() - { - return image; - } - - /** - * Returns a new Token object, by default. However, if you want, you - * can create and return subclass objects based on the value of ofKind. - * Simply add the cases to the switch for all those special cases. - * For example, if you have a subclass of Token called IDToken that - * you want to create if ofKind is ID, simply add something like : - * - * case MyParserConstants.ID : return new IDToken(ofKind, image); - * - * to the following switch statement. Then you can cast matchedToken - * variable to the appropriate type and use sit in your lexical actions. - */ - public static Token newToken(int ofKind, String image) - { - switch(ofKind) - { - default : return new Token(ofKind, image); - } - } - - public static Token newToken(int ofKind) - { - return newToken(ofKind, null); - } - -} -/* JavaCC - OriginalChecksum=4c00c4075b249dc0bbb9ca9025a068d7 (do not edit this line) */ diff --git a/src/main/java/burp/parser/TokenMgrError.java b/src/main/java/burp/parser/TokenMgrError.java deleted file mode 100644 index 7753079..0000000 --- a/src/main/java/burp/parser/TokenMgrError.java +++ /dev/null @@ -1,146 +0,0 @@ -/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 7.0 */ -/* JavaCCOptions: */ -package burp.parser; - -/** Token Manager Error. */ -public class TokenMgrError extends Error -{ - - /** - * The version identifier for this Serializable class. - * Increment only if the serialized form of the - * class changes. - */ - private static final long serialVersionUID = 1L; - - /* - * Ordinals for various reasons why an Error of this type can be thrown. - */ - - /** - * Lexical error occurred. - */ - public static final int LEXICAL_ERROR = 0; - - /** - * An attempt was made to create a second instance of a static token manager. - */ - public static final int STATIC_LEXER_ERROR = 1; - - /** - * Tried to change to an invalid lexical state. - */ - public static final int INVALID_LEXICAL_STATE = 2; - - /** - * Detected (and bailed out of) an infinite loop in the token manager. - */ - public static final int LOOP_DETECTED = 3; - - /** - * Indicates the reason why the exception is thrown. It will have - * one of the above 4 values. - */ - int errorCode; - - /** - * Replaces unprintable characters by their escaped (or unicode escaped) - * equivalents in the given string - */ - protected static final String addEscapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - - /** - * Returns a detailed message for the Error when it is thrown by the - * token manager to indicate a lexical error. - * Parameters : - * EOFSeen : indicates if EOF caused the lexical error - * curLexState : lexical state in which this error occurred - * errorLine : line number when the error occurred - * errorColumn : column number when the error occurred - * errorAfter : prefix that was seen before this error occurred - * curchar : the offending character - * Note: You can customize the lexical error message by modifying this method. - */ - protected static String LexicalErr(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, int curChar) { - char curChar1 = (char)curChar; - return("Lexical error at line " + - errorLine + ", column " + - errorColumn + ". Encountered: " + - (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar1)) + "\"") + " (" + (int)curChar + "), ") + - "after : \"" + addEscapes(errorAfter) + "\""); - } - - /** - * You can also modify the body of this method to customize your error messages. - * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not - * of end-users concern, so you can return something like : - * - * "Internal Error : Please file a bug report .... " - * - * from this method for such cases in the release version of your parser. - */ - public String getMessage() { - return super.getMessage(); - } - - /* - * Constructors of various flavors follow. - */ - - /** No arg constructor. */ - public TokenMgrError() { - } - - /** Constructor with message and reason. */ - public TokenMgrError(String message, int reason) { - super(message); - errorCode = reason; - } - - /** Full Constructor. */ - public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, int curChar, int reason) { - this(LexicalErr(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); - } -} -/* JavaCC - OriginalChecksum=03a2b7fd4dba9b9d2d2a0b1de94b284c (do not edit this line) */ diff --git a/src/main/java/burp/parser/Element.java b/src/main/javacc/burp/parser/Element.java similarity index 100% rename from src/main/java/burp/parser/Element.java rename to src/main/javacc/burp/parser/Element.java diff --git a/src/main/java/burp/parser/parser.jj b/src/main/javacc/burp/parser/parser.jj similarity index 100% rename from src/main/java/burp/parser/parser.jj rename to src/main/javacc/burp/parser/parser.jj From 7d5f8b06fa54cc1fabdf6a0af0c13e3b9a8ac18e Mon Sep 17 00:00:00 2001 From: Corey <1339555+CoreyD97@users.noreply.github.com> Date: Sat, 23 Dec 2023 17:28:35 +0000 Subject: [PATCH 13/25] Setup tests --- build.gradle | 4 + src/main/java/burp/BurpExtender.java | 5 + src/test/java/burp/ConvertorTests.java | 37 +++++ src/test/java/burp/StubExtensionHelpers.java | 148 ++++++++++++++++++ .../burp/parser/HackvertorParserTest.java | 2 + 5 files changed, 196 insertions(+) create mode 100644 src/test/java/burp/ConvertorTests.java create mode 100644 src/test/java/burp/StubExtensionHelpers.java diff --git a/build.gradle b/build.gradle index 965c68c..dbfc451 100644 --- a/build.gradle +++ b/build.gradle @@ -65,4 +65,8 @@ jar{ tasks.withType(Jar) { destinationDirectory = file("$rootDir/releases/") +} + +test { + useJUnitPlatform() } \ No newline at end of file diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index c6c77dd..d68c45b 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -1733,4 +1733,9 @@ public void alert(String msg) { public Component getUiComponent() { return extensionPanel; } + + //Used in tests + public static void setHelpers(IExtensionHelpers helpers) { + BurpExtender.helpers = helpers; + } } diff --git a/src/test/java/burp/ConvertorTests.java b/src/test/java/burp/ConvertorTests.java new file mode 100644 index 0000000..6bec980 --- /dev/null +++ b/src/test/java/burp/ConvertorTests.java @@ -0,0 +1,37 @@ +package burp; + +import burp.parser.Element; +import burp.parser.HackvertorParser; +import burp.parser.ParseException; +import org.junit.jupiter.api.Test; + +import java.util.LinkedList; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +public class ConvertorTests { + + private final Hackvertor hackvertor; + + public ConvertorTests() { + this.hackvertor = new Hackvertor(); + BurpExtender.setHelpers(new StubExtensionHelpers()); + } + + @Test + void convertSpaceInTag() throws ParseException { + String spaceInContent = "<@base64> <@/base64>"; + String converted = hackvertor.convert(spaceInContent, hackvertor); + assertEquals("IA==", converted); + } + + @Test + void parseSpaces() throws ParseException { + String spaceInContent = "<@base64> <@/base64>"; + LinkedList parsed = HackvertorParser.parse(spaceInContent); + assertEquals(3, parsed.size()); + assertInstanceOf(Element.TextElement.class, parsed.get(1)); + assertEquals(" ", parsed.get(1).toString()); + } +} diff --git a/src/test/java/burp/StubExtensionHelpers.java b/src/test/java/burp/StubExtensionHelpers.java new file mode 100644 index 0000000..18462e5 --- /dev/null +++ b/src/test/java/burp/StubExtensionHelpers.java @@ -0,0 +1,148 @@ +package burp; + +import org.python.apache.xerces.impl.dv.util.Base64; + +import java.net.URL; +import java.util.List; + +public class StubExtensionHelpers implements IExtensionHelpers { + @Override + public IRequestInfo analyzeRequest(IHttpRequestResponse request) { + return null; + } + + @Override + public IRequestInfo analyzeRequest(IHttpService httpService, byte[] request) { + return null; + } + + @Override + public IRequestInfo analyzeRequest(byte[] request) { + return null; + } + + @Override + public IResponseInfo analyzeResponse(byte[] response) { + return null; + } + + @Override + public IParameter getRequestParameter(byte[] request, String parameterName) { + return null; + } + + @Override + public String urlDecode(String data) { + return null; + } + + @Override + public String urlEncode(String data) { + return null; + } + + @Override + public byte[] urlDecode(byte[] data) { + return new byte[0]; + } + + @Override + public byte[] urlEncode(byte[] data) { + return new byte[0]; + } + + @Override + public byte[] base64Decode(String data) { + return new byte[0]; + } + + @Override + public byte[] base64Decode(byte[] data) { + return base64Decode(data); + } + + @Override + public String base64Encode(String data) { + return Base64.encode(data.getBytes()); + } + + @Override + public String base64Encode(byte[] data) { + return null; + } + + @Override + public byte[] stringToBytes(String data) { + return new byte[0]; + } + + @Override + public String bytesToString(byte[] data) { + return null; + } + + @Override + public int indexOf(byte[] data, byte[] pattern, boolean caseSensitive, int from, int to) { + return 0; + } + + @Override + public byte[] buildHttpMessage(List headers, byte[] body) { + return new byte[0]; + } + + @Override + public byte[] buildHttpRequest(URL url) { + return new byte[0]; + } + + @Override + public byte[] addParameter(byte[] request, IParameter parameter) { + return new byte[0]; + } + + @Override + public byte[] removeParameter(byte[] request, IParameter parameter) { + return new byte[0]; + } + + @Override + public byte[] updateParameter(byte[] request, IParameter parameter) { + return new byte[0]; + } + + @Override + public byte[] toggleRequestMethod(byte[] request) { + return new byte[0]; + } + + @Override + public IHttpService buildHttpService(String host, int port, String protocol) { + return null; + } + + @Override + public IHttpService buildHttpService(String host, int port, boolean useHttps) { + return null; + } + + @Override + public IParameter buildParameter(String name, String value, byte type) { + return null; + } + + @Override + public IScannerInsertionPoint makeScannerInsertionPoint(String insertionPointName, byte[] baseRequest, int from, int to) { + return null; + } + + @Override + public IResponseVariations analyzeResponseVariations(byte[]... responses) { + return null; + } + + @Override + public IResponseKeywords analyzeResponseKeywords(List keywords, byte[]... responses) { + return null; + } +} diff --git a/src/test/java/burp/parser/HackvertorParserTest.java b/src/test/java/burp/parser/HackvertorParserTest.java index 57d6dea..9efc9a4 100644 --- a/src/test/java/burp/parser/HackvertorParserTest.java +++ b/src/test/java/burp/parser/HackvertorParserTest.java @@ -1,6 +1,8 @@ package burp.parser; import org.junit.jupiter.api.Test; +import java.util.LinkedList; + import static org.junit.jupiter.api.Assertions.*; class HackvertorParserTest { From d577b621feea4519b64b13f87b0fce7175da73da Mon Sep 17 00:00:00 2001 From: Corey <1339555+CoreyD97@users.noreply.github.com> Date: Sat, 23 Dec 2023 17:30:52 +0000 Subject: [PATCH 14/25] Move parser test --- src/test/java/burp/ConvertorTests.java | 9 --------- src/test/java/burp/parser/HackvertorParserTest.java | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/java/burp/ConvertorTests.java b/src/test/java/burp/ConvertorTests.java index 6bec980..b7249d3 100644 --- a/src/test/java/burp/ConvertorTests.java +++ b/src/test/java/burp/ConvertorTests.java @@ -25,13 +25,4 @@ void convertSpaceInTag() throws ParseException { String converted = hackvertor.convert(spaceInContent, hackvertor); assertEquals("IA==", converted); } - - @Test - void parseSpaces() throws ParseException { - String spaceInContent = "<@base64> <@/base64>"; - LinkedList parsed = HackvertorParser.parse(spaceInContent); - assertEquals(3, parsed.size()); - assertInstanceOf(Element.TextElement.class, parsed.get(1)); - assertEquals(" ", parsed.get(1).toString()); - } } diff --git a/src/test/java/burp/parser/HackvertorParserTest.java b/src/test/java/burp/parser/HackvertorParserTest.java index 9efc9a4..c797700 100644 --- a/src/test/java/burp/parser/HackvertorParserTest.java +++ b/src/test/java/burp/parser/HackvertorParserTest.java @@ -19,4 +19,13 @@ void parseUnicode2() { HackvertorParser.parse("’"); }); } + + @Test + void parseSpaces() throws ParseException { + String spaceInContent = "<@base64> <@/base64>"; + LinkedList parsed = HackvertorParser.parse(spaceInContent); + assertEquals(3, parsed.size()); + assertInstanceOf(Element.TextElement.class, parsed.get(1)); + assertEquals(" ", parsed.get(1).toString()); + } } \ No newline at end of file From 6bcc62ed8a7868bf1c263626fdc7aff53996bc2b Mon Sep 17 00:00:00 2001 From: Corey <1339555+CoreyD97@users.noreply.github.com> Date: Sat, 23 Dec 2023 17:34:32 +0000 Subject: [PATCH 15/25] Add test for #92 --- src/test/java/burp/ConvertorTests.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/burp/ConvertorTests.java b/src/test/java/burp/ConvertorTests.java index b7249d3..ed65b54 100644 --- a/src/test/java/burp/ConvertorTests.java +++ b/src/test/java/burp/ConvertorTests.java @@ -25,4 +25,15 @@ void convertSpaceInTag() throws ParseException { String converted = hackvertor.convert(spaceInContent, hackvertor); assertEquals("IA==", converted); } + + //Test for #92. + @Test + void testSpaceInAttribute(){ + String plaintext = "<@ascii2hex('')>abcd<@/ascii2hex>"; + assertEquals("61626364", hackvertor.convert(plaintext, hackvertor)); + plaintext = "<@ascii2hex(' ')>abcd<@/ascii2hex>"; + assertEquals("61 62 63 64", hackvertor.convert(plaintext, hackvertor)); + plaintext = "<@ascii2hex(' ')>abcd<@/ascii2hex>"; + assertEquals("61 62 63 64", hackvertor.convert(plaintext, hackvertor)); + } } From e0a6ae6479487b2d6abf83df8a85091bdc5739c1 Mon Sep 17 00:00:00 2001 From: Corey <1339555+CoreyD97@users.noreply.github.com> Date: Sat, 23 Dec 2023 17:35:41 +0000 Subject: [PATCH 16/25] Fixes #92 whitespace issue in parser --- src/main/javacc/burp/parser/parser.jj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/javacc/burp/parser/parser.jj b/src/main/javacc/burp/parser/parser.jj index ecd22e7..919c76c 100644 --- a/src/main/javacc/burp/parser/parser.jj +++ b/src/main/javacc/burp/parser/parser.jj @@ -55,7 +55,7 @@ TOKEN_MGR_DECLS : { } } -<*> SKIP: { " " | "=\r" | "=\r\n" } +<*> SKIP: { "=\r" | "=\r\n" } <*> TOKEN [IGNORE_CASE]: { <#IDENTIFIER: (["0"-"9", "a"-"z", "A"-"Z","_", "-"])+ > | <#QUOTED_STRING: ( "'" ("\\" ~[] | ~["'", "\\"] )* "'" ) | ( "\"" ("\\" ~[] | ~["\"", "\\"] )* "\"" ) > From a29571c344667747806f3e5cfdfc174e45c8359d Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Thu, 4 Jan 2024 12:51:49 +0000 Subject: [PATCH 17/25] Updated the readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a48f8a5..39af7b0 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ # Hackvertor Hackvertor is a tag based conversion tool written in Java implemented as a Burp Suite extension. Tags are constructed as follows: -<@base64_0><@/base64_0> the @ symbol is used as an identifier that it's a Hackvertor tag followed by the name of the tag in this case base64, the name is then followed by an underscore and a unique tag number. +<@base64><@/base64> the @ symbol is used as an identifier that it's a Hackvertor tag followed by the name of the tag in this case base64. -Tags also support arguments. The find tag allows you to find a string by regex and has parenthesis after the unique tag number: -<@find_0("\\w")>abc<@/find_0> this indicates it supports arguments. The argument in this case is the regex string to find on the text inbetween the tags. Hackvertor allows you to use two types of arguments either strings (double, single) or numbers (including hex). +Tags also support arguments. The find tag allows you to find a string by regex and has parenthesis after the tag name: +<@find("\\w")>abc<@/find> this indicates it supports arguments. The argument in this case is the regex string to find on the text in-between the tags. Hackvertor allows you to use three types of arguments either strings (double, single), boolean (true, false) or numbers (including hex). # Changelog From 32819976ae084ce9371f4d4b7bd45a2193fed512 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Fri, 5 Jan 2024 07:51:32 +0000 Subject: [PATCH 18/25] Updated version number in manifest --- BappManifest.bmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BappManifest.bmf b/BappManifest.bmf index c6f52a1..f02da45 100644 --- a/BappManifest.bmf +++ b/BappManifest.bmf @@ -2,7 +2,7 @@ Uuid: 65033cbd2c344fbabe57ac060b5dd100 ExtensionType: 1 Name: Hackvertor RepoName: hackvertor -ScreenVersion: 1.7.49 +ScreenVersion: 1.8.9 SerialVersion: 35 MinPlatformVersion: 0 ProOnly: False From 4d4cdc77d4700cdc8243b77d5720f8ae366f2f58 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Fri, 5 Jan 2024 12:17:00 +0000 Subject: [PATCH 19/25] Update maven.yml --- .github/workflows/maven.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 0b41167..732ef03 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -40,6 +40,5 @@ jobs: - name: Release uses: hackvertor/release-action@v1.12.0 with: - tag: "latest_hackvertor_release" allowUpdates: true artifacts: "releases/*.jar" From ab1bc9ef1c737b67fc589a6fc0b4737ac3ad8785 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Fri, 5 Jan 2024 12:21:11 +0000 Subject: [PATCH 20/25] Update maven.yml --- .github/workflows/maven.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 732ef03..552999b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -41,4 +41,5 @@ jobs: uses: hackvertor/release-action@v1.12.0 with: allowUpdates: true + name: 'latest' artifacts: "releases/*.jar" From 521bf85267e21138cc20608542018c6d4e9b2f7d Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Fri, 5 Jan 2024 12:41:29 +0000 Subject: [PATCH 21/25] Update maven.yml --- .github/workflows/maven.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 552999b..aaca1e5 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -3,15 +3,10 @@ name: Java CI with Maven -on: +on: push: - branches: [ master ] tags: - - 'v*' - pull_request: - branches: [ master ] - tags: - - 'v*' + - '*' jobs: build: @@ -40,6 +35,6 @@ jobs: - name: Release uses: hackvertor/release-action@v1.12.0 with: + name: ${{github.ref_name}} allowUpdates: true - name: 'latest' artifacts: "releases/*.jar" From 42396a9cdaf67bc877bb48f7cb2c2926f36d591f Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Mon, 8 Jan 2024 12:12:07 +0000 Subject: [PATCH 22/25] Added space and new line tags --- README.md | 4 ++++ src/main/java/burp/BurpExtender.java | 2 +- src/main/java/burp/Convertors.java | 4 ++++ src/main/java/burp/Hackvertor.java | 2 ++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 39af7b0..67df74a 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ Tags also support arguments. The find tag allows you to find a string by regex a # Changelog +**1.8.10 2024-01-08** + +- Added new line and space tags + **1.8.9 2023-12-22** - Fixed #79 No contextual menu entries for requests in Proxy History and Sitemap diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index d68c45b..228101a 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -206,7 +206,7 @@ public void run() { } try { hackvertor = new Hackvertor(); - stdout.println("Hackvertor v1.8.9"); + stdout.println("Hackvertor v1.8.10"); loadCustomTags(); loadGlobalVariables(); registerPayloadProcessors(); diff --git a/src/main/java/burp/Convertors.java b/src/main/java/burp/Convertors.java index 0ccc8f8..3c35103 100644 --- a/src/main/java/burp/Convertors.java +++ b/src/main/java/burp/Convertors.java @@ -404,6 +404,10 @@ public static String callTag(HashMap variableMap, JSONArray cust return lowercase(output); case "unique": return unique(output); + case "space": + return " "; + case "newline": + return "\n"; case "remove_output": return remove_output(output); case "capitalise": diff --git a/src/main/java/burp/Hackvertor.java b/src/main/java/burp/Hackvertor.java index d5db3ce..3fe7679 100644 --- a/src/main/java/burp/Hackvertor.java +++ b/src/main/java/burp/Hackvertor.java @@ -256,6 +256,8 @@ void init() { tags.add(new Tag(Tag.Category.String, "reverse", true, "reverse(String str)")); tags.add(new Tag(Tag.Category.String, "length", true, "len(String str)")); tags.add(new Tag(Tag.Category.String, "unique", true, "unique(String str)")); + tags.add(new Tag(Tag.Category.String, "space", false, "space()")); + tags.add(new Tag(Tag.Category.String, "newline", false, "newline()")); tag = new Tag(Tag.Category.String, "find", true, "find(String str, String find, int group)"); tag.argument1 = new TagArgument("string", "find"); tag.argument2 = new TagArgument("int", "-1"); From 682fdf1ac9bd6b1900698e4f612ec55060364bd8 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Mon, 8 Jan 2024 12:27:26 +0000 Subject: [PATCH 23/25] Added ean13 to the tag store --- README.md | 1 + tag-store/ean13/ean13.py | 1 + tag-store/tag-store.json | 9 ++++++++- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tag-store/ean13/ean13.py diff --git a/README.md b/README.md index 67df74a..00d66ec 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Tags also support arguments. The find tag allows you to find a string by regex a **1.8.10 2024-01-08** - Added new line and space tags +- Added ean13 tag to the tag store **1.8.9 2023-12-22** diff --git a/tag-store/ean13/ean13.py b/tag-store/ean13/ean13.py new file mode 100644 index 0000000..3784907 --- /dev/null +++ b/tag-store/ean13/ean13.py @@ -0,0 +1 @@ +z=input;y=z.replace('.','');output=z+str(10-(sum([3*int(x) for x in y[1:][::-2]])+sum([int(x) for x in y[::-1][1::2]]))%10)[-1] \ No newline at end of file diff --git a/tag-store/tag-store.json b/tag-store/tag-store.json index 5ac5bde..e77c50f 100644 --- a/tag-store/tag-store.json +++ b/tag-store/tag-store.json @@ -25,5 +25,12 @@ "argument2Type": "Number", "argument2Default": "1337", "language": "Python" + }, + { + "tagName": "ean13", + "description": "EAN13 checksum", + "author": "pentagridsec", + "numberOfArgs": 0, + "language": "Python" } -] \ No newline at end of file +] From 5fff0e228ffc73114724c78271b12b83db8d59dd Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Mon, 8 Jan 2024 12:48:28 +0000 Subject: [PATCH 24/25] Allowed regex replace to use capture groups. Fixes #95 --- src/main/java/burp/Convertors.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/burp/Convertors.java b/src/main/java/burp/Convertors.java index 3c35103..9d03859 100644 --- a/src/main/java/burp/Convertors.java +++ b/src/main/java/burp/Convertors.java @@ -2607,7 +2607,7 @@ static String replace(String str, String find, String replace) { static String regex_replace(String str, String find, String replace) { String output = ""; try { - output = str.replaceAll(find, replace.replace("\\", "\\\\").replace("$", "\\$")); + output = str.replaceAll(find, replace.replace("\\", "\\\\")); } catch (PatternSyntaxException e) { stderr.println(e.getMessage()); } From 03835807c301f3536c2f8a1a20fd4a97f45bea13 Mon Sep 17 00:00:00 2001 From: Gareth Heyes Date: Mon, 8 Jan 2024 12:49:15 +0000 Subject: [PATCH 25/25] Updated readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 00d66ec..5cb5287 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Tags also support arguments. The find tag allows you to find a string by regex a - Added new line and space tags - Added ean13 tag to the tag store +- Allowed regex replace to use capture groups **1.8.9 2023-12-22**