├── .gitignore ├── .idea ├── artifacts │ └── passive_scan_client_jar.xml ├── compiler.xml ├── dictionaries │ └── c0ny1.xml ├── jarRepositories.xml ├── libraries │ └── Maven__net_portswigger_burp_extender_burp_extender_api_1_7_22.xml ├── misc.xml ├── modules.xml ├── qaplug_profiles.xml ├── uiDesigner.xml ├── vcs.xml └── workspace.xml ├── README.md ├── doc ├── process.png └── show.gif ├── passive-scan-client.iml ├── pom.xml └── src └── main └── java └── burp ├── BurpExtender.java ├── Config.java ├── GUI.java ├── HttpAndHttpsProxy.java ├── HttpLogTable.java ├── HttpLogTableModel.java ├── LogEntry.java └── Utils.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | *.class 5 | 6 | # Log file 7 | *.log 8 | 9 | # BlueJ files 10 | *.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | .mtj.tmp/ 14 | 15 | # Package Files # 16 | *.jar 17 | *.war 18 | *.nar 19 | *.ear 20 | *.zip 21 | *.tar.gz 22 | *.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | 27 | ### Java template 28 | # Compiled class file 29 | *.class 30 | 31 | # Log file 32 | *.log 33 | 34 | # BlueJ files 35 | *.ctxt 36 | 37 | # Mobile Tools for Java (J2ME) 38 | .mtj.tmp/ 39 | 40 | # Package Files # 41 | *.jar 42 | *.war 43 | *.nar 44 | *.ear 45 | *.zip 46 | *.tar.gz 47 | *.rar 48 | 49 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 50 | hs_err_pid* 51 | 52 | target 53 | out 54 | .DS_Store 55 | .idea/* -------------------------------------------------------------------------------- /.idea/artifacts/passive_scan_client_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/passive_scan_client_jar 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/dictionaries/c0ny1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_portswigger_burp_extender_burp_extender_api_1_7_22.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/qaplug_profiles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 465 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 31 | 32 | 33 | 35 | 36 | 38 | 39 | 46 | 47 | 48 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Abstraction issuesJava 61 | 62 | 63 | AccessibilityLintAndroid 64 | 65 | 66 | Android 67 | 68 | 69 | Assignment issuesGroovy 70 | 71 | 72 | Assignment issuesJava 73 | 74 | 75 | Assignment issuesJavaScript 76 | 77 | 78 | Bitwise operation issuesJava 79 | 80 | 81 | Bitwise operation issuesJavaScript 82 | 83 | 84 | CDI (Contexts and Dependency Injection) 85 | 86 | 87 | CSS 88 | 89 | 90 | Class structureJava 91 | 92 | 93 | Code maturityJava 94 | 95 | 96 | Code quality toolsJavaScript 97 | 98 | 99 | Code style issuesJava 100 | 101 | 102 | CodeSpring CoreSpring 103 | 104 | 105 | CoffeeScript 106 | 107 | 108 | Control flow issuesGroovy 109 | 110 | 111 | Control flow issuesJava 112 | 113 | 114 | Control flow issuesJavaScript 115 | 116 | 117 | CorrectnessLintAndroid 118 | 119 | 120 | DOM issuesJavaScript 121 | 122 | 123 | Declaration redundancyJava 124 | 125 | 126 | ECMAScript 6 migration aidsJavaScript 127 | 128 | 129 | Error handlingJavaScript 130 | 131 | 132 | FreeMarker 133 | 134 | 135 | GPathGroovy 136 | 137 | 138 | General 139 | 140 | 141 | GeneralJava 142 | 143 | 144 | GeneralJavaScript 145 | 146 | 147 | Google App Engine 148 | 149 | 150 | Groovy 151 | 152 | 153 | Guice 154 | 155 | 156 | HTML 157 | 158 | 159 | IconsUsabilityLintAndroid 160 | 161 | 162 | InitializationJava 163 | 164 | 165 | InternationalizationJava 166 | 167 | 168 | InternationalizationLintAndroid 169 | 170 | 171 | J2ME issuesJava 172 | 173 | 174 | JUnitJava 175 | 176 | 177 | Java 178 | 179 | 180 | Java 5Java language level migration aidsJava 181 | 182 | 183 | Java 8Java language level migration aidsJava 184 | 185 | 186 | Java interop issuesKotlin 187 | 188 | 189 | Java language level issuesJava 190 | 191 | 192 | Java language level migration aidsJava 193 | 194 | 195 | JavaScript 196 | 197 | 198 | JavadocJava 199 | 200 | 201 | Kotlin 202 | 203 | 204 | LintAndroid 205 | 206 | 207 | LintLintAndroid 208 | 209 | 210 | LoggingJava 211 | 212 | 213 | MemoryJava 214 | 215 | 216 | MessagesCorrectnessLintAndroid 217 | 218 | 219 | Naming conventionsGroovy 220 | 221 | 222 | Naming conventionsJava 223 | 224 | 225 | Naming conventionsJavaScript 226 | 227 | 228 | Naming conventionsKotlin 229 | 230 | 231 | Numeric issuesJava 232 | 233 | 234 | Other problemsKotlin 235 | 236 | 237 | PerformanceJava 238 | 239 | 240 | PerformanceLintAndroid 241 | 242 | 243 | PortabilityJava 244 | 245 | 246 | Potentially confusing code constructsGroovy 247 | 248 | 249 | Potentially confusing code constructsJavaScript 250 | 251 | 252 | Probable bugsCSS 253 | 254 | 255 | Probable bugsCoffeeScript 256 | 257 | 258 | Probable bugsGroovy 259 | 260 | 261 | Probable bugsJava 262 | 263 | 264 | Probable bugsJavaScript 265 | 266 | 267 | Probable bugsKotlin 268 | 269 | 270 | Properties Files 271 | 272 | 273 | RELAX NG 274 | 275 | 276 | Redundant constructsKotlin 277 | 278 | 279 | Reflective accessJava 280 | 281 | 282 | RegExp 283 | 284 | 285 | SQL 286 | 287 | 288 | SecurityJava 289 | 290 | 291 | SecurityLintAndroid 292 | 293 | 294 | Spring 295 | 296 | 297 | Spring CoreSpring 298 | 299 | 300 | Struts 301 | 302 | 303 | Struts 1Struts 304 | 305 | 306 | Struts 2Struts 307 | 308 | 309 | Style issuesKotlin 310 | 311 | 312 | StyleGroovy 313 | 314 | 315 | Threading issuesJava 316 | 317 | 318 | UI Form 319 | 320 | 321 | UsabilityLintAndroid 322 | 323 | 324 | Velocity 325 | 326 | 327 | Verbose or redundant code constructsJava 328 | 329 | 330 | VisibilityJava 331 | 332 | 333 | WebSocket 334 | 335 | 336 | XPath 337 | 338 | 339 | XSLT 340 | 341 | 342 | 343 | 344 | Android 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 403 | 404 | 409 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 1560504663123 430 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | file://$PROJECT_DIR$/src/main/java/burp/BurpExtender.java 486 | 75 487 | 489 | 490 | 491 | 492 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Passive Scan Client | Burp被动扫描流量转发插件 2 | 3 | 4 | ## 0x01 插件简介 5 | 6 | ``` 7 | Q1: 将浏览器代理到被动扫描器上,访问网站变慢,甚至有时被封ip,这该怎么办? 8 | Q2: 需要人工渗透的同时后台进行被动扫描,到底是代理到burp还是被动扫描器? 9 | Q3: ...... 10 | ``` 11 | 12 | 该插件正是为了解决该问题,将`正常访问网站的流量`与`提交给被动扫描器的流量`分开,互不影响。 13 | 14 | ![流程图](./doc/process.png) 15 | 16 | ## 0x02 插件编译 17 | 18 | ``` 19 | mvn package 20 | ``` 21 | 22 | ## 0x03 插件演示 23 | 24 | 可以通过插件将流量转发到各种被动式扫描器中,这里我选`xray`来演示. 25 | 26 | ![动图演示](./doc/show.gif) 27 | 28 | ## 0x04 一些被动式漏洞扫描器 29 | * [GourdScanV2](https://github.com/ysrc/GourdScanV2) 由ysrc出品的基于sqlmapapi的被动式漏洞扫描器 30 | * [xray](https://github.com/chaitin/xray) 由长亭科技出品的一款被动式漏洞扫描器 31 | * [w13scan](https://github.com/boy-hack/w13scan) Passive Security Scanner (被动安全扫描器) 32 | * [Fox-scan](https://github.com/fengxuangit/Fox-scan) 基于sqlmapapi的主动和被动资源发现的漏洞扫描工具 33 | * [SQLiScanner](https://github.com/0xbug/SQLiScanner) 一款基于sqlmapapi和Charles的被动SQL注入漏洞扫描工具 34 | * [sqli-hunter](https://github.com/zt2/sqli-hunter) 基于sqlmapapi,ruby编写的漏洞代理型检测工具 35 | * [passive_scan](https://github.com/netxfly/passive_scan) 基于http代理的web漏洞扫描器的实现 -------------------------------------------------------------------------------- /doc/process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/c0ny1/passive-scan-client/a113685dbfe83932c225c4e4bfbd2687bec933b7/doc/process.png -------------------------------------------------------------------------------- /doc/show.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/c0ny1/passive-scan-client/a113685dbfe83932c225c4e4bfbd2687bec933b7/doc/show.gif -------------------------------------------------------------------------------- /passive-scan-client.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | me.gv7.tools.burpextend 8 | passive-scan-client 9 | 0.3.1 10 | 11 | 12 | 13 | 14 | net.portswigger.burp.extender 15 | burp-extender-api 16 | 1.7.22 17 | 18 | 19 | 20 | 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-assembly-plugin 25 | 26 | 27 | package 28 | 29 | single 30 | 31 | 32 | 33 | 34 | 35 | jar-with-dependencies 36 | 37 | 38 | 39 | 40 | org.apache.maven.plugins 41 | maven-compiler-plugin 42 | 3.1 43 | 44 | 1.7 45 | 1.7 46 | utf-8 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/main/java/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.awt.Component; 4 | import java.awt.event.ActionEvent; 5 | import java.awt.event.ActionListener; 6 | import java.io.PrintWriter; 7 | import java.util.*; 8 | import java.util.concurrent.ExecutorService; 9 | import java.util.concurrent.Executors; 10 | import javax.swing.*; 11 | import javax.swing.table.TableColumn; 12 | import javax.swing.table.TableColumnModel; 13 | 14 | // 插件入口 15 | public class BurpExtender implements IBurpExtender,ITab,IProxyListener { 16 | public final static String extensionName = "Passive Scan Client"; 17 | public final static String version ="0.3.1"; 18 | public static IBurpExtenderCallbacks callbacks; 19 | public static IExtensionHelpers helpers; 20 | public static PrintWriter stdout; 21 | public static PrintWriter stderr; 22 | public static GUI gui; 23 | public static final List log = new ArrayList(); 24 | public static BurpExtender burpExtender; 25 | private ExecutorService executorService; 26 | 27 | // 通过参数 callbacks 可以获得核心基础库,例如日志、请求、返回值修改等 28 | @Override 29 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) { 30 | this.burpExtender = this; 31 | this.callbacks = callbacks; 32 | this.helpers = callbacks.getHelpers(); 33 | this.stdout = new PrintWriter(callbacks.getStdout(),true); 34 | this.stderr = new PrintWriter(callbacks.getStderr(),true); 35 | 36 | // 注册菜单拓展 37 | callbacks.registerContextMenuFactory(new Send2PSCMenu()); 38 | callbacks.setExtensionName(extensionName + " " + version); 39 | BurpExtender.this.gui = new GUI(); 40 | SwingUtilities.invokeLater(new Runnable() { 41 | public void run() { 42 | BurpExtender.this.callbacks.addSuiteTab(BurpExtender.this); 43 | BurpExtender.this.callbacks.registerProxyListener(BurpExtender.this); 44 | stdout.println(Utils.getBanner()); 45 | } 46 | }); 47 | executorService = Executors.newSingleThreadExecutor(); 48 | //必须等插件界面显示完毕,重置JTable列宽才生效 49 | SwingUtilities.invokeLater(new Runnable() { 50 | @Override 51 | public void run() { 52 | //按照比例显示列宽 53 | float[] columnWidthPercentage = {5.0f, 5.0f, 55.0f, 20.0f, 15.0f}; 54 | int tW = GUI.logTable.getWidth(); 55 | TableColumn column; 56 | TableColumnModel jTableColumnModel = GUI.logTable.getColumnModel(); 57 | int cantCols = jTableColumnModel.getColumnCount(); 58 | for (int i = 0; i < cantCols; i++) { 59 | column = jTableColumnModel.getColumn(i); 60 | int pWidth = Math.round(columnWidthPercentage[i] * tW); 61 | column.setPreferredWidth(pWidth); 62 | } 63 | } 64 | }); 65 | } 66 | 67 | // 68 | // 实现ITab 69 | // 70 | 71 | @Override 72 | public String getTabCaption() { 73 | return extensionName; 74 | } 75 | 76 | @Override 77 | public Component getUiComponent() { 78 | return gui.getComponet(); 79 | } 80 | 81 | // IHttpRequestResponse 接口包含了每个请求和响应的细节,在 brupsuite 中的每个请求或者响应都是 IHttpRequestResponse 实例。通过 getRequest()可以获取请求和响应的细节信息。 82 | public void processProxyMessage(boolean messageIsRequest, final IInterceptedProxyMessage iInterceptedProxyMessage) { 83 | if (!messageIsRequest && Config.IS_RUNNING) { 84 | IHttpRequestResponse reprsp = iInterceptedProxyMessage.getMessageInfo(); 85 | IHttpService httpService = reprsp.getHttpService(); 86 | String host = reprsp.getHttpService().getHost(); 87 | //stdout.println(Config.DOMAIN_REGX); 88 | if(Config.DOMAIN_REGX!="" && !Utils.isMathch(Config.DOMAIN_REGX,host)){ 89 | return; 90 | } 91 | 92 | String url = helpers.analyzeRequest(httpService,reprsp.getRequest()).getUrl().toString(); 93 | String url2 = url; 94 | url = url.indexOf("?") > 0 ? url.substring(0, url.indexOf("?")) : url; 95 | if(Config.SUFFIX_REGX!="" && Utils.isMathch(Config.SUFFIX_REGX,url)){ 96 | return; 97 | } 98 | if(Config.BLACKLIST_REGX!="" && Utils.isMathch(Config.BLACKLIST_REGX,url2)){ 99 | return; 100 | } 101 | 102 | final IHttpRequestResponse resrsp = iInterceptedProxyMessage.getMessageInfo(); 103 | 104 | //final LogEntry logEntry = new LogEntry(1,callbacks.saveBuffersToTempFiles(iInterceptedProxyMessage.getMessageInfo()),helpers.analyzeRequest(resrsp).getUrl()); 105 | 106 | // create a new log entry with the message details 107 | executorService.submit(new Runnable() { 108 | @Override 109 | public void run() { 110 | synchronized(log) { 111 | int row = log.size(); 112 | String method = helpers.analyzeRequest(resrsp).getMethod(); 113 | Map mapResult = null; 114 | try { 115 | mapResult = HttpAndHttpsProxy.Proxy(resrsp); 116 | } catch (InterruptedException e) { 117 | e.printStackTrace(); 118 | } 119 | 120 | log.add(new LogEntry(iInterceptedProxyMessage.getMessageReference(), 121 | callbacks.saveBuffersToTempFiles(resrsp), helpers.analyzeRequest(resrsp).getUrl(), 122 | method, 123 | mapResult) 124 | ); 125 | GUI.logTable.getHttpLogTableModel().fireTableRowsInserted(row, row); 126 | } 127 | } 128 | }); 129 | } 130 | } 131 | 132 | 133 | // 实现右键,需要先注册菜单拓展 134 | public class Send2PSCMenu implements IContextMenuFactory{ 135 | @Override 136 | public List createMenuItems(IContextMenuInvocation invocation) { 137 | final IHttpRequestResponse[] messages = invocation.getSelectedMessages(); 138 | JMenuItem i1 = new JMenuItem("Send to Passive Scan Client"); 139 | i1.addActionListener(new ActionListener() { 140 | @Override 141 | public void actionPerformed(ActionEvent e) { 142 | for (final IHttpRequestResponse message : messages) { 143 | executorService.submit(new Runnable() { 144 | @Override 145 | public void run() { 146 | synchronized (log) { 147 | int row = log.size(); 148 | String method = helpers.analyzeRequest(message).getMethod(); 149 | byte[] req = message.getRequest(); 150 | 151 | String req_str = new String(req); 152 | //向代理转发请求 153 | Map mapResult = null; 154 | try { 155 | mapResult = HttpAndHttpsProxy.Proxy(message); 156 | } catch (InterruptedException ex) { 157 | ex.printStackTrace(); 158 | } 159 | log.add(new LogEntry(row + 1, 160 | callbacks.saveBuffersToTempFiles(message), helpers.analyzeRequest(message).getUrl(), 161 | method, 162 | mapResult) 163 | ); 164 | GUI.logTable.getHttpLogTableModel().fireTableRowsInserted(row, row); 165 | } 166 | } 167 | }); 168 | } 169 | } 170 | }); 171 | return Arrays.asList(i1); 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /src/main/java/burp/Config.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | public class Config { 4 | public static boolean IS_RUNNING = false; 5 | public static String PROXY_HOST = "127.0.0.1"; 6 | public static Integer PROXY_PORT = 1664; 7 | public static String PROXY_USERNAME = null; 8 | public static String PROXY_PASSWORD = null; 9 | public static Integer PROXY_TIMEOUT = 5000; 10 | public static String DOMAIN_REGX = ""; 11 | public static String SUFFIX_REGX = "js|css|jpeg|gif|jpg|png|pdf|rar|zip|docx|doc|svg|jpeg|ico|woff|woff2|ttf|otf"; 12 | 13 | // 新增关键字、域名黑名单 14 | public static String BLACKLIST_REGX = "google.com|baidu.com|mozilla.org|mozilla.com|googleapis.com|delete|remove"; 15 | 16 | public static Integer REQUEST_TOTAL = 0; 17 | public static Integer SUCCESS_TOTAL = 0; 18 | public static Integer FAIL_TOTAL = 0; 19 | 20 | public static Integer INTERVAL_TIME = 5000; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/burp/GUI.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.awt.*; 4 | import java.awt.event.ActionEvent; 5 | import javax.swing.*; 6 | import javax.swing.border.EmptyBorder; 7 | import javax.swing.event.ChangeEvent; 8 | import javax.swing.event.ChangeListener; 9 | 10 | public class GUI implements IMessageEditorController { 11 | private JPanel contentPane; 12 | private JLabel lbHost; 13 | private JTextField tfHost; 14 | private JLabel lbPort; 15 | private JTextField tfPort; 16 | private JLabel lbTimeout; 17 | private JTextField tfTimeout; 18 | private JLabel lbIntervalTime; 19 | private JTextField tfIntervalTime; 20 | private JLabel lbUsername; 21 | private JTextField tfUsername; 22 | private JLabel lbPassword; 23 | private JTextField tfPassword; 24 | private JTextField tfDomain; 25 | private JTextField tfExcludeSuffix; 26 | private JTextField tfBlackList; 27 | private JToggleButton btnConn; 28 | private JButton btnClear; 29 | private JSplitPane splitPane; 30 | public static HttpLogTable logTable; 31 | public static IHttpRequestResponse currentlyDisplayedItem; 32 | public static JLabel lbRequestCount; 33 | public static JLabel lbSuccesCount; 34 | public static JLabel lbFailCount; 35 | 36 | public static IMessageEditor requestViewer; 37 | public static IMessageEditor responseViewer; 38 | public static ITextEditor proxyRspViewer; 39 | 40 | 41 | public GUI() { 42 | contentPane = new JPanel(); 43 | contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 44 | contentPane.setLayout(new BorderLayout(0, 0)); 45 | 46 | //////////////////////////////////////////////////////////////////// 47 | // topPanel start 48 | //////////////////////////////////////////////////////////////////// 49 | JPanel topPanel = new JPanel(); 50 | GridBagLayout gridBagLayout = new GridBagLayout(); 51 | // 列数,行数 52 | gridBagLayout.columnWidths = new int[] { 0, 0 }; 53 | gridBagLayout.rowHeights = new int[] { 40, 32, 0, 0 }; 54 | // 各列占宽度比,各行占高度比 55 | gridBagLayout.columnWeights = new double[] { 1.0D, Double.MIN_VALUE }; 56 | gridBagLayout.rowWeights = new double[] { 0.0D, 0.0D, 1.0D, Double.MIN_VALUE }; 57 | topPanel.setLayout(gridBagLayout); 58 | 59 | JPanel ConfigPanel = new JPanel(); 60 | GridBagConstraints gbc_panel = new GridBagConstraints(); 61 | gbc_panel.insets = new Insets(5, 5, 5, 5); 62 | gbc_panel.fill = 2; 63 | gbc_panel.gridx = 0; 64 | gbc_panel.gridy = 0; 65 | topPanel.add(ConfigPanel, gbc_panel); 66 | 67 | GridBagLayout gbl_panel = new GridBagLayout(); 68 | gbl_panel.columnWidths = new int[] { 40, 100, 0, 39, 33, 25, 0, 0, 0 }; 69 | gbl_panel.rowHeights = new int[] { 0, 0 }; 70 | gbl_panel.columnWeights = new double[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D,0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D,0.0D, Double.MIN_VALUE }; 71 | gbl_panel.rowWeights = new double[] { 0.0D,Double.MIN_VALUE }; 72 | ConfigPanel.setLayout(gbl_panel); 73 | 74 | lbHost = new JLabel("Host:"); 75 | GridBagConstraints gbc_lbHost = new GridBagConstraints(); 76 | gbc_lbHost.fill = 2; 77 | // insets 内边距 78 | gbc_lbHost.insets = new Insets(0, 0, 0, 5); 79 | // 坐标位置,从左上角开始布局 80 | gbc_lbHost.gridx = 0; 81 | gbc_lbHost.gridy = 0; 82 | ConfigPanel.add(lbHost, gbc_lbHost); 83 | 84 | tfHost = new JTextField(); 85 | tfHost.setColumns(10); 86 | tfHost.setText("127.0.0.1"); 87 | GridBagConstraints gbc_tfHost = new GridBagConstraints(); 88 | gbc_tfHost.fill = 2; 89 | gbc_tfHost.insets = new Insets(0, 0, 0, 5); 90 | gbc_tfHost.gridx = 1; 91 | gbc_tfHost.gridy = 0; 92 | ConfigPanel.add(tfHost, gbc_tfHost); 93 | 94 | lbPort = new JLabel("Port:"); 95 | GridBagConstraints gbc_lbPort = new GridBagConstraints(); 96 | gbc_lbPort.fill = 2; 97 | gbc_lbPort.insets = new Insets(0, 0, 0, 5); 98 | gbc_lbPort.gridx = 2; 99 | gbc_lbPort.gridy = 0; 100 | ConfigPanel.add(lbPort, gbc_lbPort); 101 | 102 | tfPort = new JTextField(); 103 | tfPort.setText("1664"); 104 | tfPort.setColumns(10); 105 | GridBagConstraints gbc_tfPort = new GridBagConstraints(); 106 | gbc_tfPort.fill = 2; 107 | gbc_tfPort.insets = new Insets(0, 0, 0, 5); 108 | gbc_tfPort.gridx = 3; 109 | gbc_tfPort.gridy = 0; 110 | ConfigPanel.add(tfPort, gbc_tfPort); 111 | 112 | lbUsername = new JLabel("Username:"); 113 | GridBagConstraints gbc_lbUsername = new GridBagConstraints(); 114 | gbc_lbUsername.fill = 2; 115 | gbc_lbUsername.insets = new Insets(0, 0, 0, 5); 116 | gbc_lbUsername.gridx = 4; 117 | gbc_lbUsername.gridy = 0; 118 | ConfigPanel.add(lbUsername, gbc_lbUsername); 119 | 120 | tfUsername = new JTextField(); 121 | tfUsername.setText(""); 122 | tfUsername.setColumns(10); 123 | GridBagConstraints gbc_tfUsername = new GridBagConstraints(); 124 | gbc_tfUsername.fill = 2; 125 | gbc_tfUsername.insets = new Insets(0, 0, 0, 5); 126 | gbc_tfUsername.gridx = 5; 127 | gbc_tfUsername.gridy = 0; 128 | ConfigPanel.add(tfUsername, gbc_tfUsername); 129 | 130 | lbPassword = new JLabel("Password:"); 131 | GridBagConstraints gbc_lbPassword = new GridBagConstraints(); 132 | gbc_lbPassword.fill = 2; 133 | gbc_lbPassword.insets = new Insets(0, 0, 0, 5); 134 | gbc_lbPassword.gridx = 6; 135 | gbc_lbPassword.gridy = 0; 136 | ConfigPanel.add(lbPassword, gbc_lbPassword); 137 | 138 | tfPassword = new JTextField(); 139 | tfPassword.setText(""); 140 | tfPassword.setColumns(10); 141 | GridBagConstraints gbc_tfPassword = new GridBagConstraints(); 142 | gbc_tfPassword.fill = 2; 143 | gbc_tfPassword.insets = new Insets(0, 0, 0, 5); 144 | gbc_tfPassword.gridx = 7; 145 | gbc_tfPassword.gridy = 0; 146 | ConfigPanel.add(tfPassword, gbc_tfPassword); 147 | 148 | lbTimeout = new JLabel("Timeout:"); 149 | GridBagConstraints gbc_lbTimeout = new GridBagConstraints(); 150 | gbc_lbTimeout.fill = 2; 151 | gbc_lbTimeout.gridx = 8; 152 | gbc_lbTimeout.gridy = 0; 153 | ConfigPanel.add(lbTimeout, gbc_lbTimeout); 154 | 155 | tfTimeout = new JTextField(); 156 | tfTimeout.setText("5000"); 157 | tfTimeout.setColumns(5); 158 | GridBagConstraints gbc_tfTimeout = new GridBagConstraints(); 159 | gbc_tfTimeout.fill = 2; 160 | gbc_tfTimeout.insets = new Insets(0, 0, 0, 5); 161 | gbc_tfTimeout.gridx = 9; 162 | gbc_tfTimeout.gridy = 0; 163 | ConfigPanel.add(tfTimeout, gbc_tfTimeout); 164 | 165 | // 增加间隔时间 166 | lbIntervalTime = new JLabel("Interva lTime:"); 167 | GridBagConstraints gbc_lbIntervalTime = new GridBagConstraints(); 168 | gbc_lbIntervalTime.fill = 2; 169 | gbc_lbIntervalTime.gridx = 10; 170 | gbc_lbIntervalTime.gridy = 0; 171 | ConfigPanel.add(lbIntervalTime, gbc_lbIntervalTime); 172 | 173 | tfIntervalTime = new JTextField(); 174 | tfIntervalTime.setText("5000"); 175 | tfIntervalTime.setColumns(5); 176 | GridBagConstraints gbc_tfIntervalTime = new GridBagConstraints(); 177 | // fill属性用来处理GridBagLayout网格布局时子节点渲染的占位大小,2为撑满父组件 178 | gbc_tfIntervalTime.fill = 2; 179 | gbc_tfIntervalTime.insets = new Insets(0, 0, 0, 5); 180 | gbc_tfIntervalTime.gridx = 11; 181 | gbc_tfIntervalTime.gridy = 0; 182 | ConfigPanel.add(tfIntervalTime, gbc_tfIntervalTime); 183 | 184 | GridBagConstraints gbc_lb1 = new GridBagConstraints(); 185 | // 子组件对于整体外层组件的浮动 186 | gbc_lb1.anchor = 15; 187 | gbc_lb1.insets = new Insets(0, 0, 0, 5); 188 | gbc_lb1.gridx = 12; 189 | gbc_lb1.gridy = 0; 190 | ConfigPanel.add(new JLabel(""), gbc_lb1); 191 | 192 | btnConn = new JToggleButton("Run"); 193 | btnConn.addChangeListener(new ChangeListener() { 194 | public void stateChanged(ChangeEvent arg0) { 195 | boolean isSelected = btnConn.isSelected(); 196 | 197 | if(isSelected){ 198 | btnConn.setText("Stop"); 199 | Config.IS_RUNNING = true; 200 | Config.PROXY_HOST = tfHost.getText(); 201 | Config.PROXY_PORT = Integer.valueOf(tfPort.getText()); 202 | Config.PROXY_TIMEOUT = Integer.valueOf(tfTimeout.getText()); 203 | Config.PROXY_USERNAME = tfUsername.getText(); 204 | Config.PROXY_PASSWORD = tfPassword.getText(); 205 | Config.DOMAIN_REGX = tfDomain.getText(); 206 | Config.SUFFIX_REGX = tfExcludeSuffix.getText(); 207 | Config.BLACKLIST_REGX = tfBlackList.getText(); 208 | Config.INTERVAL_TIME = Integer.valueOf(tfIntervalTime.getText()); 209 | setAllEnabled(false); 210 | }else{ 211 | btnConn.setText("Run"); 212 | Config.IS_RUNNING = false; 213 | setAllEnabled(true); 214 | } 215 | btnConn.setSelected(isSelected); 216 | 217 | } 218 | }); 219 | GridBagConstraints gbc_btnConn = new GridBagConstraints(); 220 | gbc_btnConn.fill = 2; 221 | gbc_btnConn.insets = new Insets(0, 0, 0, 5); 222 | gbc_btnConn.gridx = 13; 223 | gbc_btnConn.gridy = 0; 224 | ConfigPanel.add(btnConn, gbc_btnConn); 225 | 226 | btnClear = new JButton("Clear"); 227 | btnClear.addActionListener(new AbstractAction() { 228 | @Override 229 | public void actionPerformed(ActionEvent e) { 230 | int n = JOptionPane.showConfirmDialog(null, "Are you sure you want to clear the data?", "Passvie Scan Client prompt", JOptionPane.YES_NO_OPTION); 231 | if(n == 0) { 232 | Config.REQUEST_TOTAL = 0; 233 | lbRequestCount.setText("0"); 234 | Config.SUCCESS_TOTAL = 0; 235 | lbSuccesCount.setText("0"); 236 | Config.FAIL_TOTAL = 0; 237 | lbFailCount.setText("0"); 238 | BurpExtender.log.clear(); 239 | logTable.getHttpLogTableModel().fireTableDataChanged();//通知模型更新 240 | logTable.updateUI();//刷新表格 241 | requestViewer.setMessage("".getBytes(),true); 242 | responseViewer.setMessage("".getBytes(),false); 243 | proxyRspViewer.setText("".getBytes()); 244 | } 245 | } 246 | }); 247 | GridBagConstraints gbc_btnClear = new GridBagConstraints(); 248 | gbc_btnClear.fill = 2; 249 | gbc_btnClear.insets = new Insets(0, 0, 0, 5); 250 | gbc_btnClear.gridx = 14; 251 | gbc_btnClear.gridy = 0; 252 | ConfigPanel.add(btnClear, gbc_btnClear); 253 | //////////////////////////////////////////////////////////////////// 254 | 255 | JPanel FilterPanel2 = new JPanel(); 256 | GridBagConstraints gbc_panel_2 = new GridBagConstraints(); 257 | gbc_panel_2.insets = new Insets(0, 5, 5, 5); 258 | gbc_panel_2.fill = 2; 259 | gbc_panel_2.gridx = 0; 260 | gbc_panel_2.gridy = 1; 261 | topPanel.add(FilterPanel2, gbc_panel_2); 262 | GridBagLayout gbl_panel_2 = new GridBagLayout(); 263 | gbl_panel_2.columnWidths = new int[] { 40, 225, 0, 0, 0 }; 264 | gbl_panel_2.rowHeights = new int[] { 0, 0 }; 265 | gbl_panel_2.columnWeights = new double[] { 0.0D, 0.0D, 0.0D,0.0D,1.0D, 0.0D, 0.0D,0.0D,0.0D,0.0D,0.0D,0.0D,Double.MIN_VALUE }; 266 | gbl_panel_2.rowWeights = new double[] { 0.0D, Double.MIN_VALUE }; 267 | FilterPanel2.setLayout(gbl_panel_2); 268 | 269 | // 黑名单,用于过滤关键字 270 | JLabel lbBlackList = new JLabel("BlackList:"); 271 | GridBagConstraints gbc_lbBlackList = new GridBagConstraints(); 272 | gbc_lbBlackList.insets = new Insets(0, 0, 0, 5); 273 | gbc_lbBlackList.anchor = 13; 274 | gbc_lbBlackList.fill = 2; 275 | gbc_lbBlackList.gridx = 0; 276 | gbc_lbBlackList.gridy = 0; 277 | FilterPanel2.add(lbBlackList, gbc_lbBlackList); 278 | 279 | tfBlackList = new JTextField(90); 280 | tfBlackList.setText("google.com|baidu.com|mozilla.org|mozilla.com|googleapis.com|delete|remove"); 281 | GridBagConstraints gbc_tfBlackList = new GridBagConstraints(); 282 | gbc_tfBlackList.insets = new Insets(0, 0, 0, 5); 283 | gbc_tfBlackList.fill = 2; 284 | gbc_tfBlackList.gridx = 1; 285 | gbc_tfBlackList.gridy = 0; 286 | FilterPanel2.add(tfBlackList, gbc_tfBlackList); 287 | 288 | JPanel FilterPanel = new JPanel(); 289 | GridBagConstraints gbc_panel_1 = new GridBagConstraints(); 290 | gbc_panel_1.insets = new Insets(0, 5, 5, 5); 291 | gbc_panel_1.fill = 2; 292 | gbc_panel_1.gridx = 0; 293 | gbc_panel_1.gridy = 2; 294 | topPanel.add(FilterPanel, gbc_panel_1); 295 | GridBagLayout gbl_panel_1 = new GridBagLayout(); 296 | gbl_panel_1.columnWidths = new int[] { 40, 225, 0, 0, 0 }; 297 | gbl_panel_1.rowHeights = new int[] { 0, 0 }; 298 | gbl_panel_1.columnWeights = new double[] { 0.0D, 0.0D, 0.0D,0.0D,1.0D, 0.0D, 0.0D,0.0D,0.0D,0.0D,0.0D,0.0D,Double.MIN_VALUE }; 299 | gbl_panel_1.rowWeights = new double[] { 0.0D, Double.MIN_VALUE }; 300 | FilterPanel.setLayout(gbl_panel_1); 301 | 302 | JLabel lbDomain = new JLabel("Domain:"); 303 | GridBagConstraints gbc_lblDomain = new GridBagConstraints(); 304 | gbc_lblDomain.insets = new Insets(0, 0, 0, 5); 305 | gbc_lblDomain.anchor = 13; 306 | gbc_lblDomain.gridx = 0; 307 | gbc_lblDomain.gridy = 0; 308 | FilterPanel.add(lbDomain, gbc_lblDomain); 309 | 310 | tfDomain = new JTextField(20); 311 | tfDomain.setText(""); 312 | GridBagConstraints gbc_tfDomain = new GridBagConstraints(); 313 | gbc_tfDomain.insets = new Insets(0, 0, 0, 5); 314 | gbc_tfDomain.fill = 2; 315 | gbc_tfDomain.gridx = 1; 316 | gbc_tfDomain.gridy = 0; 317 | FilterPanel.add(tfDomain, gbc_tfDomain); 318 | 319 | 320 | JLabel lbExcludeSuffix = new JLabel("Exclude suffix:"); 321 | GridBagConstraints gbc_lbExcludeSuffix = new GridBagConstraints(); 322 | gbc_lbExcludeSuffix.insets = new Insets(0, 0, 0, 5); 323 | gbc_lbExcludeSuffix.anchor = 13; 324 | gbc_lbExcludeSuffix.fill = 2; 325 | gbc_lbExcludeSuffix.gridx = 2; 326 | gbc_lbExcludeSuffix.gridy = 0; 327 | FilterPanel.add(lbExcludeSuffix, gbc_lbExcludeSuffix); 328 | 329 | tfExcludeSuffix = new JTextField(35); 330 | tfExcludeSuffix.setText("js|css|jpeg|gif|jpg|png|pdf|rar|zip|docx|doc|svg|jpeg|ico|woff|woff2|ttf|otf"); 331 | GridBagConstraints gbc_tfExcludeSuffix = new GridBagConstraints(); 332 | gbc_tfExcludeSuffix.insets = new Insets(0, 0, 0, 5); 333 | gbc_tfExcludeSuffix.fill = 2; 334 | gbc_tfExcludeSuffix.gridx = 3; 335 | gbc_tfExcludeSuffix.gridy = 0; 336 | FilterPanel.add(tfExcludeSuffix, gbc_tfExcludeSuffix); 337 | // 338 | // GridBagConstraints gbc_vb4 = new GridBagConstraints(); 339 | // gbc_vb4.insets = new Insets(0, 0, 0, 5); 340 | // gbc_vb4.fill = 2; 341 | // gbc_vb4.gridx = 7; 342 | // gbc_vb4.gridy = 0; 343 | // FilterPanel.add(Box.createVerticalBox(), gbc_vb4); 344 | 345 | // 转发url总数,默认0 346 | JLabel lbRequest = new JLabel("Total:"); 347 | GridBagConstraints gbc_lbRequest = new GridBagConstraints(); 348 | gbc_lbRequest.insets = new Insets(0, 0, 0, 5); 349 | gbc_lbRequest.fill = 2; 350 | gbc_lbRequest.gridx = 6; 351 | gbc_lbRequest.gridy = 0; 352 | FilterPanel.add(lbRequest, gbc_lbRequest); 353 | 354 | 355 | lbRequestCount = new JLabel("0"); 356 | lbRequestCount.setForeground(new Color(0,0,255)); 357 | GridBagConstraints gbc_lbRequestCount = new GridBagConstraints(); 358 | gbc_lbRequestCount.insets = new Insets(0, 0, 0, 5); 359 | gbc_lbRequestCount.fill = 2; 360 | gbc_lbRequestCount.gridx = 7; 361 | gbc_lbRequestCount.gridy = 0; 362 | FilterPanel.add(lbRequestCount, gbc_lbRequestCount); 363 | 364 | GridBagConstraints gbc_vb2 = new GridBagConstraints(); 365 | gbc_vb2.insets = new Insets(0, 0, 0, 5); 366 | gbc_vb2.fill = 2; 367 | gbc_vb2.gridx = 8; 368 | gbc_vb2.gridy = 0; 369 | FilterPanel.add(Box.createVerticalBox(), gbc_vb2); 370 | 371 | // 转发成功url数,默认0 372 | JLabel lbSucces = new JLabel("Success:"); 373 | GridBagConstraints gbc_lbSucces = new GridBagConstraints(); 374 | gbc_lbSucces.insets = new Insets(0, 0, 0, 5); 375 | gbc_lbSucces.fill = 2; 376 | gbc_lbSucces.gridx = 9; 377 | gbc_lbSucces.gridy = 0; 378 | FilterPanel.add(lbSucces, gbc_lbSucces); 379 | 380 | lbSuccesCount = new JLabel("0"); 381 | lbSuccesCount.setForeground(new Color(0, 255, 0)); 382 | GridBagConstraints gbc_lbSuccesCount = new GridBagConstraints(); 383 | gbc_lbSuccesCount.insets = new Insets(0, 0, 0, 5); 384 | gbc_lbSuccesCount.fill = 2; 385 | gbc_lbSuccesCount.gridx = 10; 386 | gbc_lbSuccesCount.gridy = 0; 387 | FilterPanel.add(lbSuccesCount, gbc_lbSuccesCount); 388 | 389 | GridBagConstraints gbc_vb3 = new GridBagConstraints(); 390 | gbc_vb3.insets = new Insets(0, 0, 0, 5); 391 | gbc_vb3.fill = 2; 392 | gbc_vb3.gridx = 11; 393 | gbc_vb3.gridy = 0; 394 | FilterPanel.add(Box.createVerticalBox(), gbc_vb3); 395 | // 转发失败url数,默认0 396 | JLabel lbFail = new JLabel("Fail:"); 397 | GridBagConstraints gbc_lbFail = new GridBagConstraints(); 398 | gbc_lbFail.insets = new Insets(0, 0, 0, 5); 399 | gbc_lbFail.fill = 2; 400 | gbc_lbFail.gridx = 12; 401 | gbc_lbFail.gridy = 0; 402 | FilterPanel.add(lbFail, gbc_lbFail); 403 | 404 | lbFailCount = new JLabel("0"); 405 | lbFailCount.setForeground(new Color(255, 0, 0)); 406 | GridBagConstraints gbc_lbFailCount = new GridBagConstraints(); 407 | gbc_lbFailCount.insets = new Insets(0, 0, 0, 5); 408 | gbc_lbFailCount.fill = 2; 409 | gbc_lbFailCount.gridx = 13; 410 | gbc_lbFailCount.gridy = 0; 411 | FilterPanel.add(lbFailCount, gbc_lbFailCount); 412 | 413 | contentPane.add(topPanel,BorderLayout.NORTH); 414 | //////////////////////////////////////////////////////////////////// 415 | // topPanl end 416 | //////////////////////////////////////////////////////////////////// 417 | 418 | splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); 419 | splitPane.setDividerLocation(0.5); 420 | contentPane.add(splitPane, BorderLayout.CENTER); 421 | 422 | HttpLogTableModel model = new HttpLogTableModel(); 423 | logTable = new HttpLogTable(model); 424 | //JTable表头排序,以下两种方法均存在问题,导致界面混乱。 425 | //方式一 426 | //TableRowSorter tableRowSorter=new TableRowSorter(model); 427 | //logTable.setRowSorter(tableRowSorter); 428 | //方式二 429 | //logTable.setAutoCreateRowSorter(true); 430 | 431 | JScrollPane jspLogTable = new JScrollPane(logTable); 432 | splitPane.setTopComponent(jspLogTable); 433 | 434 | 435 | JTabbedPane tabs = new JTabbedPane(); 436 | requestViewer = BurpExtender.callbacks.createMessageEditor(this, false); 437 | responseViewer = BurpExtender.callbacks.createMessageEditor(this, false); 438 | proxyRspViewer = BurpExtender.callbacks.createTextEditor(); 439 | 440 | tabs.addTab("Request", requestViewer.getComponent()); 441 | tabs.addTab("Original response", responseViewer.getComponent()); 442 | tabs.addTab("Proxy response",proxyRspViewer.getComponent()); 443 | splitPane.setBottomComponent(tabs); 444 | 445 | BurpExtender.callbacks.customizeUiComponent(topPanel); 446 | BurpExtender.callbacks.customizeUiComponent(btnConn); 447 | BurpExtender.callbacks.customizeUiComponent(splitPane); 448 | BurpExtender.callbacks.customizeUiComponent(contentPane); 449 | } 450 | 451 | public Component getComponet(){ 452 | return contentPane; 453 | } 454 | 455 | public IHttpService getHttpService() { 456 | return currentlyDisplayedItem.getHttpService(); 457 | } 458 | 459 | public byte[] getRequest() { 460 | return currentlyDisplayedItem.getRequest(); 461 | } 462 | 463 | public byte[] getResponse() { 464 | return currentlyDisplayedItem.getResponse(); 465 | } 466 | 467 | public void setAllEnabled(boolean is){ 468 | tfHost.setEnabled(is); 469 | tfPort.setEnabled(is); 470 | tfUsername.setEnabled(is); 471 | tfPassword.setEnabled(is); 472 | tfTimeout.setEnabled(is); 473 | tfDomain.setEnabled(is); 474 | tfExcludeSuffix.setEnabled(is); 475 | tfBlackList.setEnabled(is); 476 | tfIntervalTime.setEnabled(is); 477 | } 478 | } -------------------------------------------------------------------------------- /src/main/java/burp/HttpAndHttpsProxy.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; 4 | import java.io.*; 5 | import java.net.HttpURLConnection; 6 | import java.net.InetSocketAddress; 7 | import java.net.Proxy; 8 | import java.net.URL; 9 | import java.net.Proxy.Type; 10 | import java.security.cert.CertificateException; 11 | import java.security.cert.X509Certificate; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | import javax.net.ssl.HostnameVerifier; 16 | import javax.net.ssl.HttpsURLConnection; 17 | import javax.net.ssl.SSLContext; 18 | import javax.net.ssl.SSLSession; 19 | import javax.net.ssl.TrustManager; 20 | import javax.net.ssl.X509TrustManager; 21 | 22 | //https://blog.csdn.net/sbc1232123321/article/details/79334130,http、https代理设置 23 | public class HttpAndHttpsProxy { 24 | public static Map Proxy(IHttpRequestResponse requestResponse) throws InterruptedException{ 25 | byte[] req = requestResponse.getRequest(); 26 | String url = null; 27 | byte[] reqbody = null; 28 | List headers = null; 29 | 30 | IHttpService httpService = requestResponse.getHttpService(); 31 | IRequestInfo reqInfo = BurpExtender.helpers.analyzeRequest(httpService,req); 32 | 33 | if(reqInfo.getMethod().equals("POST")){ 34 | int bodyOffset = reqInfo.getBodyOffset(); 35 | String body = null; 36 | try { 37 | body = new String(req, bodyOffset, req.length - bodyOffset, "UTF-8"); 38 | reqbody = body.getBytes("UTF-8"); 39 | } catch (UnsupportedEncodingException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | //BurpExtender.stderr.println("[+] url: " + resInfo.getUrl()); 44 | headers = reqInfo.getHeaders(); 45 | url = reqInfo.getUrl().toString(); 46 | Thread.sleep(Config.INTERVAL_TIME); 47 | if(httpService.getProtocol().equals("https")){ 48 | return HttpsProxy(url, headers, reqbody, Config.PROXY_HOST, Config.PROXY_PORT,Config.PROXY_USERNAME,Config.PROXY_PASSWORD); 49 | }else { 50 | return HttpProxy(url, headers, reqbody, Config.PROXY_HOST, Config.PROXY_PORT,Config.PROXY_USERNAME,Config.PROXY_PASSWORD); 51 | } 52 | } 53 | 54 | public static Map HttpsProxy(String url, List headers,byte[] body, String proxy, int port,String username,String password){ 55 | Map mapResult = new HashMap(); 56 | String status = ""; 57 | String rspHeader = ""; 58 | String result = ""; 59 | 60 | HttpsURLConnection httpsConn = null; 61 | PrintWriter out = null; 62 | BufferedReader in = null; 63 | 64 | BufferedReader reader = null; 65 | 66 | try { 67 | 68 | URL urlClient = new URL(url); 69 | SSLContext sc = SSLContext.getInstance("SSL"); 70 | // 指定信任https 71 | sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); 72 | //创建代理虽然是https也是Type.HTTP 73 | Proxy proxy1=new Proxy(Type.HTTP, new InetSocketAddress(proxy, port)); 74 | //设置代理 75 | httpsConn = (HttpsURLConnection) urlClient.openConnection(proxy1); 76 | 77 | //设置账号密码 78 | if(username != null && username != "" && password != null && password != "" ) { 79 | String user_pass = String.format("%s:%s", username, password); 80 | String headerKey = "Proxy-Authorization"; 81 | String headerValue = "Basic " + Base64.encode(user_pass.getBytes()); 82 | httpsConn.setRequestProperty(headerKey, headerValue); 83 | } 84 | 85 | httpsConn.setSSLSocketFactory(sc.getSocketFactory()); 86 | httpsConn.setHostnameVerifier(new TrustAnyHostnameVerifier()); 87 | // 设置通用的请求属性 88 | for(String header:headers){ 89 | if(header.startsWith("GET") || 90 | header.startsWith("POST") || 91 | header.startsWith("PUT")){ 92 | continue; 93 | } 94 | String[] h = header.split(":"); 95 | String header_key = h[0].trim(); 96 | String header_value = h[1].trim(); 97 | httpsConn.setRequestProperty(header_key, header_value); 98 | } 99 | // 发送POST请求必须设置如下两行 100 | httpsConn.setDoOutput(true); 101 | httpsConn.setDoInput(true); 102 | 103 | 104 | // 获取URLConnection对象对应的输出流 105 | out = new PrintWriter(httpsConn.getOutputStream()); 106 | 107 | if(body != null) { 108 | // 发送请求参数 109 | out.print(new String(body)); 110 | } 111 | // flush输出流的缓冲 112 | out.flush(); 113 | // 定义BufferedReader输入流来读取URL的响应 114 | in = new BufferedReader( 115 | new InputStreamReader(httpsConn.getInputStream())); 116 | String line; 117 | while ((line = in.readLine()) != null) { 118 | result += line; 119 | result += "\r\n"; 120 | } 121 | // 断开连接 122 | httpsConn.disconnect(); 123 | //BurpExtender.stdout.println("====result===="+result); 124 | // 获取响应头 125 | Map> mapHeaders = httpsConn.getHeaderFields(); 126 | for (Map.Entry> entry : mapHeaders.entrySet()) { 127 | String key = entry.getKey(); 128 | List values = entry.getValue(); 129 | String value = ""; 130 | for(String v:values){ 131 | value += v; 132 | } 133 | 134 | if(key == null) { 135 | String header_line = String.format("%s\r\n",value); 136 | rspHeader += header_line; 137 | }else{ 138 | String header_line = String.format("%s: %s\r\n", key, value); 139 | rspHeader += header_line; 140 | } 141 | } 142 | 143 | //BurpExtender.stdout.println("返回结果https:" + httpsConn.getResponseMessage()); 144 | status = String.valueOf(httpsConn.getResponseCode()); 145 | Utils.updateSuccessCount(); 146 | } catch (Exception e) { 147 | e.printStackTrace(); 148 | BurpExtender.stderr.println("[*] " + e.getMessage()); 149 | result = e.getMessage(); 150 | Utils.updateFailCount(); 151 | } finally { 152 | try { 153 | if (reader != null) { 154 | reader.close(); 155 | } 156 | } catch (IOException e) { 157 | } 158 | try { 159 | if (in != null) { 160 | in.close(); 161 | } 162 | } catch (IOException e) { 163 | e.printStackTrace(); 164 | } 165 | if (out != null) { 166 | out.close(); 167 | } 168 | } 169 | 170 | try { 171 | status = String.valueOf(httpsConn.getResponseCode()); 172 | } catch (IOException e) { 173 | status = e.getMessage(); 174 | BurpExtender.stderr.println("[*] " + e.getMessage()); 175 | } 176 | 177 | mapResult.put("status",status); 178 | mapResult.put("header",rspHeader); 179 | mapResult.put("result",result); 180 | return mapResult; 181 | } 182 | 183 | public static Map HttpProxy(String url,List headers,byte[] body, String proxy, int port,String username,String password) { 184 | Map mapResult = new HashMap(); 185 | String status = ""; 186 | String rspHeader = ""; 187 | String result = ""; 188 | 189 | 190 | HttpURLConnection httpsConn = null; 191 | PrintWriter out = null; 192 | BufferedReader in = null; 193 | BufferedReader reader = null; 194 | try { 195 | URL urlClient = new URL(url); 196 | SSLContext sc = SSLContext.getInstance("SSL"); 197 | // 指定信任https 198 | sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); 199 | 200 | //创建代理 201 | Proxy proxy1=new Proxy(Type.HTTP, new InetSocketAddress(proxy, port)); 202 | //设置代理 203 | httpsConn = (HttpURLConnection) urlClient.openConnection(proxy1); 204 | 205 | //设置账号密码 206 | if(username != null && username != "" && password != null && password != "" ) { 207 | String user_pass = String.format("%s:%s", username, password); 208 | String headerKey = "Proxy-Authorization"; 209 | String headerValue = "Basic " + Base64.encode(user_pass.getBytes()); 210 | httpsConn.setRequestProperty(headerKey, headerValue); 211 | } 212 | 213 | 214 | // 设置通用的请求属性 215 | for(String header:headers){ 216 | if(header.startsWith("GET") || 217 | header.startsWith("POST") || 218 | header.startsWith("PUT")){ 219 | continue; 220 | } 221 | String[] h = header.split(":"); 222 | String header_key = h[0].trim(); 223 | String header_value = h[1].trim(); 224 | //BurpExtender.stdout.println("key: " + h[0].trim()); 225 | //BurpExtender.stdout.println("value: " + h[1].trim()); 226 | httpsConn.setRequestProperty(header_key, header_value); 227 | } 228 | //设置控制请求方法的Flag 229 | String methodFlag = ""; 230 | // 设置通用的请求属性 231 | for(String header:headers){ 232 | if(header.startsWith("GET") || 233 | header.startsWith("POST") || 234 | header.startsWith("PUT")){ 235 | if(header.startsWith("GET")){ 236 | methodFlag = "GET"; 237 | } 238 | else if(header.startsWith("POST")|| 239 | header.startsWith("PUT")){ 240 | methodFlag = "POST"; 241 | }//在循环中重复设置了methodFlag,代码非常的丑陋冗余,请见谅 242 | continue; 243 | }//判断结束后以键值对的方式获取header 244 | String[] h = header.split(":"); 245 | String header_key = h[0].trim(); 246 | String header_value = h[1].trim(); 247 | httpsConn.setRequestProperty(header_key, header_value); 248 | } 249 | 250 | if (methodFlag.equals("GET")){ 251 | // 发送GET请求必须设置如下两行 252 | httpsConn.setDoOutput(false); 253 | httpsConn.setDoInput(true); 254 | 255 | // 获取URLConnection对象的连接 256 | httpsConn.connect(); 257 | } 258 | else if(methodFlag.equals("POST")){ 259 | // 发送POST请求必须设置如下两行 260 | httpsConn.setDoOutput(true); 261 | httpsConn.setDoInput(true); 262 | 263 | // 获取URLConnection对象对应的输出流 264 | out = new PrintWriter(httpsConn.getOutputStream()); 265 | if(body != null) { 266 | // 发送请求参数 267 | out.print(new String(body)); 268 | } 269 | // flush输出流的缓冲 270 | out.flush(); 271 | } 272 | // 定义BufferedReader输入流来读取URL的响应 273 | in = new BufferedReader(new InputStreamReader(httpsConn.getInputStream())); 274 | String line; 275 | while ((line = in.readLine()) != null) { 276 | result += line; 277 | result += "\r\n"; 278 | } 279 | // 断开连接 280 | httpsConn.disconnect(); 281 | Map> mapHeaders = httpsConn.getHeaderFields(); 282 | for (Map.Entry> entry : mapHeaders.entrySet()) { 283 | String key = entry.getKey(); 284 | List values = entry.getValue(); 285 | String value = ""; 286 | for(String v:values){ 287 | value += v; 288 | } 289 | 290 | if(key == null) { 291 | String header_line = String.format("%s\r\n",value); 292 | rspHeader += header_line; 293 | }else{ 294 | String header_line = String.format("%s: %s\r\n", key, value); 295 | rspHeader += header_line; 296 | } 297 | } 298 | 299 | //BurpExtender.stdout.println("====result===="+result); 300 | //BurpExtender.stdout.println("返回结果http:" + httpConn.getResponseMessage()); 301 | status = String.valueOf(httpsConn.getResponseCode()); 302 | Utils.updateSuccessCount(); 303 | } catch (Exception e) { 304 | //e.printStackTrace(); 305 | BurpExtender.stderr.println("[*] " + e.getMessage()); 306 | result = e.getMessage(); 307 | Utils.updateFailCount(); 308 | } finally { 309 | try { 310 | if (reader != null) { 311 | reader.close(); 312 | } 313 | } catch (IOException e) { 314 | } 315 | try { 316 | if (in != null) { 317 | in.close(); 318 | } 319 | } catch (IOException e) { 320 | e.printStackTrace(); 321 | } 322 | if (out != null) { 323 | out.close(); 324 | } 325 | } 326 | 327 | try { 328 | status = String.valueOf(httpsConn.getResponseCode()); 329 | } catch (IOException e) { 330 | status = e.getMessage(); 331 | BurpExtender.stderr.println("[*] " + e.getMessage()); 332 | } 333 | mapResult.put("status",status); 334 | mapResult.put("header",rspHeader); 335 | mapResult.put("result",result); 336 | return mapResult; 337 | } 338 | 339 | 340 | 341 | private static class TrustAnyTrustManager implements X509TrustManager { 342 | 343 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 344 | } 345 | 346 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 347 | } 348 | 349 | public X509Certificate[] getAcceptedIssuers() { 350 | return new X509Certificate[] {}; 351 | } 352 | } 353 | 354 | private static class TrustAnyHostnameVerifier implements HostnameVerifier { 355 | public boolean verify(String hostname, SSLSession session) { 356 | return true; 357 | } 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /src/main/java/burp/HttpLogTable.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import javax.swing.*; 4 | import javax.swing.table.TableModel; 5 | 6 | public class HttpLogTable extends JTable { 7 | private HttpLogTableModel httpLogTableModel; 8 | 9 | public HttpLogTableModel getHttpLogTableModel() { 10 | return httpLogTableModel; 11 | } 12 | 13 | 14 | public HttpLogTable(TableModel tableModel) { 15 | super(tableModel); 16 | this.httpLogTableModel = (HttpLogTableModel) tableModel; 17 | } 18 | 19 | @Override 20 | public void changeSelection(int row, int col, boolean toggle, boolean extend) { 21 | super.changeSelection(row, col, toggle, extend); 22 | // show the log entry for the selected row 23 | LogEntry logEntry = BurpExtender.log.get(row); 24 | GUI.requestViewer.setMessage(logEntry.requestResponse.getRequest(), true); 25 | GUI.responseViewer.setMessage(logEntry.requestResponse.getResponse(), false); 26 | GUI.proxyRspViewer.setText(logEntry.proxyResponse.getBytes()); 27 | GUI.proxyRspViewer.setEditable(false); 28 | GUI.currentlyDisplayedItem = logEntry.requestResponse; 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/burp/HttpLogTableModel.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import javax.swing.table.AbstractTableModel; 4 | 5 | public class HttpLogTableModel extends AbstractTableModel { 6 | public int getRowCount() { 7 | return BurpExtender.log.size(); 8 | } 9 | 10 | public int getColumnCount() { 11 | return 5; 12 | } 13 | 14 | @Override 15 | public String getColumnName(int columnIndex) { 16 | 17 | switch (columnIndex) 18 | { 19 | case 0: 20 | return "#"; 21 | case 1: 22 | return "Method"; 23 | case 2: 24 | return "URL"; 25 | case 3: 26 | return "Status"; 27 | case 4: 28 | return "Time"; 29 | default: 30 | return ""; 31 | } 32 | } 33 | 34 | @Override 35 | public Class getColumnClass(int columnIndex) 36 | { 37 | return String.class; 38 | } 39 | 40 | 41 | public Object getValueAt(int rowIndex, int columnIndex) { 42 | LogEntry logEntry = BurpExtender.log.get(rowIndex); 43 | 44 | switch (columnIndex) { 45 | case 0: 46 | return logEntry.id; 47 | case 1: 48 | return logEntry.method; 49 | case 2: 50 | return logEntry.url.toString(); 51 | case 3: 52 | return logEntry.status; 53 | case 4: 54 | return logEntry.requestTime; 55 | default: 56 | return ""; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/burp/LogEntry.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.net.URL; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.Map; 7 | 8 | public class LogEntry { 9 | final int id; 10 | final IHttpRequestResponsePersisted requestResponse; 11 | final URL url; 12 | final String method; 13 | final String status; 14 | final String proxyResponse; 15 | public String requestTime; 16 | 17 | LogEntry(int id, IHttpRequestResponsePersisted requestResponse, URL url, String method, Map mapResult) { 18 | this.id = id; 19 | this.requestResponse = requestResponse; 20 | this.url = url; 21 | this.method = method; 22 | this.status = mapResult.get("status"); 23 | this.proxyResponse = mapResult.get("header") + "\r\n" + mapResult.get("result"); 24 | this.requestTime = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/burp/Utils.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | public class Utils { 7 | public static String getBanner(){ 8 | String bannerInfo = 9 | "[+] " + BurpExtender.extensionName + " is loaded\n" 10 | + "[+] ^_^\n" 11 | + "[+]\n" 12 | + "[+] #####################################\n" 13 | + "[+] " + BurpExtender.extensionName + " v" + BurpExtender.version +"\n" 14 | + "[+] anthor: c0ny1\n" 15 | + "[+] email: root@gv7.me\n" 16 | + "[+] github: http://github.com/c0ny1/passive-scan-client\n" 17 | + "[+] ####################################\n" 18 | + "[+] Please enjoy it!\n"; 19 | return bannerInfo; 20 | } 21 | 22 | // 匹配规则 23 | public static boolean isMathch(String regx,String str){ 24 | Pattern pat = Pattern.compile("([\\w]+[\\.]|)("+regx+")",Pattern.CASE_INSENSITIVE);//正则判断 25 | Matcher mc= pat.matcher(str);//条件匹配 26 | if(mc.find()){ 27 | return true; 28 | }else{ 29 | return false; 30 | } 31 | } 32 | 33 | // 更新成功数据 34 | public static void updateSuccessCount(){ 35 | synchronized(Config.FAIL_TOTAL){ 36 | Config.REQUEST_TOTAL++; 37 | Config.SUCCESS_TOTAL++; 38 | GUI.lbRequestCount.setText(String.valueOf(Config.REQUEST_TOTAL)); 39 | GUI.lbSuccesCount.setText(String.valueOf(Config.SUCCESS_TOTAL)); 40 | } 41 | } 42 | 43 | // 更新失败数据 44 | public static void updateFailCount(){ 45 | synchronized(Config.SUCCESS_TOTAL){ 46 | Config.REQUEST_TOTAL++; 47 | Config.FAIL_TOTAL++; 48 | GUI.lbRequestCount.setText(String.valueOf(Config.REQUEST_TOTAL)); 49 | GUI.lbFailCount.setText(String.valueOf(Config.FAIL_TOTAL)); 50 | } 51 | } 52 | } 53 | --------------------------------------------------------------------------------