diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index c8aeb3a..0b41167 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -6,8 +6,12 @@ name: Java CI with Maven on: push: branches: [ master ] + tags: + - 'v*' pull_request: branches: [ master ] + tags: + - 'v*' jobs: build: @@ -15,10 +19,27 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build with Maven - run: mvn -B package --file pom.xml + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'oracle' + java-version: '17' + cache: 'gradle' + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build with Gradle + run: ./gradlew build + - name: Creating the jar file + run: ./gradlew jar + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + path: ./releases/*.jar + name: Downloadable Extension File + - name: Release + uses: hackvertor/release-action@v1.12.0 + with: + tag: "latest_hackvertor_release" + allowUpdates: true + artifacts: "releases/*.jar" diff --git a/.gitignore b/.gitignore index e72d88e..cf2764c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,10 @@ bin/ build/ target/ out/ +/releases/ #intellij .idea/ .classpath/ .project/ /build/ -/.gradle/ +/.gradle/ \ No newline at end of file diff --git a/BappManifest.bmf b/BappManifest.bmf index 25361f1..0c13af4 100644 --- a/BappManifest.bmf +++ b/BappManifest.bmf @@ -2,12 +2,12 @@ Uuid: 65033cbd2c344fbabe57ac060b5dd100 ExtensionType: 1 Name: Hackvertor RepoName: hackvertor -ScreenVersion: 1.7.38 +ScreenVersion: 1.7.49 SerialVersion: 41 MinPlatformVersion: 0 ProOnly: False Author: Portswigger Web Security - Gareth Heyes ShortDescription: Converts data using a tag-based configuration to apply various encoding and escaping operations. -EntryPoint: build/libs/hackvertor-all.jar -BuildCommand: ./gradlew fatJar +EntryPoint: releases/hackvertor-all.jar +BuildCommand: ./gradlew jar SupportedProducts: Pro, Community diff --git a/build.gradle b/build.gradle index 7ccc257..930a3e9 100644 --- a/build.gradle +++ b/build.gradle @@ -12,25 +12,25 @@ repositories { dependencies { implementation 'net.portswigger.burp.extender:burp-extender-api:1.7.22' - implementation 'commons-codec:commons-codec:1.10' - implementation 'org.apache.commons:commons-lang3:3.7' - implementation 'org.unbescape:unbescape:1.1.5.RELEASE' - implementation 'org.bouncycastle:bcpkix-jdk15on:1.60' - implementation 'com.auth0:java-jwt:3.4.0' - implementation 'org.json:json:20190722' - implementation 'commons-io:commons-io:2.6' + implementation 'commons-codec:commons-codec:1.15' + implementation 'org.apache.commons:commons-lang3:3.12.0' + implementation 'org.unbescape:unbescape:1.1.6.RELEASE' + implementation 'org.bouncycastle:bcpkix-jdk15on:1.70' + implementation 'com.auth0:java-jwt:4.3.0' + implementation 'org.json:json:20230227' + implementation 'commons-io:commons-io:2.11.0' implementation 'org.apache.commons:commons-compress:1.22' implementation 'org.brotli:dec:0.1.2' - implementation 'org.python:jython-standalone:2.7.0' + implementation 'org.python:jython-standalone:2.7.3b1' implementation 'bsf:bsf:2.4.0' implementation 'org.apache-extras.beanshell:bsh:2.0b6' - implementation 'org.codehaus.groovy:groovy-all:3.0.7' + 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.2.2' + implementation 'com.fifesoft:rsyntaxtextarea:3.3.1' implementation 'com.fifesoft:autocomplete:3.3.1' - testImplementation 'junit:junit:4.13.1' - testImplementation 'org.junit.jupiter:junit-jupiter:5.7.1' + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' } sourceSets { @@ -44,21 +44,19 @@ sourceSets { } } -task fatJar(type: Jar) { - baseName = project.name + '-all' +jar{ duplicatesStrategy = DuplicatesStrategy.EXCLUDE + archivesBaseName = project.name + '-all' from { - configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } - configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } - } { - exclude 'META-INF/MANIFEST.MF' - exclude 'META-INF/*.SF' - exclude 'META-INF/*.DSA' - exclude 'META-INF/*.RSA' + (configurations.runtimeClasspath).collect { it.isDirectory() ? it : zipTree(it) } + }{ + exclude "META-INF/*.SF" + exclude "META-INF/*.DSA" + exclude "META-INF/*.RSA" + exclude "META-INF/*.txt" } - with jar } -/*test { - useJUnitPlatform() -}*/ +tasks.withType(Jar) { + destinationDirectory = file("$rootDir/releases/") +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fc..da1db5f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/burp/Base58.java b/src/main/java/burp/Base58.java new file mode 100644 index 0000000..bc6c8fb --- /dev/null +++ b/src/main/java/burp/Base58.java @@ -0,0 +1,75 @@ +package burp; + +import java.math.BigInteger; + +public class Base58 { + private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); + private static final BigInteger BASE = BigInteger.valueOf(58); + + public static String encode(byte[] input) { + if (input.length == 0) { + return ""; + } + + // Convert the input bytes to a BigInteger + BigInteger num = new BigInteger(1, input); + + // Encode the BigInteger as base58 + StringBuilder sb = new StringBuilder(); + while (num.compareTo(BigInteger.ZERO) > 0) { + BigInteger[] qr = num.divideAndRemainder(BASE); + sb.append(ALPHABET[qr[1].intValue()]); + num = qr[0]; + } + + // Add leading '1' characters for each leading zero byte in the input + for (int i = 0; i < input.length && input[i] == 0; i++) { + sb.append(ALPHABET[0]); + } + + return sb.reverse().toString(); + } + + public static byte[] decode(String input) { + if (input.length() == 0) { + return new byte[0]; + } + + // Convert the base58 input to a BigInteger + BigInteger num = BigInteger.ZERO; + for (int i = 0; i < input.length(); i++) { + char c = input.charAt(i); + int digit = -1; + for (int j = 0; j < ALPHABET.length; j++) { + if (ALPHABET[j] == c) { + digit = j; + break; + } + } + if (digit == -1) { + throw new IllegalArgumentException("Invalid character '" + c + "' at position " + i); + } + num = num.multiply(BASE).add(BigInteger.valueOf(digit)); + } + + // Convert the BigInteger to a byte array + byte[] bytes = num.toByteArray(); + + // Remove any leading zero bytes + if (bytes.length > 0 && bytes[0] == 0) { + byte[] tmp = new byte[bytes.length - 1]; + System.arraycopy(bytes, 1, tmp, 0, tmp.length); + bytes = tmp; + } + + // Add leading zero bytes for each leading '1' character in the input + int numZeros = 0; + for (int i = 0; i < input.length() && input.charAt(i) == ALPHABET[0]; i++) { + numZeros++; + } + byte[] result = new byte[numZeros + bytes.length]; + System.arraycopy(bytes, 0, result, numZeros, bytes.length); + + return result; + } +} diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index e1c13dc..8e6d8bf 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -2,11 +2,10 @@ import burp.ui.ExtensionPanel; import burp.ui.HackvertorInput; +import burp.ui.HackvertorMessageTab; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; -import org.fife.ui.rsyntaxtextarea.Theme; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -202,7 +201,7 @@ public void run() { } try { hackvertor = new Hackvertor(); - stdout.println("Hackvertor v1.7.38"); + stdout.println("Hackvertor v1.7.49"); loadCustomTags(); loadGlobalVariables(); registerPayloadProcessors(); @@ -787,13 +786,13 @@ public void actionPerformed(ActionEvent e) { try { if (language.equals("JavaScript")) { - output = javascript(new HashMap<>(), input, code, tagCodeExecutionKey, customTagOptions, hackvertor.getCustomTags()); + output = javascript(new HashMap<>(), input, code, tagCodeExecutionKey, customTagOptions, hackvertor.getCustomTags(), null); } else if(language.equals("Python")){ - output = python(new HashMap<>(), input, code, tagCodeExecutionKey, customTagOptions, hackvertor.getCustomTags()); + output = python(new HashMap<>(), input, code, tagCodeExecutionKey, customTagOptions, hackvertor.getCustomTags(), null); } else if(language.equals("Java")){ - output = java(new HashMap<>(), input, code, tagCodeExecutionKey, customTagOptions, hackvertor.getCustomTags()); + output = java(new HashMap<>(), input, code, tagCodeExecutionKey, customTagOptions, hackvertor.getCustomTags(), null); } else if(language.equals("Groovy")){ - output = groovy(new HashMap<>(), input, code, tagCodeExecutionKey, customTagOptions, hackvertor.getCustomTags()); + output = groovy(new HashMap<>(), input, code, tagCodeExecutionKey, customTagOptions, hackvertor.getCustomTags(), null); } }catch (Exception ee){ ee.printStackTrace(); @@ -1062,6 +1061,7 @@ public void createCustomTag(String tagName, String language, String code, String public void extensionUnloaded() { hvShutdown = true; burpMenuBar.remove(hvMenuBar); + burpMenuBar.revalidate(); burpMenuBar.repaint(); callbacks.printOutput("Hackvertor unloaded"); } @@ -1082,9 +1082,9 @@ public int[] getHeaderOffsets(byte[] request, String header) { int end = request.length; while (i < end) { int line_start = i; - while (i < end && request[i++] != ' ') { + while (i < end && request[i++] != ':') { } - byte[] header_name = Arrays.copyOfRange(request, line_start, i - 2); + byte[] header_name = Arrays.copyOfRange(request, line_start, i - 1); int headerValueStart = i; while (i < end && request[i++] != '\n') { } @@ -1111,7 +1111,7 @@ public byte[] setHeader(byte[] request, String header, String value) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { outputStream.write(Arrays.copyOfRange(request, 0, offsets[1])); - outputStream.write(helpers.stringToBytes(value)); + outputStream.write(helpers.stringToBytes(" " + value)); outputStream.write(Arrays.copyOfRange(request, offsets[2], request.length)); return outputStream.toByteArray(); } catch (IOException e) { diff --git a/src/main/java/burp/Convertors.java b/src/main/java/burp/Convertors.java index 44468ae..fbc568d 100644 --- a/src/main/java/burp/Convertors.java +++ b/src/main/java/burp/Convertors.java @@ -184,13 +184,13 @@ public static String callTag(HashMap variableMap, JSONArray cust String language = customTag.getString("language").toLowerCase(); String code = customTag.getString("code"); if (language.equals("javascript")) { - return javascript(variableMap, output, code, eKey, customTagOptions, customTags); + return javascript(variableMap, output, code, eKey, customTagOptions, customTags, hackvertor); } else if (language.equals("python")) { - return python(variableMap, output, code, eKey, customTagOptions, customTags); + return python(variableMap, output, code, eKey, customTagOptions, customTags, hackvertor); } else if (language.equals("java")) { - return java(variableMap, output, code, eKey, customTagOptions, customTags); + return java(variableMap, output, code, eKey, customTagOptions, customTags, hackvertor); } else if (language.equals("groovy")) { - return groovy(variableMap, output, code, eKey, customTagOptions, customTags); + return groovy(variableMap, output, code, eKey, customTagOptions, customTags, hackvertor); } } } @@ -233,6 +233,10 @@ public static String callTag(HashMap variableMap, JSONArray cust case "get_var": case "get_variable": return variableMap.getOrDefault(getString(arguments,0), StringUtils.isEmpty(output) ? "UNDEFINED" : output); + case "increment_var": + return increment_var(globalVariables, getInt(arguments, 0), getString(arguments, 1), getBoolean(arguments, 2)); + case "decrement_var": + return decrement_var(globalVariables, getInt(arguments, 0), getString(arguments, 1), getBoolean(arguments, 2)); case "context_url": return context_url(getString(arguments,0), hackvertor); case "context_header": @@ -362,6 +366,10 @@ public static String callTag(HashMap variableMap, JSONArray cust return base32_encode(output); case "d_base32": return decode_base32(output); + case "base58": + return base58_encode(output); + case "d_base58": + return decode_base58(output); case "base64": return base64Encode(output); case "d_base64": @@ -405,7 +413,7 @@ public static String callTag(HashMap variableMap, JSONArray cust case "length": return len(output); case "find": - return find(output, getString(arguments, 0)); + return find(output, getString(arguments, 0), getInt(arguments, 1)); case "replace": return replace(output, getString(arguments, 0), getString(arguments, 1)); case "regex_replace": @@ -422,6 +430,10 @@ public static String callTag(HashMap variableMap, JSONArray cust return Double.toString(index_of_coincidence(output)); case "guess_key_length": return Integer.toString(guess_key_length(output)); + case "if_regex": + return if_regex(output, getString(arguments, 0), getString(arguments, 1)); + case "if_not_regex": + return if_not_regex(output, getString(arguments, 0), getString(arguments, 1)); case "chunked_dec2hex": return chunked_dec2hex(output); case "dec2hex": @@ -558,6 +570,8 @@ public static String callTag(HashMap variableMap, JSONArray cust return convert_base(output, getString(arguments, 0), getInt(arguments, 1), getInt(arguments, 2)); case "zeropad": return zeropad(output, getString(arguments, 0), getInt(arguments, 1)); + case "uuid": + return uuid(); case "behavior": return behavior(output); case "css_expression": @@ -579,25 +593,17 @@ public static String callTag(HashMap variableMap, JSONArray cust case "throw_eval": return throw_eval(output); case "python": - return python(variableMap, output, getString(arguments, 0), getString(arguments, 1), null, customTags); + return python(variableMap, output, getString(arguments, 0), getString(arguments, 1), null, customTags, null); case "javascript": - return javascript(variableMap, output, getString(arguments, 0), getString(arguments, 1), null, customTags); + return javascript(variableMap, output, getString(arguments, 0), getString(arguments, 1), null, customTags, null); case "java": - return java(variableMap, output, getString(arguments, 0), getString(arguments, 1), null, customTags); + return java(variableMap, output, getString(arguments, 0), getString(arguments, 1), null, customTags, null); case "groovy": - return groovy(variableMap, output, getString(arguments, 0), getString(arguments, 1), null, customTags); + return groovy(variableMap, output, getString(arguments, 0), getString(arguments, 1), null, customTags, null); case "read_url": return read_url(output, getString(arguments, 0), getBoolean(arguments, 1), getString(arguments, 2)); case "system": return system(output, getBoolean(arguments, 0), getString(arguments, 1)); - case "loop_for": - return loop_for(variableMap, customTags, output, getInt(arguments, 0), getInt(arguments, 1), getInt(arguments, 2), getString(arguments, 3)); - case "loop_letters_lower": - return loop_letters_lower(variableMap, customTags, output, getString(arguments, 0)); - case "loop_letters_upper": - return loop_letters_upper(variableMap, customTags, output, getString(arguments, 0)); - case "loop_numbers": - return loop_letters_numbers(variableMap, customTags, output, getString(arguments, 0)); } } @@ -852,7 +858,8 @@ static String context_header(String properties, Hackvertor hackvertor) { for(String header : headers) { String[] nameValue = header.split(":"); if(nameValue.length > 1) { - properties = properties.replace("$" + nameValue[0].trim(), nameValue[1].trim()); + properties = properties.replace("$" + nameValue[0].trim(), nameValue[1].trim() + + (nameValue.length > 2 ? ":" + String.join(":", Arrays.copyOfRange(nameValue, 2, nameValue.length)) : "")); } } return properties; @@ -869,6 +876,36 @@ static String context_param(String properties, Hackvertor hackvertor) { return properties; } + static String increment_var(HashMap variableMap, int start, String variableName, Boolean enabled) { + if(!enabled) { + return "This tag is disabled until you enable it in the tag params to prevent unintentional variable declaration."; + } + int value = 0; + if(variableMap.containsKey(variableName)) { + value = Integer.parseInt(variableMap.get(variableName)); + } else { + value = start; + } + String returnValue = String.valueOf(value); + variableMap.put(variableName, String.valueOf(value+1)); + return returnValue; + } + + static String decrement_var(HashMap variableMap, int start, String variableName, Boolean enabled) { + if(!enabled) { + return "This tag is disabled until you enable it in the tag params to prevent unintentional variable declaration."; + } + int value = 0; + if(variableMap.containsKey(variableName)) { + value = Integer.parseInt(variableMap.get(variableName)); + } else { + value = start; + } + String returnValue = String.valueOf(value); + variableMap.put(variableName, String.valueOf(value-1)); + return returnValue; + } + static String context_body(Hackvertor hackvertor) { if(hackvertor == null) { return ""; @@ -1088,12 +1125,20 @@ static String decode_html_entities(String str) { static String base32_encode(String str) { Base32 base32 = new Base32(); - return new String(base32.encode(str.getBytes())); + return helpers.bytesToString(base32.encode(helpers.stringToBytes(str))); } static String decode_base32(String str) { Base32 base32 = new Base32(); - return new String(base32.decode(str.getBytes())); + return helpers.bytesToString(base32.decode(str.getBytes())); + } + + static String base58_encode(String str) { + return Base58.encode(helpers.stringToBytes(str)); + } + + static String decode_base58(String str) { + return helpers.bytesToString(Base58.decode(str)); } static String base64Encode(String str) { @@ -1976,6 +2021,22 @@ static String dec2hex(String str, String regex) { return regexMatcher.appendTail(result).toString(); } + static String if_regex(String str, String regex, String value) { + Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); + Matcher regexMatcher = pattern.matcher(value); + if(regexMatcher.find()) { + return str; + } + return ""; + } + static String if_not_regex(String str, String regex, String value) { + Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); + Matcher regexMatcher = pattern.matcher(value); + if(!regexMatcher.find()) { + return str; + } + return ""; + } static String chunked_dec2hex(String str) { try { return Integer.toHexString(Integer.parseInt(str)); @@ -2466,12 +2527,16 @@ static String len(String str) { return Integer.toString(str.length()); } - static String find(String str, String find) { + static String find(String str, String find, int group) { java.util.List allMatches = new ArrayList(); try { Matcher m = Pattern.compile(find).matcher(str); while (m.find()) { - allMatches.add(m.group()); + if(group == -1) { + allMatches.add(m.group()); + } else { + allMatches.add(m.group(group)); + } } } catch (PatternSyntaxException e) { stderr.println(e.getMessage()); @@ -2960,6 +3025,10 @@ static String zeropad(String str, String splitChar, int amount) { return StringUtils.join(chars, ","); } + static String uuid() { + return UUID.randomUUID().toString(); + } + static String eval_fromcharcode(String str) { return "eval(String.fromCharCode(" + to_charcode(str) + "))"; } @@ -3010,7 +3079,7 @@ static String template_eval(String str) { return "eval(`" + str.replaceAll("(.)", "$1\\${[]}") + "`)"; } - static String python(HashMap variableMap, String input, String code, String executionKey, JSONObject customTagOptions, JSONArray customTags) { + static String python(HashMap variableMap, String input, String code, String executionKey, JSONObject customTagOptions, JSONArray customTags, Hackvertor hackvertor) { if (!codeExecutionTagsEnabled) { return "Code execution tags are disabled by default. Use the menu bar to enable them."; } @@ -3064,7 +3133,7 @@ static String python(HashMap variableMap, String input, String c "sys.stdout = StreamWrapper(orig_stdout)\n" + "from burp import Convertors\n" + "def convert(input):\n" + - " return Convertors.convert(variableMap, customTags, input)\n" + + " return Convertors.weakConvert(variableMap, customTags, input, hackvertor)\n" + "\n"; pythonInterpreter.exec(initCode + code); @@ -3082,7 +3151,7 @@ static String python(HashMap variableMap, String input, String c } } - static String java(HashMap variableMap, String input, String code, String executionKey, JSONObject customTagOptions, JSONArray customTags) { + static String java(HashMap variableMap, String input, String code, String executionKey, JSONObject customTagOptions, JSONArray customTags, Hackvertor hackvertor) { if (!codeExecutionTagsEnabled) { return "Code execution tags are disabled by default. Use the menu bar to enable them."; } @@ -3103,8 +3172,10 @@ static String java(HashMap variableMap, String input, String cod javaInterpreter.set("customTags", customTags); String initCode = "import burp.Convertors;\n" + "public String convert(String input) {\n" + - " return Convertors.convert(variableMap, customTags, input);\n" + + " return Convertors.weakConvert(variableMap, customTags, input, hackvertor);\n" + "}\n"; + + for (Map.Entry entry : variableMap.entrySet()) { String name = entry.getKey(); Object value = entry.getValue(); @@ -3137,7 +3208,7 @@ static String java(HashMap variableMap, String input, String cod return "Unable to parse Java:" + e.toString(); } } - static String groovy(HashMap variableMap, String input, String code, String executionKey, JSONObject customTagOptions, JSONArray customTags) { + static String groovy(HashMap variableMap, String input, String code, String executionKey, JSONObject customTagOptions, JSONArray customTags, Hackvertor hackvertor) { if (!codeExecutionTagsEnabled) { return "Code execution tags are disabled by default. Use the menu bar to enable them."; } @@ -3158,7 +3229,7 @@ static String groovy(HashMap variableMap, String input, String c data.setVariable("customTags", customTags); String initCode = "import burp.Convertors;\n" + "public String convert(String input) {\n" + - " return Convertors.convert(variableMap, customTags, input);\n" + + " return Convertors.weakConvert(variableMap, customTags, input, hackvertor);\n" + "}\n"; try { if (code.endsWith(".groovy")) { @@ -3171,7 +3242,7 @@ static String groovy(HashMap variableMap, String input, String c } return shell.getVariable("output").toString(); } - static String javascript(HashMap variableMap, String input, String code, String executionKey, JSONObject customTagOptions, JSONArray customTags) { + static String javascript(HashMap variableMap, String input, String code, String executionKey, JSONObject customTagOptions, JSONArray customTags, Hackvertor hackvertor) { if (!codeExecutionTagsEnabled) { return "Code execution tags are disabled by default. Use the menu bar to enable them."; } @@ -3197,7 +3268,7 @@ static String javascript(HashMap variableMap, String input, Stri public String invoke(final V8Object receiver, final V8Array parameters) { if (parameters.length() > 0) { Object input = parameters.get(0); - String output = convert(variableMap, customTags, input.toString()); + String output = Convertors.weakConvert(variableMap, customTags, input.toString(), hackvertor); if (input instanceof Releasable) { ((Releasable) input).release(); } @@ -3358,40 +3429,4 @@ static String read_url(String input, String charset, Boolean enabled, String exe return "Unable to get response"; } } - - static String loop_for(HashMap variableMap, JSONArray customTags, String input, int start, int end, int increment, String variable) { - String output = ""; - for (int i = start; i < end; i += increment) { - variableMap.put(variable, Integer.toString(i)); - output += convert(variableMap, customTags, input); - } - return output; - } - - static String loop_letters_lower(HashMap variableMap, JSONArray customTags, String input, String variable) { - String output = ""; - for (char letter = 'a'; letter <= 'z'; letter++) { - variableMap.put(variable, Character.toString(letter)); - output += convert(variableMap, customTags, input);; - } - return output; - } - - static String loop_letters_upper(HashMap variableMap, JSONArray customTags, String input, String variable) { - String output = ""; - for (char letter = 'A'; letter <= 'Z'; letter++) { - variableMap.put(variable, Character.toString(letter)); - output += convert(variableMap, customTags, input); - } - return output; - } - - static String loop_letters_numbers(HashMap variableMap, JSONArray customTags, String input, String variable) { - String output = ""; - for (char num = '0'; num <= '9'; num++) { - variableMap.put(variable, Character.toString(num)); - output += convert(variableMap, customTags, input); - } - return output; - } } diff --git a/src/main/java/burp/Hackvertor.java b/src/main/java/burp/Hackvertor.java index 22ba072..7ab8e5c 100644 --- a/src/main/java/burp/Hackvertor.java +++ b/src/main/java/burp/Hackvertor.java @@ -33,6 +33,10 @@ public byte[] getRequest() { return request; } + public void setRequest(byte[] request) { + this.request = request; + } + public static String removeHackvertorTags(String input) { try { input = HackvertorParser.parse(input).stream() @@ -142,6 +146,7 @@ void init() { tags.add(new Tag(Tag.Category.Encrypt, "guess_key_length", true, "guess_key_length(String ciphertext)")); tags.add(new Tag(Tag.Category.Encode, "saml", true, "saml(String str)")); tags.add(new Tag(Tag.Category.Encode, "base32", true, "base32_encode(String str)")); + tags.add(new Tag(Tag.Category.Encode, "base58", true, "base58Encode(String str)")); tags.add(new Tag(Tag.Category.Encode, "base64", true, "base64Encode(String str)")); tags.add(new Tag(Tag.Category.Encode, "base64url", true, "base64urlEncode(String str)")); tags.add(new Tag(Tag.Category.Encode, "html_entities", true, "html_entities(String str)")); @@ -174,6 +179,7 @@ void init() { 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)")); tags.add(new Tag(Tag.Category.Decode, "d_base32", true, "decode_base32(String str)")); + tags.add(new Tag(Tag.Category.Decode, "d_base58", true, "decode_base58(String str)")); tags.add(new Tag(Tag.Category.Decode, "d_base64", true, "decode_base64(String str)")); tags.add(new Tag(Tag.Category.Decode, "d_base64url", true, "decode_base64url(String str)")); tags.add(new Tag(Tag.Category.Decode, "d_html_entities", true, "decode_html_entities(String str)")); @@ -193,6 +199,14 @@ void init() { tag = new Tag(Tag.Category.Decode, "d_jwt_verify", true, "d_jwt_verify(String token, String secret)"); tag.argument1 = new TagArgument("string", "secret"); tags.add(tag); + tag = new Tag(Tag.Category.Conditions, "if_regex", true, "if_regex(String str, String regex, String value)"); + tag.argument1 = new TagArgument("string", "regex"); + tag.argument2 = new TagArgument("string", "value"); + tags.add(tag); + tag = new Tag(Tag.Category.Conditions, "if_not_regex", true, "if_not_regex(String str, String regex, String value)"); + tag.argument1 = new TagArgument("string", "regex"); + tag.argument2 = new TagArgument("string", "value"); + tags.add(tag); tags.add(new Tag(Tag.Category.Convert, "chunked_dec2hex", true, "chunked_dec2hex(String str)")); tag = new Tag(Tag.Category.Convert, "dec2hex", true, "dec2hex(String str, String regex)"); tag.argument1 = new TagArgument("string", "(\\d+)"); @@ -228,8 +242,9 @@ 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)")); - tag = new Tag(Tag.Category.String, "find", true, "find(String str, String find)"); + 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"); tags.add(tag); tag = new Tag(Tag.Category.String, "replace", true, "replace(String str, String find, String replace)"); tag.argument1 = new TagArgument("string", "find"); @@ -402,6 +417,8 @@ void init() { tag.argument1 = new TagArgument("string", ","); tag.argument2 = new TagArgument("int", "2"); tags.add(tag); + tag = new Tag(Tag.Category.Math, "uuid", false, "uuid()"); + tags.add(tag); tags.add(new Tag(Tag.Category.XSS, "behavior", true, "behavior(String str)")); tags.add(new Tag(Tag.Category.XSS, "css_expression", true, "css_expression(String str)")); tags.add(new Tag(Tag.Category.XSS, "datasrc", true, "datasrc(String str)")); @@ -415,6 +432,16 @@ void init() { Tag setTag = new Tag(Tag.Category.Variables, "set_variable1", true, "Special tag that lets you store the results of a conversion. Change variable1 to your own variable name. The argument specifies if the variable is global."); setTag.argument1 = new TagArgument("boolean", "false"); tags.add(setTag); + tag = new Tag(Tag.Category.Variables, "increment_var", false, "increment_var(int start, String variableName, Boolean enabled)//This tag allows you to declare a variable and initialize it and then every subsequent conversion increments it."); + tag.argument1 = new TagArgument("number", "0"); + tag.argument2 = new TagArgument("string", "variable"); + tag.argument3 = new TagArgument("boolean", "false"); + tags.add(tag); + tag = new Tag(Tag.Category.Variables, "decrement_var", false, "decrement_var(int start, String variableName, Boolean enabled)//This tag allows you to declare a variable and initialize it and then every subsequent conversion decrements it."); + tag.argument1 = new TagArgument("number", "0"); + tag.argument2 = new TagArgument("string", "variable"); + tag.argument3 = new TagArgument("boolean", "false"); + tags.add(tag); tags.add(new Tag(Tag.Category.Variables, "get_variable1", false, "Special tag that lets you get a previously set variable. Change var to your own variable name.")); tag = new Tag(Tag.Category.Variables, "context_url", false, "context_url(String properties"); tag.argument1 = new TagArgument("string", "$protocol $host $path $file $query $port"); @@ -427,21 +454,6 @@ void init() { tag = new Tag(Tag.Category.Variables, "context_param", false, "context_url(String paramName"); tag.argument1 = new TagArgument("string", "$paramName"); tags.add(tag); - tag = new Tag(Tag.Category.Loops, "loop_for", true, "loop_for(String input, int start, int end, int increment, String i)//Does a for loop. Use a Hackvertor variable inside the tags to retrieve the position in the loop."); - tag.argument1 = new TagArgument("int", "0"); - tag.argument2 = new TagArgument("int", "10"); - tag.argument3 = new TagArgument("int", "1"); - tag.argument4 = new TagArgument("string", "i"); - tags.add(tag); - tag = new Tag(Tag.Category.Loops, "loop_letters_lower", true, "loop_letters_lower(String input, String variable)//Loops through all lowecase letters. Use a Hackvertor variable inside the tags to retrieve the letter"); - tag.argument1 = new TagArgument("string", "letter"); - tags.add(tag); - tag = new Tag(Tag.Category.Loops, "loop_letters_upper", true, "loop_letters_upper(String input, String variable)//Loops through all uppercase letters. Use a Hackvertor variable inside the tags to retrieve the letter"); - tag.argument1 = new TagArgument("string", "letter"); - tags.add(tag); - tag = new Tag(Tag.Category.Loops, "loop_numbers", true, "loop_numbers(String input, String variable)//Loops through all numbers. Use a Hackvertor variable inside the tags to retrieve the number"); - tag.argument1 = new TagArgument("string", "number"); - tags.add(tag); tag = new Tag(Tag.Category.Languages, "python", true, "python(String input, String code, String codeExecuteKey)"); tag.argument1 = new TagArgument("string", "output = input.upper()"); tag.argument2 = new TagArgument("string", tagCodeExecutionKey); diff --git a/src/main/java/burp/Tag.java b/src/main/java/burp/Tag.java index 5752d19..4068e3f 100644 --- a/src/main/java/burp/Tag.java +++ b/src/main/java/burp/Tag.java @@ -2,7 +2,7 @@ public class Tag { public enum Category { - Custom, Variables, Encode, Decode, String, Convert, Math, Hash, HMAC, Fake, Charsets, Compression, Date, Loops, Encrypt, Decrypt, Languages, System, XSS + Custom, Variables, Encode, Decode, String, Convert, Conditions, Math, Hash, HMAC, Fake, Charsets, Compression, Date, Encrypt, Decrypt, Languages, System, XSS }; public Category category; diff --git a/src/main/java/burp/Utils.java b/src/main/java/burp/Utils.java index 304f287..7cd2efb 100644 --- a/src/main/java/burp/Utils.java +++ b/src/main/java/burp/Utils.java @@ -1,6 +1,8 @@ package burp; import burp.parser.Element; +import burp.ui.HackvertorInput; +import burp.ui.MenuScroller; import org.apache.commons.lang3.StringUtils; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.Theme; @@ -185,12 +187,11 @@ public static void fixRSyntaxAreaBurp() { UIManager.put("RTextAreaUI.inputMap", null); } - public static void configureRSyntaxArea(RSyntaxTextArea area) { + public static void configureRSyntaxArea(HackvertorInput area) { area.setLineWrap(true); if(BurpExtender.isDarkTheme) { Utils.applyThemeToRSyntaxTextArea(area, "dark"); } callbacks.customizeUiComponent(area); - area.setFont(new Font("Courier New", Font.PLAIN, area.getFont().getSize())); } } diff --git a/src/main/java/burp/parser/Element.java b/src/main/java/burp/parser/Element.java index 31d7fcf..9dcdd13 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(StringUtils.isNumeric(argument) || argument.equals("true") || argument.equals("false")) + if((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) + "'"); @@ -57,9 +57,10 @@ public String toString() { sb.append("("); for (int i = 0; i < arguments.size(); i++) { if(i != 0) sb.append(","); - if(StringUtils.isNumeric(arguments.get(i))){ - sb.append(arguments.get(i)); - }else { + String argument = arguments.get(i); + if((argument.startsWith("-") && StringUtils.isNumeric(argument.substring(1))) || StringUtils.isNumeric(argument) || argument.equals("true") || argument.equals("false")) { + sb.append(argument); + } else { sb.append("\"").append(arguments.get(i)).append("\""); } } diff --git a/src/main/java/burp/ui/HackvertorInput.java b/src/main/java/burp/ui/HackvertorInput.java index b795912..ba17aa5 100644 --- a/src/main/java/burp/ui/HackvertorInput.java +++ b/src/main/java/burp/ui/HackvertorInput.java @@ -7,14 +7,39 @@ import javax.swing.*; import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; import static burp.BurpExtender.callbacks; public class HackvertorInput extends RSyntaxTextArea { public HackvertorInput() { super(); - callbacks.customizeUiComponent(this); - this.updateFont(); + HackvertorInput that = this; + this.addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { + + } + + @Override + public void keyPressed(KeyEvent e) { + if ((e.getKeyCode() == KeyEvent.VK_PLUS || e.getKeyCode() == KeyEvent.VK_EQUALS) && (e.isMetaDown() || (e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0)) { + int fontSize = that.getFont().getSize(); + that.changeFontSize(fontSize + 1); + } else if ((e.getKeyCode() == KeyEvent.VK_MINUS) && (e.isMetaDown() || (e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0)) { + int fontSize = that.getFont().getSize(); + that.changeFontSize(fontSize - 1); + } else if ((e.isControlDown() || e.isMetaDown()) && (e.getKeyCode() == KeyEvent.VK_0)) { + getFontSizeFromBurp(); + } + } + + @Override + public void keyReleased(KeyEvent e) { + + } + }); } public void updateUI() { super.updateUI(); @@ -25,11 +50,16 @@ public void updateUI() { } else { Utils.applyThemeToRSyntaxTextArea(this, "default"); } + getFontSizeFromBurp(); }); + } + + public void getFontSizeFromBurp() { callbacks.customizeUiComponent(this); - this.updateFont(); + this.changeFontSize(this.getFont().getSize()); } - public void updateFont() { - this.setFont(new Font("Courier New", Font.PLAIN, this.getFont().getSize())); + + public void changeFontSize(int fontSize) { + this.setFont(new Font("Courier New", Font.PLAIN, fontSize)); } } diff --git a/src/main/java/burp/HackvertorMessageTab.java b/src/main/java/burp/ui/HackvertorMessageTab.java similarity index 97% rename from src/main/java/burp/HackvertorMessageTab.java rename to src/main/java/burp/ui/HackvertorMessageTab.java index c67b2cc..765807c 100644 --- a/src/main/java/burp/HackvertorMessageTab.java +++ b/src/main/java/burp/ui/HackvertorMessageTab.java @@ -1,5 +1,8 @@ -package burp; +package burp.ui; +import burp.BurpExtender; +import burp.Hackvertor; +import burp.IMessageEditorTab; import burp.ui.HackvertorPanel; import javax.swing.*; diff --git a/src/main/java/burp/ui/HackvertorPanel.java b/src/main/java/burp/ui/HackvertorPanel.java index c0ea160..5b55ff2 100644 --- a/src/main/java/burp/ui/HackvertorPanel.java +++ b/src/main/java/burp/ui/HackvertorPanel.java @@ -47,8 +47,6 @@ public HackvertorPanel(Hackvertor hackvertor, boolean showLogo){ this.inputArea = new HackvertorInput(); this.outputArea = new HackvertorInput(); Utils.fixRSyntaxAreaBurp(); - callbacks.customizeUiComponent(this.inputArea); - callbacks.customizeUiComponent(this.outputArea); this.inputArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML); this.outputArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML); Utils.configureRSyntaxArea(this.inputArea); diff --git a/src/main/java/burp/JTabbedPaneClosable.java b/src/main/java/burp/ui/JTabbedPaneClosable.java similarity index 98% rename from src/main/java/burp/JTabbedPaneClosable.java rename to src/main/java/burp/ui/JTabbedPaneClosable.java index e051220..73081e4 100644 --- a/src/main/java/burp/JTabbedPaneClosable.java +++ b/src/main/java/burp/ui/JTabbedPaneClosable.java @@ -1,7 +1,6 @@ -package burp; +package burp.ui; import javax.swing.*; -import javax.swing.plaf.metal.MetalIconFactory; import java.awt.*; import java.awt.event.*; diff --git a/src/main/java/burp/MenuScroller.java b/src/main/java/burp/ui/MenuScroller.java similarity index 99% rename from src/main/java/burp/MenuScroller.java rename to src/main/java/burp/ui/MenuScroller.java index ddb1256..b1f1d98 100644 --- a/src/main/java/burp/MenuScroller.java +++ b/src/main/java/burp/ui/MenuScroller.java @@ -2,7 +2,7 @@ * @(#)MenuScroller.java 1.5.0 04/02/12 */ -package burp; +package burp.ui; import java.awt.Color; import java.awt.Component;