├── README.md
├── img
└── screenshot.png
├── paramFuzzer.iml
├── paramFuzzer.jar
├── params.txt
├── pom.xml
└── src
├── main
├── java
│ └── paramFuzzer
│ │ ├── CompareStrSimUtil.java
│ │ ├── Main.java
│ │ └── Requests.java
└── resources
│ └── params.txt
└── test
└── java
├── CompareStrSimUtil.java
└── test.java
/README.md:
--------------------------------------------------------------------------------
1 | # paramFuzzer
2 |
3 | 一款高效的参数fuzz工具|A faster param fuzzing test tool
4 |
5 | 二分法暴力的Fuzz参数,本地测试23000+的字典1秒内跑完。
6 |
7 | 同等条件下,效率上肯定比其他工具快就对了.
8 |
9 | -u参数,-m参数是必须的,-p和-v分别是指定参数字典以及参数值,可有可无。
10 |
11 | options:
12 |
13 | ```
14 | java -jar paramFuzzer.jar -h
15 | ```
16 |
17 | 
18 |
19 | ### TODO LIST:
20 |
21 | 1. 读取数据包。任意位置FUZZ。
22 | 2. 识别中间件,再次加快FUZZ效率。
23 |
--------------------------------------------------------------------------------
/img/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheKingOfDuck/paramFuzzer/68073d006c6cb0b8cedc49913d762a2e7ca90609/img/screenshot.png
--------------------------------------------------------------------------------
/paramFuzzer.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/paramFuzzer.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TheKingOfDuck/paramFuzzer/68073d006c6cb0b8cedc49913d762a2e7ca90609/paramFuzzer.jar
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | Github.TheKingOfDuck.paramFuzzer
8 | paramFuzzer
9 | demo
10 |
11 |
12 |
13 |
14 | org.apache.maven.plugins
15 | maven-jar-plugin
16 |
17 |
18 |
19 | paramFuzzer.Main
20 |
21 |
22 |
23 |
24 |
25 | org.apache.maven.plugins
26 | maven-shade-plugin
27 | 2.4.1
28 |
29 |
30 | package
31 |
32 | shade
33 |
34 |
35 |
36 |
37 | paramFuzzer.Main
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | commons-cli
50 | commons-cli
51 | 1.4
52 |
53 |
54 | com.github.kevinsawicki
55 | http-request
56 | 6.0
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/main/java/paramFuzzer/CompareStrSimUtil.java:
--------------------------------------------------------------------------------
1 | package paramFuzzer;
2 |
3 | public class CompareStrSimUtil {
4 |
5 | private static int compare(String str, String target, boolean isIgnore) {
6 | int d[][]; // 矩阵
7 | int n = str.length();
8 | int m = target.length();
9 | int i; // 遍历str的
10 | int j; // 遍历target的
11 | char ch1; // str的
12 | char ch2; // target的
13 | int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
14 | if (n == 0) {
15 | return m;
16 | }
17 | if (m == 0) {
18 | return n;
19 | }
20 | d = new int[n + 1][m + 1];
21 | for (i = 0; i <= n; i++) { // 初始化第一列
22 | d[i][0] = i;
23 | }
24 |
25 | for (j = 0; j <= m; j++) { // 初始化第一行
26 | d[0][j] = j;
27 | }
28 |
29 | for (i = 1; i <= n; i++) { // 遍历str
30 | ch1 = str.charAt(i - 1);
31 | // 去匹配target
32 | for (j = 1; j <= m; j++) {
33 | ch2 = target.charAt(j - 1);
34 | if (isIgnore) {
35 | if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
36 | temp = 0;
37 | } else {
38 | temp = 1;
39 | }
40 | } else {
41 | if (ch1 == ch2) {
42 | temp = 0;
43 | } else {
44 | temp = 1;
45 | }
46 | }
47 |
48 | // 左边+1,上边+1, 左上角+temp取最小
49 | d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
50 | }
51 | }
52 | return d[n][m];
53 | }
54 |
55 | private static int min(int one, int two, int three) {
56 | return (one = one < two ? one : two) < three ? one : three;
57 | }
58 |
59 | public static float getSimilarityRatio(String str, String target, boolean isIgnore) {
60 | float ret = 0;
61 | if (Math.max(str.length(), target.length()) == 0) {
62 | ret = 1;
63 | } else {
64 | ret = 1 - (float) compare(str, target, isIgnore) / Math.max(str.length(), target.length());
65 | }
66 | return ret;
67 | }
68 |
69 | public static float simCalc(String oldStr, String newStr) {
70 | CompareStrSimUtil lt = new CompareStrSimUtil();
71 | //System.out.println("similarityRatio=" + lt.getSimilarityRatio(oldStr, newStr, true));
72 | return lt.getSimilarityRatio(oldStr, newStr, true);
73 | }
74 |
75 |
76 | }
77 |
78 |
--------------------------------------------------------------------------------
/src/main/java/paramFuzzer/Main.java:
--------------------------------------------------------------------------------
1 | package paramFuzzer;
2 |
3 | import org.apache.commons.cli.*;
4 |
5 | import java.io.*;
6 | import java.util.ArrayList;
7 |
8 | public class Main {
9 |
10 | public static ArrayList ReadParams(String filename) {
11 | ArrayList paramList = new ArrayList();
12 | try {
13 | //String filename = "/Users/CoolCat/tools/burp/fuzzDicts/paramDict/php.txt";
14 | File file = new File(filename);
15 | String line = null;
16 | if (file.exists()) {
17 | BufferedReader in = new BufferedReader(new FileReader(filename));
18 | while ((line = in.readLine()) != null) {
19 | //System.out.println(line);
20 | line = line.replaceAll("\n", "").replaceAll("\r", "");
21 | paramList.add(line);
22 | }
23 | in.close();
24 | }else {
25 | System.out.println("[!]params.txt not found");
26 | }
27 | } catch (IOException e) {
28 | e.printStackTrace();
29 | }
30 | //System.out.println(paramList);
31 | return paramList;
32 | }
33 |
34 | public static boolean simhash(boolean Dynamic, String res, String raw1, String raw2) {
35 |
36 | boolean flag = false;
37 | if (!Dynamic) {
38 | if (!res.equals(raw2)) {
39 | flag = true;
40 | }
41 | } else {
42 |
43 | //字符长度差异高于3个字符串就视作变化了,对付时间戳很好用
44 | if (raw1.length() - raw2.length() == 0) {
45 | if (res.length() != raw1.length())
46 | flag = true;
47 | }
48 |
49 | //差异大于20%就视作返回内容变化了
50 | CompareStrSimUtil simhash = new CompareStrSimUtil();
51 | float raw = simhash.simCalc(raw1, raw2);
52 | //System.out.println("raw=========>" + raw);
53 | float sim = simhash.simCalc(res, raw2);
54 |
55 | //if (res.contains("CoolCat")){
56 | //System.out.println(true);
57 | //System.out.println(raw-sim);
58 | //}
59 | //System.out.println("sim=========>" + sim+"\n");
60 | if (raw > sim + 0.2) {
61 | flag = true;
62 | }
63 |
64 |
65 | //System.out.println("动态算法");
66 | }
67 | return flag;
68 |
69 | }
70 |
71 | public static void split(String[] requrl, String res, Requests requests, boolean Dynamic, String raw1, String raw2) {
72 | //System.out.println(requrl[0]);
73 |
74 | String part1 = "";
75 | String part2 = "";
76 |
77 | String[] params = requrl[1].split("&");
78 | if (params.length > 2) {
79 | part1 = requrl[1].split(params[params.length / 2])[0] + params[params.length / 2];
80 | String temp_part2 = requrl[1].split(params[params.length / 2])[1];
81 | StringBuilder temp_part22 = new StringBuilder(temp_part2).replace(0, 1, "");
82 | part2 = temp_part22.toString();
83 | } else if (params.length == 2) {
84 | part1 = params[0];
85 | part2 = params[1];
86 | } else {
87 | System.out.printf("[+]%s?%s\n", requrl[0], params[0]);
88 | }
89 |
90 | res = requests.get(requrl[0], part1);
91 | boolean flag2 = simhash(Dynamic, res, raw1, raw2);
92 |
93 | if (flag2) {
94 | System.out.println("[+]split:" + part1.length());
95 | String url = requrl[0] + "?" + part1;
96 | String[] requrl2 = url.split("\\?");
97 | split(requrl2, res, requests, Dynamic, raw1, raw2);
98 | }
99 |
100 | res = requests.get(requrl[0], part2);
101 | boolean flag3 = simhash(Dynamic, res, raw1, raw2);
102 | if (flag3) {
103 | System.out.println("[+]split:" + part2.length());
104 | String url = requrl[0] + "?" + part2;
105 | String[] requrl3 = url.split("\\?");
106 | split(requrl3, res, requests, Dynamic, raw1, raw2);
107 | }
108 |
109 | }
110 |
111 | public static void split2(String requrl, String res, Requests requests, boolean Dynamic, String raw1, String raw2, String allParams) {
112 |
113 | //System.out.println(allParams);
114 |
115 | String part1 = "";
116 | String part2 = "";
117 |
118 | String[] params = allParams.split("&");
119 | if (params.length > 2) {
120 | part1 = allParams.split(params[params.length / 2])[0] + params[params.length / 2];
121 | String temp_part2 = allParams.split(params[params.length / 2])[1];
122 | StringBuilder temp_part22 = new StringBuilder(temp_part2).replace(0, 1, "");
123 | part2 = temp_part22.toString();
124 | } else if (params.length == 2) {
125 | part1 = params[0];
126 | part2 = params[1];
127 | } else if (params.length < 2) {
128 | System.out.printf("[+]%s\tPOST: %s\n", requrl, params[0]);
129 | //System.exit(0);
130 | }
131 |
132 | res = requests.post(requrl, part1);
133 | boolean flag2 = simhash(Dynamic, res, raw1, raw2);
134 |
135 | if (flag2) {
136 | System.out.println("[+]split:" + part1.split("&").length);
137 | split2(requrl, res, requests, Dynamic, raw1, raw2, part1);
138 | }
139 |
140 | res = requests.post(requrl, part2);
141 | boolean flag3 = simhash(Dynamic, res, raw1, raw2);
142 | if (flag3) {
143 | System.out.println("[+]split:" + part2.split("&").length);
144 | split2(requrl, res, requests, Dynamic, raw1, raw2, part2);
145 | }
146 |
147 | }
148 |
149 | public static void main(String[] args){
150 |
151 | String logo = "\n" +
152 | " ______ \n" +
153 | " version:0.1 | ____| \n" +
154 | " _ __ __ _ _ __ __ _ _ __ ___ | |__ _ _ ___________ _ __ \n" +
155 | "| '_ \\ / _` | '__/ _` | '_ ` _ \\| __| | | |_ /_ / _ \\ '__|\n" +
156 | "| |_) | (_| | | | (_| | | | | | | | | |_| |/ / / / __/ | \n" +
157 | "| .__/ \\__,_|_| \\__,_|_| |_| |_|_| \\__,_/___/___\\___|_| \n" +
158 | "| | Coding by CoolCat \n" +
159 | "|_| https://github.com/TheKingOfDuck \n";
160 |
161 | System.out.println(logo);
162 |
163 | try {
164 | //System.out.println("aa");
165 | CommandLineParser parser = new BasicParser();
166 | Options options = new Options();
167 |
168 | //url参数为必须
169 | options.addOption("u", "url", true, "Target Url");
170 | //m参数为必须
171 | options.addOption("m", "method", true, "Requests Method");
172 | //param参数
173 | options.addOption("p", "param", true, "Params File");
174 |
175 | options.addOption("v", "value", true, "Params value");
176 | //read参数 读取数据包暂不考虑
177 | //options.addOption("r","read",true,"Requests Package");
178 | //help参数
179 | options.addOption("h", "help", false, "Help Info");
180 |
181 | CommandLine commandLine = parser.parse(options, args);
182 |
183 | String helpinfo = "[?]CommandLine:\n" +
184 | "\t-u\t--url\t\ttarget url\n" +
185 | "\t-m\t--method\trequests method\n" +
186 | "\t-p\t--param\t\tparam file\n" +
187 | "\t-v\t--value\t\tparam value\n" +
188 | "\t-h\t--help\t\thelp info\n\n" +
189 | "eg:java -jar paramFuzzer.jar -u http://test.com/index.php -m get -p params.txt -v hello";
190 | if (commandLine.hasOption("h")) {
191 | System.out.println(helpinfo);
192 | System.exit(0);
193 | }
194 |
195 |
196 | String param_file = "params.txt";
197 | if (commandLine.hasOption("p")) {
198 | param_file = commandLine.getOptionValue("p");
199 | } else {
200 | param_file = "params.txt";
201 | }
202 | ArrayList paramList = ReadParams(param_file);
203 | //System.out.println(paramList);
204 | String paramValue = "1";
205 |
206 | if (commandLine.hasOption("v")) {
207 | paramValue = commandLine.getOptionValue("v");
208 | //System.out.println(paramValue);
209 | }
210 |
211 | if (commandLine.hasOption("u") & commandLine.hasOption("m")) {
212 | String method = commandLine.getOptionValue("m");
213 | String url = commandLine.getOptionValue("u");
214 | Requests requests = new Requests();
215 | String raw1 = requests.get(url, "paramFuzzer=1.0");
216 | String raw2 = requests.get(url, "paramFuzzer=2.0");
217 |
218 | //如果返回包有变化就用相似度算法进行比较
219 | boolean Dynamic = true;
220 | if (raw1.equals(raw2)) {
221 | Dynamic = false;
222 | }
223 |
224 | System.out.printf("[+]Dynamic Response: %s\n\tProgram's judgment is not correct every time\n", Dynamic);
225 |
226 |
227 | if (method.toLowerCase().equals("get")) {
228 | //System.out.println(paramList.size());
229 |
230 | ////GET最大长度限制是8198
231 | for (int i = 0; i < paramList.size(); i++) {
232 |
233 | if (url.contains("?")) {
234 | url = url + "&" + paramList.get(i) + "=" + paramValue;
235 | } else {
236 | url = url + "?" + paramList.get(i) + "=" + paramValue;
237 | }
238 | //System.out.println(url);
239 |
240 | if (url.length() > 8000) {
241 | //System.out.println(url);
242 |
243 | String[] requrl = url.split("\\?");
244 | //System.out.println(requrl[1]);
245 |
246 | String res = requests.get(requrl[0], requrl[1]);
247 | boolean flag = simhash(Dynamic, res, raw1, raw2);
248 |
249 | if (flag) {
250 | System.out.println("[+]Got:" + url.length());
251 | split(requrl, res, requests, Dynamic, raw1, raw2);
252 | }
253 | url = commandLine.getOptionValue("u");
254 | }
255 | if (i == paramList.size() - 1) {
256 | //System.out.println(url);
257 |
258 | String[] requrl = url.split("\\?");
259 | //System.out.println(requrl[1]);
260 |
261 | String res = requests.get(requrl[0], requrl[1]);
262 | boolean flag = simhash(Dynamic, res, raw1, raw2);
263 |
264 | if (flag) {
265 | System.out.println("[+]Got:" + url.length());
266 | split(requrl, res, requests, Dynamic, raw1, raw2);
267 | }
268 | }
269 |
270 | }
271 |
272 | } else if (method.toLowerCase().equals("post")) {
273 |
274 | String tempParams = "paramFuzzer=byCoolCat";
275 | int m = 0;
276 | for (int i = 0; i < paramList.size(); i++) {
277 | m++;
278 | if (m > 998) {
279 | //System.out.println(tempParams);
280 |
281 | String res3 = requests.post(url, tempParams);
282 | boolean flag = simhash(Dynamic, res3, raw1, raw2);
283 |
284 | if (flag) {
285 | System.out.println("[+]Got:" + url);
286 | split2(url, res3, requests, Dynamic, raw1, raw2, tempParams);
287 | }
288 |
289 | tempParams = "paramFuzzer=byCoolCat";
290 | m = 0;
291 | }
292 |
293 | //System.out.println(m);
294 |
295 | tempParams = tempParams + "&" + paramList.get(i) + "=" + paramValue;
296 |
297 | if (i == paramList.size() - 1) {
298 | //System.out.println(tempParams);
299 | String res3 = requests.post(url, tempParams);
300 | boolean flag = simhash(Dynamic, res3, raw1, raw2);
301 |
302 | if (flag) {
303 | System.out.println("[+]Got:" + url);
304 | split2(url, res3, requests, Dynamic, raw1, raw2, tempParams);
305 | }
306 | }
307 |
308 | }
309 | }else {
310 | System.out.printf("[!]%s method not support",commandLine.getOptionValue("m"));
311 | System.exit(0);
312 | }
313 | } else {
314 | System.out.println("[!]java -jar paramFuzzer.jar -u http://test.com:8888/index.php -m get -p params.txt -v CoolCat");
315 | System.exit(0);
316 | }
317 | }catch (Exception e){
318 | e.printStackTrace();
319 | }
320 |
321 |
322 | }
323 | }
324 |
--------------------------------------------------------------------------------
/src/main/java/paramFuzzer/Requests.java:
--------------------------------------------------------------------------------
1 | package paramFuzzer;
2 |
3 | import com.github.kevinsawicki.http.HttpRequest;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | public class Requests {
9 |
10 |
11 | public static void setProxy(boolean proxy) {
12 | if (proxy){
13 | HttpRequest.proxyHost("127.0.0.1");
14 | HttpRequest.proxyPort(8080);
15 | }
16 | }
17 |
18 | public static String get(String url,String params) {
19 |
20 | setProxy(false);
21 | String param_url = String.format("%s?%s",url,params);
22 |
23 | try {
24 | Map Headers=new HashMap();
25 |
26 | Headers.put("User-Agent","paramFuzzer v0.1");
27 |
28 | HttpRequest res = HttpRequest.get(param_url).headers(Headers).followRedirects(false).readTimeout(5000);
29 |
30 | //System.out.println(String.format("StatCode:%s",res.code()));
31 | //System.out.println(String.format("Response:%s",res.body()));
32 | return res.body();
33 | }catch (Exception e){
34 | System.out.println(e);
35 | return "err";
36 | }
37 | }
38 |
39 | public static String post(String url,String params) {
40 |
41 | setProxy(false);
42 |
43 | try {
44 |
45 | Map Headers=new HashMap();
46 |
47 | Headers.put("User-Agent","paramFuzzer v0.1");
48 | String Data = params;
49 |
50 | HttpRequest res = HttpRequest.post(url).headers(Headers).send(Data).followRedirects(false).readTimeout(5000);
51 |
52 | //System.out.println(String.format("StatCode:%s",res.code()));
53 | //System.out.println(String.format("Response:%s",res.body()));
54 |
55 |
56 |
57 | return res.body();
58 | }catch (Exception e){
59 | System.out.println(e);
60 | return "err";
61 | }
62 | }
63 |
64 |
65 |
66 |
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/test/java/CompareStrSimUtil.java:
--------------------------------------------------------------------------------
1 | public class CompareStrSimUtil {
2 | private static int compare(String str, String target, boolean isIgnore) {
3 | int d[][]; // 矩阵
4 | int n = str.length();
5 | int m = target.length();
6 | int i; // 遍历str的
7 | int j; // 遍历target的
8 | char ch1; // str的
9 | char ch2; // target的
10 | int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
11 | if (n == 0) {
12 | return m;
13 | }
14 | if (m == 0) {
15 | return n;
16 | }
17 | d = new int[n + 1][m + 1];
18 | for (i = 0; i <= n; i++) { // 初始化第一列
19 | d[i][0] = i;
20 | }
21 |
22 | for (j = 0; j <= m; j++) { // 初始化第一行
23 | d[0][j] = j;
24 | }
25 |
26 | for (i = 1; i <= n; i++) { // 遍历str
27 | ch1 = str.charAt(i - 1);
28 | // 去匹配target
29 | for (j = 1; j <= m; j++) {
30 | ch2 = target.charAt(j - 1);
31 | if (isIgnore) {
32 | if (ch1 == ch2 || ch1 == ch2 + 32 || ch1 + 32 == ch2) {
33 | temp = 0;
34 | } else {
35 | temp = 1;
36 | }
37 | } else {
38 | if (ch1 == ch2) {
39 | temp = 0;
40 | } else {
41 | temp = 1;
42 | }
43 | }
44 |
45 | // 左边+1,上边+1, 左上角+temp取最小
46 | d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
47 | }
48 | }
49 | return d[n][m];
50 | }
51 |
52 | private static int min(int one, int two, int three) {
53 | return (one = one < two ? one : two) < three ? one : three;
54 | }
55 |
56 | public static float getSimilarityRatio(String str, String target, boolean isIgnore) {
57 | float ret = 0;
58 | if (Math.max(str.length(), target.length()) == 0) {
59 | ret = 1;
60 | } else {
61 | ret = 1 - (float) compare(str, target, isIgnore) / Math.max(str.length(), target.length());
62 | }
63 | return ret;
64 | }
65 |
66 | public static void main(String[] args) {
67 | CompareStrSimUtil lt = new CompareStrSimUtil();
68 | String str = "ABC";
69 | String target = "BC";
70 | System.out.println("similarityRatio=" + lt.getSimilarityRatio(str, target, true));
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/test/java/test.java:
--------------------------------------------------------------------------------
1 | import org.apache.commons.cli.Option;
2 | import org.apache.commons.cli.OptionBuilder;
3 | import org.apache.commons.cli.*;
4 |
5 | import java.io.*;
6 | import java.util.ArrayList;
7 |
8 | public class test {
9 |
10 | // public static StringBuffer readFileContent(String fileName) {
11 | // File file = new File(fileName);
12 | // BufferedReader reader = null;
13 | // String[] sbf = {};
14 | // try {
15 | // reader = new BufferedReader(new FileReader(file));
16 | // String tempStr;
17 | // while ((tempStr = reader.readLine()) != null) {
18 | // sbf.;
19 | // }
20 | // reader.close();
21 | // return sbf;
22 | // } catch (IOException e) {
23 | // e.printStackTrace();
24 | // } finally {
25 | // if (reader != null) {
26 | // try {
27 | // reader.close();
28 | // } catch (IOException e1) {
29 | // e1.printStackTrace();
30 | // }
31 | // }
32 | // }
33 | // return sbf;
34 | // }
35 | public static void main(String[] args) {
36 | Options options = new Options();
37 | Option option0 = OptionBuilder.hasArg(true).create("t");
38 | option0.setArgName("t");
39 | Option option1 = OptionBuilder.hasArg(true).create("c");
40 | option1.setArgName("c");
41 | options.addOption(option0);
42 | options.addOption(option1);
43 |
44 | PosixParser parser = new PosixParser();
45 | try {
46 | CommandLine commandLine = parser.parse(options, args);
47 | for (Option option : commandLine.getOptions()) {
48 | System.out.println(option.getArgName() + " : " + option.getValue());
49 | }
50 | } catch (ParseException e) {
51 | e.printStackTrace();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------