├── .gitignore ├── src └── main │ └── java │ └── burp │ ├── JavaGUIUtils.java │ ├── SystemUtils.java │ ├── Getter.java │ ├── IPAddressUtils.java │ ├── Common.java │ └── HelperPlus.java ├── .github └── workflows │ ├── manual-publish.yml │ └── maven-publish.yml ├── pom.xml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | .project 4 | .classpath 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /src/main/java/burp/JavaGUIUtils.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.swing.JTextArea; 7 | 8 | public class JavaGUIUtils { 9 | public static List getLinesFromTextArea(JTextArea textarea){ 10 | return textToLines(textarea.getText()); 11 | } 12 | 13 | /** 14 | * 换行符的可能性有三种,都必须考虑到 15 | * @param input 16 | * @return 17 | */ 18 | public static List textToLines(String input){ 19 | String[] lines = input.split("(\r\n|\r|\n)", -1); 20 | List result = new ArrayList(); 21 | for(String line: lines) { 22 | line = line.trim(); 23 | if (!line.equalsIgnoreCase("")) { 24 | result.add(line.trim()); 25 | } 26 | } 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/workflows/manual-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: read 15 | packages: write 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Set up JDK 11 20 | uses: actions/setup-java@v3 21 | with: 22 | java-version: '11' 23 | distribution: 'temurin' 24 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 25 | settings-path: ${{ github.workspace }} # location for the settings.xml file 26 | 27 | - name: Build with Maven 28 | run: mvn -B package --file pom.xml 29 | 30 | - name: Publish to GitHub Packages Apache Maven 31 | run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml 32 | env: 33 | GITHUB_TOKEN: ${{ github.token }} 34 | -------------------------------------------------------------------------------- /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | - master 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | contents: read 18 | packages: write 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Set up JDK 11 23 | uses: actions/setup-java@v3 24 | with: 25 | java-version: '11' 26 | distribution: 'temurin' 27 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 28 | settings-path: ${{ github.workspace }} # location for the settings.xml file 29 | 30 | - name: Build with Maven 31 | run: mvn -B package --file pom.xml 32 | 33 | - name: Publish to GitHub Packages Apache Maven 34 | run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml 35 | env: 36 | GITHUB_TOKEN: ${{ github.token }} 37 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | com.github.bit4woo 6 | burp-api-common 7 | 0.1.5 8 | jar 9 | 10 | 11 | mvnrepository 12 | mvnrepository 13 | http://www.mvnrepository.com 14 | 15 | 16 | 17 | 18 | 19 | 20 | net.portswigger.burp.extender 21 | burp-extender-api 22 | 2.1 23 | 24 | 25 | 26 | commons-net 27 | commons-net 28 | 3.10.0 29 | 30 | 31 | com.github.seancfoley 32 | ipaddress 33 | 5.3.3 34 | 35 | 36 | 37 | 38 | 39 | org.apache.maven.plugins 40 | maven-compiler-plugin 41 | 3.2 42 | 43 | 44 | 1.7 45 | 1.7 46 | UTF-8 47 | 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-source-plugin 53 | 54 | 55 | attach-sources 56 | 57 | jar 58 | 59 | 60 | 61 | 62 | UTF-8 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-javadoc-plugin 68 | 69 | 70 | attach-javadocs 71 | 72 | jar 73 | 74 | 75 | 76 | 77 | UTF-8 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | github 86 | burp-api-common 87 | https://maven.pkg.github.com/bit4woo/burp-api-common 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # burp-api-common 2 | common methods used by myself. 3 | 4 | 编写burp插件过程中积累的常用方法 5 | 6 | ### 使用方法一(推荐) 7 | 8 | 基于[JitPack](https://jitpack.io/#jitpack/burp-api-common) 9 | 10 | [![Release](https://jitpack.io/v/bit4woo/burp-api-common.svg)](https://jitpack.io/#bit4woo/burp-api-common) 11 | 12 | To use it in your Maven build add: 13 | 14 | 在pom.xml文件中添加如下配置,位置在``的下级。 15 | 16 | ```xml 17 | 18 | 19 | jitpack.io 20 | https://jitpack.io 21 | 22 | 23 | ``` 24 | 25 | and the dependency: 26 | 27 | 然后再添加如下依赖配置,位置在 ``的下级。 28 | 29 | 注意version字段,当使用“master-SNAPSHOT”作为版本时,会使用最新代码 30 | 31 | ``` 32 | 33 | 34 | com.github.bit4woo 35 | burp-api-common 36 | master-SNAPSHOT 37 | 38 | ``` 39 | 40 | 如果要使用具体版本配置如下,**注意version的值包含一个“v”**。 41 | 42 | ```xml 43 | 44 | com.github.bit4woo 45 | burp-api-common 46 | v0.1.3 47 | 48 | ``` 49 | 50 | 51 | 52 | 53 | 54 | ### 使用方法二(备选) 55 | 56 | 基于[Github packages](https://github.com/bit4woo/burp-api-common/packages) 57 | 58 | 直接在pom.xml中添加如下依赖配置,位置在 ``的下级,version的值不包含“v”。 59 | 60 | ```xml 61 | 62 | com.github.bit4woo 63 | burp-api-common 64 | 0.1.3 65 | 66 | ``` 67 | 68 | 创建或修改/Users/user/.m2/setttings.xml 文件,如果使用过GitHub Packages,就无需再修改了。更多详情参考[这里](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry) 69 | 70 | ```xml 71 | 75 | 76 | 77 | github 78 | 79 | 80 | 81 | 82 | github 83 | 84 | 85 | central 86 | https://repo1.maven.org/maven2 87 | 88 | 89 | github 90 | https://maven.pkg.github.com/bit4woo/* 91 | 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | github 102 | bit4woo 103 | Your-github-access-token 104 | 105 | 106 | 107 | 108 | UTF-8 109 | UTF-8 110 | 111 | 112 | ``` 113 | 114 | -------------------------------------------------------------------------------- /src/main/java/burp/SystemUtils.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.awt.Desktop; 4 | import java.awt.Toolkit; 5 | import java.awt.datatransfer.Clipboard; 6 | import java.awt.datatransfer.StringSelection; 7 | import java.io.BufferedOutputStream; 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.File; 10 | import java.io.FileInputStream; 11 | import java.io.FileNotFoundException; 12 | import java.io.FileOutputStream; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.io.InputStreamReader; 16 | import java.net.URI; 17 | import java.net.URL; 18 | import java.nio.charset.Charset; 19 | import java.text.SimpleDateFormat; 20 | import java.util.Arrays; 21 | import java.util.Date; 22 | import java.util.Map; 23 | 24 | /** 25 | * 常用操作系统操作:打开浏览器、打开文件夹、操作剪切板等 26 | * 27 | */ 28 | public class SystemUtils { 29 | 30 | public static String getNowTimeString() { 31 | SimpleDateFormat simpleDateFormat = 32 | new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); 33 | return simpleDateFormat.format(new Date()); 34 | } 35 | 36 | public static void browserOpen(Object url,String browser) throws Exception{ 37 | String urlString = null; 38 | URI uri = null; 39 | if (url instanceof String) { 40 | urlString = (String) url; 41 | uri = new URI((String)url); 42 | }else if (url instanceof URL) { 43 | uri = ((URL)url).toURI(); 44 | urlString = url.toString(); 45 | } 46 | if(browser == null ||browser.equalsIgnoreCase("default") || browser.equalsIgnoreCase("")) { 47 | //whether null must be the first 48 | Desktop desktop = Desktop.getDesktop(); 49 | if(Desktop.isDesktopSupported()&&desktop.isSupported(Desktop.Action.BROWSE)){ 50 | desktop.browse(uri); 51 | } 52 | }else { 53 | String[] cmdArray = new String[] {browser,urlString}; 54 | 55 | //runtime.exec(browser+" "+urlString);//当命令中有空格时会有问题 56 | Runtime.getRuntime().exec(cmdArray); 57 | } 58 | } 59 | 60 | public static boolean isWindows() { 61 | String OS_NAME = System.getProperty("os.name").toLowerCase(); 62 | if (OS_NAME.contains("windows")) { 63 | return true; 64 | } else { 65 | return false; 66 | } 67 | } 68 | 69 | public static boolean isWindows10() { 70 | String OS_NAME = System.getProperty("os.name").toLowerCase(); 71 | if (OS_NAME.equalsIgnoreCase("windows 10")) { 72 | return true; 73 | } 74 | return false; 75 | } 76 | 77 | public static boolean isMac(){ 78 | String os = System.getProperty("os.name").toLowerCase(); 79 | return (os.indexOf( "mac" ) >= 0); 80 | } 81 | 82 | /** 83 | * //linux or unix 84 | * @return 85 | */ 86 | public static boolean isUnix(){ 87 | String os = System.getProperty("os.name").toLowerCase(); 88 | return (os.indexOf( "nix") >=0 || os.indexOf( "nux") >=0); 89 | } 90 | 91 | /** 92 | * 获取系统默认编码 93 | * //https://javarevisited.blogspot.com/2012/01/get-set-default-character-encoding.html 94 | * @return 95 | */ 96 | private static String getSystemCharSet() { 97 | return Charset.defaultCharset().toString(); 98 | } 99 | 100 | /** 101 | * 将文本写入系统剪切板 102 | * @param text 103 | */ 104 | public static void writeToClipboard(String text) { 105 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 106 | StringSelection selection = new StringSelection(text); 107 | clipboard.setContents(selection, null); 108 | } 109 | 110 | 111 | 112 | /** 113 | * 114 | * 拼接命令行中的命令 115 | * 116 | * parserPath --- python.exe java.exe .... 117 | * executerPath --- sqlmap.py nmap.exe .... 118 | * parameters ---- -v -A -r xxx.file ..... 119 | * 120 | */ 121 | public static String genCmd(String parserPath,String executerPath, String parameter) { 122 | StringBuilder command = new StringBuilder(); 123 | 124 | if (parserPath != null){ 125 | if (parserPath.contains(" ")) { 126 | parserPath = "\""+parserPath+"\"";//如果路径中包含空格,需要引号 127 | } 128 | command.append(parserPath); 129 | command.append(" "); 130 | } 131 | 132 | if (executerPath != null){ 133 | 134 | if (executerPath.contains(" ")) { 135 | executerPath = "\""+executerPath+"\"";//如果路径中包含空格,需要引号 136 | } 137 | 138 | command.append(executerPath); 139 | command.append(" "); 140 | } 141 | 142 | if (parameter != null && !parameter.equals("")) { 143 | command.append(parameter); 144 | } 145 | command.append(System.lineSeparator()); 146 | return command.toString(); 147 | } 148 | 149 | 150 | 151 | /** 152 | * 通知执行bat文件来执行命令 153 | */ 154 | public static Process runBatchFile(String batfilepath) { 155 | String command = ""; 156 | if (isWindows()) { 157 | command="cmd /c start " + batfilepath; 158 | } else { 159 | if (new File("/bin/sh").exists()) { 160 | command="/bin/sh " + batfilepath; 161 | } 162 | else if (new File("/bin/bash").exists()) { 163 | command="/bin/bash " + batfilepath; 164 | } 165 | } 166 | try { 167 | Process process = Runtime.getRuntime().exec(command); 168 | process.waitFor();//等待执行完成 169 | return process; 170 | } catch (Exception e) { 171 | e.printStackTrace(); 172 | return null; 173 | } 174 | } 175 | 176 | public static String genBatchFile(String cmdContent, String batchFileName) { 177 | try { 178 | if (batchFileName == null || batchFileName.trim().equals("")) { 179 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMdd-HHmmss"); 180 | String timeString = simpleDateFormat.format(new Date()); 181 | batchFileName = timeString+".bat"; 182 | }else if(!batchFileName.endsWith(".bat") && !batchFileName.endsWith(".cmd")) { 183 | batchFileName = batchFileName+".bat"; 184 | } 185 | String workdir = System.getProperty("user.home"); 186 | File batFile = new File(workdir,batchFileName); 187 | if (!batFile.exists()) { 188 | batFile.createNewFile(); 189 | } 190 | if (isMac()){ 191 | cmdContent = String.format("osascript -e 'tell app \"Terminal\" to do script \"%s\"'",cmdContent); 192 | } 193 | byte2File(cmdContent.getBytes(),batFile); 194 | return batFile.getAbsolutePath(); 195 | } catch (IOException e) { 196 | e.printStackTrace(); 197 | return null; 198 | } 199 | } 200 | 201 | public static void startCmdConsole() { 202 | try { 203 | Process process = null; 204 | if (isWindows()) { 205 | process = Runtime.getRuntime().exec("cmd /c start cmd.exe"); 206 | } else if (isMac()){ 207 | ///System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal 208 | process = Runtime.getRuntime().exec("open -n -F -a /System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal"); 209 | }else if (isUnix()) { 210 | process = Runtime.getRuntime().exec("/usr/bin/gnome-terminal");//kali和Ubuntu测试通过 211 | // if(new File("/usr/bin/gnome-terminal").exists()) { 212 | // process = Runtime.getRuntime().exec("/usr/bin/gnome-terminal"); 213 | // }else { 214 | // process = Runtime.getRuntime().exec("/usr/bin/xterm");//只能使用shift+insert 进行粘贴操作,但是修改剪切板并不能修改它粘贴的内容。 215 | //貌似和使用了openjdk有关,故暂时只支持gnome-terminal. 216 | // } 217 | } 218 | process.waitFor();//等待执行完成 219 | } catch (Exception e) { 220 | e.printStackTrace(); 221 | } 222 | } 223 | 224 | /* 225 | * 切换工作目录 226 | */ 227 | public static String changeDirCommand(String dir){ 228 | //运行命令的工作目录,work path 229 | String command = "cd "+dir+System.lineSeparator(); 230 | 231 | if (isWindows()) {//如果是windows,还要注意不同磁盘的切换 232 | String diskString = dir.split(":")[0]; 233 | command =command+ diskString+":"+System.lineSeparator(); 234 | } 235 | return command; 236 | } 237 | 238 | /** 239 | * 判断某个文件是否在环境变量中 240 | */ 241 | @Deprecated 242 | public static boolean isInEnvironmentPath(String filename) { 243 | if (filename == null) { 244 | return false; 245 | } 246 | Map values = System.getenv(); 247 | String pathvalue = values.get("PATH"); 248 | if (pathvalue == null) { 249 | pathvalue = values.get("path"); 250 | } 251 | if (pathvalue == null) { 252 | pathvalue = values.get("Path"); 253 | } 254 | // System.out.println(pathvalue); 255 | String[] items = pathvalue.split(";"); 256 | for (String item:items) { 257 | File tmpPath = new File(item); 258 | if (tmpPath.isDirectory()) { 259 | // System.out.println(Arrays.asList(tmpPath.listFiles())); 260 | File fullpath = new File(item,filename); 261 | if (Arrays.asList(tmpPath.listFiles()).contains(fullpath)) { 262 | return true; 263 | }else { 264 | continue; 265 | } 266 | } 267 | } 268 | return false; 269 | } 270 | 271 | /** 272 | * 检测某个命令是否存在,根据which where命令来的,如果不在环境变量中应该读取不到! 273 | */ 274 | public static String isCommandExists(String cmd) { 275 | if (isWindows()) { 276 | cmd = "where "+cmd; 277 | }else { 278 | cmd = "which "+cmd; 279 | } 280 | try { 281 | //启动进程 282 | Process process = Runtime.getRuntime().exec(cmd); 283 | //获取输入流 284 | InputStream inputStream = process.getInputStream(); 285 | //转成字符输入流 286 | InputStreamReader inputStreamReader = new InputStreamReader(inputStream, getSystemCharSet()); 287 | int len = -1; 288 | char[] c = new char[1024]; 289 | StringBuffer outputString = new StringBuffer(); 290 | //读取进程输入流中的内容 291 | while ((len = inputStreamReader.read(c)) != -1) { 292 | String s = new String(c, 0, len); 293 | outputString.append(s); 294 | //System.out.print(s); 295 | } 296 | inputStream.close(); 297 | return outputString.toString().trim();//去除换行符 298 | } 299 | catch (IOException e) { 300 | e.printStackTrace(); 301 | } 302 | return ""; 303 | } 304 | 305 | 306 | public static void OpenFolder(String path) throws IOException { 307 | Desktop.getDesktop().open(new File(path)); 308 | } 309 | 310 | public static void byte2File(byte[] buf, File file) 311 | { 312 | BufferedOutputStream bos = null; 313 | FileOutputStream fos = null; 314 | try 315 | { 316 | file.createNewFile(); 317 | fos = new FileOutputStream(file); 318 | bos = new BufferedOutputStream(fos); 319 | bos.write(buf); 320 | } 321 | catch (Exception e) 322 | { 323 | e.printStackTrace(); 324 | } 325 | finally 326 | { 327 | if (bos != null) 328 | { 329 | try 330 | { 331 | bos.close(); 332 | } 333 | catch (IOException e) 334 | { 335 | e.printStackTrace(); 336 | } 337 | } 338 | if (fos != null) 339 | { 340 | try 341 | { 342 | fos.close(); 343 | } 344 | catch (IOException e) 345 | { 346 | e.printStackTrace(); 347 | } 348 | } 349 | } 350 | } 351 | 352 | public static byte[] File2byte(String filePath) 353 | { 354 | byte[] buffer = null; 355 | try 356 | { 357 | File file = new File(filePath); 358 | FileInputStream fis = new FileInputStream(file); 359 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 360 | byte[] b = new byte[1024]; 361 | int n; 362 | while ((n = fis.read(b)) != -1) 363 | { 364 | bos.write(b, 0, n); 365 | } 366 | fis.close(); 367 | bos.close(); 368 | buffer = bos.toByteArray(); 369 | } 370 | catch (FileNotFoundException e) 371 | { 372 | e.printStackTrace(); 373 | } 374 | catch (IOException e) 375 | { 376 | e.printStackTrace(); 377 | } 378 | return buffer; 379 | } 380 | 381 | public static void editWithVSCode(String filepath) { 382 | // /Applications/Visual Studio Code.app/Contents/MacOS/Electron 383 | if (filepath.contains(" ")){ 384 | filepath = "\""+filepath+"\""; 385 | } 386 | if (isMac()) { 387 | try { 388 | String[] cmdArray = new String[] {"/Applications/Visual Studio Code.app/Contents/MacOS/Electron",filepath}; 389 | Runtime.getRuntime().exec(cmdArray); 390 | } catch (IOException e) { 391 | e.printStackTrace(); 392 | } 393 | } 394 | if (isWindows()) { 395 | try { 396 | String[] cmdArray = new String[] {"code.cmd",filepath}; 397 | Runtime.getRuntime().exec(cmdArray); 398 | } catch (IOException e) { 399 | e.printStackTrace(); 400 | } 401 | } 402 | } 403 | 404 | 405 | public static void main(String args[]) { 406 | System.out.println(isCommandExists("python")); 407 | } 408 | } 409 | 410 | -------------------------------------------------------------------------------- /src/main/java/burp/Getter.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URL; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.LinkedHashMap; 8 | import java.util.List; 9 | import java.util.Map.Entry; 10 | 11 | /* 12 | * source code: https://github.com/bit4woo/burp-api-common/blob/master/src/main/java/burp/Getter.java 13 | * author: bit4woo 14 | * github: https://github.com/bit4woo 15 | */ 16 | 17 | public class Getter { 18 | private static IExtensionHelpers helpers; 19 | private final static String Header_Spliter = ":"; 20 | private final static String Header_Connector = ": ";//contains space 21 | private final static String Header_firstLine_Spliter = " "; 22 | 23 | public Getter(IExtensionHelpers helpers) { 24 | Getter.helpers = helpers; 25 | } 26 | 27 | /* 28 | * 获取header的字符串数组,是构造burp中请求需要的格式。 29 | * return headers list 30 | */ 31 | public List getHeaderList(boolean messageIsRequest,IHttpRequestResponse messageInfo) { 32 | if (null == messageInfo) return null; 33 | byte[] requestOrResponse = null; 34 | if(messageIsRequest) { 35 | requestOrResponse = messageInfo.getRequest(); 36 | }else { 37 | requestOrResponse = messageInfo.getResponse(); 38 | } 39 | return getHeaderList(messageIsRequest,requestOrResponse); 40 | } 41 | 42 | /* 43 | * 获取请求包或者响应包中的header List 44 | */ 45 | public List getHeaderList(boolean IsRequest,byte[] requestOrResponse) { 46 | if (null == requestOrResponse) return null; 47 | if(IsRequest) { 48 | IRequestInfo analyzeRequest = helpers.analyzeRequest(requestOrResponse); 49 | List headers = analyzeRequest.getHeaders(); 50 | return headers; 51 | }else { 52 | IResponseInfo analyzeResponse = helpers.analyzeResponse(requestOrResponse); 53 | List headers = analyzeResponse.getHeaders(); 54 | return headers; 55 | } 56 | } 57 | 58 | /* 59 | * 获取所有headers,当做一个string看待。 60 | * 主要用于判断是否包含某个特殊字符串 61 | * List getHeaders 调用toString()方法,得到如下格式:[111111, 2222] 62 | * 就能满足上面的场景了,废弃这个函数 63 | */ 64 | @Deprecated 65 | public String getHeaderString(boolean messageIsRequest,IHttpRequestResponse messageInfo) { 66 | List headers =null; 67 | StringBuilder headerString = new StringBuilder(); 68 | if(messageIsRequest) { 69 | IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo); 70 | headers = analyzeRequest.getHeaders(); 71 | }else { 72 | IResponseInfo analyzeResponse = helpers.analyzeResponse(messageInfo.getResponse()); 73 | headers = analyzeResponse.getHeaders(); 74 | } 75 | 76 | for (String header : headers) { 77 | headerString.append(header); 78 | } 79 | 80 | return headerString.toString(); 81 | } 82 | 83 | /* 84 | * 获取header的map格式,key:value形式 85 | * 这种方式可以用put函数轻松实现:如果有则update,如果无则add。 86 | * !!!注意:这个方法获取到的map,第一行将分割成形如 key = "GET", value= "/cps.gec/limit/information.html HTTP/1.1" 87 | * 响应包则分割成形如:key = "HTTP/1.1", value="200 OK" 88 | */ 89 | public LinkedHashMap getHeaderMap(boolean messageIsRequest,IHttpRequestResponse messageInfo) { 90 | if (messageInfo == null) return null; 91 | List headers=getHeaderList(messageIsRequest, messageInfo); 92 | return headerListToHeaderMap(headers); 93 | } 94 | 95 | /* 96 | * use LinkedHashMap to keep headers in order 97 | */ 98 | public LinkedHashMap getHeaderMap(boolean messageIsRequest,byte[] requestOrResponse) { 99 | if (requestOrResponse == null) return null; 100 | List headers=getHeaderList(messageIsRequest, requestOrResponse); 101 | return headerListToHeaderMap(headers); 102 | } 103 | 104 | /* 105 | * 仅该类内部调用 106 | */ 107 | private static LinkedHashMap headerListToHeaderMap(List headers) { 108 | LinkedHashMap result = new LinkedHashMap(); 109 | if (null == headers) return null; 110 | for (String header : headers) { 111 | if (headers.indexOf(header) == 0) { 112 | String headerName = header.split(Header_firstLine_Spliter, 2)[0];//这里的limit=2 可以理解成分割成2份 113 | String headerValue = header.split(Header_firstLine_Spliter, 2)[1]; 114 | result.put(headerName, headerValue); 115 | }else { 116 | //https://www.w3.org/Protocols/rfc2068/rfc2068-->4.2 Message Headers 117 | //https://blog.csdn.net/u012572955/article/details/50144535/ 118 | //每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域 值前可以添加任何数量的空格符 119 | try { 120 | String headerName = header.split(Header_Spliter, 2)[0].trim();//这里的limit=2 可以理解成分割成2份,否则referer可能别分成3份 121 | String headerValue = header.split(Header_Spliter, 2)[1].trim(); 122 | result.put(headerName, headerValue); 123 | }catch (Exception e) { 124 | System.out.println("Wrong header -- "+header); 125 | } 126 | } 127 | } 128 | return result; 129 | } 130 | 131 | 132 | 133 | public List headerMapToHeaderList(LinkedHashMap Headers){ 134 | List result = new ArrayList(); 135 | for (Entry header:Headers.entrySet()) { 136 | String key = header.getKey(); 137 | String value = header.getValue(); 138 | if (isFirstLine(key,value)) {//识别第一行 139 | String item = key+Header_firstLine_Spliter+value; 140 | result.add(0, item); 141 | }else { 142 | String item = key+Header_Connector+value; 143 | result.add(item); 144 | } 145 | } 146 | return result; 147 | } 148 | 149 | public static boolean isFirstLine(String key,String Value) { 150 | //GET /sys/remark/pages.pvt?t=1593481248723&limit=3&start=0&sysId=2111 HTTP/1.1 151 | //HTTP/1.1 200 OK 152 | if (key.startsWith("HTTP/")) {//response first line 153 | return true; 154 | } 155 | try { 156 | if (Value.split(" ",2)[1].startsWith("HTTP/")) { 157 | return true; 158 | } 159 | }catch(Exception e){} 160 | 161 | return false; 162 | } 163 | 164 | /* 165 | * 获取某个header的值,如果没有此header,返回null。 166 | */ 167 | public String getHeaderValueOf(boolean messageIsRequest,IHttpRequestResponse messageInfo, String headerName) { 168 | LinkedHashMap headers = getHeaderMap(messageIsRequest,messageInfo); 169 | if (null ==headers || headerName ==null) return null; 170 | return headers.get(headerName.trim()); 171 | } 172 | 173 | /* 174 | * 获取某个header的值,如果没有此header,返回null。 175 | */ 176 | public String getHeaderValueOf(boolean messageIsRequest,byte[] requestOrResponse, String headerName) { 177 | LinkedHashMap headers=getHeaderMap(messageIsRequest,requestOrResponse); 178 | if (null ==headers || headerName ==null) return null; 179 | return headers.get(headerName.trim()); 180 | } 181 | 182 | 183 | public byte[] getBody(boolean messageIsRequest,IHttpRequestResponse messageInfo) { 184 | if (messageInfo == null){ 185 | return null; 186 | } 187 | byte[] requestOrResponse = null; 188 | if(messageIsRequest) { 189 | requestOrResponse = messageInfo.getRequest(); 190 | }else { 191 | requestOrResponse = messageInfo.getResponse(); 192 | } 193 | return getBody(messageIsRequest, requestOrResponse); 194 | } 195 | 196 | public byte[] getBody(boolean isRequest,byte[] requestOrResponse) { 197 | if (requestOrResponse == null){ 198 | return null; 199 | } 200 | int bodyOffset = -1; 201 | if(isRequest) { 202 | IRequestInfo analyzeRequest = helpers.analyzeRequest(requestOrResponse); 203 | bodyOffset = analyzeRequest.getBodyOffset(); 204 | }else { 205 | IResponseInfo analyzeResponse = helpers.analyzeResponse(requestOrResponse); 206 | bodyOffset = analyzeResponse.getBodyOffset(); 207 | } 208 | byte[] byte_body = Arrays.copyOfRange(requestOrResponse, bodyOffset, requestOrResponse.length);//not length-1 209 | //String body = new String(byte_body); //byte[] to String 210 | return byte_body; 211 | } 212 | 213 | 214 | /* 215 | * 注意,这里获取的URL包含了默认端口! 216 | * this return value of url contains default port, 80 :443 217 | * eg. http://bit4woo.com:80/ 218 | */ 219 | @Deprecated 220 | public String getShortUrlStringWithDefaultPort(IHttpRequestResponse messageInfo) { 221 | URL fullUrl = getFullURLWithDefaultPort(messageInfo); 222 | if (fullUrl == null) { 223 | return null; 224 | }else { 225 | String shortUrl = fullUrl.toString().replace(fullUrl.getFile(), "/"); 226 | return shortUrl; 227 | } 228 | } 229 | 230 | /* 231 | * 232 | * this return value of url will NOT contains default port, 80 :443 233 | * eg. https://www.baidu.com 234 | */ 235 | @Deprecated 236 | public String getShortUrlStringWithoutDefaultPort(IHttpRequestResponse messageInfo) { 237 | return messageInfo.getHttpService().toString()+"/"; //this result of this method doesn't contains default port 238 | } 239 | 240 | @Deprecated 241 | public String getFullUrlStringWithDefaultPort(IHttpRequestResponse messageInfo) { 242 | 243 | URL fullUrl = getFullURLWithDefaultPort(messageInfo); 244 | if (fullUrl == null) { 245 | return null; 246 | }else { 247 | return fullUrl.toString(); 248 | } 249 | } 250 | 251 | /* 252 | * 253 | */ 254 | @Deprecated 255 | public String getFullUrlStringWithoutDefaultPort(IHttpRequestResponse messageInfo) { 256 | URL fullUrl = getFullURLWithDefaultPort(messageInfo); 257 | if (fullUrl == null) { 258 | return null; 259 | }else { 260 | try { 261 | if (fullUrl.getProtocol().equalsIgnoreCase("https") && fullUrl.getPort() == 443) { 262 | return new URL(fullUrl.toString().replaceFirst(":443/", ":/")).toString(); 263 | } 264 | if (fullUrl.getProtocol().equalsIgnoreCase("http") && fullUrl.getPort() == 80) { 265 | return new URL(fullUrl.toString().replaceFirst(":80/", ":/")).toString(); 266 | } 267 | } catch (MalformedURLException e) { 268 | e.printStackTrace(); 269 | } 270 | return null; 271 | } 272 | } 273 | 274 | /* 275 | * return Type is URL,not String. 276 | * use equal() function to compare URL object. the string contains default port or not both OK, but the path(/) is sensitive 277 | * URL对象可以用它自己提供的equal()函数进行对比,是否包含默认端口都是没有关系的。但最后的斜杠path却是有关系的。 278 | * 279 | * eg. http://bit4woo.com:80/ 包含默认端口和默认path(/) 280 | */ 281 | public URL getShortURL(IHttpRequestResponse messageInfo){ 282 | if (null == messageInfo) return null; 283 | String shortUrlString = messageInfo.getHttpService().toString();//http://www.baidu.com 284 | shortUrlString = formateURLString(shortUrlString); 285 | try { 286 | return new URL(shortUrlString); 287 | } catch (MalformedURLException e) { 288 | e.printStackTrace(); 289 | return null; 290 | } 291 | } 292 | 293 | /* 294 | * return Type is URL,not String. 295 | * use equal() function to compare URL object. the string contains default port or not both OK, but the path(/) is sensitive 296 | * URL对象可以用它自己提供的equal()函数进行对比,是否包含默认端口都是没有关系的。但最后的斜杠path却是有关系的。 297 | * 298 | * 这个函数的返回结果转换成字符串是包含了默认端口的。 299 | * http://bit4woo.com:80/test.html#123 300 | */ 301 | public final URL getFullURL(IHttpRequestResponse messageInfo){ 302 | if (null == messageInfo) return null; 303 | IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo); 304 | return analyzeRequest.getUrl(); 305 | } 306 | 307 | @Deprecated 308 | private final URL getFullURLWithDefaultPort(IHttpRequestResponse messageInfo){ 309 | return getFullURL(messageInfo); 310 | } 311 | 312 | 313 | /* 314 | * to let url String contains default port(80\443) and default path(/) 315 | * 316 | * from: http://bit4woo.com 317 | * to : http://bit4woo.com:80/ 318 | */ 319 | public static String formateURLString(String urlString) { 320 | try { 321 | //urlString = "https://www.runoob.com"; 322 | URL url = new URL(urlString); 323 | String host = url.getHost(); 324 | int port = url.getPort(); 325 | String path = url.getPath(); 326 | 327 | if (port == -1) { 328 | String newHost = url.getHost()+":"+url.getDefaultPort(); 329 | urlString = urlString.replace(host, newHost); 330 | } 331 | 332 | if (path.equals("")) { 333 | urlString = urlString+"/"; 334 | } 335 | } catch (MalformedURLException e) { 336 | e.printStackTrace(); 337 | } 338 | return urlString; 339 | } 340 | 341 | 342 | public String getHost(IHttpRequestResponse messageInfo) { 343 | return messageInfo.getHttpService().getHost(); 344 | } 345 | 346 | public short getStatusCode(IHttpRequestResponse messageInfo) { 347 | if (messageInfo == null || messageInfo.getResponse() == null) { 348 | return -1; 349 | } 350 | IResponseInfo analyzedResponse = helpers.analyzeResponse(messageInfo.getResponse()); 351 | return analyzedResponse.getStatusCode(); 352 | } 353 | 354 | public short getStatusCode(byte[] response) { 355 | if (response == null) { 356 | return -1; 357 | } 358 | try { 359 | IResponseInfo analyzedResponse = helpers.analyzeResponse(response); 360 | return analyzedResponse.getStatusCode(); 361 | } catch (Exception e) { 362 | return -1; 363 | } 364 | } 365 | 366 | public List getParas(IHttpRequestResponse messageInfo){ 367 | IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo); 368 | return analyzeRequest.getParameters(); 369 | } 370 | 371 | public List getParas(byte[] request){ 372 | IRequestInfo analyzeRequest = helpers.analyzeRequest(request); 373 | return analyzeRequest.getParameters(); 374 | } 375 | 376 | public String getMethod(IHttpRequestResponse messageInfo){ 377 | if (messageInfo == null || messageInfo.getRequest() == null) { 378 | return null; 379 | } 380 | IRequestInfo analyzedRequest = helpers.analyzeRequest(messageInfo.getRequest()); 381 | return analyzedRequest.getMethod(); 382 | } 383 | 384 | public String getMethod(byte[] request){ 385 | if (request == null) { 386 | return null; 387 | } 388 | try { 389 | IRequestInfo analyzedRequest = helpers.analyzeRequest(request); 390 | return analyzedRequest.getMethod(); 391 | } catch (Exception e) { 392 | return null; 393 | } 394 | } 395 | 396 | public String getHTTPBasicCredentials(IHttpRequestResponse messageInfo) throws Exception{ 397 | String authHeader = getHeaderValueOf(true, messageInfo, "Authorization").trim(); 398 | String[] parts = authHeader.split("\\s"); 399 | 400 | if (parts.length != 2) 401 | throw new Exception("Wrong number of HTTP Authorization header parts"); 402 | 403 | if (!parts[0].equalsIgnoreCase("Basic")) 404 | throw new Exception("HTTP authentication must be Basic"); 405 | 406 | return parts[1]; 407 | } 408 | 409 | public static void main(String args[]) { 410 | String key = "POST"; 411 | String value = "/cbil-ic/services/CosRefundService HTTP/1.1"; 412 | key = "HTTP/1.1"; 413 | value = "500 Server Error"; 414 | key = "User-Agent"; 415 | value = "okHTTP/3.12.1"; 416 | System.out.println(isFirstLine(key,value)); 417 | } 418 | } 419 | -------------------------------------------------------------------------------- /src/main/java/burp/IPAddressUtils.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import inet.ipaddr.AddressStringException; 4 | import inet.ipaddr.IPAddress; 5 | import inet.ipaddr.IPAddressSeqRange; 6 | import inet.ipaddr.IPAddressString; 7 | import org.apache.commons.net.util.SubnetUtils; 8 | import org.apache.commons.net.util.SubnetUtils.SubnetInfo; 9 | 10 | import java.util.*; 11 | 12 | public class IPAddressUtils { 13 | 14 | public static boolean isPrivateIPv4(String ipAddress) { 15 | try { 16 | String[] ipAddressArray = ipAddress.split("\\."); 17 | int[] ipParts = new int[ipAddressArray.length]; 18 | for (int i = 0; i < ipAddressArray.length; i++) { 19 | ipParts[i] = Integer.parseInt(ipAddressArray[i].trim()); 20 | } 21 | 22 | switch (ipParts[0]) { 23 | case 10: 24 | case 127: 25 | return true; 26 | case 172: 27 | return (ipParts[1] >= 16) && (ipParts[1] < 32); 28 | case 192: 29 | return (ipParts[1] == 168); 30 | case 169: 31 | return (ipParts[1] == 254); 32 | } 33 | } catch (Exception ex) { 34 | } 35 | 36 | return false; 37 | } 38 | 39 | public static boolean isPrivateIPv6(String ipAddress) { 40 | boolean isPrivateIPv6 = false; 41 | String[] ipParts = ipAddress.trim().split(":"); 42 | if (ipParts.length > 0) { 43 | String firstBlock = ipParts[0]; 44 | String prefix = firstBlock.substring(0, 2); 45 | 46 | if (firstBlock.equalsIgnoreCase("fe80") 47 | || firstBlock.equalsIgnoreCase("100") 48 | || ((prefix.equalsIgnoreCase("fc") && firstBlock.length() >= 4)) 49 | || ((prefix.equalsIgnoreCase("fd") && firstBlock.length() >= 4))) { 50 | isPrivateIPv6 = true; 51 | } 52 | } 53 | return isPrivateIPv6; 54 | } 55 | 56 | /** 57 | * 校验字符串是否是一个合格的IP地址 58 | * 会发现如下类型的IP,是有效的IP地址,但是实际情况却不会有人这么写。 59 | * 应当从我们的正则中剔除 60 | * PING 181.002.245.007 (181.2.245.7): 56 data bytes 61 | * @param ip 62 | * @return 63 | */ 64 | public static boolean isValidIP (String ip) { 65 | try { 66 | if ( ip == null || ip.isEmpty() ) { 67 | return false; 68 | } 69 | if (ip.contains(":")) { 70 | String[] ipAndPort = ip.split(":"); 71 | if (ipAndPort.length !=2) { 72 | return false; 73 | } 74 | ip = ipAndPort[0]; 75 | int port = Integer.parseInt(ipAndPort[1]); 76 | if ( port < 0 || port > 65535 ) { 77 | return false; 78 | } 79 | } 80 | 81 | String[] parts = ip.split( "\\." ); 82 | if ( parts.length != 4 ) { 83 | return false; 84 | } 85 | 86 | for ( String s : parts ) { 87 | if (s.startsWith("0") && s.length() > 1 ) { 88 | return false; 89 | } 90 | int i = Integer.parseInt( s ); 91 | if ( (i < 0) || (i > 255) ) { 92 | return false; 93 | } 94 | } 95 | if ( ip.endsWith(".") ) { 96 | return false; 97 | } 98 | 99 | return true; 100 | } catch (NumberFormatException nfe) { 101 | return false; 102 | } 103 | } 104 | 105 | public static boolean isValidSubnet(String subnet) { 106 | if (null == subnet) return false; 107 | subnet = subnet.replaceAll(" ", ""); 108 | if (subnet.contains("/")) { 109 | String[] parts = subnet.split("/"); 110 | if (parts.length ==2) { 111 | String ippart = parts[0]; 112 | int num = Integer.parseInt(parts[1]); 113 | if (isValidIP(ippart) && num>1 && num < 32) { 114 | return true; 115 | } 116 | } 117 | } 118 | if (subnet.contains("-")) {//这里的方法不完整 119 | String[] parts = subnet.split("-"); 120 | if (parts.length ==2) { 121 | String ippart1 = parts[0]; 122 | String ippart2 = parts[1]; 123 | if (isValidIP(ippart1) && isValidIP(ippart2)) { 124 | return true; 125 | } 126 | } 127 | } 128 | return false; 129 | } 130 | 131 | 132 | public static Set toClassCSubNets(Set IPSet) { 133 | Set subNets= new HashSet(); 134 | for (String ip:IPSet) { 135 | ip = ipClean(ip); 136 | if (isValidIP(ip)) { 137 | String subnet = ip.substring(0,ip.lastIndexOf("."))+".0/24"; 138 | subNets.add(subnet); 139 | }else if(isValidSubnet(ip)) {//这里的IP也可能是网段,不要被参数名称限定了 140 | subNets.add(ip); 141 | } 142 | } 143 | return subNets; 144 | } 145 | 146 | /* 147 | * IP集合,转多个CIDR,smaller newtworks than Class C Networks 148 | */ 149 | public static Set toSmallerSubNets(Set IPSet) { 150 | Set subNets= toClassCSubNets(IPSet); 151 | Set smallSubNets= new HashSet(); 152 | 153 | try { 154 | for(String CNet:subNets) {//把所有IP按照C段进行分类 155 | SubnetUtils net = new SubnetUtils(CNet); 156 | Set tmpIPSet = new HashSet(); 157 | for (String ip:IPSet) { 158 | ip = ipClean(ip); 159 | if (isValidSubnet(ip)) {//这里的IP也可能是网段,不要被参数名称限定了 160 | smallSubNets.add(ip); 161 | continue; 162 | } 163 | if (!isValidIP(ip)) { 164 | System.out.println(ip+" invalid IP address, skip to handle it!"); 165 | continue; 166 | } 167 | 168 | if (net.getInfo().isInRange(ip) || net.getInfo().getBroadcastAddress().equals(ip.trim()) || net.getInfo().getNetworkAddress().equals(ip.trim())){ 169 | //52.74.179.0 ---sometimes .0 address is a real address. 170 | tmpIPSet.add(ip); 171 | } 172 | }//每个tmpIPSet就是一个C段的IP集合 173 | String tmpSmallNet = ipset2cidr(tmpIPSet); 174 | if (tmpSmallNet != null && !tmpSmallNet.equals("")){ 175 | smallSubNets.add(tmpSmallNet);//把一个C段中的多个IP计算出其CIDR,即更小的网段 176 | } 177 | } 178 | return smallSubNets; 179 | }catch(Exception e) { 180 | throw e; 181 | } 182 | 183 | } 184 | /* 185 | To get a smaller network with a set of IP addresses 186 | */ 187 | private static String ipset2cidr(Set IPSet) { 188 | try { 189 | if (IPSet == null || IPSet.size() <=0){ 190 | return null; 191 | } 192 | if (IPSet.size() ==1){ 193 | return IPSet.toArray(new String[0])[0]; 194 | } 195 | List list = new ArrayList(IPSet); 196 | SubnetUtils oldsamllerNetwork =new SubnetUtils(list.get(0).trim()+"/24"); 197 | for (int mask=24;mask<=32;mask++){ 198 | //System.out.println(mask); 199 | SubnetUtils samllerNetwork = new SubnetUtils(list.get(0).trim()+"/"+mask); 200 | for (String ip:IPSet) { 201 | ip = ipClean(ip); 202 | if (!isValidIP(ip)) { 203 | System.out.println(ip + "invalid IP address, skip to handle it!"); 204 | continue; 205 | } 206 | if (samllerNetwork.getInfo().isInRange(ip) || samllerNetwork.getInfo().getBroadcastAddress().equals(ip.trim()) || samllerNetwork.getInfo().getNetworkAddress().equals(ip.trim())){ 207 | //52.74.179.0 ---sometimes .0 address is a real address. 208 | continue; 209 | } 210 | else { 211 | String networkaddress = oldsamllerNetwork.getInfo().getNetworkAddress(); 212 | String tmpmask = oldsamllerNetwork.getInfo().getNetmask(); 213 | return new SubnetUtils(networkaddress,tmpmask).getInfo().getCidrSignature(); 214 | } 215 | } 216 | oldsamllerNetwork = samllerNetwork; 217 | } 218 | return null; 219 | }catch (Exception e) { 220 | throw e; 221 | } 222 | } 223 | 224 | public static String ipClean(String ip){ 225 | ip = ip.trim(); 226 | if (ip.endsWith(".")){ 227 | ip = ip.substring(0,ip.lastIndexOf(".")); 228 | } 229 | if (ip.contains(":")) { 230 | ip = ip.substring(0,ip.lastIndexOf(":")); 231 | } 232 | return ip; 233 | } 234 | 235 | /* 236 | * 多个网段转IP集合,变更表现形式,变成一个个的IP 237 | */ 238 | public static Set toIPSet (Set subNets) { 239 | Set IPSet = new HashSet(); 240 | List result = toIPList(new ArrayList<>(subNets)); 241 | IPSet.addAll(result); 242 | return IPSet; 243 | } 244 | 245 | public static List toIPList (String subnet) { 246 | List IPList = new ArrayList(); 247 | try { 248 | if (subnet.contains(":")) { 249 | return IPList;//暂时先不处理IPv6,需要研究一下 250 | //TODO 251 | } 252 | if (subnet.contains("/")){ 253 | SubnetUtils net = new SubnetUtils(subnet); 254 | SubnetInfo xx = net.getInfo(); 255 | String[] ips = xx.getAllAddresses(); 256 | IPList.add(xx.getNetworkAddress());//.0 257 | IPList.addAll(Arrays.asList(ips)); 258 | IPList.add(xx.getBroadcastAddress());//.255 259 | }else if (subnet.contains("-")) {//178.170.186.0-178.170.186.255 260 | String[] ips = subnet.split("-"); 261 | if (ips.length ==2) { 262 | String startip = ips[0].trim(); 263 | String endip = ips[1].trim(); 264 | //System.out.println(startip); 265 | //System.out.println(endip); 266 | IPAddressString string1 = new IPAddressString(startip); 267 | IPAddressString string2 = new IPAddressString(endip); 268 | IPAddress addr1 = string1.getAddress(); 269 | IPAddress addr2 = string2.getAddress(); 270 | IPAddressSeqRange range = addr1.toSequentialRange(addr2); 271 | Iterator it = range.iterator(); 272 | while (it.hasNext()){ 273 | IPAddress item = it.next(); 274 | //System.out.println(item.toString()); 275 | IPList.add(item.toString()); 276 | } 277 | } 278 | }else { //单IP 279 | IPList.add(subnet); 280 | } 281 | }catch(Exception e) { 282 | e.printStackTrace(); 283 | } 284 | return IPList; 285 | } 286 | 287 | public static List toIPList (List subNets) { 288 | List IPList = new ArrayList(); 289 | for (String subnet:subNets) { 290 | IPList.addAll(toIPList(subnet)); 291 | } 292 | return IPList; 293 | } 294 | 295 | public static boolean checkIPIsInGivenRange (String inputIP, String rangeStartIP, String rangeEndIP) 296 | throws AddressStringException { 297 | IPAddress startIPAddress = new IPAddressString(rangeStartIP).getAddress(); 298 | IPAddress endIPAddress = new IPAddressString(rangeEndIP).getAddress(); 299 | IPAddressSeqRange ipRange = startIPAddress.toSequentialRange(endIPAddress); 300 | IPAddress inputIPAddress = new IPAddressString(inputIP).toAddress(); 301 | 302 | return ipRange.contains(inputIPAddress); 303 | } 304 | 305 | public static void test3() { 306 | Set a= new HashSet(); 307 | a.add("218.213.102.6/31"); 308 | System.out.println(toIPSet(a)); 309 | Set subnets = new HashSet(); 310 | subnets.add("2402:db40:1::/48"); 311 | System.out.print(toIPSet(subnets)); 312 | 313 | String Domains = "121.32.249.172, 120.92.174.135, 121.32.249.171, 58.220.29.72, 120.92.158.137, 119.147.34.242, 183.52.13.154, 222.186.49.111, 113.96.181.216, 61.147.235.208, 113.96.181.217, 106.7.64.1, 119.147.156.231, 119.147.156.230, 113.96.181.211, 113.96.181.214, 172.18.21.10, 119.125.41.87, 222.186.18.241, 113.96.109.95, 14.215.23.246, 114.80.24.230, 120.92.168.45, 125.77.163.235, 113.101.214.238, 124.239.234.105, 183.2.192.234, 119.125.43.15, 183.2.192.112, 110.43.33.232, 183.2.192.235, 36.25.252.1, 14.215.172.215, 121.12.122.79, 14.215.172.217, 175.6.49.240, 14.215.172.216, 14.215.172.219, 114.80.24.231, 14.215.57.226, 119.125.115.232, 113.96.98.73, 14.215.57.228, 183.131.203.6, 58.222.35.205, 121.11.2.189, 14.215.166.95, 180.122.78.242, 14.215.172.220, 58.215.158.241, 14.215.172.221, 180.101.150.112, 58.216.87.204, 119.147.70.221, 110.76.40.240, 119.147.33.73, 116.5.154.179, 222.188.43.132, 222.188.43.130, 58.216.4.238, 183.61.168.248, 222.188.43.131, 110.43.34.66, 58.216.4.239, 183.61.168.240, 119.147.41.240, 183.61.168.241, 183.61.168.242, 42.120.0.158, 221.231.83.241, 119.147.41.248, 59.36.226.242, 222.188.43.129, 125.94.49.226, 119.147.33.66, 106.7.64.1, 113.96.154.93, 121.12.123.229, 121.11.2.240, 218.94.206.241, 183.131.185.41, 113.113.127.240, 119.96.250.129, 119.3.238.64, 61.147.235.194, 113.113.127.241, 124.232.170.15, 117.50.8.201, 59.32.49.99, 119.125.41.206, 183.6.241.1, 119.147.41.239, 175.6.153.1, 119.147.41.238, 113.96.98.82, 59.36.226.239, 59.36.226.238, 58.216.87.229, 106.117.245.1, 27.159.125.1, 183.61.241.232, 91.195.241.136, 183.6.231.203, 121.14.131.238, 121.14.131.237, 58.216.107.214, 61.147.236.11, 61.147.236.12, 113.113.127.237, 113.113.127.238, 183.136.135.216, 61.150.82.6, 183.136.135.224, 183.136.135.223, 183.136.135.222, 183.136.135.221, 183.136.135.220, 121.12.123.201, 125.94.50.238, 58.220.28.104, 183.61.241.229, 124.229.52.1, 111.73.62.1, 106.117.213.218, 183.136.135.215, 139.196.14.154, 183.136.135.213, 172.18.21.243, 111.73.62.1, 113.96.155.122, 113.96.155.121, 67.198.130.7, 222.186.16.244, 115.238.195.19, 124.239.239.229, 115.238.195.18, 222.186.16.240, 222.186.16.241, 183.134.13.131, 222.186.16.242, 183.134.13.130, 222.186.16.243, 14.215.56.243, 122.228.232.71, 14.215.56.242, 122.228.232.70, 14.215.56.240, 14.215.166.205, 222.186.16.248, 14.17.124.239, 27.148.180.224, 113.100.189.152, 110.167.162.1, 27.128.214.219, 113.96.98.102, 14.215.167.253, 183.61.13.209, 183.60.159.171, 121.11.2.200, 122.228.77.85, 121.9.212.151, 121.9.212.150, 119.125.45.46, 124.239.158.238, 115.238.195.21, 183.134.13.129, 183.131.11.46, 122.228.232.69, 122.228.232.68, 222.186.35.80, 222.186.35.81, 125.77.130.22, 115.238.195.20, 212.64.117.140, 124.239.239.230, 180.122.76.238, 121.9.212.141, 119.147.39.226, 121.9.244.86, 115.231.191.216, 121.9.244.85, 183.61.13.234, 121.9.244.84, 116.5.155.130, 222.186.35.79, 122.227.201.1, 14.215.55.228, 113.96.83.98, 121.32.249.233, 113.100.189.29, 113.96.109.243, 221.228.219.62, 61.146.189.54, 121.9.246.110, 113.96.109.246, 183.2.192.198, 58.216.4.248, 117.91.177.238, 14.215.166.116, 58.216.4.241, 121.32.249.249, 124.229.52.1, 58.216.4.240, 58.216.4.243, 219.135.59.170, 222.186.16.238, 58.216.4.242, 222.186.16.239, 14.17.124.238, 58.216.4.244, 219.132.165.61, 113.64.94.76, 113.105.231.252, 110.43.33.137, 58.223.210.225, 36.25.252.1, 61.146.176.145, 113.105.155.219, 121.11.2.199, 14.29.104.122, 119.147.70.218, 121.11.2.195, 119.147.70.216, 58.215.146.119, 61.160.228.240, 119.3.70.188, 175.6.161.1, 221.231.81.239, 221.231.81.238, 183.2.200.243, 183.60.228.248, 183.2.200.244, 110.43.33.124, 117.25.159.243, 121.12.122.120, 183.60.228.242, 14.215.167.213, 121.12.122.81, 14.29.104.112, 14.215.55.230, 183.146.212.129, 27.148.151.64, 183.146.212.135, 124.238.245.63, 183.146.212.132, 119.96.250.129, 183.146.212.137, 124.238.245.66, 183.146.212.136, 119.125.40.80, 183.146.212.131, 183.146.212.130, 183.2.200.238, 27.159.125.1, 120.92.144.250, 139.159.241.37, 120.92.169.201, 219.152.56.1, 124.115.135.1, 110.43.33.229, 120.92.168.34, 61.140.13.246, 183.52.12.176, 120.92.112.150, 115.238.195.3, 124.238.245.104, 115.238.195.4, 115.223.28.41, 115.238.195.2, 113.96.108.116, 115.238.195.7, 58.222.35.201, 113.96.108.118, 58.222.35.200, 115.238.195.5, 115.238.195.6, 120.92.78.57, 221.228.219.98, 113.94.141.53, 58.222.35.204, 106.225.223.20, 58.222.35.203, 27.128.211.1, 124.232.162.213"; 314 | Set IPsOfDomain = new HashSet<>(); 315 | IPsOfDomain.addAll(Arrays.asList(Domains.split(", "))); 316 | Set subnets1 = toSmallerSubNets(IPsOfDomain); 317 | System.out.println(subnets1); 318 | } 319 | 320 | public static void main(String[] args) throws AddressStringException { 321 | //System.out.println(toIPList("178.170.186.0-178.170.186.255")); 322 | //System.out.println(checkIPIsInGivenRange("178.170.186.1","178.170.186.0","178.170.186.255")); 323 | System.out.println(isValidIP("033.072.025.009")); 324 | } 325 | } -------------------------------------------------------------------------------- /src/main/java/burp/Common.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URL; 5 | import java.nio.charset.Charset; 6 | import java.text.DateFormat; 7 | import java.text.SimpleDateFormat; 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.Date; 11 | import java.util.HashSet; 12 | import java.util.List; 13 | import java.util.Random; 14 | import java.util.Set; 15 | import java.util.regex.Matcher; 16 | import java.util.regex.Pattern; 17 | 18 | /** 19 | * 常用格式校验 20 | * 各种按照正则进行提取 21 | * 数据格式化 22 | * 类型转换 23 | */ 24 | public class Common { 25 | 26 | public static final String URL_Regex = "(?:\"|')" 27 | + "(" 28 | + "((?:[a-zA-Z]{1,10}://|//)[^\"'/]{1,}\\.[a-zA-Z]{2,}[^\"']{0,})" 29 | + "|" 30 | + "((?:/|\\.\\./|\\./)[^\"'><,;| *()(%%$^/\\\\\\[\\]][^\"'><,;|()]{1,})" 31 | + "|" 32 | + "([a-zA-Z0-9_\\-/]{1,}/[a-zA-Z0-9_\\-/]{1,}\\.(?:[a-zA-Z]{1,4}|action)(?:[\\?|/][^\"|']{0,}|))" 33 | + "|" 34 | + "([a-zA-Z0-9_\\-]{1,}\\.(?:php|asp|aspx|jsp|json|action|html|js|txt|xml)(?:\\?[^\"|']{0,}|))" 35 | + ")" 36 | + "(?:\"|')"; 37 | 38 | private static final String IP_ADDRESS_STRING = 39 | "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]" 40 | + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]" 41 | + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" 42 | + "|[1-9][0-9]|[0-9]))"; 43 | 44 | //域名校验和域名提取还是要区分对待 45 | //domain.DomainProducer.grepDomain(String)是提取域名的,正则中包含了*号 46 | public static boolean isValidDomain(String domain) { 47 | if (null == domain) { 48 | return false; 49 | } 50 | final String DOMAIN_NAME_PATTERN = "([A-Za-z0-9-]{1,63}(? 255) ) { 71 | return false; 72 | } 73 | } 74 | if ( ip.endsWith(".") ) { 75 | return false; 76 | } 77 | 78 | return true; 79 | } catch (NumberFormatException nfe) { 80 | return false; 81 | } 82 | } 83 | 84 | public static boolean isPrivateIPv4(String ipAddress) { 85 | try { 86 | String[] ipAddressArray = ipAddress.split("\\."); 87 | int[] ipParts = new int[ipAddressArray.length]; 88 | for (int i = 0; i < ipAddressArray.length; i++) { 89 | ipParts[i] = Integer.parseInt(ipAddressArray[i].trim()); 90 | } 91 | 92 | switch (ipParts[0]) { 93 | case 10: 94 | case 127: 95 | return true; 96 | case 172: 97 | return (ipParts[1] >= 16) && (ipParts[1] < 32); 98 | case 192: 99 | return (ipParts[1] == 168); 100 | case 169: 101 | return (ipParts[1] == 254); 102 | } 103 | } catch (Exception ex) { 104 | } 105 | 106 | return false; 107 | } 108 | 109 | public static boolean isPrivateIPv6(String ipAddress) { 110 | boolean isPrivateIPv6 = false; 111 | String[] ipParts = ipAddress.trim().split(":"); 112 | if (ipParts.length > 0) { 113 | String firstBlock = ipParts[0]; 114 | String prefix = firstBlock.substring(0, 2); 115 | 116 | if (firstBlock.equalsIgnoreCase("fe80") 117 | || firstBlock.equalsIgnoreCase("100") 118 | || ((prefix.equalsIgnoreCase("fc") && firstBlock.length() >= 4)) 119 | || ((prefix.equalsIgnoreCase("fd") && firstBlock.length() >= 4))) { 120 | isPrivateIPv6 = true; 121 | } 122 | } 123 | return isPrivateIPv6; 124 | } 125 | 126 | public static ArrayList regexFind(String regex,String content) { 127 | ArrayList result = new ArrayList(); 128 | Pattern pRegex = Pattern.compile(regex); 129 | Matcher matcher = pRegex.matcher(content); 130 | while (matcher.find()) {//多次查找 131 | result.add(matcher.group()); 132 | } 133 | return result; 134 | } 135 | 136 | public static String replaceLast(String string, String toReplace, String replacement) { 137 | int pos = string.lastIndexOf(toReplace); 138 | if (pos > -1) { 139 | return string.substring(0, pos) 140 | + replacement 141 | + string.substring(pos + toReplace.length()); 142 | } else { 143 | return string; 144 | } 145 | } 146 | 147 | /** 148 | * byte[]数组截取 149 | * srcPoC 是原数组的起始位置,length是要截取的长度 150 | * 151 | */ 152 | public byte[] subByte(byte[] b,int srcPos,int length){ 153 | byte[] b1 = new byte[length]; 154 | System.arraycopy(b, srcPos, b1, 0, length); 155 | return b1; 156 | } 157 | 158 | 159 | public static String cleanDomain(String domain) { 160 | if (domain == null){ 161 | return null; 162 | } 163 | domain = domain.toLowerCase().trim(); 164 | if (domain.startsWith("http://")|| domain.startsWith("https://")) { 165 | try { 166 | domain = new URL(domain).getHost(); 167 | } catch (MalformedURLException e) { 168 | return null; 169 | } 170 | }else { 171 | if (domain.contains(":")) {//处理带有端口号的域名 172 | domain = domain.substring(0,domain.indexOf(":")); 173 | } 174 | } 175 | 176 | if (domain.endsWith(".")) { 177 | domain = domain.substring(0,domain.length()-1); 178 | } 179 | 180 | return domain; 181 | } 182 | 183 | public static Set grepDomain(String httpResponse) { 184 | httpResponse = httpResponse.toLowerCase(); 185 | //httpResponse = cleanResponse(httpResponse); 186 | Set domains = new HashSet<>(); 187 | //"^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$" 188 | final String DOMAIN_NAME_PATTERN = "([A-Za-z0-9-*]{1,63}(? grepURL(String httpResponse) { 210 | httpResponse = httpResponse.toLowerCase(); 211 | Set URLs = new HashSet<>(); 212 | 213 | String[] lines = httpResponse.split("\r\n"); 214 | 215 | Pattern pt = Pattern.compile(URL_Regex); 216 | for (String line:lines) {//分行进行提取,似乎可以提高成功率?PATH_AND_QUERY 217 | Matcher matcher = pt.matcher(line); 218 | while (matcher.find()) {//多次查找 219 | String url = matcher.group(); 220 | URLs.add(url); 221 | } 222 | } 223 | 224 | List tmplist= new ArrayList<>(URLs); 225 | return tmplist; 226 | } 227 | 228 | public static List grepIP(String httpResponse) { 229 | Set IPSet = new HashSet<>(); 230 | String[] lines = httpResponse.split("\r\n"); 231 | 232 | Pattern pt = Pattern.compile(IP_ADDRESS_STRING); 233 | for (String line:lines) { 234 | Matcher matcher = pt.matcher(line); 235 | while (matcher.find()) {//多次查找 236 | String tmpIP = matcher.group(); 237 | IPSet.add(tmpIP); 238 | } 239 | } 240 | 241 | List tmplist= new ArrayList<>(IPSet); 242 | Collections.sort(tmplist); 243 | return tmplist; 244 | } 245 | 246 | public static List grepIPAndPort(String httpResponse) { 247 | Set IPSet = new HashSet<>(); 248 | String[] lines = httpResponse.split("\r\n"); 249 | 250 | for (String line:lines) { 251 | String pattern = "\\d{1,3}(?:\\.\\d{1,3}){3}(?::\\d{1,5})?"; 252 | Pattern pt = Pattern.compile(pattern); 253 | Matcher matcher = pt.matcher(line); 254 | while (matcher.find()) {//多次查找 255 | String tmpIP = matcher.group(); 256 | IPSet.add(tmpIP); 257 | } 258 | } 259 | 260 | List tmplist= new ArrayList<>(IPSet); 261 | Collections.sort(tmplist); 262 | return tmplist; 263 | } 264 | 265 | @Deprecated //从burp的Email addresses disclosed这个issue中提取,废弃这个 266 | public static Set grepEmail(String httpResponse) { 267 | Set Emails = new HashSet<>(); 268 | final String REGEX_EMAIL = "[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+"; 269 | 270 | Pattern pDomainNameOnly = Pattern.compile(REGEX_EMAIL); 271 | Matcher matcher = pDomainNameOnly.matcher(httpResponse); 272 | while (matcher.find()) {//多次查找 273 | Emails.add(matcher.group()); 274 | System.out.println(matcher.group()); 275 | } 276 | 277 | return Emails; 278 | } 279 | 280 | /** 281 | * 获取随机字符串 282 | * @param length 283 | * @return 284 | */ 285 | public static String getRandomString(int length) { 286 | String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; 287 | Random random = new Random(); 288 | char[] text = new char[length]; 289 | for (int i = 0; i < length; i++) { 290 | text[i] = str.charAt(random.nextInt(str.length())); 291 | } 292 | return new String(text); 293 | } 294 | 295 | public static String getSystemCharSet() { 296 | return Charset.defaultCharset().toString(); 297 | 298 | //System.out.println(System.getProperty("file.encoding")); 299 | } 300 | 301 | public static Long getTimestamp(Date date){ 302 | if (null == date) { 303 | return (long) 0; 304 | } 305 | return date.getTime(); 306 | } 307 | 308 | /* 309 | * 标准的时间格式要求 2020-12-11 12:00:00 310 | * 效果如同 https://tool.lu/timestamp/ 311 | */ 312 | public static Long getTimestamp(String date) throws Exception{ 313 | if (null == date) { 314 | return (long) 0; 315 | } 316 | DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 317 | return dateFormat.parse(date).getTime(); 318 | } 319 | 320 | public static String timeStr() { 321 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式 322 | String time = df.format(new Date());// new Date()为获取当前系统时间 323 | return time; 324 | } 325 | 326 | public static String timePlusOrSub(long sec) { 327 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式 328 | String time = df.format(new Date(new Date().getTime() + sec * 1000));// new Date()为获取当前系统时间 329 | return time; 330 | } 331 | 332 | /** 333 | * 字符串转unicode 334 | * 335 | * @param str 336 | * @return 337 | */ 338 | public static String stringToUnicode(String str) { 339 | StringBuffer sb = new StringBuffer(); 340 | char[] c = str.toCharArray(); 341 | for (int i = 0; i < c.length; i++) { 342 | sb.append("\\u" + Integer.toHexString(c[i])); 343 | } 344 | return sb.toString(); 345 | } 346 | 347 | /** 348 | * unicode转字符串 349 | * 350 | * @param unicode 351 | * @return 352 | */ 353 | public static String unicodeToString(String unicode) { 354 | StringBuffer sb = new StringBuffer(); 355 | String[] hex = unicode.split("\\\\u"); 356 | for (int i = 1; i < hex.length; i++) { 357 | int index = Integer.parseInt(hex[i], 16); 358 | sb.append((char) index); 359 | } 360 | return sb.toString(); 361 | } 362 | 363 | /** 364 | * 将10进制转换为16进制 365 | * @param decimal 10进制 366 | * @return 16进制 367 | */ 368 | public static String decimalToHex(int decimal) { 369 | String hex = Integer.toHexString(decimal); 370 | return hex.toUpperCase(); 371 | } 372 | 373 | public static boolean isNumeric(String str){ 374 | for(int i=str.length();--i>=0;){ 375 | int chr=str.charAt(i); 376 | if(chr<48 || chr>57) { 377 | return false; 378 | } 379 | } 380 | return true; 381 | } 382 | 383 | /* 384 | *将形如 https://www.runoob.com的URL统一转换为 385 | * https://www.runoob.com:443/ 386 | * 387 | * 因为末尾的斜杠,影响URL类的equals的结果。 388 | * 而默认端口影响String格式的对比结果。 389 | */ 390 | 391 | public static String formateURLString(String urlString) { 392 | try { 393 | //urlString = "https://www.runoob.com"; 394 | URL url = new URL(urlString); 395 | String host = url.getHost(); 396 | int port = url.getPort(); 397 | String path = url.getPath(); 398 | 399 | if (port == -1) { 400 | String newHost = url.getHost()+":"+url.getDefaultPort(); 401 | urlString = urlString.replace(host, newHost); 402 | } 403 | 404 | if (path.equals("")) { 405 | urlString = urlString+"/"; 406 | } 407 | } catch (MalformedURLException e) { 408 | e.printStackTrace(); 409 | } 410 | return urlString; 411 | } 412 | 413 | /** 414 | * baseUrl格式:https://www.runoob.com 415 | * @param urlString 416 | * @return 417 | */ 418 | public static String getBaseUrl(String urlString) { 419 | try { 420 | //urlString = "https://www.runoob.com"; 421 | URL url = new URL(urlString); 422 | String procotol = url.getProtocol(); 423 | String host = url.getHost(); 424 | int port = url.getPort(); 425 | 426 | if (port == -1) { 427 | port = url.getDefaultPort(); 428 | } 429 | return procotol+"://"+host+":"+port; 430 | } catch (MalformedURLException e) { 431 | e.printStackTrace(); 432 | return urlString; 433 | } 434 | } 435 | 436 | 437 | public static List removePrefixAndSuffix(List input,String Prefix,String Suffix) { 438 | ArrayList result = new ArrayList(); 439 | if (Prefix == null && Suffix == null) { 440 | return result; 441 | } else { 442 | if (Prefix == null) { 443 | Prefix = ""; 444 | } 445 | 446 | if (Suffix == null) { 447 | Suffix = ""; 448 | } 449 | 450 | List content = input; 451 | for (String item:content) { 452 | if (item.startsWith(Prefix)) { 453 | //https://stackoverflow.com/questions/17225107/convert-java-string-to-string-compatible-with-a-regex-in-replaceall 454 | String tmp = Pattern.quote(Prefix);//自动实现正则转义 455 | item = item.replaceFirst(tmp, ""); 456 | } 457 | if (item.endsWith(Suffix)) { 458 | String tmp = Pattern.quote(reverse(Suffix));//自动实现正则转义 459 | item = reverse(item).replaceFirst(tmp, ""); 460 | item = reverse(item); 461 | } 462 | result.add(item); 463 | } 464 | return result; 465 | } 466 | } 467 | 468 | public static String reverse(String str) { 469 | if (str == null) { 470 | return null; 471 | } 472 | return new StringBuffer(str).reverse().toString(); 473 | } 474 | 475 | /** 476 | * 拼接多个byte[]数组的方法 477 | * @param arrays 478 | * @return 479 | */ 480 | public static byte[] join(byte[]... arrays) 481 | { 482 | int len = 0; 483 | for (byte[] arr : arrays) 484 | { 485 | len += arr.length;//计算多个数组的长度总和 486 | } 487 | 488 | byte[] result = new byte[len]; 489 | int idx = 0; 490 | 491 | for (byte[] arr : arrays) 492 | { 493 | for (byte b : arr) 494 | { 495 | result[idx++] = b; 496 | } 497 | } 498 | 499 | return result; 500 | } 501 | 502 | 503 | /** 504 | * https://stackoverflow.com/questions/21341027/find-indexof-a-byte-array-within-another-byte-array 505 | * Search the data byte array for the first occurrence 506 | * of the byte array pattern. 507 | */ 508 | public static int BytesIndexOf(byte[] data, byte[] pattern) { 509 | int[] failure = computeFailure(pattern); 510 | 511 | int j = 0; 512 | 513 | for (int i = 0; i < data.length; i++) { 514 | while (j > 0 && pattern[j] != data[i]) { 515 | j = failure[j - 1]; 516 | } 517 | if (pattern[j] == data[i]) { 518 | j++; 519 | } 520 | if (j == pattern.length) { 521 | return i - pattern.length + 1; 522 | } 523 | } 524 | return -1; 525 | } 526 | 527 | /** 528 | * Computes the failure function using a boot-strapping process, 529 | * where the pattern is matched against itself. 530 | */ 531 | private static int[] computeFailure(byte[] pattern) { 532 | int[] failure = new int[pattern.length]; 533 | 534 | int j = 0; 535 | for (int i = 1; i < pattern.length; i++) { 536 | while (j>0 && pattern[j] != pattern[i]) { 537 | j = failure[j - 1]; 538 | } 539 | if (pattern[j] == pattern[i]) { 540 | j++; 541 | } 542 | failure[i] = j; 543 | } 544 | 545 | return failure; 546 | } 547 | 548 | 549 | public static List allIndexesOf(String word,String guess) { 550 | List result = new ArrayList(); 551 | int index = word.indexOf(guess); 552 | while (index >= 0) { 553 | result.add(index); 554 | index = word.indexOf(guess, index + 1); 555 | } 556 | return result; 557 | } 558 | 559 | public static void test() { 560 | // test IPv4 561 | String ipv4Address = "127.56.87.4"; 562 | 563 | if (isPrivateIPv4(ipv4Address)) { 564 | System.out.println("This is a private IPv4"); 565 | } 566 | 567 | // test IPv6 568 | String ipv6Address = "fe80:db8:a0b:12f0::1"; 569 | 570 | if (isPrivateIPv6(ipv6Address)) { 571 | System.out.println("This is a private IPv6"); 572 | } 573 | } 574 | 575 | public static void main(String[] args) { 576 | System.out.println(URL_Regex); 577 | } 578 | } 579 | -------------------------------------------------------------------------------- /src/main/java/burp/HelperPlus.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URI; 5 | import java.net.URISyntaxException; 6 | import java.net.URL; 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.Iterator; 10 | import java.util.List; 11 | 12 | /** 13 | * source code: https://github.com/bit4woo/burp-api-common/blob/master/src/main/java/burp/HelperPlus.java 14 | * author: bit4woo 15 | * github: https://github.com/bit4woo 16 | * 17 | * String getHeadersAsStr(boolean isRequest,byte[] requestOrResponse) 18 | * String getHeadersAsStr(boolean messageIsRequest,IHttpRequestResponse messageInfo) 19 | * getHeaderList 20 | * getHeaderLine 21 | * getHeaderValueOf 22 | * 23 | * addOrUpdateHeaderList 24 | * removeHeaderList 25 | * 26 | * getBody 27 | * updateBoby #将body看做一个整体进行替换 28 | * 29 | * shorturl 30 | * url 31 | * protocol 32 | * host 33 | * port 34 | * 35 | * getParameters 36 | * addParameter --Helper中已经存在 37 | * byte[] addParameter(byte[] request, IParameter parameter); 38 | * byte[] removeParameter(byte[] request, IParameter parameter); 39 | * byte[] updateParameter(byte[] request, IParameter parameter); 40 | * Paras 41 | * 42 | * method 43 | * statusCode 44 | * 45 | * 46 | */ 47 | 48 | public class HelperPlus{ 49 | private static IExtensionHelpers helpers; 50 | private final static String Header_Spliter = ":"; 51 | private final static String Header_Connector = ": ";//contains space 52 | private final static String Header_firstLine_Spliter = " "; 53 | 54 | public HelperPlus(IExtensionHelpers helpers) { 55 | HelperPlus.helpers = helpers; 56 | } 57 | /** 58 | * 返回HTTP请求或响应的整个header头部分,与body相对应 59 | */ 60 | public String getHeadersAsStr(boolean isRequest,byte[] requestOrResponse) { 61 | if (requestOrResponse == null){ 62 | return null; 63 | } 64 | int bodyOffset = -1; 65 | if(isRequest) { 66 | IRequestInfo analyzeRequest = helpers.analyzeRequest(requestOrResponse); 67 | bodyOffset = analyzeRequest.getBodyOffset(); 68 | }else { 69 | IResponseInfo analyzeResponse = helpers.analyzeResponse(requestOrResponse); 70 | bodyOffset = analyzeResponse.getBodyOffset(); 71 | } 72 | byte[] byte_header = Arrays.copyOfRange(requestOrResponse,0,bodyOffset);//not length-1 73 | return new String(byte_header); 74 | } 75 | 76 | /** 77 | * 返回HTTP请求或响应的整个header头部分,与body相对应 78 | */ 79 | public String getHeadersAsStr(boolean messageIsRequest,IHttpRequestResponse messageInfo) { 80 | if (messageInfo == null){ 81 | return null; 82 | } 83 | byte[] requestOrResponse = null; 84 | if(messageIsRequest) { 85 | requestOrResponse = messageInfo.getRequest(); 86 | }else { 87 | requestOrResponse = messageInfo.getResponse(); 88 | } 89 | return getHeadersAsStr(messageIsRequest, requestOrResponse); 90 | } 91 | 92 | /** 93 | * 获取header的字符串数组,是构造burp中请求需要的格式。 94 | * return headers list 95 | */ 96 | public List getHeaderList(boolean messageIsRequest,IHttpRequestResponse messageInfo) { 97 | if (null == messageInfo) { 98 | return new ArrayList<>(); 99 | } 100 | byte[] requestOrResponse; 101 | if(messageIsRequest) { 102 | requestOrResponse = messageInfo.getRequest(); 103 | }else { 104 | requestOrResponse = messageInfo.getResponse(); 105 | } 106 | return getHeaderList(messageIsRequest,requestOrResponse); 107 | } 108 | 109 | /** 110 | * 获取请求包或者响应包中的header List 111 | */ 112 | public List getHeaderList(boolean IsRequest,byte[] requestOrResponse) { 113 | if (null == requestOrResponse) { 114 | return new ArrayList<>(); 115 | } 116 | if(IsRequest) { 117 | IRequestInfo analyzeRequest = helpers.analyzeRequest(requestOrResponse); 118 | List headers = analyzeRequest.getHeaders(); 119 | return headers; 120 | }else { 121 | IResponseInfo analyzeResponse = helpers.analyzeResponse(requestOrResponse); 122 | List headers = analyzeResponse.getHeaders(); 123 | return headers; 124 | } 125 | } 126 | 127 | /** 128 | * 新增或更新header 129 | */ 130 | public static List addOrUpdateHeader(List headers,String headerName,String headerValue) { 131 | for (String header:headers) { 132 | if (header.contains(":")) { 133 | try { 134 | String headerNameOrigin = header.split(Header_Spliter, 2)[0].trim();//这里的limit=2 可以理解成分割成2份,否则referer可能别分成3份 135 | if (headerNameOrigin.equalsIgnoreCase(headerName)) { 136 | int index = headers.indexOf(header); 137 | headers.remove(header); 138 | headers.add(index, headerName+Header_Connector+headerValue); 139 | return headers; 140 | } 141 | }catch (Exception e) { 142 | 143 | } 144 | } 145 | } 146 | headers.add(headerName+Header_Connector+headerValue); 147 | return headers; 148 | } 149 | 150 | /** 151 | * 新增或更新header 152 | */ 153 | public IHttpRequestResponse addOrUpdateHeader(boolean messageIsRequest,IHttpRequestResponse messageInfo,String headerName,String headerValue){ 154 | List headers = getHeaderList(messageIsRequest,messageInfo); 155 | byte[] body = getBody(messageIsRequest,messageInfo); 156 | headers = addOrUpdateHeader(headers,headerName,headerValue); 157 | byte[] RequestOrResponse = helpers.buildHttpMessage(headers, body); 158 | if (messageIsRequest) { 159 | messageInfo.setRequest(RequestOrResponse); 160 | }else { 161 | messageInfo.setResponse(RequestOrResponse); 162 | } 163 | return messageInfo; 164 | } 165 | 166 | /** 167 | * 新增或更新header 168 | */ 169 | public byte[] addOrUpdateHeader(boolean isRequest,byte[] requestOrResponse,String headerName,String headerValue){ 170 | List headers = getHeaderList(isRequest,requestOrResponse); 171 | byte[] body = getBody(isRequest,requestOrResponse); 172 | headers = addOrUpdateHeader(headers,headerName,headerValue); 173 | return helpers.buildHttpMessage(headers, body); 174 | } 175 | 176 | /** 177 | * 删除header 178 | */ 179 | public static List removeHeader(List headers,String headerNameOrHeaderLine) { 180 | Iterator it = headers.iterator(); 181 | while(it.hasNext()) { 182 | String header = it.next(); 183 | String headerName = header.split(Header_Spliter, 2)[0].trim(); 184 | if (header.toLowerCase().startsWith(headerNameOrHeaderLine.toLowerCase().trim()) 185 | && headerNameOrHeaderLine.length() >= headerName.length()) { 186 | it.remove(); 187 | } 188 | } 189 | return headers; 190 | } 191 | 192 | /** 193 | * 删除header 194 | */ 195 | public IHttpRequestResponse removeHeader(boolean messageIsRequest,IHttpRequestResponse messageInfo,String headerNameOrHeaderLine){ 196 | List headers = getHeaderList(messageIsRequest,messageInfo); 197 | byte[] body = getBody(messageIsRequest,messageInfo); 198 | headers = removeHeader(headers,headerNameOrHeaderLine); 199 | byte[] RequestOrResponse = helpers.buildHttpMessage(headers, body); 200 | if (messageIsRequest) { 201 | messageInfo.setRequest(RequestOrResponse); 202 | }else { 203 | messageInfo.setResponse(RequestOrResponse); 204 | } 205 | return messageInfo; 206 | } 207 | 208 | /** 209 | * 删除特定的header。 210 | */ 211 | public byte[] removeHeader(boolean isRequest,byte[] requestOrResponse, String headerNameOrHeaderLine) { 212 | List headers = getHeaderList(isRequest,requestOrResponse); 213 | byte[] body = getBody(isRequest,requestOrResponse); 214 | headers = removeHeader(headers,headerNameOrHeaderLine); 215 | return helpers.buildHttpMessage(headers, body); 216 | } 217 | 218 | 219 | /** 220 | * 获取某个header的整行,如果没有此header,返回null,以header的名称作为查找依据。 221 | */ 222 | public static String getHeaderLine(List headers,String headerName) { 223 | if (null ==headers || headerName ==null) return null; 224 | for (String header:headers) { 225 | if (header.contains(":")) { 226 | try { 227 | String headerNameOrigin = header.split(Header_Spliter, 2)[0].trim();//这里的limit=2 可以理解成分割成2份,否则referer可能别分成3份 228 | if (headerNameOrigin.equalsIgnoreCase(headerName)) { 229 | return header; 230 | } 231 | }catch (Exception e) { 232 | 233 | } 234 | } 235 | } 236 | return null; 237 | } 238 | 239 | /** 240 | * 获取某个header的整行,如果没有此header,返回null,以header的名称作为查找依据。 241 | */ 242 | public String getHeaderLine(boolean messageIsRequest,IHttpRequestResponse messageInfo, String headerName) { 243 | List headers = getHeaderList(messageIsRequest,messageInfo); 244 | return getHeaderLine(headers,headerName); 245 | } 246 | 247 | /** 248 | * 获取某个header的整行,如果没有此header,返回null,以header的名称作为查找依据。 249 | */ 250 | public String getHeaderLine(boolean messageIsRequest,byte[] requestOrResponse, String headerName) { 251 | List headers=getHeaderList(messageIsRequest,requestOrResponse); 252 | return getHeaderLine(headers,headerName); 253 | } 254 | 255 | /** 256 | * 获取某个header的值,如果没有此header,返回null。 257 | */ 258 | public static String getHeaderValueOf(List headers,String headerName) { 259 | if (null ==headers || headerName ==null) return null; 260 | for (String header:headers) { 261 | if (header.contains(":")) { 262 | try { 263 | String headerNameOrigin = header.split(Header_Spliter, 2)[0].trim();//这里的limit=2 可以理解成分割成2份,否则referer可能别分成3份 264 | String headerValue = header.split(Header_Spliter, 2)[1].trim(); 265 | if (headerNameOrigin.equalsIgnoreCase(headerName)) { 266 | return headerValue; 267 | } 268 | }catch (Exception e) { 269 | 270 | } 271 | } 272 | } 273 | return null; 274 | } 275 | 276 | /** 277 | * 获取某个header的值,如果没有此header,返回null。 278 | */ 279 | public String getHeaderValueOf(boolean messageIsRequest,IHttpRequestResponse messageInfo, String headerName) { 280 | List headers = getHeaderList(messageIsRequest,messageInfo); 281 | return getHeaderValueOf(headers,headerName); 282 | } 283 | 284 | /** 285 | * 获取某个header的值,如果没有此header,返回null。 286 | */ 287 | public String getHeaderValueOf(boolean messageIsRequest,byte[] requestOrResponse, String headerName) { 288 | List headers=getHeaderList(messageIsRequest,requestOrResponse); 289 | return getHeaderValueOf(headers,headerName); 290 | } 291 | 292 | /** 293 | * 获取数据包的body 294 | */ 295 | public static byte[] getBody(boolean isRequest,byte[] requestOrResponse) { 296 | if (requestOrResponse == null){ 297 | return null; 298 | } 299 | int bodyOffset = -1; 300 | 301 | if (helpers != null) { 302 | if(isRequest) { 303 | IRequestInfo analyzeRequest = helpers.analyzeRequest(requestOrResponse); 304 | bodyOffset = analyzeRequest.getBodyOffset(); 305 | }else { 306 | IResponseInfo analyzeResponse = helpers.analyzeResponse(requestOrResponse); 307 | bodyOffset = analyzeResponse.getBodyOffset(); 308 | } 309 | }else { 310 | bodyOffset = Common.BytesIndexOf("\r\n\r\n".getBytes(), requestOrResponse); 311 | bodyOffset = bodyOffset+4; 312 | } 313 | byte[] byte_body = Arrays.copyOfRange(requestOrResponse, bodyOffset, requestOrResponse.length);//not length-1 314 | //String body = new String(byte_body); //byte[] to String 315 | return byte_body; 316 | } 317 | 318 | /** 319 | * 获取数据包的body 320 | */ 321 | public static byte[] getBody(boolean messageIsRequest,IHttpRequestResponse messageInfo) { 322 | if (messageInfo == null){ 323 | return null; 324 | } 325 | byte[] requestOrResponse = null; 326 | if(messageIsRequest) { 327 | requestOrResponse = messageInfo.getRequest(); 328 | }else { 329 | requestOrResponse = messageInfo.getResponse(); 330 | } 331 | return getBody(messageIsRequest, requestOrResponse); 332 | } 333 | 334 | /** 335 | * 更新数据包的body 336 | */ 337 | public IHttpRequestResponse UpdateBody(boolean messageIsRequest,IHttpRequestResponse messageInfo,byte[] body){ 338 | List headers = getHeaderList(messageIsRequest,messageInfo); 339 | byte[] RequestOrResponse = helpers.buildHttpMessage(headers, body); 340 | if (messageIsRequest) { 341 | messageInfo.setRequest(RequestOrResponse); 342 | }else { 343 | messageInfo.setResponse(RequestOrResponse); 344 | } 345 | return messageInfo; 346 | } 347 | 348 | /** 349 | * 更新数据包的body 350 | */ 351 | public byte[] UpdateBody(boolean isRequest,byte[] requestOrResponse,byte[] body){ 352 | List headers = getHeaderList(isRequest,requestOrResponse); 353 | return helpers.buildHttpMessage(headers, body); 354 | } 355 | 356 | /** 357 | * return Type is URL,not String. 358 | * use equal() function to compare URL object. 359 | * the string contains default port or not both OK, but the path(/) is sensitive 360 | * URL对象可以用它自己提供的equal()函数进行对比,是否包含默认端口都是没有关系的。但最后的斜杠path却是有关系的。 361 | * 362 | * result example: 363 | * 364 | * eg. http://bit4woo.com/ 不包含默认端口;包含默认path(/) 365 | * 是符合通常浏览器中使用格式的 366 | */ 367 | public static URL getShortURL(IHttpRequestResponse messageInfo){ 368 | if (null == messageInfo) return null; 369 | IHttpService service = messageInfo.getHttpService(); 370 | //String shortUrlString = messageInfo.getHttpService().toString();//http://www.baidu.com 371 | //新版本burp中,API发生了变化,返回结果是这种burp.Ze6r@7f06cf44/ 372 | 373 | String shortUrlString = getShortURL(service); 374 | try { 375 | return new URL(shortUrlString); 376 | } catch (MalformedURLException e) { 377 | e.printStackTrace(); 378 | return null; 379 | } 380 | } 381 | 382 | public static String getShortURL(IHttpService service){ 383 | //String shortUrlString = messageInfo.getHttpService().toString();//http://www.baidu.com 384 | //新版本burp中,API发生了变化,返回结果是这种burp.Ze6r@7f06cf44/ 385 | if (service ==null){ 386 | return null; 387 | } 388 | String shortUrlString = service.getProtocol()+"://"+service.getHost()+":"+service.getPort()+"/"; 389 | shortUrlString = removeDefaultPort(shortUrlString); 390 | return shortUrlString; 391 | } 392 | 393 | /** 394 | * return Type is URL,not String. 395 | * use equal() function to compare URL object. 396 | * the string contains default port or not both OK, but the path(/) is sensitive 397 | * URL对象可以用它自己提供的equal()函数进行对比,是否包含默认端口都是没有关系的。但最后的斜杠path却是有关系的。 398 | * 399 | * result example: 400 | * 401 | * eg. http://bit4woo.com:80/ 包含默认端口和默认path(/) 402 | * @param messageInfo 403 | * @return 404 | */ 405 | public static URL getShortURLWithDefaultPort(IHttpRequestResponse messageInfo){ 406 | if (null == messageInfo) return null; 407 | IHttpService service = messageInfo.getHttpService(); 408 | //String shortUrlString = messageInfo.getHttpService().toString();//http://www.baidu.com 409 | //新版本burp中,API发生了变化,返回结果是这种burp.Ze6r@7f06cf44/ 410 | String shortUrlString = getShortURL(service); 411 | shortUrlString = formateURLString(shortUrlString); 412 | try { 413 | return new URL(shortUrlString); 414 | } catch (MalformedURLException e) { 415 | e.printStackTrace(); 416 | return null; 417 | } 418 | } 419 | 420 | 421 | /** 422 | * return Type is URL,not String. 423 | * use equal() function to compare URL object. the string contains default port or not both OK, but the path(/) is sensitive 424 | * URL对象可以用它自己提供的equal()函数进行对比,是否包含默认端口都是没有关系的。但最后的斜杠path却是有关系的。 425 | * 426 | * 不包含默认端口的URL格式,符合通常浏览器中的格式 427 | * http://bit4woo.com/test.html#123 428 | */ 429 | public final URL getFullURL(IHttpRequestResponse messageInfo){ 430 | if (null == messageInfo) return null; 431 | IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo); 432 | String tmpurl = analyzeRequest.getUrl().toString(); 433 | tmpurl = removeDefaultPort(tmpurl); 434 | try { 435 | URL url = new URL(tmpurl); 436 | return url; 437 | } catch (MalformedURLException e) { 438 | e.printStackTrace(); 439 | return null; 440 | } 441 | } 442 | 443 | /** 444 | * return Type is URL,not String. 445 | * use equal() function to compare URL object. the string contains default port or not both OK, but the path(/) is sensitive 446 | * URL对象可以用它自己提供的equal()函数进行对比,是否包含默认端口都是没有关系的。但最后的斜杠path却是有关系的。 447 | * 448 | * 这个函数的返回结果转换成字符串是包含了默认端口的。 449 | * http://bit4woo.com:80/test.html#123 450 | */ 451 | public final URL getFullURLWithDefaultPort(IHttpRequestResponse messageInfo){ 452 | if (null == messageInfo) return null; 453 | IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo); 454 | return analyzeRequest.getUrl(); 455 | } 456 | 457 | 458 | /** 459 | * to let url String contains default port(80\443) and default path(/) 460 | * 461 | * from: http://bit4woo.com 462 | * to : http://bit4woo.com:80/ 463 | */ 464 | @Deprecated 465 | public static String formateURLString(String urlString) { 466 | return addDefaultPort(urlString); 467 | } 468 | 469 | /** 470 | * 对URL添加默认端口。 471 | * burp中获取到的URL是包含默认端口的,但是平常浏览器中的URL格式都是不包含默认端口的。 472 | * 应该尽量和平常使用习惯保存一致!所以尽量避免使用该函数。 473 | * @param urlString 474 | * @return 475 | */ 476 | public static String addDefaultPort(String urlString) { 477 | try { 478 | //urlString = "https://www.runoob.com"; 479 | URL url = new URL(urlString); 480 | String host = url.getHost(); 481 | int port = url.getPort(); 482 | String path = url.getPath(); 483 | 484 | if (port == -1) { 485 | String newHost = url.getHost()+":"+url.getDefaultPort(); 486 | urlString = urlString.replaceFirst(host, newHost); 487 | } 488 | 489 | if (path.equals("")) { 490 | urlString = urlString+"/"; 491 | } 492 | return new URL(urlString).toString(); 493 | } catch (MalformedURLException e) { 494 | e.printStackTrace(); 495 | return urlString; 496 | } 497 | } 498 | 499 | // 添加默认端口的方法 500 | public static String getUrlWithDefaultPort(String url) { 501 | try { 502 | URI uri = new URI(url); 503 | 504 | // 如果URL中没有明确指定端口,且协议为http,则添加默认端口80 505 | if (uri.getPort() == -1 ) { 506 | if ("http".equalsIgnoreCase(uri.getScheme())) { 507 | return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), 80, uri.getPath(), uri.getQuery(), uri.getFragment()).toString(); 508 | } 509 | if ("https".equalsIgnoreCase(uri.getScheme())) { 510 | return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), 443, uri.getPath(), uri.getQuery(), uri.getFragment()).toString(); 511 | } 512 | } 513 | // 其他情况直接返回原始URL 514 | return url; 515 | } catch (URISyntaxException e) { 516 | // 处理URI语法错误 517 | e.printStackTrace(); 518 | return url; 519 | } 520 | } 521 | 522 | /** 523 | * remove default port(80\443) from the url 524 | * 这个格式和我们平常浏览器中看到的格式才是一致的,符合使用习惯 525 | * 526 | * from: http://bit4woo.com:80/ 527 | * to : http://bit4woo.com/ 528 | */ 529 | public static String removeDefaultPort(String urlString) { 530 | try { 531 | //urlString = "https://www.runoob.com"; 532 | URL url = new URL(urlString); 533 | String protocol = url.getProtocol(); 534 | String host = url.getHost(); 535 | int port = url.getPort();//不包含端口时返回-1 536 | String path = url.getPath(); 537 | 538 | if ((port == 80 && protocol.equalsIgnoreCase("http")) 539 | || (port == 443 && protocol.equalsIgnoreCase("https"))) { 540 | String oldHost = url.getHost()+":"+url.getPort(); 541 | urlString = urlString.replaceFirst(oldHost, host); 542 | } 543 | 544 | if (path.equals("")) { 545 | urlString = urlString+"/"; 546 | } 547 | return new URL(urlString).toString(); 548 | } catch (MalformedURLException e) { 549 | e.printStackTrace(); 550 | return urlString; 551 | } 552 | } 553 | 554 | public static String getHost(IHttpRequestResponse messageInfo) { 555 | return messageInfo.getHttpService().getHost(); 556 | } 557 | 558 | public static String getProtocol(IHttpRequestResponse messageInfo) { 559 | return messageInfo.getHttpService().getProtocol(); 560 | } 561 | 562 | public static int getPort(IHttpRequestResponse messageInfo) { 563 | return messageInfo.getHttpService().getPort(); 564 | } 565 | 566 | public short getStatusCode(IHttpRequestResponse messageInfo) { 567 | if (messageInfo == null || messageInfo.getResponse() == null) { 568 | return -1; 569 | } 570 | IResponseInfo analyzedResponse = helpers.analyzeResponse(messageInfo.getResponse()); 571 | return analyzedResponse.getStatusCode(); 572 | } 573 | 574 | public short getStatusCode(byte[] response) { 575 | if (response == null) { 576 | return -1; 577 | } 578 | try { 579 | IResponseInfo analyzedResponse = helpers.analyzeResponse(response); 580 | return analyzedResponse.getStatusCode(); 581 | } catch (Exception e) { 582 | return -1; 583 | } 584 | } 585 | 586 | 587 | 588 | public List getParameters(IHttpRequestResponse messageInfo){ 589 | IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo); 590 | return analyzeRequest.getParameters(); 591 | } 592 | 593 | public List getParameters(byte[] request){ 594 | IRequestInfo analyzeRequest = helpers.analyzeRequest(request); 595 | return analyzeRequest.getParameters(); 596 | } 597 | 598 | 599 | /** 600 | * 使用burp.IExtensionHelpers.getRequestParameter(byte[], String),未考虑同名参数的情况! 601 | */ 602 | public IParameter getParameterByKey(IHttpRequestResponse messageInfo,String key){ 603 | return helpers.getRequestParameter(messageInfo.getRequest(), key); 604 | } 605 | 606 | public IParameter getParameterByKey(byte[] request,String key){ 607 | return helpers.getRequestParameter(request, key); 608 | } 609 | 610 | 611 | /** 612 | * 根据参数的key查找IParameter对象,考虑了同名函数的情况,但这种情况很少,几乎用不上。 613 | * 尽量不要使用这个函数 614 | */ 615 | @Deprecated 616 | public static List findParametersByKey(List parameters,String key){ 617 | List result = new ArrayList(); 618 | for (IParameter para:parameters) { 619 | if (para.getName().equalsIgnoreCase(key)){ 620 | result.add(para); 621 | } 622 | } 623 | return result; 624 | } 625 | 626 | /** 627 | * 根据参数的key和type查找IParameter对象 628 | * 考虑了同名函数的情况,但这种情况很少,几乎用不上 629 | * 尽量不要使用这个函数 630 | */ 631 | @Deprecated 632 | public static List findParametersByKeyAndType(List parameters,String key,byte type){ 633 | List result = new ArrayList(); 634 | for (IParameter para:parameters) { 635 | if (para.getName().equalsIgnoreCase(key) && para.getType() == type){ 636 | result.add(para); 637 | } 638 | } 639 | return result; 640 | } 641 | 642 | /** 643 | * 考虑了同名函数的情况,但这种情况很少,几乎用不上 644 | * 尽量不要使用这个函数 645 | */ 646 | @Deprecated 647 | public List getParametersByKeyAndType(IHttpRequestResponse messageInfo,String key,byte type){ 648 | IRequestInfo analyzeRequest = helpers.analyzeRequest(messageInfo); 649 | List paras = analyzeRequest.getParameters(); 650 | return findParametersByKeyAndType(paras,key,type); 651 | } 652 | 653 | /** 654 | * 考虑了同名函数的情况,但这种情况很少,几乎用不上 655 | * 尽量不要使用这个函数 656 | */ 657 | @Deprecated 658 | public List getParametersByKeyAndType(byte[] request,String key,byte type){ 659 | IRequestInfo analyzeRequest = helpers.analyzeRequest(request); 660 | return findParametersByKeyAndType(analyzeRequest.getParameters(),key,type); 661 | } 662 | 663 | 664 | public IHttpRequestResponse addOrUpdateParameter(IHttpRequestResponse messageInfo,IParameter para){ 665 | byte[] request = messageInfo.getRequest(); 666 | request = addOrUpdateParameter(request, para); 667 | messageInfo.setRequest(request); 668 | return messageInfo; 669 | } 670 | 671 | public byte[] addOrUpdateParameter(byte[] request,IParameter para){ 672 | IParameter existPara = helpers.getRequestParameter(request, para.getName()); 673 | if (null != existPara) { 674 | request = helpers.removeParameter(request, existPara); 675 | } 676 | request = helpers.addParameter(request, para); 677 | return request; 678 | } 679 | 680 | public IHttpRequestResponse removeParameter(IHttpRequestResponse messageInfo, IParameter parameter) { 681 | byte[] request = messageInfo.getRequest(); 682 | request = helpers.removeParameter(request, parameter); 683 | messageInfo.setRequest(request); 684 | return messageInfo; 685 | } 686 | 687 | 688 | public String getMethod(IHttpRequestResponse messageInfo){ 689 | if (messageInfo == null || messageInfo.getRequest() == null) { 690 | return null; 691 | } 692 | IRequestInfo analyzedRequest = helpers.analyzeRequest(messageInfo.getRequest()); 693 | return analyzedRequest.getMethod(); 694 | } 695 | 696 | public String getMethod(byte[] request){ 697 | if (request == null) { 698 | return null; 699 | } 700 | try { 701 | IRequestInfo analyzedRequest = helpers.analyzeRequest(request); 702 | return analyzedRequest.getMethod(); 703 | } catch (Exception e) { 704 | return null; 705 | } 706 | } 707 | 708 | public String getHTTPBasicCredentials(IHttpRequestResponse messageInfo) throws Exception{ 709 | String authHeader = getHeaderValueOf(true, messageInfo, "Authorization").trim(); 710 | String[] parts = authHeader.split("\\s"); 711 | 712 | if (parts.length != 2) 713 | throw new Exception("Wrong number of HTTP Authorization header parts"); 714 | 715 | if (!parts[0].equalsIgnoreCase("Basic")) 716 | throw new Exception("HTTP authentication must be Basic"); 717 | 718 | return parts[1]; 719 | } 720 | 721 | private static void test1() { 722 | List headerList = new ArrayList(); 723 | headerList.add("User-Agent: sssss"); 724 | headerList.add("Use: sssss"); 725 | headerList.add("User: sssss"); 726 | headerList.add("Agent: sssss"); 727 | List newHeader = removeHeader(headerList,"Use"); 728 | System.out.println(newHeader.toString()); 729 | newHeader = addOrUpdateHeader(headerList,"Use1","xxxx"); 730 | System.out.println(newHeader.toString()); 731 | } 732 | private static void test2() { 733 | String url = "http://www.baidu.com"; 734 | String url2 = "https://www.baidu.com:443"; 735 | System.out.println(addDefaultPort(url)); 736 | System.out.println(removeDefaultPort(url2)); 737 | System.out.println(removeDefaultPort(url)); 738 | System.out.println(addDefaultPort(url)); 739 | } 740 | public static void main(String args[]) { 741 | test2(); 742 | } 743 | } 744 | --------------------------------------------------------------------------------