├── .gitignore
├── .gradle
├── 8.10
│ ├── checksums
│ │ └── checksums.lock
│ ├── dependencies-accessors
│ │ └── gc.properties
│ ├── executionHistory
│ │ ├── executionHistory.bin
│ │ └── executionHistory.lock
│ ├── expanded
│ │ └── expanded.lock
│ ├── fileChanges
│ │ └── last-build.bin
│ ├── fileHashes
│ │ ├── fileHashes.bin
│ │ ├── fileHashes.lock
│ │ └── resourceHashesCache.bin
│ └── gc.properties
├── buildOutputCleanup
│ ├── buildOutputCleanup.lock
│ ├── cache.properties
│ └── outputFiles.bin
├── file-system.probe
└── vcs-1
│ └── gc.properties
├── .idea
├── .gitignore
├── compiler.xml
├── gradle.xml
├── misc.xml
└── vcs.xml
├── README.md
├── build.gradle
├── build
├── classes
│ └── java
│ │ └── main
│ │ └── burpsuite
│ │ ├── MenuItemsProvider.class
│ │ ├── MyTableModel$LogEntry.class
│ │ ├── MyTableModel.class
│ │ ├── Settings$1.class
│ │ ├── Settings$2.class
│ │ ├── Settings$3.class
│ │ ├── Settings$4.class
│ │ ├── Settings$5.class
│ │ ├── Settings$6.class
│ │ ├── Settings$7.class
│ │ ├── Settings.class
│ │ ├── UnkeyInput$1.class
│ │ ├── UnkeyInput$2.class
│ │ ├── UnkeyInput$3.class
│ │ ├── UnkeyInput.class
│ │ └── proxyHandler.class
├── libs
│ └── UnkeyInput-1.0.jar
├── resources
│ └── main
│ │ ├── Parameters.txt
│ │ └── allHeaders.txt
└── tmp
│ ├── compileJava
│ └── previous-compilation-data.bin
│ └── jar
│ └── MANIFEST.MF
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── images
├── 1.png
├── 2.png
└── 3.png
├── settings.gradle
└── src
└── main
├── java
└── burpsuite
│ ├── MenuItemsProvider.java
│ ├── MyTableModel.java
│ ├── Settings.java
│ ├── UnkeyInput.java
│ └── proxyHandler.java
└── resources
├── Parameters.txt
└── allHeaders.txt
/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gitignore
--------------------------------------------------------------------------------
/.gradle/8.10/checksums/checksums.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/checksums/checksums.lock
--------------------------------------------------------------------------------
/.gradle/8.10/dependencies-accessors/gc.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/dependencies-accessors/gc.properties
--------------------------------------------------------------------------------
/.gradle/8.10/executionHistory/executionHistory.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/executionHistory/executionHistory.bin
--------------------------------------------------------------------------------
/.gradle/8.10/executionHistory/executionHistory.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/executionHistory/executionHistory.lock
--------------------------------------------------------------------------------
/.gradle/8.10/expanded/expanded.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/expanded/expanded.lock
--------------------------------------------------------------------------------
/.gradle/8.10/fileChanges/last-build.bin:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gradle/8.10/fileHashes/fileHashes.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/fileHashes/fileHashes.bin
--------------------------------------------------------------------------------
/.gradle/8.10/fileHashes/fileHashes.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/fileHashes/fileHashes.lock
--------------------------------------------------------------------------------
/.gradle/8.10/fileHashes/resourceHashesCache.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/fileHashes/resourceHashesCache.bin
--------------------------------------------------------------------------------
/.gradle/8.10/gc.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/8.10/gc.properties
--------------------------------------------------------------------------------
/.gradle/buildOutputCleanup/buildOutputCleanup.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/buildOutputCleanup/buildOutputCleanup.lock
--------------------------------------------------------------------------------
/.gradle/buildOutputCleanup/cache.properties:
--------------------------------------------------------------------------------
1 | #Tue Jan 07 13:12:14 EST 2025
2 | gradle.version=8.10
3 |
--------------------------------------------------------------------------------
/.gradle/buildOutputCleanup/outputFiles.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/buildOutputCleanup/outputFiles.bin
--------------------------------------------------------------------------------
/.gradle/file-system.probe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/file-system.probe
--------------------------------------------------------------------------------
/.gradle/vcs-1/gc.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/.gradle/vcs-1/gc.properties
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Unkey Input
2 |
3 | Burp suite extension to find unkey headers OR parameters
4 |
5 |
6 |
7 |
8 |
9 |  |
10 |  |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Features
21 |
22 |
23 | 1 - Unique cache key per every request
24 |
25 |
26 | - Random _parameter , _Cookie and User-Agent
27 | - Remove If-Modified-Since and If-None-Match
28 |
29 |
30 |
31 | 2 - add top HTTP headers to your incoming HTTP requests
32 |
33 | ```sh
34 | GET /?_parameter=372586408566 HTTP/1.1
35 | Host: 0ad800b603698249817511ea0076000a.web-security-academy.net
36 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/372586408566 Safari/372586408566
37 | Cookie: _Cookie=372586408566
38 | Pragma: akamai-x-check-cacheable,akamai-x-cache-on
39 | Fastly-Debug: 1
40 | X-Http-Forwarded-For: X-Http-Forwarded-For-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
41 | X-Forwarded-For-Original: X-Forwarded-For-Original-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
42 | X-Forwarded-Client-Ip: X-Forwarded-Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
43 | X-Cluster-Client-Ip: X-Cluster-Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
44 | X-Original-Forwarded-For: X-Original-Forwarded-For-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
45 | X-Wap-Client-Ip: X-Wap-Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
46 | Fastly-Client-Ip: Fastly-Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
47 | X-Client-Ip: X-Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
48 | X-Wap-Profile: X-Wap-Profile-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
49 | X-Proxyuser-Uri: X-Proxyuser-Uri-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
50 | X-Remote-Ip: X-Remote-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
51 | X-Wap-Network-Client-Ip: X-Wap-Network-Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
52 | X-Originating-Ip: X-Originating-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
53 | Client-Ip: Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
54 | X-Host: X-Host-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
55 | X-Forwarded-Uri: X-Forwarded-Uri-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
56 | Cf-Connecting-Ip: Cf-Connecting-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
57 | X-True-Ip: X-True-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
58 | X-Rewrite-Url: X-Rewrite-Url-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
59 | X-Original-Url: X-Original-Url-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
60 | X-Proxyuser-Ip: X-Proxyuser-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
61 | X-Proxyuser-Host: X-Proxyuser-Host-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
62 | Referer: Referer-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
63 | X-Forwarded-Host: X-Forwarded-Host-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
64 | X-Remote-Addr: X-Remote-Addr-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
65 | X-Original-Host: X-Original-Host-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
66 | X-Originating-Host: X-Originating-Host-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
67 | True-Client-Ip: True-Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
68 | X-Real-Host: X-Real-Host-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
69 | Akamai-Client-Ip: Akamai-Client-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
70 | X-Forwarded-Path: X-Forwarded-Path-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
71 | X-Original-Cookie: X-Original-Cookie-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
72 | X-Forwarded-By: X-Forwarded-By-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
73 | Forwarded: Forwarded-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
74 | X-Forwarded-For: X-Forwarded-For-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
75 | X-Original-User-Agent: X-Original-User-Agent-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
76 | X-Real-Ip: X-Real-Ip-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
77 | X-Forwarded-Server: X-Forwarded-Server-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
78 | X-Original-Referer: X-Original-Referer-%3Cxss%3E%253Cxss%253E\u003Cxss\u003E
79 | ```
80 |
81 | 3 - Contain context menu to fuzz
82 |
83 | - TitleCase Headers
84 | - LowerCase Headers
85 | - UpperCase Headers
86 | - Hyphen to Underscore
87 | - Duplicate Headers
88 | - Hex to Headers
89 |
90 | - Hex Before Headers
91 | - Hex After Headers
92 |
93 | - Duplicate Header With Space
94 | - Fuzz Parameters
95 |
96 | - Query
97 | - Body
98 |
99 | - Fuzz Cookie
100 |
101 |
102 | Reference
103 |
104 | Beyond Web Caching Vulnerabilities
105 |
106 |
107 | © Copyright
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | }
4 |
5 | group = 'burpsuite'
6 | version = '1.0'
7 |
8 |
9 | repositories {
10 | mavenCentral()
11 | }
12 |
13 | dependencies {
14 | implementation 'net.portswigger.burp.extensions:montoya-api:+'
15 | }
16 |
17 |
18 | jar {
19 | from {
20 | configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
21 | }
22 | }
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/MenuItemsProvider.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/MenuItemsProvider.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/MyTableModel$LogEntry.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/MyTableModel$LogEntry.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/MyTableModel.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/MyTableModel.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/Settings$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/Settings$1.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/Settings$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/Settings$2.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/Settings$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/Settings$3.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/Settings$4.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/Settings$4.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/Settings$5.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/Settings$5.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/Settings$6.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/Settings$6.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/Settings$7.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/Settings$7.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/Settings.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/Settings.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/UnkeyInput$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/UnkeyInput$1.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/UnkeyInput$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/UnkeyInput$2.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/UnkeyInput$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/UnkeyInput$3.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/UnkeyInput.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/UnkeyInput.class
--------------------------------------------------------------------------------
/build/classes/java/main/burpsuite/proxyHandler.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/classes/java/main/burpsuite/proxyHandler.class
--------------------------------------------------------------------------------
/build/libs/UnkeyInput-1.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/libs/UnkeyInput-1.0.jar
--------------------------------------------------------------------------------
/build/tmp/compileJava/previous-compilation-data.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/build/tmp/compileJava/previous-compilation-data.bin
--------------------------------------------------------------------------------
/build/tmp/jar/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 |
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Jan 07 13:12:09 EST 2025
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/images/1.png
--------------------------------------------------------------------------------
/images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/images/2.png
--------------------------------------------------------------------------------
/images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0xAwali/UnkeyInput/20a9ce5f381dc8770b37f9bec6a5c0921672e5f6/images/3.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'UnkeyInput'
2 |
3 |
--------------------------------------------------------------------------------
/src/main/java/burpsuite/MenuItemsProvider.java:
--------------------------------------------------------------------------------
1 | package burpsuite;
2 |
3 | import burp.api.montoya.MontoyaApi;
4 | import burp.api.montoya.http.message.HttpRequestResponse;
5 | import burp.api.montoya.http.message.StatusCodeClass;
6 | import burp.api.montoya.http.message.params.HttpParameterType;
7 | import burp.api.montoya.http.message.requests.HttpRequest;
8 | import burp.api.montoya.persistence.PersistedObject;
9 | import burp.api.montoya.ui.contextmenu.ContextMenuEvent;
10 | import burp.api.montoya.ui.contextmenu.ContextMenuItemsProvider;
11 | import burp.api.montoya.ui.contextmenu.InvocationType;
12 | import javax.swing.*;
13 | import java.awt.*;
14 | import java.io.BufferedReader;
15 | import java.io.InputStream;
16 | import java.io.InputStreamReader;
17 | import java.util.ArrayList;
18 | import java.util.Collections;
19 | import java.util.List;
20 | import java.util.concurrent.ExecutorService;
21 | import java.util.concurrent.Executors;
22 | import java.util.concurrent.ThreadLocalRandom;
23 |
24 | import static burp.api.montoya.http.message.params.HttpParameter.*;
25 | import static burpsuite.UnkeyInput.*;
26 |
27 | public class MenuItemsProvider implements ContextMenuItemsProvider {
28 |
29 | private final MontoyaApi api;
30 | private final MyTableModel table;
31 |
32 | private static final String[] HEADERS_TO_REMOVE = {
33 | "Akamai-Client-Ip", "Cf-Connecting-Ip", "Client-Ip", "Fastly-Client-Ip", "Forwarded", "Referer", "True-Client-Ip",
34 | "X-Client-Ip", "X-Cluster-Client-Ip", "X-Forwarded-By", "X-Forwarded-Client-Ip", "X-Forwarded-For", "X-Forwarded-For-Original",
35 | "X-Forwarded-Host", "X-Forwarded-Path", "X-Forwarded-Server", "X-Forwarded-Uri", "X-Host", "X-Http-Forwarded-For",
36 | "X-Original-Cookie", "X-Original-Forwarded-For", "X-Original-Host", "X-Original-Referer", "X-Original-Url", "X-Original-User-Agent",
37 | "X-Originating-Host", "X-Originating-Ip", "X-Proxyuser-Host", "X-Proxyuser-Ip", "X-Proxyuser-Uri", "X-Real-Host", "X-Real-Ip",
38 | "X-Remote-Addr", "X-Remote-Ip", "X-Rewrite-Url", "X-True-Ip", "X-Wap-Client-Ip", "X-Wap-Network-Client-Ip", "X-Wap-Profile"
39 | };
40 |
41 | private static final String[] CACHE_HEADERS = {
42 | "Age", "CDN-Cache", "CF-Cache-Status", "Server-Timing", "X-Cache", "X-Cache-Info", "X-Cache-Remote", "X-Check-Cacheable",
43 | "X-Drupal-Cache", "X-Drupal-Dynamic-Cache", "X-Proxy-Cache", "X-Rack-Cache", "Akamai-Cache-Status"
44 | };
45 |
46 | PersistedObject persistence;
47 | private List additionalHeaders;
48 | private List parameters;
49 |
50 | public MenuItemsProvider(MontoyaApi api, MyTableModel table, PersistedObject persist) {
51 | this.api = api;
52 | this.table = table;
53 | this.additionalHeaders = loadAdditionalHeaders();
54 | this.parameters = loadParameters();
55 | this.persistence = persist;
56 |
57 |
58 | }
59 |
60 | // Load additional headers from the resources folder
61 | private List loadAdditionalHeaders() {
62 | List headers = new ArrayList<>();
63 | try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("allHeaders.txt");
64 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
65 | String line;
66 | while ((line = reader.readLine()) != null) {
67 | headers.add(line.trim());
68 | }
69 | } catch (Exception e) {
70 | api.logging().logToError("Failed to load additional headers: " + e.getMessage());
71 | }
72 | return headers;
73 | }
74 |
75 | // Load parameters from the resources folder
76 | private List loadParameters() {
77 | List parameters = new ArrayList<>();
78 | try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("Parameters.txt");
79 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
80 | String line;
81 | while ((line = reader.readLine()) != null) {
82 | parameters.add(line.trim());
83 | }
84 | } catch (Exception e) {
85 | api.logging().logToError("Failed to load parameters: " + e.getMessage());
86 | }
87 | return parameters;
88 | }
89 |
90 | @Override
91 | public List provideMenuItems(ContextMenuEvent event) {
92 | if (event.isFrom(InvocationType.PROXY_HISTORY)) {
93 | List menuItemList = new ArrayList<>();
94 |
95 | // Existing menu items
96 | JMenuItem fuzzHeaders = new JMenuItem("TitleCase Headers");
97 | fuzzHeaders.addActionListener(l -> titleCaseHeaders(event));
98 | menuItemList.add(fuzzHeaders);
99 |
100 | JMenuItem lowerCaseHeaders = new JMenuItem("LowerCase Headers");
101 | lowerCaseHeaders.addActionListener(l -> upperORlower(event, true));
102 | menuItemList.add(lowerCaseHeaders);
103 |
104 | JMenuItem upperCaseHeaders = new JMenuItem("UpperCase Headers");
105 | upperCaseHeaders.addActionListener(l -> upperORlower(event, false));
106 | menuItemList.add(upperCaseHeaders);
107 |
108 | JMenuItem convertHyphenToUnderscore = new JMenuItem("Convert Hyphen to Underscore");
109 | convertHyphenToUnderscore.addActionListener(l -> convertHyphenToUnderscore(event));
110 | menuItemList.add(convertHyphenToUnderscore);
111 |
112 | JMenuItem duplicateHeader = new JMenuItem("Duplicate Header");
113 | duplicateHeader.addActionListener(l -> duplicateHeader(event));
114 | menuItemList.add(duplicateHeader);
115 |
116 | // Add new menu item for Fuzz Parameters with submenus
117 | JMenu addHexToHeader = new JMenu("Add Hex to Headers");
118 |
119 | JMenuItem HexHeaderValue = new JMenuItem("Hex Before Headers");
120 | HexHeaderValue.addActionListener(l -> HexHeaderValue(event));
121 | addHexToHeader.add(HexHeaderValue);
122 |
123 | JMenuItem HeaderHexValue = new JMenuItem("Hex After Headers");
124 | HeaderHexValue.addActionListener(l -> HeaderHexValue(event));
125 | addHexToHeader.add(HeaderHexValue);
126 |
127 | menuItemList.add(addHexToHeader);
128 |
129 | JMenuItem duplicateHeaderWithSpace = new JMenuItem("Duplicate Header With Space");
130 | duplicateHeaderWithSpace.addActionListener(l -> duplicateHeaderWithSpace(event));
131 | menuItemList.add(duplicateHeaderWithSpace);
132 |
133 | // Add new menu item for Fuzz Parameters with submenus
134 | JMenu fuzzParametersMenu = new JMenu("Fuzz Parameters");
135 | // Submenu: Query
136 | JMenuItem queryMenuItem = new JMenuItem("Query");
137 | queryMenuItem.addActionListener(l -> fuzzQuery(event));
138 | fuzzParametersMenu.add(queryMenuItem);
139 |
140 | // Submenu: Body
141 | JMenu bodyMenu = new JMenu("Body");
142 |
143 | // Submenu under Body: Url-Encoding
144 | JMenuItem urlEncodingMenuItem = new JMenuItem("urlencoded");
145 | urlEncodingMenuItem.addActionListener(l -> fuzzBodyUrlEncoding(event));
146 | bodyMenu.add(urlEncodingMenuItem);
147 |
148 | // Submenu under Body: json
149 | JMenuItem jsonMenuItem = new JMenuItem("json");
150 | jsonMenuItem.addActionListener(l -> fuzzBodyJson(event));
151 | bodyMenu.add(jsonMenuItem);
152 |
153 | // Submenu under Body: xml
154 | JMenuItem xmlMenuItem = new JMenuItem("xml");
155 | xmlMenuItem.addActionListener(l -> fuzzBodyXml(event));
156 | bodyMenu.add(xmlMenuItem);
157 |
158 | fuzzParametersMenu.add(bodyMenu);
159 | menuItemList.add(fuzzParametersMenu);
160 |
161 | JMenuItem fuzzCookie = new JMenuItem("Fuzz Cookie");
162 | fuzzCookie.addActionListener(l -> fuzzCookie(event));
163 | menuItemList.add(fuzzCookie);
164 |
165 |
166 |
167 | return menuItemList;
168 | }
169 | return Collections.emptyList();
170 | }
171 |
172 | private List getAllHeaders() {
173 | List allHeaders = new ArrayList<>();
174 | Collections.addAll(allHeaders, HEADERS_TO_REMOVE);
175 | allHeaders.addAll(additionalHeaders); // Use headers loaded from the file
176 | return allHeaders;
177 | }
178 |
179 | private boolean isCached(HttpRequestResponse httpRequestResponse) {
180 | if (httpRequestResponse.response().body().toString().contains(persistence.getString(YOUR_MATCH)) || httpRequestResponse.response().headers().toString().contains(persistence.getString(YOUR_MATCH))) {
181 | for (String header : CACHE_HEADERS) {
182 | if (httpRequestResponse.response().hasHeader(header)) {
183 | return true;
184 | }
185 | }
186 | }
187 | return false;
188 | }
189 |
190 | private boolean isNOTCached(HttpRequestResponse httpRequestResponse) {
191 | if (httpRequestResponse.response().body().toString().contains(persistence.getString(YOUR_MATCH))) {
192 | if(httpRequestResponse.hasResponse() && (!httpRequestResponse.response().isStatusCodeClass(StatusCodeClass.CLASS_3XX_REDIRECTION))){
193 | return true;
194 | }
195 | }
196 | return false;
197 | }
198 |
199 |
200 | private List> splitIntoChunks(T[] array, int chunkSize) {
201 | List> chunks = new ArrayList<>();
202 | for (int i = 0; i < array.length; i += chunkSize) {
203 | List chunk = new ArrayList<>();
204 | for (int j = i; j < Math.min(i + chunkSize, array.length); j++) {
205 | chunk.add(array[j]);
206 | }
207 | chunks.add(chunk);
208 | }
209 | return chunks;
210 | }
211 |
212 | private void titleCaseHeaders(ContextMenuEvent event) {
213 | List requestResponses = event.selectedRequestResponses();
214 | if (requestResponses.isEmpty()) {
215 | return;
216 | }
217 |
218 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
219 |
220 | List allHeaders = getAllHeaders();
221 | List> headerChunks = splitIntoChunks(allHeaders.toArray(new String[0]), persistence.getInteger(YOUR_HEADERS_PER_REQUEST));
222 |
223 | for (HttpRequestResponse requestResponse : requestResponses) {
224 | executorService.submit(() -> {
225 | try {
226 | HttpRequest baseRequest = requestResponse.request();
227 |
228 | // Remove headers from HEADERS_TO_REMOVE
229 | for (String header : HEADERS_TO_REMOVE) {
230 | baseRequest = baseRequest.withRemovedHeader(header);
231 | }
232 | // Process each chunk
233 | for (List chunk : headerChunks) {
234 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
235 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
236 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
237 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
238 |
239 | for (String header : chunk) {
240 | String headerValue = header + "-" + persistence.getString(YOUR_PAYLOAD);
241 | chunkRequest = chunkRequest.withHeader(header, headerValue);
242 | }
243 |
244 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
245 |
246 | if (isCached(modifiedRequestResponse)) {
247 | table.add(modifiedRequestResponse,true);
248 | } else if (isNOTCached(modifiedRequestResponse)) {
249 | table.add(modifiedRequestResponse,false);
250 | }
251 | }
252 | } catch (Exception e) {
253 | api.logging().logToError("Failed to send request: " + e.getMessage());
254 | }
255 | });
256 | }
257 | executorService.shutdown();
258 | }
259 |
260 | private void upperORlower(ContextMenuEvent event, boolean toLowerCase) {
261 | List requestResponses = event.selectedRequestResponses();
262 | if (requestResponses.isEmpty()) {
263 | return;
264 | }
265 |
266 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
267 |
268 | List allHeaders = getAllHeaders(); // Use combined headers
269 | List> headerChunks = splitIntoChunks(allHeaders.toArray(new String[0]), persistence.getInteger(YOUR_HEADERS_PER_REQUEST));
270 |
271 | for (HttpRequestResponse requestResponse : requestResponses) {
272 | executorService.submit(() -> {
273 | try {
274 | HttpRequest baseRequest = requestResponse.request();
275 |
276 | // Remove headers from HEADERS_TO_REMOVE
277 | for (String header : HEADERS_TO_REMOVE) {
278 | baseRequest = baseRequest.withRemovedHeader(header);
279 | }
280 | // Process each chunk
281 | for (List chunk : headerChunks) {
282 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
283 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
284 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
285 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
286 |
287 | for (String header : chunk) {
288 | String headerValue = header + "-" + persistence.getString(YOUR_PAYLOAD); // Set value to "header-xxxxxxxxxxxxxx"
289 | chunkRequest = chunkRequest.withHeader(toLowerCase ? header.toLowerCase() : header.toUpperCase(), headerValue);
290 | }
291 |
292 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
293 |
294 | if (isCached(modifiedRequestResponse)) {
295 | table.add(modifiedRequestResponse,true);
296 | } else if (isNOTCached(modifiedRequestResponse)) {
297 | table.add(modifiedRequestResponse,false);
298 | }
299 | }
300 | } catch (Exception e) {
301 | api.logging().logToError("Failed to send request: " + e.getMessage());
302 | }
303 | });
304 | }
305 | executorService.shutdown();
306 | }
307 |
308 |
309 | private void convertHyphenToUnderscore(ContextMenuEvent event) {
310 | List requestResponses = event.selectedRequestResponses();
311 | if (requestResponses.isEmpty()) {
312 | return;
313 | }
314 |
315 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
316 |
317 | List allHeaders = getAllHeaders(); // Use combined headers
318 | List> headerChunks = splitIntoChunks(allHeaders.toArray(new String[0]), persistence.getInteger(YOUR_HEADERS_PER_REQUEST));
319 |
320 | for (HttpRequestResponse requestResponse : requestResponses) {
321 | executorService.submit(() -> {
322 | try {
323 | HttpRequest baseRequest = requestResponse.request();
324 |
325 | // Remove headers from HEADERS_TO_REMOVE
326 | for (String header : HEADERS_TO_REMOVE) {
327 | baseRequest = baseRequest.withRemovedHeader(header);
328 | }
329 | // Process each chunk
330 | for (List chunk : headerChunks) {
331 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
332 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
333 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
334 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
335 |
336 | for (String header : chunk) {
337 | if (header.contains("-")) { // Only process headers containing hyphens
338 | String newHeader = header.replace("-", "_"); // Convert hyphens to underscores
339 | String headerValue = header + "-" + persistence.getString(YOUR_PAYLOAD); // Set value to "header-xxxxxxxxxxxxxx"
340 | chunkRequest = chunkRequest.withHeader(newHeader, headerValue);
341 | }
342 | }
343 |
344 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
345 |
346 | if (isCached(modifiedRequestResponse)) {
347 | table.add(modifiedRequestResponse,true);
348 | } else if (isNOTCached(modifiedRequestResponse)) {
349 | table.add(modifiedRequestResponse,false);
350 | }
351 | }
352 | } catch (Exception e) {
353 | api.logging().logToError("Failed to send request: " + e.getMessage());
354 | }
355 | });
356 | }
357 | executorService.shutdown();
358 | }
359 |
360 | private void duplicateHeader(ContextMenuEvent event) {
361 | List requestResponses = event.selectedRequestResponses();
362 | if (requestResponses.isEmpty()) {
363 | return;
364 | }
365 |
366 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
367 |
368 | List allHeaders = getAllHeaders(); // Use combined headers
369 | List> headerChunks = splitIntoChunks(allHeaders.toArray(new String[0]), persistence.getInteger(YOUR_HEADERS_PER_REQUEST));
370 |
371 | for (HttpRequestResponse requestResponse : requestResponses) {
372 | executorService.submit(() -> {
373 | try {
374 | HttpRequest baseRequest = requestResponse.request();
375 |
376 | // Remove headers from HEADERS_TO_REMOVE
377 | for (String header : HEADERS_TO_REMOVE) {
378 | baseRequest = baseRequest.withRemovedHeader(header);
379 | }
380 | // Process each chunk
381 | for (List chunk : headerChunks) {
382 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
383 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
384 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
385 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
386 |
387 | for (String header : chunk) {
388 | String headerValue = header + "-" + persistence.getString(YOUR_PAYLOAD); // Set value to "header-xxxxxxxxxxxxxx"
389 | chunkRequest = chunkRequest.withAddedHeader(header, headerValue); // Add the original header
390 | chunkRequest = chunkRequest.withAddedHeader(header, headerValue); // Add the duplicate header
391 | }
392 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
393 | if (isCached(modifiedRequestResponse)) {
394 | table.add(modifiedRequestResponse,true);
395 | } else if (isNOTCached(modifiedRequestResponse)) {
396 | table.add(modifiedRequestResponse,false);
397 | }
398 | }
399 | } catch (Exception e) {
400 | api.logging().logToError("Failed to send request: " + e.getMessage());
401 | }
402 | });
403 | }
404 | executorService.shutdown();
405 | }
406 |
407 |
408 | private void HexHeaderValue(ContextMenuEvent event) {
409 | List requestResponses = event.selectedRequestResponses();
410 | if (requestResponses.isEmpty()) {
411 | return;
412 | }
413 |
414 | // Define the hex values for non-printable characters
415 | int[] hexValues = {0x1, 0x4, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0x1F, 0x20, 0x7F, 0xA0, 0xFF};
416 |
417 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
418 |
419 |
420 | List allHeaders = getAllHeaders(); // Use combined headers
421 | List> headerChunks = splitIntoChunks(allHeaders.toArray(new String[0]), persistence.getInteger(YOUR_HEADERS_PER_REQUEST));
422 |
423 | for (HttpRequestResponse requestResponse : requestResponses) {
424 | executorService.submit(() -> {
425 | try {
426 |
427 | HttpRequest baseRequest = requestResponse.request();
428 | // Remove headers from HEADERS_TO_REMOVE
429 | for (String header : HEADERS_TO_REMOVE) {
430 | baseRequest = baseRequest.withRemovedHeader(header);
431 | }
432 | // Process each chunk
433 | for (List chunk : headerChunks) {
434 | // Create a base request with random parameters
435 | // Iterate through hex values and send a separate request for each
436 | for (int hexValue : hexValues) {
437 | // Convert hex value to a non-printable character
438 | char nonPrintableChar = (char) hexValue;
439 |
440 | // Create a copy of the base request for this iteration
441 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
442 |
443 | HttpRequest chunkRequest = baseRequest
444 | .withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
445 | .withUpdatedParameters(cookieParameter("_Cookie", String.valueOf(randomNumber)))
446 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
447 | // Add non-printable character to each header in the chunk
448 | for (String header : chunk) {
449 | // Prepend the non-printable character to the header name
450 | String newHeaderName = nonPrintableChar + header;
451 | String headerValue = header + "-" + persistence.getString(YOUR_PAYLOAD); // Set value to "header-xxxxxxxxxxxxxx"
452 | // Add the modified header to the request
453 | chunkRequest = chunkRequest.withHeader(newHeaderName, headerValue);
454 | }
455 | // Send the modified request
456 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
457 |
458 | // Check if the response body is valid and add to the table
459 | if (isCached(modifiedRequestResponse)) {
460 | table.add(modifiedRequestResponse,true);
461 | } else if (isNOTCached(modifiedRequestResponse)) {
462 | table.add(modifiedRequestResponse,false);
463 | }
464 | }
465 | }
466 | } catch (Exception e) {
467 | api.logging().logToError("Failed to send request: " + e.getMessage());
468 | }
469 | });
470 | }
471 | executorService.shutdown();
472 | }
473 |
474 |
475 |
476 | private void HeaderHexValue(ContextMenuEvent event) {
477 | List requestResponses = event.selectedRequestResponses();
478 | if (requestResponses.isEmpty()) {
479 | return;
480 | }
481 |
482 | // Define the hex values for non-printable characters
483 | int[] hexValues = {0x1, 0x4, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0x1F, 0x20, 0x7F, 0xA0, 0xFF};
484 |
485 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
486 |
487 |
488 | List allHeaders = getAllHeaders(); // Use combined headers
489 | List> headerChunks = splitIntoChunks(allHeaders.toArray(new String[0]), persistence.getInteger(YOUR_HEADERS_PER_REQUEST));
490 |
491 | for (HttpRequestResponse requestResponse : requestResponses) {
492 | executorService.submit(() -> {
493 | try {
494 |
495 | HttpRequest baseRequest = requestResponse.request();
496 | // Remove headers from HEADERS_TO_REMOVE
497 | for (String header : HEADERS_TO_REMOVE) {
498 | baseRequest = baseRequest.withRemovedHeader(header);
499 | }
500 |
501 | // Process each chunk
502 | for (List chunk : headerChunks) {
503 |
504 | // Create a base request with random parameters
505 |
506 | // Iterate through hex values and send a separate request for each
507 | for (int hexValue : hexValues) {
508 | // Convert hex value to a non-printable character
509 | char nonPrintableChar = (char) hexValue;
510 |
511 | // Create a copy of the base request for this iteration
512 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
513 |
514 | HttpRequest chunkRequest = baseRequest
515 | .withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
516 | .withUpdatedParameters(cookieParameter("_Cookie", String.valueOf(randomNumber)))
517 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
518 | // Add non-printable character to each header in the chunk
519 | for (String header : chunk) {
520 | // Prepend the non-printable character to the header name
521 | String newHeaderName = header + nonPrintableChar;
522 | String headerValue = header + "-" + persistence.getString(YOUR_PAYLOAD); // Set value to "header-xxxxxxxxxxxxxx"
523 | // Add the modified header to the request
524 | chunkRequest = chunkRequest.withHeader(newHeaderName, headerValue);
525 | }
526 | // Send the modified request
527 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
528 |
529 | // Check if the response body is valid and add to the table
530 | if (isCached(modifiedRequestResponse)) {
531 | table.add(modifiedRequestResponse,true);
532 | } else if (isNOTCached(modifiedRequestResponse)) {
533 | table.add(modifiedRequestResponse,false);
534 | }
535 | }
536 | }
537 | } catch (Exception e) {
538 | api.logging().logToError("Failed to send request: " + e.getMessage());
539 | }
540 | });
541 | }
542 | executorService.shutdown();
543 | }
544 |
545 |
546 | private void duplicateHeaderWithSpace(ContextMenuEvent event) {
547 | List requestResponses = event.selectedRequestResponses();
548 | if (requestResponses.isEmpty()) {
549 | return;
550 | }
551 |
552 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
553 |
554 |
555 | List allHeaders = getAllHeaders(); // Use combined headers
556 | List> headerChunks = splitIntoChunks(allHeaders.toArray(new String[0]), persistence.getInteger(YOUR_HEADERS_PER_REQUEST));
557 |
558 | for (HttpRequestResponse requestResponse : requestResponses) {
559 | executorService.submit(() -> {
560 | try {
561 | HttpRequest baseRequest = requestResponse.request();
562 |
563 | // Remove headers from HEADERS_TO_REMOVE
564 | for (String header : HEADERS_TO_REMOVE) {
565 | baseRequest = baseRequest.withRemovedHeader(header);
566 | }
567 | // Process each chunk
568 | for (List chunk : headerChunks) {
569 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
570 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
571 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
572 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
573 |
574 | for (String header : chunk) {
575 | String headerValue = header + "-" + persistence.getString(YOUR_PAYLOAD); // Set value to "header-xxxxxxxxxxxxxx"
576 | String newHeader = " " + header; // Add space to header name
577 | chunkRequest = chunkRequest.withAddedHeader(newHeader, headerValue); // Add the original header
578 | chunkRequest = chunkRequest.withAddedHeader(header, headerValue); // Add the duplicate header
579 | }
580 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
581 | if (isCached(modifiedRequestResponse)) {
582 | table.add(modifiedRequestResponse,true);
583 | } else if (isNOTCached(modifiedRequestResponse)) {
584 | table.add(modifiedRequestResponse,false);
585 | }
586 | }
587 | } catch (Exception e) {
588 | api.logging().logToError("Failed to send request: " + e.getMessage());
589 | }
590 | });
591 | }
592 | executorService.shutdown();
593 | }
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 | private void fuzzCookie(ContextMenuEvent event) {
602 | List requestResponses = event.selectedRequestResponses();
603 | if (requestResponses.isEmpty()) {
604 | return;
605 | }
606 |
607 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
608 |
609 |
610 | List parameters = loadParameters(); // Load parameters from the file
611 | List> parameterChunks = splitIntoChunks(parameters.toArray(new String[0]), persistence.getInteger(YOUR_PARAMETERS_COOKIE_PER_REQUEST));
612 |
613 | for (HttpRequestResponse requestResponse : requestResponses) {
614 | executorService.submit(() -> {
615 | try {
616 | HttpRequest baseRequest = requestResponse.request();
617 |
618 | // Remove unwanted headers
619 | for (String header : HEADERS_TO_REMOVE) {
620 | baseRequest = baseRequest.withRemovedHeader(header);
621 | }
622 |
623 | // Process each chunk of 50 parameters
624 | for (List chunk : parameterChunks) {
625 | // Create a new request with the current chunk of parameters
626 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
627 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
628 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
629 |
630 | // Add each parameter in the chunk to the request
631 | for (String parameter : chunk) {
632 | chunkRequest = chunkRequest.withAddedParameters(cookieParameter(parameter, persistence.getString(YOUR_PAYLOAD)));
633 | }
634 |
635 | // Send the modified request
636 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
637 |
638 | // Check if the response is valid and add it to the table
639 | if (isCached(modifiedRequestResponse)) {
640 | table.add(modifiedRequestResponse,true);
641 | } else if (isNOTCached(modifiedRequestResponse)) {
642 | table.add(modifiedRequestResponse,false);
643 | }
644 | }
645 | } catch (Exception e) {
646 | api.logging().logToError("Failed to send request: " + e.getMessage());
647 | }
648 | });
649 | }
650 | executorService.shutdown();
651 | }
652 |
653 |
654 |
655 |
656 | // Example action methods for the new menu items
657 | private void fuzzQuery(ContextMenuEvent event) {
658 | List requestResponses = event.selectedRequestResponses();
659 | if (requestResponses.isEmpty()) {
660 | return;
661 | }
662 |
663 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
664 |
665 | List parameters = loadParameters(); // Load parameters from the file
666 | List> parameterChunks = splitIntoChunks(parameters.toArray(new String[0]), persistence.getInteger(YOUR_PARAMETERS_QUERY_PER_REQUEST));
667 |
668 | for (HttpRequestResponse requestResponse : requestResponses) {
669 | executorService.submit(() -> {
670 | try {
671 | HttpRequest baseRequest = requestResponse.request();
672 |
673 | // Remove unwanted headers
674 | for (String header : HEADERS_TO_REMOVE) {
675 | baseRequest = baseRequest.withRemovedHeader(header);
676 | }
677 |
678 | // Process each chunk of 50 parameters
679 | for (List chunk : parameterChunks) {
680 | // Create a new request with the current chunk of parameters
681 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
682 | HttpRequest chunkRequest = baseRequest
683 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
684 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
685 |
686 | // Add each parameter in the chunk to the request
687 | for (String parameter : chunk) {
688 | chunkRequest = chunkRequest.withAddedParameters(parameter(parameter, persistence.getString(YOUR_PAYLOAD), HttpParameterType.URL));
689 | }
690 |
691 | // Send the modified request
692 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
693 |
694 | // Check if the response is valid and add it to the table
695 | if (isCached(modifiedRequestResponse)) {
696 | table.add(modifiedRequestResponse,true);
697 | } else if (isNOTCached(modifiedRequestResponse)) {
698 | table.add(modifiedRequestResponse,false);
699 | }
700 | }
701 | } catch (Exception e) {
702 | api.logging().logToError("Failed to send request: " + e.getMessage());
703 | }
704 | });
705 | }
706 | executorService.shutdown();
707 | } // Add your logic here
708 |
709 |
710 | private void fuzzBodyUrlEncoding(ContextMenuEvent event) {
711 | List requestResponses = event.selectedRequestResponses();
712 | if (requestResponses.isEmpty()) {
713 | return;
714 | }
715 |
716 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
717 |
718 |
719 | List parameters = loadParameters(); // Load parameters from the file
720 | List> parameterChunks = splitIntoChunks(parameters.toArray(new String[0]), persistence.getInteger(YOUR_PARAMETERS_BODY_PER_REQUEST));
721 |
722 | for (HttpRequestResponse requestResponse : requestResponses) {
723 | executorService.submit(() -> {
724 | try {
725 | HttpRequest baseRequest = requestResponse.request();
726 |
727 | // Remove unwanted headers
728 | for (String header : HEADERS_TO_REMOVE) {
729 | baseRequest = baseRequest.withRemovedHeader(header);
730 | }
731 |
732 | // Process each chunk of 50 parameters
733 | for (List chunk : parameterChunks) {
734 | // Create a new request with the current chunk of parameters
735 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
736 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
737 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
738 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
739 | // Add each parameter in the chunk to the request
740 | for (String parameter : chunk) {
741 | chunkRequest = chunkRequest.withAddedParameters(parameter(parameter, persistence.getString(YOUR_PAYLOAD), HttpParameterType.BODY));
742 | }
743 |
744 | // Send the modified request
745 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
746 |
747 | // Check if the response is valid and add it to the table
748 | if (isCached(modifiedRequestResponse)) {
749 | table.add(modifiedRequestResponse,true);
750 | } else if (isNOTCached(modifiedRequestResponse)) {
751 | table.add(modifiedRequestResponse,false);
752 | }
753 | }
754 | } catch (Exception e) {
755 | api.logging().logToError("Failed to send request: " + e.getMessage());
756 | }
757 | });
758 | }
759 | executorService.shutdown();
760 | }
761 |
762 | private void fuzzBodyJson(ContextMenuEvent event) {
763 | List requestResponses = event.selectedRequestResponses();
764 | if (requestResponses.isEmpty()) {
765 | return;
766 | }
767 |
768 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
769 |
770 |
771 | List parameters = loadParameters(); // Load parameters from the file
772 | List> parameterChunks = splitIntoChunks(parameters.toArray(new String[0]), persistence.getInteger(YOUR_PARAMETERS_BODY_PER_REQUEST));
773 |
774 | for (HttpRequestResponse requestResponse : requestResponses) {
775 | executorService.submit(() -> {
776 | try {
777 | HttpRequest baseRequest = requestResponse.request();
778 |
779 | // Remove unwanted headers
780 | for (String header : HEADERS_TO_REMOVE) {
781 | baseRequest = baseRequest.withRemovedHeader(header);
782 | }
783 |
784 | // Process each chunk of 50 parameters
785 | for (List chunk : parameterChunks) {
786 | // Create a new request with the current chunk of parameters
787 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
788 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
789 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
790 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
791 |
792 | // Add each parameter in the chunk to the request
793 | for (String parameter : chunk) {
794 | chunkRequest = chunkRequest.withAddedParameters(parameter(parameter, persistence.getString(YOUR_PAYLOAD), HttpParameterType.JSON));
795 | }
796 |
797 | // Send the modified request
798 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
799 |
800 | if (isCached(modifiedRequestResponse)) {
801 | table.add(modifiedRequestResponse,true);
802 | } else if (isNOTCached(modifiedRequestResponse)) {
803 | table.add(modifiedRequestResponse,false);
804 | }
805 | }
806 | } catch (Exception e) {
807 | api.logging().logToError("Failed to send request: " + e.getMessage());
808 | }
809 | });
810 | }
811 | executorService.shutdown();
812 | }
813 |
814 | private void fuzzBodyXml(ContextMenuEvent event) {
815 | List requestResponses = event.selectedRequestResponses();
816 | if (requestResponses.isEmpty()) {
817 | return;
818 | }
819 |
820 | ExecutorService executorService = Executors.newFixedThreadPool(persistence.getInteger(YOUR_THREAD));
821 |
822 |
823 | List parameters = loadParameters(); // Load parameters from the file
824 | List> parameterChunks = splitIntoChunks(parameters.toArray(new String[0]), persistence.getInteger(YOUR_PARAMETERS_BODY_PER_REQUEST));
825 |
826 | for (HttpRequestResponse requestResponse : requestResponses) {
827 | executorService.submit(() -> {
828 | try {
829 | HttpRequest baseRequest = requestResponse.request();
830 |
831 | // Remove unwanted headers
832 | for (String header : HEADERS_TO_REMOVE) {
833 | baseRequest = baseRequest.withRemovedHeader(header);
834 | }
835 |
836 | // Process each chunk of 50 parameters
837 | for (List chunk : parameterChunks) {
838 | // Create a new request with the current chunk of parameters
839 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
840 | HttpRequest chunkRequest = baseRequest.withUpdatedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
841 | .withUpdatedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
842 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber);
843 |
844 | // Add each parameter in the chunk to the request
845 | for (String parameter : chunk) {
846 | chunkRequest = chunkRequest.withAddedParameters(parameter(parameter, persistence.getString(YOUR_PAYLOAD), HttpParameterType.XML));
847 | }
848 |
849 | // Send the modified request
850 | HttpRequestResponse modifiedRequestResponse = api.http().sendRequest(chunkRequest);
851 |
852 | // Check if the response is valid and add it to the table
853 | if (isCached(modifiedRequestResponse)) {
854 | table.add(modifiedRequestResponse,true);
855 | } else if (isNOTCached(modifiedRequestResponse)) {
856 | table.add(modifiedRequestResponse,false);
857 | }
858 | }
859 | } catch (Exception e) {
860 | api.logging().logToError("Failed to send request: " + e.getMessage());
861 | }
862 | });
863 | }
864 | executorService.shutdown();
865 | }
866 | }
--------------------------------------------------------------------------------
/src/main/java/burpsuite/MyTableModel.java:
--------------------------------------------------------------------------------
1 | package burpsuite;
2 |
3 | import burp.api.montoya.MontoyaApi;
4 | import burp.api.montoya.http.message.HttpRequestResponse;
5 | import burp.api.montoya.proxy.http.InterceptedResponse;
6 | import javax.swing.table.AbstractTableModel;
7 | import java.util.*;
8 |
9 |
10 | public class MyTableModel extends AbstractTableModel {
11 |
12 | private final MontoyaApi api;
13 | private final List log;
14 |
15 | private static class LogEntry {
16 | private final Object message;
17 | private final Boolean cache;
18 |
19 |
20 | public LogEntry(Object message, Boolean cache) {
21 | this.message = message;
22 | this.cache = cache;
23 |
24 | }
25 | public Object getMessage() {
26 | return message;
27 | }
28 |
29 | public boolean isHttpRequestResponse() {
30 | return message instanceof HttpRequestResponse;
31 | }
32 |
33 | public boolean isInterceptedResponse() {
34 | return message instanceof InterceptedResponse;
35 | }
36 |
37 |
38 | public Boolean getCache() {
39 | return cache;
40 | }
41 | }
42 |
43 | public MyTableModel(MontoyaApi api) {
44 | this.api = api;
45 | this.log = new ArrayList<>(); // Initialize the list
46 | }
47 |
48 | @Override
49 | public synchronized int getRowCount() {
50 | return log.size(); // Return the size of the list
51 | }
52 |
53 | @Override
54 | public int getColumnCount() {
55 | return 4;
56 | }
57 |
58 | @Override
59 | public String getColumnName(int column) {
60 | return switch (column) {
61 | case 0 -> "#";
62 | case 1 -> "Host";
63 | case 2 -> "Cache";
64 | case 3 -> "Path";
65 | default -> "";
66 | };
67 | }
68 |
69 | @Override
70 | public synchronized Object getValueAt(int rowIndex, int columnIndex) {
71 | LogEntry entry = log.get(rowIndex);
72 |
73 | switch (columnIndex) {
74 | case 0:
75 | return rowIndex + 1;
76 | case 1:
77 | if (entry.isHttpRequestResponse()) {
78 | HttpRequestResponse httpRequestResponse = (HttpRequestResponse) (entry.getMessage());
79 | return httpRequestResponse.request().headerValue("Host");
80 | } else if (entry.isInterceptedResponse()) {
81 | InterceptedResponse interceptedResponse = (InterceptedResponse) (entry.getMessage());
82 | return interceptedResponse.request().headerValue("Host");
83 | } else {
84 | return "";
85 | }
86 |
87 | case 2:
88 | if (entry.getCache()) {
89 | return "Yes";
90 | } else {
91 | return "No";
92 | }
93 | case 3:
94 | if (entry.isHttpRequestResponse()) {
95 | HttpRequestResponse httpRequestResponse = (HttpRequestResponse) (entry.getMessage());
96 | return httpRequestResponse.request().pathWithoutQuery();
97 | } else if (entry.isInterceptedResponse()) {
98 | InterceptedResponse interceptedResponse = (InterceptedResponse) (entry.getMessage());
99 | return interceptedResponse.request().pathWithoutQuery();
100 | } else {
101 | return "";
102 | }
103 | default:
104 | return "";
105 | }
106 | }
107 |
108 | public synchronized void add(Object message,Boolean cache) {
109 | LogEntry entry = new LogEntry(message,cache);
110 | log.add(entry);
111 | int index = log.size() - 1;
112 | fireTableRowsInserted(index, index);
113 | }
114 |
115 | public synchronized Object get(int rowIndex) {
116 | LogEntry entry = log.get(rowIndex);
117 | return entry.getMessage();
118 | }
119 | }
--------------------------------------------------------------------------------
/src/main/java/burpsuite/Settings.java:
--------------------------------------------------------------------------------
1 | package burpsuite;
2 |
3 | import burp.api.montoya.persistence.PersistedObject;
4 |
5 | import javax.swing.*;
6 | import java.awt.*;
7 | import java.awt.event.ActionEvent;
8 | import java.awt.event.ActionListener;
9 |
10 | import static burpsuite.UnkeyInput.*;
11 |
12 | public class Settings extends JPanel {
13 |
14 | PersistedObject persistence;
15 | public Settings(PersistedObject persist) {
16 |
17 | this.persistence = persist;
18 | // Set the layout to GridBagLayout for precise control
19 | this.setLayout(new GridBagLayout());
20 | GridBagConstraints gbc = new GridBagConstraints();
21 | gbc.fill = GridBagConstraints.HORIZONTAL;
22 | gbc.anchor = GridBagConstraints.NORTHWEST;
23 | gbc.insets = new Insets(20, 5, 1, 5);
24 |
25 | // First row: Description Label
26 | String payloadDescription = "Enter your payload to use :";
27 | JLabel payloadDescriptionLabel = new JLabel(payloadDescription);
28 | gbc.gridx = 0; // Column 0
29 | gbc.gridy = 0; // Row 0
30 | gbc.gridwidth = 3; // Span across 3 columns
31 | gbc.anchor = GridBagConstraints.WEST; // Align to the left
32 | this.add(payloadDescriptionLabel, gbc);
33 |
34 | // First row: Label, TextField, Button
35 | JLabel label1 = new JLabel("Payload : ");
36 | JTextField payloadInput = new JTextField(persistence.getString(YOUR_PAYLOAD), 30); // Smaller width
37 | JButton saveBtn1 = new JButton("Save");
38 |
39 | // Add ActionListener to the first button
40 | saveBtn1.addActionListener(new ActionListener() {
41 | @Override
42 | public void actionPerformed(ActionEvent e) {
43 | String payload = payloadInput.getText();
44 | if (payload.isEmpty()) {
45 | JOptionPane.showMessageDialog(Settings.this, "Payload cannot be empty", "Unkey Input", JOptionPane.ERROR_MESSAGE);
46 | } else {
47 | persistence.setString(YOUR_PAYLOAD, payload);
48 | JOptionPane.showMessageDialog(Settings.this, payload + " saved", "Unkey Input", JOptionPane.INFORMATION_MESSAGE);
49 | }
50 | }
51 | });
52 |
53 | // Add components of the first row
54 | gbc.gridx = 0; // Column 0
55 | gbc.gridy = 1; // Row 1
56 | gbc.gridwidth = 1; // Reset gridwidth
57 | this.add(label1, gbc);
58 |
59 | gbc.gridx = 1; // Column 1
60 | gbc.gridy = 1; // Row 1
61 | this.add(payloadInput, gbc);
62 |
63 | gbc.gridx = 2; // Column 2
64 | gbc.gridy = 1; // Row 1
65 | this.add(saveBtn1, gbc);
66 |
67 | // Second row: Description Label
68 | String matchDescription = "Enter your match :";
69 | JLabel timeoutDescriptionLabel = new JLabel(matchDescription);
70 | gbc.gridx = 0; // Column 0
71 | gbc.gridy = 2; // Row 2
72 | gbc.gridwidth = 3; // Span across 3 columns
73 | this.add(timeoutDescriptionLabel, gbc);
74 |
75 | // Second row: Label, TextField, Button
76 | JLabel label2 = new JLabel("Match : ");
77 | JTextField matchInput = new JTextField(persistence.getString(YOUR_MATCH), 30); // Smaller width
78 | JButton saveBtn2 = new JButton("Save");
79 |
80 | // Add ActionListener to the second button
81 | saveBtn2.addActionListener(new ActionListener() {
82 | @Override
83 | public void actionPerformed(ActionEvent e) {
84 | String match = matchInput.getText();
85 | if (match.isEmpty()) {
86 | JOptionPane.showMessageDialog(Settings.this, "Match cannot be empty", "Unkey Input", JOptionPane.ERROR_MESSAGE);
87 | } else {
88 | persistence.setString(YOUR_MATCH, match);
89 | JOptionPane.showMessageDialog(Settings.this, match + " saved", "Unkey Input", JOptionPane.INFORMATION_MESSAGE);
90 | }
91 | }
92 | });
93 |
94 | // Add components of the second row
95 | gbc.gridx = 0; // Column 0
96 | gbc.gridy = 3; // Row 3
97 | gbc.gridwidth = 1; // Reset gridwidth
98 | this.add(label2, gbc);
99 |
100 | gbc.gridx = 1; // Column 1
101 | gbc.gridy = 3; // Row 3
102 | this.add(matchInput, gbc);
103 |
104 | gbc.gridx = 2; // Column 2
105 | gbc.gridy = 3; // Row 3
106 | this.add(saveBtn2, gbc);
107 |
108 | // Third row: Description Label
109 | String thredsDescription = "Set number of threads :";
110 | JLabel thredsDescriptionLabel = new JLabel(thredsDescription);
111 | gbc.gridx = 0; // Column 0
112 | gbc.gridy = 4; // Row 4
113 | gbc.gridwidth = 3; // Span across 3 columns
114 | this.add(thredsDescriptionLabel, gbc);
115 |
116 | // Third row: Label, TextField, Button
117 | JLabel label3 = new JLabel("Threads : ");
118 | JTextField thredsInput = new JTextField(Integer.toString(persistence.getInteger(YOUR_THREAD)), 30); // Smaller width
119 | JButton saveBtn3 = new JButton("Save");
120 |
121 | // Add ActionListener to the third button
122 | saveBtn3.addActionListener(new ActionListener() {
123 | @Override
124 | public void actionPerformed(ActionEvent e) {
125 | String threads = thredsInput.getText();
126 | if (threads.isEmpty()) {
127 | JOptionPane.showMessageDialog(Settings.this, "Threads cannot be empty", "Unkey Input", JOptionPane.ERROR_MESSAGE);
128 | } else {
129 | persistence.setInteger(YOUR_THREAD, Integer.parseInt(threads));
130 | JOptionPane.showMessageDialog(Settings.this, threads + " saved", "Unkey Input", JOptionPane.INFORMATION_MESSAGE);
131 | }
132 | }
133 | });
134 |
135 | // Add components of the third row
136 | gbc.gridx = 0; // Column 0
137 | gbc.gridy = 5; // Row 5
138 | gbc.gridwidth = 1; // Reset gridwidth
139 | this.add(label3, gbc);
140 |
141 | gbc.gridx = 1; // Column 1
142 | gbc.gridy = 5; // Row 5
143 | this.add(thredsInput, gbc);
144 |
145 | gbc.gridx = 2; // Column 2
146 | gbc.gridy = 5; // Row 5
147 | this.add(saveBtn3, gbc);
148 |
149 | // Fourth row: Description Label
150 | String headersDescription = "Set number of headers per request :";
151 | JLabel headersDescriptionLabel = new JLabel(headersDescription);
152 | gbc.gridx = 0; // Column 0
153 | gbc.gridy = 6; // Row 6
154 | gbc.gridwidth = 3; // Span across 3 columns
155 | this.add(headersDescriptionLabel, gbc);
156 |
157 | // Fourth row: Label, TextField, Button
158 | JLabel label4 = new JLabel("Headers : ");
159 | JTextField headersInput = new JTextField(Integer.toString(persistence.getInteger(YOUR_HEADERS_PER_REQUEST)), 30); // Smaller width
160 | JButton saveBtn4 = new JButton("Save");
161 |
162 | // Add ActionListener to the fourth button
163 | saveBtn4.addActionListener(new ActionListener() {
164 | @Override
165 | public void actionPerformed(ActionEvent e) {
166 | String header = headersInput.getText();
167 |
168 | if (header.isEmpty()) {
169 | JOptionPane.showMessageDialog(Settings.this, "Number of headers cannot be empty", "Unkey Input", JOptionPane.ERROR_MESSAGE);
170 | } else {
171 | persistence.setInteger(YOUR_HEADERS_PER_REQUEST, Integer.parseInt(header));
172 | JOptionPane.showMessageDialog(Settings.this, header + " saved", "Unkey Input", JOptionPane.INFORMATION_MESSAGE);
173 | }
174 | }
175 | });
176 |
177 | // Add components of the fourth row
178 | gbc.gridx = 0; // Column 0
179 | gbc.gridy = 7; // Row 7
180 | gbc.gridwidth = 1; // Reset gridwidth
181 | this.add(label4, gbc);
182 |
183 | gbc.gridx = 1; // Column 1
184 | gbc.gridy = 7; // Row 7
185 | this.add(headersInput, gbc);
186 |
187 | gbc.gridx = 2; // Column 2
188 | gbc.gridy = 7; // Row 7
189 | this.add(saveBtn4, gbc);
190 |
191 | // Fifth row: Description Label
192 | String queryDescription = "Set number of query parameters per request :";
193 | JLabel queryDescriptionLabel = new JLabel(queryDescription);
194 | gbc.gridx = 0; // Column 0
195 | gbc.gridy = 8; // Row 8
196 | gbc.gridwidth = 3; // Span across 3 columns
197 | this.add(queryDescriptionLabel, gbc);
198 |
199 | // Fifth row: Label, TextField, Button
200 | JLabel label5 = new JLabel("Query : ");
201 | JTextField queryInput = new JTextField(Integer.toString(persistence.getInteger(YOUR_PARAMETERS_QUERY_PER_REQUEST)), 30); // Wider width for User-Agent
202 | JButton saveBtn5 = new JButton("Save");
203 |
204 | // Add ActionListener to the fifth button
205 | saveBtn5.addActionListener(new ActionListener() {
206 | @Override
207 | public void actionPerformed(ActionEvent e) {
208 | String query = queryInput.getText();
209 |
210 | if (query.isEmpty()) {
211 | JOptionPane.showMessageDialog(Settings.this, "Number of query parameters cannot be empty", "Unkey Input", JOptionPane.ERROR_MESSAGE);
212 | } else {
213 | persistence.setInteger(YOUR_PARAMETERS_QUERY_PER_REQUEST, Integer.parseInt(query));
214 | JOptionPane.showMessageDialog(Settings.this, query + " saved", "Unkey Input", JOptionPane.INFORMATION_MESSAGE);
215 | }
216 | }
217 | });
218 |
219 | // Add components of the fifth row
220 | gbc.gridx = 0; // Column 0
221 | gbc.gridy = 9; // Row 9
222 | gbc.gridwidth = 1; // Reset gridwidth
223 | this.add(label5, gbc);
224 |
225 | gbc.gridx = 1; // Column 1
226 | gbc.gridy = 9; // Row 9
227 | this.add(queryInput, gbc);
228 |
229 | gbc.gridx = 2; // Column 2
230 | gbc.gridy = 9; // Row 9
231 | this.add(saveBtn5, gbc);
232 |
233 | // Sixth row: Description Label
234 | String cookieDescription = "Set number of cookie parameters per request :";
235 | JLabel cookieDescriptionLabel = new JLabel(cookieDescription);
236 | gbc.gridx = 0; // Column 0
237 | gbc.gridy = 10; // Row 10
238 | gbc.gridwidth = 3; // Span across 3 columns
239 | this.add(cookieDescriptionLabel, gbc);
240 |
241 | // Sixth row: Label, TextField, Button
242 | JLabel label6 = new JLabel("Cookie : ");
243 | JTextField cookieInput = new JTextField(Integer.toString(persistence.getInteger(YOUR_PARAMETERS_COOKIE_PER_REQUEST)), 30); // Wider width for proxy address
244 | JButton saveBtn6 = new JButton("Save");
245 |
246 | // Add ActionListener to the sixth button
247 | saveBtn6.addActionListener(new ActionListener() {
248 | @Override
249 | public void actionPerformed(ActionEvent e) {
250 | String cookie = cookieInput.getText();
251 | if (cookie.isEmpty()) {
252 | JOptionPane.showMessageDialog(Settings.this, "Number of cookie parameters cannot be empty", "Unkey Input", JOptionPane.ERROR_MESSAGE);
253 | } else {
254 | persistence.setInteger(YOUR_PARAMETERS_COOKIE_PER_REQUEST, Integer.parseInt(cookie));
255 | JOptionPane.showMessageDialog(Settings.this, cookie + " saved", "Unkey Input", JOptionPane.INFORMATION_MESSAGE);
256 | }
257 | }
258 | });
259 |
260 | // Add components of the sixth row
261 | gbc.gridx = 0; // Column 0
262 | gbc.gridy = 11; // Row 11
263 | gbc.gridwidth = 1; // Reset gridwidth
264 | this.add(label6, gbc);
265 |
266 | gbc.gridx = 1; // Column 1
267 | gbc.gridy = 11; // Row 11
268 | this.add(cookieInput, gbc);
269 |
270 | gbc.gridx = 2; // Column 2
271 | gbc.gridy = 11; // Row 11
272 | this.add(saveBtn6, gbc);
273 |
274 | // Seventh row: Description Label
275 | String bodyDescription = "Set number of body parameters per request :";
276 | JLabel bodyDescriptionLabel = new JLabel(bodyDescription);
277 | gbc.gridx = 0; // Column 0
278 | gbc.gridy = 12; // Row 12
279 | gbc.gridwidth = 3; // Span across 3 columns
280 | this.add(bodyDescriptionLabel, gbc);
281 |
282 | // Seventh row: Label, TextField, Button
283 | JLabel label7 = new JLabel("Body : ");
284 | JTextField bodyInput = new JTextField(Integer.toString(persistence.getInteger(YOUR_PARAMETERS_BODY_PER_REQUEST)), 30); // Wider width for cookie
285 | JButton saveBtn7 = new JButton("Save");
286 |
287 | // Add ActionListener to the seventh button
288 | saveBtn7.addActionListener(new ActionListener() {
289 | @Override
290 | public void actionPerformed(ActionEvent e) {
291 | String body = bodyInput.getText();
292 | if (body.isEmpty()) {
293 | JOptionPane.showMessageDialog(Settings.this, "Number of body parameters cannot be empty", "Unkey Input", JOptionPane.ERROR_MESSAGE);
294 | } else {
295 | persistence.setInteger(YOUR_PARAMETERS_BODY_PER_REQUEST, Integer.parseInt(body));
296 | JOptionPane.showMessageDialog(Settings.this, body + " saved", "Unkey Input", JOptionPane.INFORMATION_MESSAGE);
297 | }
298 | }
299 | });
300 |
301 | gbc.gridx = 0; // Column 0
302 | gbc.gridy = 13; // Row 13
303 | gbc.gridwidth = 1; // Reset gridwidth
304 | this.add(label7, gbc);
305 |
306 | gbc.gridx = 1; // Column 1
307 | gbc.gridy = 13; // Row 13
308 | this.add(bodyInput, gbc);
309 |
310 | gbc.gridx = 2; // Column 2
311 | gbc.gridy = 13; // Row 13
312 | this.add(saveBtn7, gbc);
313 | }
314 | }
--------------------------------------------------------------------------------
/src/main/java/burpsuite/UnkeyInput.java:
--------------------------------------------------------------------------------
1 | package burpsuite;
2 |
3 | import burp.api.montoya.BurpExtension;
4 | import burp.api.montoya.MontoyaApi;
5 | import burp.api.montoya.http.message.HttpRequestResponse;
6 | import burp.api.montoya.persistence.PersistedObject;
7 | import burp.api.montoya.proxy.http.InterceptedResponse;
8 | import burp.api.montoya.ui.UserInterface;
9 | import burp.api.montoya.ui.editor.HttpRequestEditor;
10 | import burp.api.montoya.ui.editor.HttpResponseEditor;
11 | import javax.swing.*;
12 | import javax.swing.table.DefaultTableCellRenderer;
13 | import javax.swing.table.TableColumn;
14 | import javax.swing.table.TableModel;
15 | import javax.swing.table.TableRowSorter;
16 | import java.awt.*;
17 | import java.awt.event.ActionEvent;
18 | import java.awt.event.InputEvent;
19 | import java.awt.event.KeyEvent;
20 | import java.time.LocalDateTime;
21 | import java.time.format.DateTimeFormatter;
22 | import java.util.Comparator;
23 | import java.util.Locale;
24 | import static burp.api.montoya.ui.editor.EditorOptions.READ_ONLY;
25 |
26 | public class UnkeyInput implements BurpExtension {
27 |
28 | private MontoyaApi api;
29 | DateTimeFormatter dateTimeFormatter;
30 |
31 | static final String YOUR_PAYLOAD = "YOUR_PAYLOAD";
32 | static final String YOUR_MATCH = "YOUR_MATCH";
33 | static final String YOUR_THREAD = "YOUR_THREAD";
34 | static final String YOUR_HEADERS_PER_REQUEST = "YOUR_HEADERS_PER_REQUEST";
35 | static final String YOUR_PARAMETERS_QUERY_PER_REQUEST = "YOUR_PARAMETERS_QUERY_PER_REQUEST";
36 | static final String YOUR_PARAMETERS_BODY_PER_REQUEST = "YOUR_PARAMETERS_BODY_PER_REQUEST";
37 | static final String YOUR_PARAMETERS_COOKIE_PER_REQUEST = "YOUR_PARAMETERS_COOKIE_PER_REQUEST";
38 |
39 |
40 |
41 | @Override
42 | public void initialize(MontoyaApi montoyaApi) {
43 | this.api = montoyaApi;
44 | this.dateTimeFormatter = DateTimeFormatter.ofPattern("d MMM yyyy", Locale.ENGLISH);
45 |
46 | PersistedObject persist = api.persistence().extensionData();
47 |
48 | String PAYLOAD = persist.getString(YOUR_PAYLOAD);
49 | if (PAYLOAD == null) {
50 | PAYLOAD = "%3Cxss%3E%253Cxss%253E\\u003Cxss\\u003E";
51 | }
52 | persist.setString(YOUR_PAYLOAD, PAYLOAD);
53 |
54 | String MATCH = persist.getString(YOUR_MATCH);
55 | if (MATCH == null) {
56 | MATCH = "";
57 | }
58 | persist.setString(YOUR_MATCH, MATCH);
59 |
60 | Integer THREAD = persist.getInteger(YOUR_THREAD);
61 | if (THREAD == null) {
62 | THREAD = 50;
63 | }
64 | persist.setInteger(YOUR_THREAD, THREAD);
65 |
66 | Integer HEADERS = persist.getInteger(YOUR_HEADERS_PER_REQUEST);
67 | if (HEADERS == null) {
68 | HEADERS = 100;
69 | }
70 | persist.setInteger(YOUR_HEADERS_PER_REQUEST, HEADERS);
71 |
72 | Integer QUERY = persist.getInteger(YOUR_PARAMETERS_QUERY_PER_REQUEST);
73 | if (QUERY == null) {
74 | QUERY = 30;
75 | }
76 | persist.setInteger(YOUR_PARAMETERS_QUERY_PER_REQUEST, QUERY);
77 |
78 | Integer BODY = persist.getInteger(YOUR_PARAMETERS_BODY_PER_REQUEST);
79 | if (BODY == null) {
80 | BODY = 60;
81 | }
82 | persist.setInteger(YOUR_PARAMETERS_BODY_PER_REQUEST, BODY);
83 |
84 |
85 | Integer COOKIE = persist.getInteger(YOUR_PARAMETERS_COOKIE_PER_REQUEST);
86 | if (COOKIE == null) {
87 | COOKIE = 45;
88 | }
89 | persist.setInteger(YOUR_PARAMETERS_COOKIE_PER_REQUEST, COOKIE);
90 |
91 |
92 | api.extension().setName("Unkey Input");
93 | MyTableModel table = new MyTableModel(api);
94 | api.userInterface().registerSuiteTab("Unkey Input", LoggerTab(table,persist));
95 | api.proxy().registerRequestHandler(new proxyHandler(table,persist));
96 | api.proxy().registerResponseHandler(new proxyHandler(table,persist));
97 | api.userInterface().registerContextMenuItemsProvider(new MenuItemsProvider(api,table,persist));
98 | }
99 |
100 | private Component LoggerTab(MyTableModel table, PersistedObject persist) {
101 |
102 | JTabbedPane responseCacheableGUI = new JTabbedPane();
103 |
104 | JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
105 | UserInterface userInterface = api.userInterface();
106 | HttpRequestEditor requestViewer = userInterface.createHttpRequestEditor(READ_ONLY);
107 | HttpResponseEditor responseViewer = userInterface.createHttpResponseEditor(READ_ONLY);
108 |
109 | JTabbedPane requestTab = new JTabbedPane();
110 | requestTab.addTab("Request", requestViewer.uiComponent());
111 |
112 | JTabbedPane responseTab = new JTabbedPane();
113 | responseTab.addTab("Response", responseViewer.uiComponent());
114 |
115 | JSplitPane splitTabs = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
116 |
117 | splitTabs.setLeftComponent(requestTab);
118 | splitTabs.setRightComponent(responseTab);
119 |
120 | splitPane.setRightComponent(splitTabs);
121 |
122 | JTable jTable = new JTable(table) {
123 | @Override
124 | public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
125 | super.changeSelection(rowIndex, columnIndex, toggle, extend);
126 | Object message = table.get(convertRowIndexToModel(rowIndex));
127 | if (message instanceof InterceptedResponse) {
128 | InterceptedResponse interceptedResponseMessage = (InterceptedResponse) message;
129 | requestViewer.setRequest(interceptedResponseMessage.request());
130 | responseViewer.setResponse(interceptedResponseMessage);
131 |
132 | } else if (message instanceof HttpRequestResponse) {
133 | HttpRequestResponse httpRequestResponseMessage = (HttpRequestResponse) message;
134 | requestViewer.setRequest(httpRequestResponseMessage.request());
135 | responseViewer.setResponse(httpRequestResponseMessage.response());
136 | }
137 | }
138 | };
139 |
140 | jTable.setRowHeight(30);
141 | jTable.setAutoCreateRowSorter(true);
142 | TableRowSorter sorter = new TableRowSorter<>(table);
143 | jTable.setRowSorter(sorter);
144 | sorter.setComparator(0, new Comparator() {
145 | @Override
146 | public int compare(Integer o1, Integer o2) {
147 | return o1.compareTo(o2); // Compare as integers
148 | }
149 | });
150 |
151 | jTable.getRowSorter().toggleSortOrder(0);
152 | DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
153 | centerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
154 | jTable.getColumnModel().getColumn(0).setCellRenderer(centerRenderer);
155 | jTable.getColumnModel().getColumn(2).setCellRenderer(centerRenderer);
156 |
157 |
158 | TableColumn ID = jTable.getColumnModel().getColumn(0);
159 | ID.setMinWidth(50);
160 | ID.setMaxWidth(100);
161 |
162 | TableColumn Host = jTable.getColumnModel().getColumn(1);
163 | Host.setMinWidth(350);
164 | Host.setMaxWidth(700);
165 |
166 |
167 | TableColumn CACHE = jTable.getColumnModel().getColumn(2);
168 | CACHE.setMinWidth(100);
169 | CACHE.setMaxWidth(150);
170 |
171 | JPopupMenu popupMenu = new JPopupMenu();
172 | JMenuItem sendToRepeaterMenuItem = new JMenuItem("Send to Repeater");
173 | popupMenu.add(sendToRepeaterMenuItem);
174 |
175 | Action sendToRepeaterAction = new AbstractAction() {
176 | @Override
177 | public void actionPerformed(ActionEvent e) {
178 | int[] selectedRows = jTable.getSelectedRows();
179 | for (int selectedRow : selectedRows) {
180 | Object message= table.get(jTable.convertRowIndexToModel(selectedRow));
181 | if (message instanceof InterceptedResponse) {
182 | InterceptedResponse interceptedResponseMessage = (InterceptedResponse) message;
183 | api.repeater().sendToRepeater(interceptedResponseMessage.request(),dateTimeFormatter.format(LocalDateTime.now()));
184 |
185 | } else if (message instanceof HttpRequestResponse) {
186 | HttpRequestResponse httpRequestResponseMessage = (HttpRequestResponse) message;
187 | api.repeater().sendToRepeater(httpRequestResponseMessage.request(),dateTimeFormatter.format(LocalDateTime.now()));
188 |
189 | }
190 | }
191 | }
192 | };
193 |
194 | sendToRepeaterMenuItem.addActionListener(sendToRepeaterAction);
195 | jTable.setComponentPopupMenu(popupMenu);
196 |
197 | KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK);
198 | jTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(keyStroke, "sendToRepeater");
199 | jTable.getActionMap().put("sendToRepeater", sendToRepeaterAction);
200 |
201 | JScrollPane scrollPane = new JScrollPane(jTable);
202 | splitPane.setLeftComponent(scrollPane);
203 |
204 | responseCacheableGUI.addTab("Logger",splitPane);
205 | responseCacheableGUI.addTab("Settings",new Settings(persist));
206 |
207 | return responseCacheableGUI;
208 | }
209 |
210 | }
211 |
--------------------------------------------------------------------------------
/src/main/java/burpsuite/proxyHandler.java:
--------------------------------------------------------------------------------
1 | package burpsuite;
2 |
3 | import burp.api.montoya.http.message.StatusCodeClass;
4 | import burp.api.montoya.persistence.PersistedObject;
5 | import burp.api.montoya.proxy.http.*;
6 | import burp.api.montoya.http.message.requests.HttpRequest;
7 | import burp.api.montoya.http.message.responses.HttpResponse;
8 | import java.util.concurrent.ThreadLocalRandom;
9 | import java.util.HashMap;
10 | import java.util.Map;
11 | import static burp.api.montoya.http.message.params.HttpParameter.cookieParameter;
12 | import static burp.api.montoya.http.message.params.HttpParameter.urlParameter;
13 | import static burpsuite.UnkeyInput.YOUR_MATCH;
14 | import static burpsuite.UnkeyInput.YOUR_PAYLOAD;
15 |
16 | public class proxyHandler implements ProxyRequestHandler, ProxyResponseHandler {
17 |
18 | private final MyTableModel table;
19 | PersistedObject persistence;
20 | public proxyHandler(MyTableModel table, PersistedObject persist) {
21 | this.table = table;
22 | this.persistence = persist;
23 |
24 | }
25 |
26 | private HttpRequest addCustomHeaders(HttpRequest request) {
27 | Map customHeaders = new HashMap<>();
28 | customHeaders.put("Referer", "Referer-" + persistence.getString(YOUR_PAYLOAD));
29 | customHeaders.put("Akamai-Client-Ip", "Akamai-Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
30 | customHeaders.put("Cf-Connecting-Ip", "Cf-Connecting-Ip-" + persistence.getString(YOUR_PAYLOAD));
31 | customHeaders.put("Client-Ip", "Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
32 | customHeaders.put("Fastly-Client-Ip", "Fastly-Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
33 | customHeaders.put("Forwarded", "Forwarded-" + persistence.getString(YOUR_PAYLOAD));
34 | customHeaders.put("True-Client-Ip", "True-Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
35 | customHeaders.put("X-Client-Ip", "X-Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
36 | customHeaders.put("X-Cluster-Client-Ip", "X-Cluster-Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
37 | customHeaders.put("X-Forwarded-By", "X-Forwarded-By-" + persistence.getString(YOUR_PAYLOAD));
38 | customHeaders.put("X-Forwarded-Client-Ip", "X-Forwarded-Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
39 | customHeaders.put("X-Forwarded-For", "X-Forwarded-For-" + persistence.getString(YOUR_PAYLOAD));
40 | customHeaders.put("X-Forwarded-For-Original", "X-Forwarded-For-Original-" + persistence.getString(YOUR_PAYLOAD));
41 | customHeaders.put("X-Forwarded-Host", "X-Forwarded-Host-" + persistence.getString(YOUR_PAYLOAD));
42 | customHeaders.put("X-Forwarded-Path", "X-Forwarded-Path-" + persistence.getString(YOUR_PAYLOAD));
43 | customHeaders.put("X-Forwarded-Server", "X-Forwarded-Server-" + persistence.getString(YOUR_PAYLOAD));
44 | customHeaders.put("X-Forwarded-Uri", "X-Forwarded-Uri-" + persistence.getString(YOUR_PAYLOAD));
45 | customHeaders.put("X-Host", "X-Host-" + persistence.getString(YOUR_PAYLOAD));
46 | customHeaders.put("X-Http-Forwarded-For", "X-Http-Forwarded-For-" + persistence.getString(YOUR_PAYLOAD));
47 | customHeaders.put("X-Original-Cookie", "X-Original-Cookie-" + persistence.getString(YOUR_PAYLOAD));
48 | customHeaders.put("X-Original-Forwarded-For", "X-Original-Forwarded-For-" + persistence.getString(YOUR_PAYLOAD));
49 | customHeaders.put("X-Original-Host", "X-Original-Host-" + persistence.getString(YOUR_PAYLOAD));
50 | customHeaders.put("X-Original-Referer", "X-Original-Referer-" + persistence.getString(YOUR_PAYLOAD));
51 | customHeaders.put("X-Original-Url", "X-Original-Url-" + persistence.getString(YOUR_PAYLOAD));
52 | customHeaders.put("X-Original-User-Agent", "X-Original-User-Agent-" + persistence.getString(YOUR_PAYLOAD));
53 | customHeaders.put("X-Originating-Host", "X-Originating-Host-" + persistence.getString(YOUR_PAYLOAD));
54 | customHeaders.put("X-Originating-Ip", "X-Originating-Ip-" + persistence.getString(YOUR_PAYLOAD));
55 | customHeaders.put("X-Proxyuser-Host", "X-Proxyuser-Host-" + persistence.getString(YOUR_PAYLOAD));
56 | customHeaders.put("X-Proxyuser-Ip", "X-Proxyuser-Ip-" + persistence.getString(YOUR_PAYLOAD));
57 | customHeaders.put("X-Proxyuser-Uri", "X-Proxyuser-Uri-" + persistence.getString(YOUR_PAYLOAD));
58 | customHeaders.put("X-Real-Host", "X-Real-Host-" + persistence.getString(YOUR_PAYLOAD));
59 | customHeaders.put("X-Real-Ip", "X-Real-Ip-" + persistence.getString(YOUR_PAYLOAD));
60 | customHeaders.put("X-Remote-Addr", "X-Remote-Addr-" + persistence.getString(YOUR_PAYLOAD));
61 | customHeaders.put("X-Remote-Ip", "X-Remote-Ip-" + persistence.getString(YOUR_PAYLOAD));
62 | customHeaders.put("X-Rewrite-Url", "X-Rewrite-Url-" + persistence.getString(YOUR_PAYLOAD));
63 | customHeaders.put("X-True-Ip", "X-True-Ip-" + persistence.getString(YOUR_PAYLOAD));
64 | customHeaders.put("X-Wap-Client-Ip", "X-Wap-Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
65 | customHeaders.put("X-Wap-Network-Client-Ip", "X-Wap-Network-Client-Ip-" + persistence.getString(YOUR_PAYLOAD));
66 | customHeaders.put("X-Wap-Profile", "X-Wap-Profile-" + persistence.getString(YOUR_PAYLOAD));
67 |
68 | for (Map.Entry entry : customHeaders.entrySet()) {
69 | request = request.withHeader(entry.getKey(), entry.getValue());
70 | }
71 |
72 | return request;
73 | }
74 |
75 |
76 | private boolean hasCacheHeaders(HttpResponse response) {
77 | String[] cacheHeaders = {"Age", "CDN-Cache", "CF-Cache-Status", "Server-Timing", "X-Cache", "X-Cache-Info", "X-Cache-Remote", "X-Check-Cacheable", "X-Drupal-Cache", "X-Drupal-Dynamic-Cache", "X-Proxy-Cache", "X-Rack-Cache", "Akamai-Cache-Status"};
78 | for (String header : cacheHeaders) {
79 | if (response.hasHeader(header)) {
80 | return true;
81 | }
82 | }
83 | return false;
84 | }
85 |
86 |
87 | @Override
88 | public ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest) {
89 | return ProxyRequestReceivedAction.continueWith(interceptedRequest);
90 | }
91 |
92 | @Override
93 | public ProxyRequestToBeSentAction handleRequestToBeSent(InterceptedRequest interceptedRequest) {
94 | try {
95 | long randomNumber = ThreadLocalRandom.current().nextLong(100_000_000_000L, 1_000_000_000_000L);
96 | HttpRequest modifiedRequest = interceptedRequest
97 | .withAddedParameters(urlParameter("_parameter", String.valueOf(randomNumber)))
98 | .withAddedParameters(cookieParameter("_Cookie",String.valueOf(randomNumber)))
99 | .withRemovedHeader("If-Modified-Since")
100 | .withRemovedHeader("If-None-Match")
101 | .withHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + randomNumber + " Safari/" + randomNumber)
102 | .withHeader("Pragma", "akamai-x-check-cacheable,akamai-x-cache-on")
103 | .withHeader("Fastly-Debug", "1");
104 |
105 | // Add custom headers
106 | modifiedRequest = addCustomHeaders(modifiedRequest);
107 | return ProxyRequestToBeSentAction.continueWith(modifiedRequest);
108 | } catch (Exception e) {
109 | return ProxyRequestToBeSentAction.continueWith(interceptedRequest);
110 | }
111 | }
112 | @Override
113 | public ProxyResponseReceivedAction handleResponseReceived(InterceptedResponse interceptedResponse) {
114 | try {
115 | if (interceptedResponse.body().toString().contains(persistence.getString(YOUR_MATCH)) || interceptedResponse.headers().toString().contains(persistence.getString(YOUR_MATCH))){
116 | if (hasCacheHeaders(interceptedResponse)) {
117 | table.add(interceptedResponse,true);
118 | } else if (!interceptedResponse.isStatusCodeClass(StatusCodeClass.CLASS_3XX_REDIRECTION)){
119 | table.add(interceptedResponse,false);
120 | }
121 | }
122 | return ProxyResponseReceivedAction.continueWith(interceptedResponse);
123 | } catch (Exception e) {
124 | return ProxyResponseReceivedAction.continueWith(interceptedResponse);
125 | }
126 | }
127 |
128 | @Override
129 | public ProxyResponseToBeSentAction handleResponseToBeSent(InterceptedResponse interceptedResponse) {
130 | return ProxyResponseToBeSentAction.continueWith(interceptedResponse);
131 | }
132 | }
--------------------------------------------------------------------------------