├── .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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
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 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/qaplug_profiles.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 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
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 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
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 |
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 | 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 |
353 |
354 |
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 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 | 1560504663123
430 |
431 |
432 | 1560504663123
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
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 |
488 |
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 | 
15 |
16 | ## 0x02 插件编译
17 |
18 | ```
19 | mvn package
20 | ```
21 |
22 | ## 0x03 插件演示
23 |
24 | 可以通过插件将流量转发到各种被动式扫描器中,这里我选`xray`来演示.
25 |
26 | 
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 |
--------------------------------------------------------------------------------