├── 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 | ![](https://github.com/TheKingOfDuck/paramFuzzer/blob/master/img/screenshot.png) 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 | --------------------------------------------------------------------------------