├── .idea
├── .gitignore
├── vcs.xml
├── compiler.xml
├── encodings.xml
├── misc.xml
├── jarRepositories.xml
└── uiDesigner.xml
├── src
└── main
│ ├── resources
│ ├── strings.properties
│ └── project_options.json
│ └── java
│ └── AutoBurp
│ ├── bypass
│ ├── beens
│ │ ├── OS.java
│ │ ├── Browsers.java
│ │ ├── ClientCertificate.java
│ │ ├── HTTP.java
│ │ ├── TLSNegotiation.java
│ │ ├── HTTP2.java
│ │ ├── SSL.java
│ │ ├── ProjectOptions.java
│ │ ├── ProxySettings.java
│ │ ├── Negotiation.java
│ │ ├── DomainSettings.java
│ │ ├── TLSSettings.java
│ │ ├── Proxy.java
│ │ └── MatchAndReplace.java
│ ├── TriggerCipherGuesser.java
│ ├── DomainSettingsManager.java
│ ├── TLSContextMenuItemsProvider.java
│ ├── BypassBotDetection.java
│ ├── Utilities.java
│ ├── Constants.java
│ └── DomainSettingsPanel.java
│ ├── fuzzer
│ ├── phone
│ │ └── PhoneFuzzer.java
│ └── upload
│ │ └── UploadFuzzer.java
│ ├── fingerprint
│ ├── ui
│ │ ├── renderer
│ │ │ ├── CenterRenderer.java
│ │ │ └── HeaderIconRenderer.java
│ │ ├── WrapLayout.java
│ │ ├── RequestResponsePanel.java
│ │ ├── TagsPanel.java
│ │ ├── ControlPanel.java
│ │ ├── FingerPrintTab.java
│ │ └── LogTablePanel.java
│ ├── model
│ │ ├── FingerPrintRule.java
│ │ └── TableLogModel.java
│ ├── util
│ │ ├── HTTPUtils.java
│ │ ├── Utils.java
│ │ └── FingerPrintUtils.java
│ └── FingerPrintScanner.java
│ └── generator
│ └── PhonePayloadGeneratorFactory.java
├── README.md
└── pom.xml
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/strings.properties:
--------------------------------------------------------------------------------
1 | menu_brute_force=Brute force ciphers
2 | menu_downgrade=downgrade HTTP2
3 | network_preferences=AutoBurp.bypass
4 | proxy_preferences=AutoBurp.bypass.beens.proxy
5 | negotiation=Bypass!
6 | message=Adjust ciphers to common browsers
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/OS.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | public enum OS {
4 | WINDOWS("Windows"),
5 | MACOS("Mac"),
6 | LINUX("Linux");
7 | public final String name;
8 |
9 | OS(String name) {
10 | this.name = name;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/Browsers.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | public enum Browsers {
4 | FIREFOX("Firefox"),
5 | CHROME("Chrome"),
6 | SAFARI("Safari");
7 | public final String name;
8 |
9 | Browsers(String name) {
10 | this.name = name;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/ClientCertificate.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | public class ClientCertificate {
6 | private final @Expose String[] certificates;
7 | private final @Expose boolean use;
8 |
9 | public ClientCertificate(String[] certificates, boolean use) {
10 | this.certificates = certificates;
11 | this.use = use;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/HTTP.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | public class HTTP {
6 | private @Expose HTTP2 http2;
7 |
8 | public HTTP(HTTP2 http2) {
9 | this.http2 = http2;
10 | }
11 |
12 | public HTTP2 getHttp2() {
13 | return http2;
14 | }
15 |
16 | public void setHttp2(HTTP2 http2) {
17 | this.http2 = http2;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/TLSNegotiation.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import java.util.Arrays;
4 |
5 | public record TLSNegotiation(String[] protocols, String[] ciphers) {
6 | public TLSNegotiation {
7 | }
8 |
9 | @Override
10 | public String toString() {
11 | return "TLSNegotiation{" +
12 | "protocols=" + Arrays.toString(protocols) +
13 | ", ciphers=" + Arrays.toString(ciphers) +
14 | '}';
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/HTTP2.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | public class HTTP2 {
6 | private @Expose boolean enable_http2;
7 |
8 | public HTTP2(boolean enable_http2) {
9 | this.enable_http2 = enable_http2;
10 | }
11 |
12 | public boolean getEnableHTTP2() {
13 | return enable_http2;
14 | }
15 |
16 | public void setEnableHTTP2(boolean enable_http2) {
17 | this.enable_http2 = enable_http2;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/SSL.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | public class SSL {
6 | private @Expose Negotiation negotiation;
7 |
8 | public SSL(Negotiation negotiation) {
9 | this.negotiation = negotiation;
10 | }
11 |
12 | public Negotiation getNegotiation() {
13 | return negotiation;
14 | }
15 |
16 | public void setNegotiation(Negotiation negotiation) {
17 | this.negotiation = negotiation;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/ProjectOptions.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | public class ProjectOptions {
6 | private @Expose SSL ssl;
7 | private @Expose HTTP http;
8 |
9 | public ProjectOptions(SSL ssl) {
10 | this.ssl = ssl;
11 | }
12 |
13 | public SSL getSsl() {
14 | return ssl;
15 | }
16 | public HTTP getHTTP() {
17 | return http;
18 | }
19 |
20 | public void setSsl(SSL ssl) {
21 | this.ssl = ssl;
22 | }
23 | public void setHTTP(HTTP http) {
24 | this.http = http;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/ProxySettings.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | import java.util.List;
6 |
7 | public class ProxySettings {
8 | private final @Expose Proxy proxy;
9 |
10 | public ProxySettings(Proxy proxy) {
11 | this.proxy = proxy;
12 | }
13 | public ProxySettings toggleMatchAndReplace(MatchAndReplace rule) {
14 | Proxy existing = this.proxy;
15 | existing.toggleMatchAndReplace(rule);
16 | return new ProxySettings(existing);
17 | }
18 | public ProxySettings toggleHTTPDowngradeMatchAndReplace(List rules) {
19 | Proxy existing = this.proxy;
20 | existing.toggleHTTPDowngradeMatchAndReplace(rules);
21 | return new ProxySettings(existing);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fuzzer/phone/PhoneFuzzer.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fuzzer.phone;
2 |
3 | import AutoBurp.generator.PhonePayloadGeneratorFactory;
4 | import burp.*;
5 |
6 | public class PhoneFuzzer implements IIntruderPayloadGeneratorFactory {
7 | private IExtensionHelpers helpers;
8 | private IBurpExtenderCallbacks callbacks;
9 |
10 | public PhoneFuzzer(IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) {
11 | this.helpers = helpers;
12 | this.callbacks = callbacks;
13 | }
14 |
15 | @Override
16 | public String getGeneratorName() {
17 |
18 | return "Phone Bypass Fuzzer";
19 | }
20 |
21 | @Override
22 | public IIntruderPayloadGenerator createNewInstance(IIntruderAttack attack) {
23 |
24 | return new PhonePayloadGeneratorFactory(this.helpers, attack, this.callbacks);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AutoBurpFuzz
2 |
3 | # 简介
4 | 1.tls and http 浏览器指纹绕过
5 |
6 | 2.被动指纹扫描
7 |
8 | 3.文件上传 Intruder fuzz
9 |
10 | 4.手机号 Intruder fuzz
11 |
12 | # 本人环境参考
13 | > burp环境burpsuite 2025.2
14 | >
15 | > 工具环境:
16 | > java17编写
17 | > java17编译
18 |
19 | # tls指纹绕过使用方法
20 | 1.将需要绕过的域名,直接添加既可
21 |
22 | 
23 |
24 |
25 | # upload_fuzz使用方法
26 | 1.成功加载该插件,smb_fuzz和下面同理
27 |
28 | 2.将需要fuzz的包,传送到Intruder中
29 |
30 | 3.设置这种部位为payload地址
31 |
32 |
33 |
34 | 4.然后设置如下内容
35 |
36 |
37 |
38 |
39 |
40 | # 参考项目
41 | > https://github.com/T3nk0/Upload_Auto_Fuzz
42 | >
43 | > https://github.com/shuanx/BurpFingerPrint
44 | >
45 | > https://github.com/yuziiiiiiiiii/SMS_Bomb_Fuzzer
46 | >
47 | > https://github.com/PortSwigger/bypass-bot-detection
48 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/ui/renderer/CenterRenderer.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.ui.renderer;
2 |
3 | import javax.swing.table.DefaultTableCellRenderer;
4 | import java.awt.*;
5 |
6 | /**
7 | * 居中显示的表格单元格渲染器
8 | */
9 | public class CenterRenderer extends DefaultTableCellRenderer {
10 | public CenterRenderer() {
11 | setHorizontalAlignment(CENTER);
12 | }
13 |
14 | @Override
15 | public Component getTableCellRendererComponent(javax.swing.JTable table, Object value,
16 | boolean isSelected, boolean hasFocus,
17 | int row, int column) {
18 | Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
19 |
20 | if (isSelected) {
21 | c.setBackground(new Color(66, 139, 202));
22 | c.setForeground(Color.WHITE);
23 | } else {
24 |
25 | if (row % 2 == 0) {
26 | c.setBackground(Color.WHITE);
27 | } else {
28 | c.setBackground(new Color(249, 249, 249));
29 | }
30 | c.setForeground(new Color(51, 51, 51));
31 | }
32 |
33 | return c;
34 | }
35 | }
--------------------------------------------------------------------------------
/src/main/resources/project_options.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_options":{
3 | "ssl":{
4 | "client_certificates":{
5 | "certificates":[],
6 | "use_user_options":true
7 | },
8 | "negotiation":{
9 | "allow_unsafe_renegotiation":false,
10 | "disable_ssl_session_resume":true,
11 | "enabled_ciphers":[
12 | "TLS_AES_128_GCM_SHA256",
13 | "TLS_AES_256_GCM_SHA384",
14 | "TLS_CHACHA20_POLY1305_SHA256",
15 | "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
16 | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
17 | "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
18 | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
19 | "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
20 | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
21 | "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
22 | "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
23 | "TLS_RSA_WITH_AES_128_GCM_SHA256",
24 | "TLS_RSA_WITH_AES_256_GCM_SHA384",
25 | "TLS_RSA_WITH_AES_128_CBC_SHA",
26 | "TLS_RSA_WITH_AES_256_CBC_SHA"
27 | ],
28 | "enabled_protocols":[
29 | "TLSv1.2",
30 | "TLSv1.3"
31 | ],
32 | "enforce_upstream_trust":false,
33 | "tls_negotiation_behavior":"use_custom"
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/model/FingerPrintRule.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.model;
2 |
3 | import java.util.List;
4 |
5 | public class FingerPrintRule {
6 | private String cms;
7 | private String method;
8 | private String location;
9 | private List keyword;
10 | private boolean isImportant;
11 | private String type;
12 |
13 | public FingerPrintRule() {
14 | }
15 |
16 | public FingerPrintRule(String type, boolean isImportant, String cms, String method, String location, List keyword) {
17 | this.cms = cms;
18 | this.method = method;
19 | this.location = location;
20 | this.keyword = keyword;
21 | this.type = type;
22 | this.isImportant = isImportant;
23 | }
24 |
25 | public String getType() {
26 | return type;
27 | }
28 |
29 |
30 | public boolean getIsImportant() {
31 | return isImportant;
32 | }
33 |
34 |
35 | public String getCms() {
36 | return cms;
37 | }
38 |
39 | public String getMethod() {
40 | return method;
41 | }
42 |
43 | public String getLocation() {
44 | return location;
45 | }
46 |
47 |
48 | public List getKeyword() {
49 | return keyword;
50 | }
51 |
52 | public String getInfo() {
53 | return "cms: " + cms + "\r\nmethod: " + method + "\r\nlocation: " + location + "\r\nkeyword: " + keyword.toString();
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/Negotiation.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | public class Negotiation {
6 | private @Expose String[] enabled_ciphers;
7 | private @Expose String[] enabled_protocols;
8 | private @Expose String tls_negotiation_behavior;
9 | private @Expose boolean disable_ssl_session_resume;
10 | private @Expose boolean allow_unsafe_renegotiation;
11 | private @Expose boolean enforce_upstream_trust;
12 |
13 | public Negotiation(String[] enabled_ciphers, String[] enabled_protocols, boolean disable_ssl_session_resume) {
14 | this.enabled_ciphers = enabled_ciphers;
15 | this.enabled_protocols = enabled_protocols;
16 | this.tls_negotiation_behavior = "use_custom";
17 | this.disable_ssl_session_resume = disable_ssl_session_resume;
18 | }
19 |
20 | public void setEnabledProtocols(String[] enabled_protocols) {
21 | this.enabled_protocols = enabled_protocols;
22 | }
23 |
24 | public void setEnabledCiphers(String[] enabled_ciphers) {
25 | this.enabled_ciphers = enabled_ciphers;
26 | }
27 |
28 | public void setDisableSslSessionResume(boolean disable_ssl_session_resume) {
29 | this.disable_ssl_session_resume = disable_ssl_session_resume;
30 | }
31 |
32 | public void setTlsNegotiationBehavior(String tls_negotiation_behavior) {
33 | this.tls_negotiation_behavior = tls_negotiation_behavior;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/DomainSettings.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import java.time.LocalDateTime;
4 | import java.time.format.DateTimeFormatter;
5 |
6 | public class DomainSettings {
7 | private String domain;
8 | private String browser;
9 | private String[] protocols;
10 | private String[] ciphers;
11 | private boolean httpDowngrade;
12 | private String timestamp;
13 |
14 | public DomainSettings(String domain, String browser, String[] protocols, String[] ciphers, boolean httpDowngrade) {
15 | this.domain = domain;
16 | this.browser = browser;
17 | this.protocols = protocols;
18 | this.ciphers = ciphers;
19 | this.httpDowngrade = httpDowngrade;
20 | this.timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
21 | }
22 |
23 | public String getDomain() {
24 | return domain;
25 | }
26 |
27 | public String getBrowser() {
28 | return browser;
29 | }
30 |
31 | public String[] getProtocols() {
32 | return protocols;
33 | }
34 |
35 | public String[] getCiphers() {
36 | return ciphers;
37 | }
38 |
39 | public boolean isHttpDowngrade() {
40 | return httpDowngrade;
41 | }
42 |
43 | public String getTimestamp() {
44 | return timestamp;
45 | }
46 |
47 | @Override
48 | public String toString() {
49 | return String.format("域名: %s, 浏览器: %s, HTTP降级: %s, 时间: %s",
50 | domain, browser, httpDowngrade ? "是" : "否", timestamp);
51 | }
52 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/TLSSettings.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 | import AutoBurp.bypass.Constants;
5 |
6 | public class TLSSettings {
7 | private @Expose ProjectOptions project_options;
8 |
9 | public TLSSettings(ProjectOptions project_options) {
10 | this.project_options = project_options;
11 | }
12 |
13 | public void addProtocols(String[] protocols) {
14 | SSL ssl = this.project_options.getSsl();
15 | Negotiation negotiation = ssl.getNegotiation();
16 | negotiation.setEnabledProtocols(protocols);
17 | negotiation.setTlsNegotiationBehavior(Constants.BURP_TLS_NEGOTIATION);
18 | ssl.setNegotiation(negotiation);
19 | this.project_options.setSsl(ssl);
20 | }
21 |
22 | public void addCiphers(String[] ciphers) {
23 | SSL ssl = this.project_options.getSsl();
24 | Negotiation negotiation = ssl.getNegotiation();
25 | negotiation.setEnabledCiphers(ciphers);
26 | negotiation.setTlsNegotiationBehavior(Constants.BURP_TLS_NEGOTIATION);
27 | ssl.setNegotiation(negotiation);
28 | this.project_options.setSsl(ssl);
29 | }
30 |
31 | public void toggleHTTPSettings() {
32 | HTTP http = this.project_options.getHTTP();
33 | boolean enabled = http.getHttp2().getEnableHTTP2();
34 | http.setHttp2(new HTTP2(!enabled));
35 | this.project_options.setHTTP(http);
36 | }
37 |
38 | public boolean enabledHTTPDowngrade() {
39 | return this.project_options.getHTTP().getHttp2().getEnableHTTP2();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.example
8 | AutoBurpFuzz
9 | 2.0-SNAPSHOT
10 |
11 |
12 | 17
13 | 17
14 | UTF-8
15 |
16 |
17 |
18 | net.portswigger.burp.extender
19 | burp-extender-api
20 | 1.7.22
21 |
22 |
23 | com.google.code.gson
24 | gson
25 | 2.10.1
26 |
27 |
28 | net.portswigger.burp.extensions
29 | montoya-api
30 | 2024.12
31 |
32 |
33 |
34 |
35 |
36 | org.apache.maven.plugins
37 | maven-assembly-plugin
38 |
39 |
40 | package
41 |
42 | single
43 |
44 |
45 |
46 |
47 |
48 | jar-with-dependencies
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/ui/WrapLayout.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.ui;
2 |
3 | import java.awt.*;
4 |
5 | /**
6 | * 自动换行的FlowLayout实现
7 | * 当容器宽度不足时,组件会自动换行显示
8 | */
9 | public class WrapLayout extends FlowLayout {
10 |
11 | public WrapLayout(int align, int hgap, int vgap) {
12 | super(align, hgap, vgap);
13 | }
14 |
15 | @Override
16 | public Dimension preferredLayoutSize(Container target) {
17 | return layoutSize(target, true);
18 | }
19 |
20 | @Override
21 | public Dimension minimumLayoutSize(Container target) {
22 | Dimension minimum = layoutSize(target, false);
23 | minimum.width -= (getHgap() + 1);
24 | return minimum;
25 | }
26 |
27 | private Dimension layoutSize(Container target, boolean preferred) {
28 | synchronized (target.getTreeLock()) {
29 |
30 | int targetWidth = target.getSize().width;
31 |
32 |
33 | if (targetWidth == 0) {
34 | targetWidth = Integer.MAX_VALUE;
35 | }
36 |
37 | int hgap = getHgap();
38 | int vgap = getVgap();
39 | Insets insets = target.getInsets();
40 | int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
41 |
42 |
43 | int maxWidth = targetWidth - horizontalInsetsAndGap;
44 |
45 |
46 | int x = 0;
47 | int y = insets.top;
48 | int rowHeight = 0;
49 |
50 |
51 | int nmembers = target.getComponentCount();
52 |
53 | for (int i = 0; i < nmembers; i++) {
54 | Component m = target.getComponent(i);
55 | if (m.isVisible()) {
56 | Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();
57 |
58 |
59 | if (x > 0 && x + d.width > maxWidth) {
60 | x = 0;
61 | y += rowHeight + vgap;
62 | rowHeight = 0;
63 | }
64 |
65 |
66 | if (x > 0) {
67 | x += hgap;
68 | }
69 | x += d.width;
70 | rowHeight = Math.max(rowHeight, d.height);
71 | }
72 | }
73 |
74 |
75 | y += rowHeight + insets.bottom;
76 |
77 | return new Dimension(targetWidth, y);
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/util/HTTPUtils.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.util;
2 |
3 | import burp.IBurpExtenderCallbacks;
4 | import burp.IExtensionHelpers;
5 | import burp.IHttpRequestResponse;
6 | import burp.IHttpService;
7 |
8 | import java.net.URL;
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | public class HTTPUtils {
13 |
14 | public static Map makeGetRequest(String getUrl, IExtensionHelpers helpers, IBurpExtenderCallbacks callbacks) {
15 |
16 | String host;
17 | int port;
18 | String protocol;
19 | String path;
20 |
21 | try {
22 |
23 | URL url = new URL(getUrl);
24 |
25 | protocol = url.getProtocol();
26 | host = url.getHost();
27 | port = url.getPort();
28 |
29 | if (port == -1 && protocol.equalsIgnoreCase("http")) {
30 | port = 80;
31 | } else if (port == -1 && protocol.equalsIgnoreCase("https")) {
32 | port = 443;
33 | }
34 |
35 | path = url.getPath();
36 | if (path.isEmpty()) {
37 | path = "/";
38 | }
39 |
40 | if (url.getQuery() != null) {
41 | path += "?" + url.getQuery();
42 | }
43 | } catch (Exception e) {
44 |
45 | callbacks.printError("Invalid URL: " + getUrl);
46 | return null;
47 | }
48 |
49 |
50 | IHttpService httpService = helpers.buildHttpService(host, port, protocol);
51 |
52 |
53 | String request = "GET " + path + " HTTP/1.1\r\n" +
54 | "Host: " + host + "\r\n" +
55 | "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36\r\n" +
56 | "Accept: */*\r\n" +
57 | "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n" +
58 | "Connection: close\r\n" +
59 | "\r\n";
60 |
61 | byte[] requestBytes = request.getBytes();
62 |
63 |
64 | IHttpRequestResponse response = callbacks.makeHttpRequest(httpService, requestBytes);
65 |
66 |
67 | Map responseData = new HashMap<>();
68 | responseData.put("responseRequest", response);
69 | responseData.put("isFindUrl", true);
70 | responseData.put("method", "GET");
71 |
72 | return responseData;
73 | }
74 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/ui/RequestResponsePanel.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.ui;
2 |
3 | import burp.*;
4 |
5 | import javax.swing.*;
6 | import java.awt.*;
7 | import java.util.Objects;
8 |
9 | public class RequestResponsePanel extends JPanel {
10 | private final IBurpExtenderCallbacks callbacks;
11 | private final IMessageEditorController controller;
12 |
13 |
14 | private IMessageEditor requestEditor;
15 | private IMessageEditor responseEditor;
16 |
17 | public RequestResponsePanel(IBurpExtenderCallbacks callbacks, IMessageEditorController controller) {
18 | this.callbacks = callbacks;
19 | this.controller = controller;
20 |
21 | setLayout(new BorderLayout());
22 |
23 |
24 | JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
25 | splitPane.setDividerLocation(0.5);
26 | splitPane.setContinuousLayout(true);
27 | add(splitPane, BorderLayout.CENTER);
28 |
29 |
30 | requestEditor = callbacks.createMessageEditor(controller, false);
31 | JPanel requestPanel = new JPanel(new BorderLayout());
32 | requestPanel.add(new JLabel("请求"), BorderLayout.NORTH);
33 | requestPanel.add(requestEditor.getComponent(), BorderLayout.CENTER);
34 | splitPane.setLeftComponent(requestPanel);
35 |
36 |
37 | responseEditor = callbacks.createMessageEditor(controller, false);
38 | JPanel responsePanel = new JPanel(new BorderLayout());
39 | responsePanel.add(new JLabel("响应"), BorderLayout.NORTH);
40 | responsePanel.add(responseEditor.getComponent(), BorderLayout.CENTER);
41 | splitPane.setRightComponent(responsePanel);
42 | }
43 |
44 | public void setRequestResponse(IHttpRequestResponse requestResponse) {
45 | if (requestResponse != null) {
46 |
47 | byte[] request = requestResponse.getRequest();
48 | byte[] response = requestResponse.getResponse();
49 |
50 |
51 | requestEditor.setMessage(new byte[0], true);
52 | responseEditor.setMessage(new byte[0], false);
53 |
54 |
55 | if (request != null) {
56 | requestEditor.setMessage(request, true);
57 | }
58 |
59 | if (response != null) {
60 | responseEditor.setMessage(response, false);
61 | }
62 | } else {
63 | clear();
64 | }
65 | }
66 |
67 | public void clear() {
68 | requestEditor.setMessage(new byte[0], true);
69 | responseEditor.setMessage(new byte[0], false);
70 | }
71 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/Proxy.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.List;
8 | import java.util.Optional;
9 |
10 | public class Proxy {
11 | private @Expose MatchAndReplace[] match_replace_rules;
12 |
13 | public Proxy(MatchAndReplace[] match_replace_rules) {
14 | this.match_replace_rules = match_replace_rules;
15 | }
16 |
17 | public MatchAndReplace[] getMatchReplaceRules() {
18 | return match_replace_rules;
19 | }
20 |
21 | public void setMatchReplaceRules(MatchAndReplace[] match_replace_rules) {
22 | this.match_replace_rules = match_replace_rules;
23 | }
24 | public void toggleMatchAndReplace(MatchAndReplace rule){
25 | List existing = new ArrayList<>(List.of(this.match_replace_rules));
26 | Arrays.stream(Browsers.values()).forEach(browser -> {
27 | Optional optional = existing.stream().filter(r -> r.filterByBrowser(browser)).findFirst();
28 | if (optional.isPresent()) {
29 | MatchAndReplace availableRule = optional.get();
30 | existing.remove(availableRule);
31 | availableRule.setEnabled(false);
32 | existing.add(availableRule);
33 |
34 | }
35 | });
36 |
37 | Optional found = existing.stream().filter(r -> r.filterByComment(rule)).findFirst();
38 | if (found.isEmpty()) {
39 | existing.add(rule);
40 | } else {
41 | MatchAndReplace availableRule = found.get();
42 | existing.remove(availableRule);
43 | availableRule.setEnabled(true);
44 | existing.add(availableRule);
45 | }
46 | setMatchReplaceRules(existing.toArray(new MatchAndReplace[0]));
47 | }
48 | public void toggleHTTPDowngradeMatchAndReplace(List rules){
49 | List existing = new ArrayList<>(List.of(this.match_replace_rules));
50 | for(MatchAndReplace rule: rules) {
51 | Optional found = existing.stream().filter(r -> r.filterByComment(rule)).findFirst();
52 | if (found.isEmpty()) {
53 | existing.add(rule);
54 | } else {
55 | MatchAndReplace availableRule = found.get();
56 | existing.remove(availableRule);
57 | availableRule.setEnabled(!availableRule.isEnabled());
58 | existing.add(availableRule);
59 | }
60 | }
61 | setMatchReplaceRules(existing.toArray(new MatchAndReplace[0]));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/beens/MatchAndReplace.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass.beens;
2 |
3 | import com.google.gson.annotations.Expose;
4 | import AutoBurp.bypass.Constants;
5 |
6 | import java.util.*;
7 |
8 | import static AutoBurp.bypass.Constants.*;
9 |
10 | public class MatchAndReplace {
11 | private @Expose String comment;
12 | private @Expose boolean enabled;
13 | private @Expose boolean is_simple_match;
14 | private @Expose String rule_type;
15 | private @Expose String string_match;
16 | private @Expose String string_replace;
17 |
18 | public MatchAndReplace(String comment, boolean enabled, boolean is_simple_match, String rule_type, String string_match, String string_replace) {
19 | this.comment = comment;
20 | this.enabled = enabled;
21 | this.is_simple_match = is_simple_match;
22 | this.rule_type = rule_type;
23 | this.string_match = string_match;
24 | this.string_replace = string_replace;
25 | }
26 |
27 | public static List createDowngradeRules(){
28 | List rules = new ArrayList<>();
29 | for(String header : MATCH_AND_REPLACE_REGEXP_HTTP2) {
30 | rules.add(new MatchAndReplace(
31 | String.format("HTTP2 Header %s downgrade rule", header),
32 | true,
33 | false,
34 | Constants.MATCH_AND_REPLACE_RULE_TYPE,
35 | header,
36 | ""
37 | ));
38 | }
39 | return rules;
40 | }
41 |
42 | public static MatchAndReplace create(Browsers browser){
43 | String platform = System.getProperty("os.name","Windows");
44 | OS optionalOS = Arrays.stream(OS.values()).filter(os -> platform.contains(os.name)).findFirst().get();
45 | String format = BROWSERS_USER_AGENTS.get(browser.name);
46 | String value = BROWSERS_PLATFORMS.get(browser.name).get(optionalOS.name);
47 | return new MatchAndReplace(
48 | String.format("Emulate %s User-Agent", browser.name),
49 | true,
50 | false,
51 | Constants.MATCH_AND_REPLACE_RULE_TYPE,
52 | Constants.MATCH_AND_REPLACE_REGEXP,
53 | String.format(format,value)
54 | );
55 | }
56 | public boolean filterByComment(MatchAndReplace filter) {
57 | return this.comment != null && filter.comment != null && this.comment.equalsIgnoreCase(filter.comment);
58 | }
59 |
60 | public boolean filterByBrowser(Browsers browser) {
61 | return this.comment != null && browser != null &&
62 | this.comment.equalsIgnoreCase(String.format("Emulate %s User-Agent", browser.name));
63 | }
64 |
65 | public void setEnabled(boolean enabled) {
66 | this.enabled = enabled;
67 | }
68 |
69 | public boolean isEnabled() {
70 | return enabled;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/ui/renderer/HeaderIconRenderer.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.ui.renderer;
2 |
3 | import javax.swing.*;
4 | import javax.swing.border.EmptyBorder;
5 | import javax.swing.table.DefaultTableCellRenderer;
6 | import javax.swing.table.JTableHeader;
7 | import java.awt.*;
8 | import java.util.Set;
9 | import java.util.HashSet;
10 |
11 | /**
12 | * 表头渲染器,支持显示排序图标和过滤图标
13 | * 优化后支持动态配置哪些列显示过滤图标
14 | */
15 | public class HeaderIconRenderer extends DefaultTableCellRenderer {
16 | private static final Color HEADER_BG_COLOR = new Color(245, 245, 245);
17 | private static final Color HEADER_TEXT_COLOR = new Color(51, 51, 51);
18 | private static final Color HEADER_BORDER_COLOR = new Color(221, 221, 221);
19 | private static final Color ICON_COLOR = new Color(119, 119, 119);
20 |
21 |
22 | private final Set filterColumns = new HashSet<>();
23 |
24 | public HeaderIconRenderer() {
25 | setHorizontalAlignment(LEFT);
26 | setHorizontalTextPosition(LEFT);
27 | setVerticalAlignment(CENTER);
28 | setOpaque(true);
29 | }
30 |
31 | /**
32 | * 添加需要显示过滤图标的列
33 | * @param columnIndex 列索引
34 | */
35 | public void addFilterColumn(int columnIndex) {
36 | filterColumns.add(columnIndex);
37 | }
38 |
39 | @Override
40 | public Component getTableCellRendererComponent(JTable table, Object value,
41 | boolean isSelected, boolean hasFocus,
42 | int row, int column) {
43 | JTableHeader header = table.getTableHeader();
44 | if (header != null) {
45 | setForeground(HEADER_TEXT_COLOR);
46 | setBackground(HEADER_BG_COLOR);
47 | setFont(header.getFont());
48 | }
49 |
50 | setBorder(BorderFactory.createCompoundBorder(
51 | BorderFactory.createMatteBorder(0, 0, 1, 1, HEADER_BORDER_COLOR),
52 | new EmptyBorder(5, 5, 5, 5)
53 | ));
54 |
55 |
56 | if (filterColumns.contains(column)) {
57 | setIcon(createFilterIcon());
58 | setIconTextGap(5);
59 | } else {
60 | setIcon(null);
61 | }
62 |
63 | setText(value == null ? "" : value.toString());
64 |
65 | return this;
66 | }
67 |
68 | private Icon createFilterIcon() {
69 | return new Icon() {
70 | @Override
71 | public void paintIcon(Component c, Graphics g, int x, int y) {
72 | Graphics2D g2d = (Graphics2D) g.create();
73 | g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
74 |
75 | int size = 8;
76 | int[] xPoints = {x, x + size, x + size/2};
77 | int[] yPoints = {y, y, y + size/2};
78 |
79 | g2d.setColor(ICON_COLOR);
80 | g2d.fillPolygon(xPoints, yPoints, 3);
81 |
82 | g2d.dispose();
83 | }
84 |
85 | @Override
86 | public int getIconWidth() {
87 | return 10;
88 | }
89 |
90 | @Override
91 | public int getIconHeight() {
92 | return 10;
93 | }
94 | };
95 | }
96 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fuzzer/upload/UploadFuzzer.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fuzzer.upload;
2 |
3 | import AutoBurp.generator.UploadPayloadGenerator;
4 | import burp.IBurpExtenderCallbacks;
5 | import burp.IExtensionHelpers;
6 | import burp.IIntruderAttack;
7 | import burp.IIntruderPayloadGenerator;
8 |
9 | import java.util.ArrayList;
10 | import java.util.HashSet;
11 | import java.util.List;
12 | import java.util.Set;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 | public class UploadFuzzer implements IIntruderPayloadGenerator {
17 | private final IExtensionHelpers helpers;
18 | private final IIntruderAttack attack;
19 | private int payloadIndex = 0;
20 | private List attackPayloads = new ArrayList<>();
21 | private boolean initialized = false;
22 |
23 | private final IBurpExtenderCallbacks callbacks;
24 |
25 | public UploadFuzzer(IExtensionHelpers helpers, IIntruderAttack attack, IBurpExtenderCallbacks callbacks) {
26 | this.helpers = helpers;
27 | this.attack = attack;
28 | this.callbacks = callbacks;
29 | }
30 |
31 | @Override
32 | public boolean hasMorePayloads() {
33 | if (!initialized) {
34 | return true;
35 | }
36 |
37 | return payloadIndex < attackPayloads.size();
38 | }
39 |
40 | @Override
41 | public byte[] getNextPayload(byte[] baseValue) {
42 | if (!initialized) {
43 |
44 | initializePayloads(baseValue);
45 | initialized = true;
46 |
47 | }
48 |
49 | if (payloadIndex >= attackPayloads.size()) {
50 | return baseValue;
51 | }
52 |
53 | String payload = attackPayloads.get(payloadIndex);
54 | payloadIndex++;
55 | return payload.getBytes();
56 | }
57 |
58 | private void initializePayloads(byte[] baseValue) {
59 | String selectedArea = new String(baseValue);
60 |
61 | boolean isFullSection = selectedArea.contains("Content-Disposition:") &&
62 | (selectedArea.contains("filename=") || selectedArea.contains("filename=\"")) &&
63 | selectedArea.contains("Content-Type:");
64 |
65 |
66 |
67 | if (isFullSection) {
68 | Matcher filenameMatcher = Pattern.compile("filename=\"([^\"]*)\"").matcher(selectedArea);
69 | Matcher namematcher = Pattern.compile("name=\"([^\"]*)\"").matcher(selectedArea);
70 | Matcher contentTypeMatcher = Pattern.compile("Content-Type:\\s*([^\\r\\n]*)").matcher(selectedArea);
71 |
72 |
73 | if (filenameMatcher.find() && filenameMatcher.group(1).contains(".")) {
74 | String originalFilename = filenameMatcher.group(1);
75 | String originalExt = originalFilename.substring(originalFilename.lastIndexOf('.') + 1);
76 | String name = namematcher.find() ? namematcher.group(1) : "file";
77 | String contentType = contentTypeMatcher.find() ? contentTypeMatcher.group(1).trim() : "image/jpeg";
78 |
79 | List sectionPayloads = UploadPayloadGenerator.getFuzzPayloadsForFullSection(selectedArea);
80 |
81 |
82 | String template = "Content-Disposition: form-data; name=\""+name+"\"; filename=\"test." + originalExt +
83 | "\"\r\nContent-Type:"+contentType;
84 | List singleElementPayloads = UploadPayloadGenerator.getAttackPayloads(template);
85 |
86 | List convertedPayloads = new ArrayList<>(singleElementPayloads);
87 |
88 | Set uniquePayloads = new HashSet<>();
89 | uniquePayloads.addAll(sectionPayloads);
90 | uniquePayloads.addAll(convertedPayloads);
91 | attackPayloads = new ArrayList<>(uniquePayloads);
92 | } else {
93 | attackPayloads = UploadPayloadGenerator.getFuzzPayloadsForFullSection(selectedArea);
94 | }
95 | } else {
96 | attackPayloads = UploadPayloadGenerator.getAttackPayloads(selectedArea);
97 | }
98 |
99 |
100 | if (attackPayloads.size() > 1000) {
101 | attackPayloads = attackPayloads.subList(0, 1000);
102 | }
103 |
104 | attack.getHttpService().getHost();
105 | }
106 |
107 | @Override
108 | public void reset() {
109 | payloadIndex = 0;
110 | }
111 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/TriggerCipherGuesser.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass;
2 |
3 | import AutoBurp.bypass.beens.Browsers;
4 | import AutoBurp.bypass.beens.MatchAndReplace;
5 | import burp.api.montoya.http.message.HttpRequestResponse;
6 | import burp.api.montoya.http.message.responses.HttpResponse;
7 |
8 | import java.awt.event.ActionEvent;
9 | import java.awt.event.ActionListener;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 | import java.util.ListIterator;
13 | import java.util.concurrent.ThreadPoolExecutor;
14 |
15 | import static AutoBurp.bypass.Constants.MAX_ATTEMPTS;
16 |
17 | public class TriggerCipherGuesser implements ActionListener, Runnable {
18 | private ThreadPoolExecutor taskEngine;
19 | private final List requestResponses;
20 |
21 | public TriggerCipherGuesser(ThreadPoolExecutor taskEngine, List requestResponses) {
22 | this.taskEngine = taskEngine;
23 | this.requestResponses = requestResponses;
24 | }
25 |
26 | @Override
27 | public void actionPerformed(ActionEvent e) {
28 | if(requestResponses.isEmpty()) return;
29 | (new Thread(this)).start();
30 | }
31 |
32 |
33 | @Override
34 | public void run() {
35 | taskEngine.execute(new Runnable() {
36 | @Override
37 | public void run() {
38 | try {
39 | Utilities.log(String.format("|*| Starting attack on %s targets", requestResponses.size()));
40 | Utilities.loadTLSSettings();
41 | ListIterator it = requestResponses.listIterator();
42 | for(String[] protocol : Constants.BRUTEFORCE_CIPHERS.keySet()) {
43 | if(!it.hasNext()) {
44 | Utilities.log("|*| Nothing to do!");
45 | break;
46 | }
47 | String[] ciphers = Constants.BRUTEFORCE_CIPHERS.get(protocol);
48 | Utilities.updateTLSSettings(protocol, ciphers);
49 | Utilities.log(String.format("|*| Probing protocols: %s", Utilities.stringify(protocol)));
50 | while (it.hasNext()) {
51 | HttpRequestResponse requestResponse = it.next();
52 | String negotiation = Utilities.negotiation(protocol,ciphers);
53 | List probs = new ArrayList<>();
54 | for(int i = 0; i < MAX_ATTEMPTS; i++) {
55 | HttpRequestResponse prob = Utilities.attemptRequest(requestResponse, negotiation);
56 | probs.add(prob);
57 | }
58 | if ( !probs.isEmpty() && Utilities.compareResponses(requestResponse, probs)) {
59 | String comment = String.format(
60 | "|*| URL %s response was changed. Status code %s. TLS settings: %s",
61 | requestResponse.request().url(),
62 | probs.stream()
63 | .map(HttpRequestResponse::response)
64 | .map(HttpResponse::statusCode)
65 | .map(String::valueOf)
66 | .reduce("",(partial,element) -> element + "," + partial),
67 | negotiation );
68 | Utilities.log(comment);
69 | Utilities.addComment(requestResponse,negotiation);
70 | it.remove();
71 | }
72 | }
73 | while (it.hasPrevious()) {
74 | it.previous();
75 | }
76 | Thread.sleep(100);
77 | }
78 |
79 | }catch (Exception e) {
80 | Utilities.log(e.getMessage());
81 | }
82 | finally {
83 | Utilities.updateTLSSettingsSync(Constants.BROWSERS_PROTOCOLS.get(Browsers.FIREFOX.name), Constants.BROWSERS_CIPHERS.get(Browsers.FIREFOX.name));
84 | Utilities.updateProxySettingsSync(MatchAndReplace.create(Browsers.FIREFOX));
85 | }
86 | }
87 | });
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/model/TableLogModel.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.model;
2 |
3 | import burp.IHttpRequestResponse;
4 | import burp.IHttpService;
5 |
6 | public class TableLogModel {
7 | private int id;
8 | private String url;
9 | private String method;
10 | private int status;
11 | private String title;
12 | private String result;
13 | private String type;
14 | private boolean isImportant;
15 | private String resultInfo;
16 |
17 | private String matchPattern;
18 | private final IHttpService httpService;
19 | private int requestResponseIndex;
20 | private String time;
21 |
22 | private String contentType;
23 |
24 | public TableLogModel(int id, String url, String method, String title, String result, String type,
25 | String resultInfo, boolean isImportant, IHttpService httpService,
26 | int requestResponseIndex, String currentTime) {
27 | this.id = id;
28 | this.url = url;
29 | this.method = method;
30 | this.title = title;
31 | this.result = result;
32 | this.type = type;
33 | this.resultInfo = resultInfo;
34 | this.isImportant = isImportant;
35 | this.time = currentTime;
36 | this.httpService = httpService;
37 | this.requestResponseIndex = requestResponseIndex;
38 | this.contentType = "";
39 | this.matchPattern = "";
40 | }
41 |
42 |
43 | public int getId() {
44 | return id;
45 | }
46 |
47 |
48 | public void setId(int id) {
49 | this.id = id;
50 | }
51 |
52 | public String getUrl() {
53 | return url;
54 | }
55 |
56 | public int getStatus() {
57 | return status;
58 | }
59 |
60 | public void setStatus(int status) {
61 | this.status = status;
62 | }
63 |
64 | public String getTitle() {
65 | return title;
66 | }
67 |
68 | public void setTitle(String title) {
69 | this.title = title;
70 | }
71 |
72 | public String getMethod() {
73 | return method;
74 | }
75 |
76 | public void setMethod(String method) {
77 | this.method = method;
78 | }
79 |
80 | public String getResult() {
81 | return result;
82 | }
83 |
84 | public void setResult(String result) {
85 | this.result = result;
86 | }
87 |
88 | public String getType() {
89 | return type;
90 | }
91 |
92 | public void setType(String type) {
93 | this.type = type;
94 | }
95 |
96 | public boolean getIsImportant() {
97 | return isImportant;
98 | }
99 |
100 | public void setIsImportant(boolean important) {
101 | isImportant = important;
102 | }
103 |
104 | public String getTime() {
105 | return time;
106 | }
107 |
108 | public int getRequestResponseIndex() {
109 | return requestResponseIndex;
110 | }
111 |
112 | public String getResultInfo() {
113 | return resultInfo;
114 | }
115 |
116 | public String getMatchPattern() {
117 | return matchPattern;
118 | }
119 |
120 | public void setMatchPattern(String matchPattern) {
121 | this.matchPattern = matchPattern;
122 | }
123 |
124 | public void setResultInfo(String resultInfo) {
125 | this.resultInfo = resultInfo;
126 | }
127 |
128 | public void setContentType(String contentType) {
129 | this.contentType = contentType;
130 | }
131 |
132 |
133 | private IHttpRequestResponse httpRequestResponse;
134 |
135 | @Override
136 | public String toString() {
137 | return "TableLogModel{" +
138 | "id=" + id +
139 | ", url='" + url + '\'' +
140 | ", status=" + status +
141 | ", title='" + title + '\'' +
142 | ", method='" + method + '\'' +
143 | ", result='" + result + '\'' +
144 | ", type='" + type + '\'' +
145 | ", isImportant=" + isImportant +
146 | ", time='" + time + '\'' +
147 | ", requestResponseIndex=" + requestResponseIndex +
148 | ", resultInfo='" + resultInfo + '\'' +
149 | ", contentType='" + contentType + '\'' +
150 | ", matchPattern='" + matchPattern + '\'' +
151 | '}';
152 | }
153 |
154 |
155 | public IHttpRequestResponse getHttpRequestResponse() {
156 | return httpRequestResponse;
157 | }
158 |
159 | public void setHttpRequestResponse(IHttpRequestResponse httpRequestResponse) {
160 | this.httpRequestResponse = httpRequestResponse;
161 | }
162 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/util/Utils.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.util;
2 |
3 | import java.net.URL;
4 | import java.util.Base64;
5 | import java.util.HashSet;
6 | import java.util.Set;
7 | import java.util.regex.Matcher;
8 | import java.util.regex.Pattern;
9 |
10 | public class Utils {
11 |
12 |
13 |
14 | public static String getUriExt(String url) {
15 | try {
16 | String path = new URL(url).getPath();
17 | int lastDotPos = path.lastIndexOf('.');
18 | if (lastDotPos > 0) {
19 | return path.substring(lastDotPos + 1).toLowerCase();
20 | }
21 | } catch (Exception e) {
22 |
23 | }
24 | return "";
25 | }
26 |
27 |
28 | public static String getTitle(String html) {
29 | Pattern pattern = Pattern.compile("(.*?)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
30 | Matcher matcher = pattern.matcher(html);
31 | if (matcher.find()) {
32 | return matcher.group(1).trim();
33 | }
34 | return "";
35 | }
36 |
37 | public static String getFaviconHash(byte[] data) {
38 | try {
39 |
40 | String base64Favicon = Base64.getEncoder().encodeToString(data);
41 |
42 |
43 | String formattedBase64Favicon = formatBase64(base64Favicon);
44 |
45 |
46 | return String.valueOf(MurmurHash3.hash32(
47 | formattedBase64Favicon.getBytes(),
48 | 0,
49 | formattedBase64Favicon.length(),
50 | 0));
51 | } catch (Exception e) {
52 | return "0";
53 | }
54 | }
55 |
56 |
57 | private static String formatBase64(String base64) {
58 | Pattern pattern = Pattern.compile(".{76}");
59 | Matcher matcher = pattern.matcher(base64);
60 | StringBuilder formattedBase64 = new StringBuilder();
61 |
62 | while (matcher.find()) {
63 | formattedBase64.append(matcher.group()).append("\n");
64 | }
65 |
66 | int remainder = base64.length() % 76;
67 | if (remainder > 0) {
68 | formattedBase64.append(base64.substring(base64.length() - remainder)).append("\n");
69 | }
70 |
71 | return formattedBase64.toString();
72 | }
73 |
74 |
75 | public static Set extractUrlsFromHtml(String baseUrl, String html) {
76 | Set urls = new HashSet<>();
77 |
78 |
79 | Pattern hrefPattern = Pattern.compile("href=[\"'](.*?)[\"']", Pattern.CASE_INSENSITIVE);
80 | Matcher hrefMatcher = hrefPattern.matcher(html);
81 | while (hrefMatcher.find()) {
82 | String url = hrefMatcher.group(1);
83 | if (!url.startsWith("#") && !url.startsWith("javascript:")) {
84 | urls.add(processUrl(baseUrl, url));
85 | }
86 | }
87 |
88 |
89 | Pattern srcPattern = Pattern.compile("src=[\"'](.*?)[\"']", Pattern.CASE_INSENSITIVE);
90 | Matcher srcMatcher = srcPattern.matcher(html);
91 | while (srcMatcher.find()) {
92 | String url = srcMatcher.group(1);
93 | urls.add(processUrl(baseUrl, url));
94 | }
95 |
96 | return urls;
97 | }
98 |
99 |
100 | public static String processUrl(String baseUrl, String relativeUrl) {
101 | try {
102 | URL base = new URL(baseUrl);
103 | URL absolute = new URL(base, relativeUrl);
104 | return absolute.toString();
105 | } catch (Exception e) {
106 | return relativeUrl;
107 | }
108 | }
109 |
110 |
111 | public static Set findUrls(URL baseUrl, String text) {
112 | Set urls = new HashSet<>();
113 |
114 |
115 | Pattern urlPattern = Pattern.compile("(https?://[^\\s\"'<>]+)", Pattern.CASE_INSENSITIVE);
116 | Matcher urlMatcher = urlPattern.matcher(text);
117 |
118 | while (urlMatcher.find()) {
119 | urls.add(urlMatcher.group(1));
120 | }
121 |
122 | return urls;
123 | }
124 |
125 |
126 | private static class MurmurHash3 {
127 | public static int hash32(byte[] data, int offset, int length, int seed) {
128 | int h1 = seed;
129 | int c1 = 0xcc9e2d51;
130 | int c2 = 0x1b873593;
131 | int roundedEnd = offset + (length & 0xfffffffc);
132 |
133 | for (int i = offset; i < roundedEnd; i += 4) {
134 | int k1 = (data[i] & 0xff) | ((data[i + 1] & 0xff) << 8) |
135 | ((data[i + 2] & 0xff) << 16) | ((data[i + 3] & 0xff) << 24);
136 |
137 | k1 *= c1;
138 | k1 = (k1 << 15) | (k1 >>> 17);
139 | k1 *= c2;
140 |
141 | h1 ^= k1;
142 | h1 = (h1 << 13) | (h1 >>> 19);
143 | h1 = h1 * 5 + 0xe6546b64;
144 | }
145 |
146 | int k1 = 0;
147 | switch (length & 0x03) {
148 | case 3:
149 | k1 = (data[roundedEnd + 2] & 0xff) << 16;
150 | case 2:
151 | k1 |= (data[roundedEnd + 1] & 0xff) << 8;
152 | case 1:
153 | k1 |= (data[roundedEnd] & 0xff);
154 | k1 *= c1;
155 | k1 = (k1 << 15) | (k1 >>> 17);
156 | k1 *= c2;
157 | h1 ^= k1;
158 | }
159 |
160 | h1 ^= length;
161 | h1 ^= h1 >>> 16;
162 | h1 *= 0x85ebca6b;
163 | h1 ^= h1 >>> 13;
164 | h1 *= 0xc2b2ae35;
165 | h1 ^= h1 >>> 16;
166 |
167 | return h1;
168 | }
169 | }
170 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/DomainSettingsManager.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass;
2 |
3 | import burp.api.montoya.MontoyaApi;
4 | import com.google.gson.Gson;
5 | import com.google.gson.reflect.TypeToken;
6 | import AutoBurp.bypass.beens.Browsers;
7 | import AutoBurp.bypass.beens.DomainSettings;
8 | import AutoBurp.bypass.beens.MatchAndReplace;
9 |
10 | import java.lang.reflect.Type;
11 | import java.net.URI;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.Optional;
15 |
16 | public class DomainSettingsManager {
17 | private static final String SETTINGS_KEY = "domain_tls_settings";
18 | private static List domainSettingsList = new ArrayList<>();
19 | private static MontoyaApi montoyaApi;
20 | private static Gson gson = new Gson();
21 |
22 | public static void initialize(MontoyaApi api) {
23 | montoyaApi = api;
24 | loadSettings();
25 | }
26 |
27 | public static void addDomainSettings(String url, Browsers browser, String[] protocols, String[] ciphers, boolean httpDowngrade) {
28 | try {
29 | String domain = extractDomain(url);
30 | if (domain == null || domain.isEmpty()) {
31 | return;
32 | }
33 |
34 |
35 | Optional existingSettings = domainSettingsList.stream()
36 | .filter(settings -> settings.getDomain().equals(domain))
37 | .findFirst();
38 |
39 | if (existingSettings.isPresent()) {
40 |
41 | domainSettingsList.remove(existingSettings.get());
42 | }
43 |
44 |
45 | DomainSettings newSettings = new DomainSettings(
46 | domain,
47 | browser.name,
48 | protocols,
49 | ciphers,
50 | httpDowngrade
51 | );
52 | domainSettingsList.add(newSettings);
53 | saveSettings();
54 |
55 |
56 | Utilities.updateTLSSettingsSync(protocols, ciphers);
57 | Utilities.updateProxySettingsSync(MatchAndReplace.create(browser));
58 |
59 |
60 | if (Utilities.enabledHTTPDowngrade() != httpDowngrade) {
61 | Utilities.updateHTTPSettings();
62 | }
63 |
64 |
65 | } catch (Exception e) {
66 | Utilities.error("添加域名设置失败: " + e.getMessage());
67 | }
68 | }
69 |
70 | public static void updateDomainSettings(String domain, Browsers browser, String[] protocols, String[] ciphers, boolean httpDowngrade) {
71 |
72 | Optional existingSettings = domainSettingsList.stream()
73 | .filter(settings -> settings.getDomain().equals(domain))
74 | .findFirst();
75 |
76 | if (existingSettings.isPresent()) {
77 |
78 | domainSettingsList.remove(existingSettings.get());
79 |
80 |
81 | DomainSettings newSettings = new DomainSettings(
82 | domain,
83 | browser.name,
84 | protocols,
85 | ciphers,
86 | httpDowngrade
87 | );
88 | domainSettingsList.add(newSettings);
89 | saveSettings();
90 |
91 |
92 | Utilities.updateTLSSettingsSync(protocols, ciphers);
93 | Utilities.updateProxySettingsSync(MatchAndReplace.create(browser));
94 |
95 |
96 | if (Utilities.enabledHTTPDowngrade() != httpDowngrade) {
97 | Utilities.updateHTTPSettings();
98 | }
99 |
100 | Utilities.log("已更新并应用域名 " + domain + " 的 TLS 设置");
101 | }
102 | }
103 |
104 | public static void removeDomainSettings(String domain) {
105 | boolean removed = domainSettingsList.removeIf(settings -> settings.getDomain().equals(domain));
106 | if (removed) {
107 | saveSettings();
108 |
109 | Utilities.loadTLSSettings();
110 |
111 | }
112 | }
113 |
114 | public static List getAllDomainSettings() {
115 | return new ArrayList<>(domainSettingsList);
116 | }
117 |
118 | public static Optional getDomainSettings(String domain) {
119 | return domainSettingsList.stream()
120 | .filter(settings -> settings.getDomain().equals(domain))
121 | .findFirst();
122 | }
123 |
124 |
125 | public static void applyDomainSettings(String domain) {
126 | Optional settings = getDomainSettings(domain);
127 | if (settings.isPresent()) {
128 | DomainSettings domainSettings = settings.get();
129 |
130 |
131 | Browsers browser = Browsers.valueOf(domainSettings.getBrowser());
132 |
133 |
134 | Utilities.updateTLSSettingsSync(domainSettings.getProtocols(), domainSettings.getCiphers());
135 |
136 |
137 | Utilities.updateProxySettingsSync(MatchAndReplace.create(browser));
138 |
139 |
140 | if (Utilities.enabledHTTPDowngrade() != domainSettings.isHttpDowngrade()) {
141 | Utilities.updateHTTPSettings();
142 | }
143 |
144 |
145 | }
146 | }
147 |
148 | private static void saveSettings() {
149 | String serializedSettings = gson.toJson(domainSettingsList);
150 | montoyaApi.persistence().preferences().setString(SETTINGS_KEY, serializedSettings);
151 | }
152 |
153 | private static void loadSettings() {
154 | String serializedSettings = montoyaApi.persistence().preferences().getString(SETTINGS_KEY);
155 | if (serializedSettings != null && !serializedSettings.isEmpty()) {
156 | Type listType = new TypeToken>(){}.getType();
157 | domainSettingsList = gson.fromJson(serializedSettings, listType);
158 | }
159 | }
160 |
161 | private static String extractDomain(String url) {
162 | try {
163 | if (!url.startsWith("http")) {
164 | url = "http://" + url;
165 | }
166 | URI uri = new URI(url);
167 | String domain = uri.getHost();
168 | return domain;
169 | } catch (Exception e) {
170 | return url;
171 | }
172 | }
173 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/util/FingerPrintUtils.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.util;
2 |
3 | import AutoBurp.fingerprint.model.FingerPrintRule;
4 | import AutoBurp.fingerprint.model.TableLogModel;
5 | import burp.IBurpExtenderCallbacks;
6 | import burp.IExtensionHelpers;
7 | import burp.IHttpService;
8 | import burp.IResponseInfo;
9 |
10 | import java.nio.charset.StandardCharsets;
11 | import java.text.SimpleDateFormat;
12 | import java.util.Arrays;
13 | import java.util.Date;
14 | import java.util.List;
15 |
16 | public class FingerPrintUtils {
17 |
18 |
19 | public static TableLogModel fingerFilter(IBurpExtenderCallbacks callbacks, int pid, String oneUrl, byte[] oneResponseBytes,
20 | IHttpService iHttpService, IExtensionHelpers helpers,
21 | List fingerprintRules, boolean isScanEnabled) {
22 | if (!isScanEnabled) {
23 | return null;
24 | }
25 |
26 |
27 |
28 | TableLogModel logModel = new TableLogModel(pid, oneUrl, "", "", "", "", "", false,
29 | iHttpService, pid, new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date()));
30 |
31 | IResponseInfo responseInfo = helpers.analyzeResponse(oneResponseBytes);
32 |
33 | String responseBody = new String(oneResponseBytes, StandardCharsets.UTF_8);
34 |
35 | String responseHeaders = responseInfo.getHeaders().toString();
36 |
37 | String responseTitle = Utils.getTitle(responseBody);
38 |
39 | String mimeType = responseInfo.getStatedMimeType().toLowerCase();
40 |
41 | if (responseTitle.isEmpty()) {
42 | responseTitle = responseBody;
43 | }
44 | String finalResponseTitle = responseTitle;
45 |
46 | String faviconHash = "0";
47 |
48 | if (finalResponseTitle.equals(responseBody)) {
49 | logModel.setTitle("-");
50 | } else {
51 | logModel.setTitle(finalResponseTitle);
52 | }
53 |
54 |
55 | if (mimeType.contains("png") || mimeType.contains("jpeg") || mimeType.contains("icon") ||
56 | mimeType.contains("image") || oneUrl.contains("favicon.") || oneUrl.contains(".ico")) {
57 | byte[] body = Arrays.copyOfRange(oneResponseBytes, responseInfo.getBodyOffset(), oneResponseBytes.length);
58 | faviconHash = Utils.getFaviconHash(body);
59 |
60 |
61 |
62 | }
63 |
64 |
65 |
66 | for (FingerPrintRule rule : fingerprintRules) {
67 | String locationContent = "";
68 | String matchLocation = "";
69 |
70 | if ("faviconhash".equals(rule.getMethod())) {
71 | locationContent = faviconHash;
72 | matchLocation = "faviconhash";
73 | } else if ("body".equals(rule.getLocation())) {
74 | locationContent = responseBody;
75 | matchLocation = "body";
76 | } else if ("header".equals(rule.getLocation())) {
77 | locationContent = responseHeaders;
78 | matchLocation = "header";
79 | } else if ("title".equals(rule.getLocation())) {
80 | locationContent = finalResponseTitle;
81 | matchLocation = "title";
82 | } else {
83 | continue;
84 | }
85 |
86 | boolean allKeywordsPresent = true;
87 | StringBuilder matchPatternBuilder;
88 |
89 |
90 | if ("faviconhash".equals(rule.getMethod())) {
91 | matchPatternBuilder = new StringBuilder("faviconhash").append(": ");
92 | try {
93 | if (!rule.getKeyword().isEmpty() && !faviconHash.equals(rule.getKeyword().get(0))) {
94 | allKeywordsPresent = false;
95 | } else if (!rule.getKeyword().isEmpty()) {
96 | matchPatternBuilder.append(rule.getKeyword().get(0));
97 | }
98 | } catch (Exception e) {
99 | allKeywordsPresent = false;
100 | }
101 | } else {
102 | matchPatternBuilder = new StringBuilder(matchLocation).append(": ");
103 |
104 | for (int i = 0; i < rule.getKeyword().size(); i++) {
105 | String keyword = rule.getKeyword().get(i);
106 | if (!locationContent.contains(keyword)) {
107 | allKeywordsPresent = false;
108 | break;
109 | }
110 |
111 | matchPatternBuilder.append(keyword);
112 | if (i < rule.getKeyword().size() - 1) {
113 | matchPatternBuilder.append(", ");
114 | }
115 | }
116 | }
117 |
118 | if (allKeywordsPresent) {
119 | if (!logModel.getResult().isEmpty()) {
120 |
121 | if (!logModel.getResult().contains(rule.getCms())) {
122 | logModel.setResult(logModel.getResult() + ", " + rule.getCms());
123 |
124 |
125 | if (logModel.getMatchPattern() != null && !logModel.getMatchPattern().isEmpty()) {
126 | logModel.setMatchPattern(logModel.getMatchPattern() + " | " + matchPatternBuilder.toString());
127 | } else {
128 | logModel.setMatchPattern(matchPatternBuilder.toString());
129 | }
130 | }
131 | } else {
132 |
133 | logModel.setResult(rule.getCms());
134 | logModel.setMatchPattern(matchPatternBuilder.toString());
135 | }
136 |
137 |
138 | logModel.setType(rule.getType());
139 | logModel.setIsImportant(rule.getIsImportant());
140 |
141 | String detailInfo = "Time: " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(new Date()) +
142 | "\r\nUrl:" + oneUrl + "\r\n指纹详细信息如下:\r\n" + rule.getInfo();
143 |
144 | if (logModel.getResultInfo().isEmpty()) {
145 | logModel.setResultInfo(detailInfo);
146 | } else {
147 | logModel.setResultInfo(logModel.getResultInfo() + "\r\n\r\n" + detailInfo);
148 | }
149 | }
150 | }
151 |
152 | return logModel;
153 | }
154 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/TLSContextMenuItemsProvider.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass;
2 |
3 | import burp.api.montoya.MontoyaApi;
4 | import burp.api.montoya.core.ToolType;
5 | import burp.api.montoya.http.message.HttpRequestResponse;
6 | import burp.api.montoya.ui.contextmenu.ContextMenuEvent;
7 | import burp.api.montoya.ui.contextmenu.ContextMenuItemsProvider;
8 | import burp.api.montoya.ui.contextmenu.MessageEditorHttpRequestResponse;
9 | import AutoBurp.bypass.beens.Browsers;
10 | import AutoBurp.bypass.beens.MatchAndReplace;
11 |
12 | import javax.swing.*;
13 | import java.awt.*;
14 | import java.util.ArrayList;
15 | import java.util.Arrays;
16 | import java.util.List;
17 | import java.util.Optional;
18 | import java.util.concurrent.ThreadPoolExecutor;
19 |
20 | public class TLSContextMenuItemsProvider implements ContextMenuItemsProvider {
21 | private ThreadPoolExecutor taskEngine;
22 |
23 | private List requestResponses;
24 | private MontoyaApi montoyaApi;
25 |
26 | public TLSContextMenuItemsProvider(ThreadPoolExecutor taskEngine, MontoyaApi montoyaApi) {
27 | this.taskEngine = taskEngine;
28 | this.montoyaApi = montoyaApi;
29 | this.requestResponses = new ArrayList<>();
30 | }
31 |
32 | @Override
33 | public List provideMenuItems(ContextMenuEvent contextMenuEvent) {
34 | if (contextMenuEvent.isFromTool(ToolType.LOGGER, ToolType.PROXY, ToolType.TARGET, ToolType.ORGANIZER)) {
35 |
36 | List menuItemList = new ArrayList<>();
37 |
38 | this.requestResponses = new ArrayList<>();
39 |
40 | if(contextMenuEvent.messageEditorRequestResponse().isPresent()) {
41 | MessageEditorHttpRequestResponse message = contextMenuEvent.messageEditorRequestResponse().get();
42 | this.requestResponses.add(message.requestResponse());
43 | String negotiation = Utilities.getComment(message.requestResponse());
44 | if(negotiation != null) {
45 | JMenuItem negotiationItem = new JMenuItem(Utilities.getResourceString("negotiation"));
46 | negotiationItem.addActionListener(e -> addManualSettings(negotiation));
47 | menuItemList.add(negotiationItem);
48 | }
49 | } else {
50 | this.requestResponses = contextMenuEvent.selectedRequestResponses();
51 | }
52 |
53 | if(this.requestResponses.isEmpty()) return null;
54 |
55 |
56 | HttpRequestResponse requestResponse = this.requestResponses.get(0);
57 | String userAgent = requestResponse.request().header("User-Agent").value();
58 | if (userAgent == null || userAgent.isBlank()) {
59 | Arrays.stream(Browsers.values()).forEach(
60 | browser -> {
61 | JMenuItem item = new JMenuItem(browser.name);
62 | item.addActionListener(e -> addTLSCiphers(browser));
63 | menuItemList.add(item);
64 | }
65 | );
66 | } else {
67 | Optional br = Arrays.stream(Browsers.values())
68 | .filter(browsers -> userAgent.contains(browsers.name)).findAny();
69 | if (br.isPresent()) {
70 | JMenuItem message = new JMenuItem(Utilities.getResourceString("message"));
71 | message.addActionListener(e -> addTLSCiphers(br.get()));
72 | menuItemList.add(message);
73 | } else {
74 | Arrays.stream(Browsers.values()).forEach(
75 | browser -> {
76 | JMenuItem item = new JMenuItem(browser.name);
77 | item.addActionListener(e -> addTLSCiphers(browser));
78 | menuItemList.add(item);
79 | }
80 | );
81 | }
82 | }
83 |
84 | String menuLabel = Utilities.enabledHTTPDowngrade() ? "Enable " : "Disable ";
85 | JMenuItem downgradeMenu = new JMenuItem(menuLabel + Utilities.getResourceString("menu_downgrade"));
86 | downgradeMenu.addActionListener(e -> downgradeHttp());
87 | menuItemList.add(downgradeMenu);
88 |
89 | JMenuItem item = new JMenuItem(Utilities.getResourceString("menu_brute_force"));
90 | item.addActionListener(new TriggerCipherGuesser(taskEngine, this.requestResponses));
91 | menuItemList.add(item);
92 |
93 |
94 | return menuItemList;
95 | }
96 |
97 | return null;
98 | }
99 |
100 | public void downgradeHttp(){
101 | Utilities.updateHTTPSettings();
102 |
103 |
104 | if (!this.requestResponses.isEmpty()) {
105 | HttpRequestResponse requestResponse = this.requestResponses.get(0);
106 | String url = requestResponse.request().url();
107 | boolean isHttpDowngradeEnabled = !Utilities.enabledHTTPDowngrade();
108 |
109 |
110 | String userAgent = requestResponse.request().header("User-Agent").value();
111 | Browsers browser = Browsers.FIREFOX;
112 | for (Browsers b : Browsers.values()) {
113 | if (userAgent != null && userAgent.contains(b.name)) {
114 | browser = b;
115 | break;
116 | }
117 | }
118 |
119 | DomainSettingsManager.addDomainSettings(
120 | url,
121 | browser,
122 | Constants.BROWSERS_PROTOCOLS.get(browser.name),
123 | Constants.BROWSERS_CIPHERS.get(browser.name),
124 | isHttpDowngradeEnabled
125 | );
126 | }
127 | }
128 |
129 | public void addTLSCiphers(Browsers browser){
130 | Utilities.updateTLSSettingsSync(Constants.BROWSERS_PROTOCOLS.get(browser.name), Constants.BROWSERS_CIPHERS.get(browser.name));
131 | Utilities.updateProxySettingsSync(MatchAndReplace.create(browser));
132 |
133 |
134 | if (!this.requestResponses.isEmpty()) {
135 | HttpRequestResponse requestResponse = this.requestResponses.get(0);
136 | String url = requestResponse.request().url();
137 | boolean isHttpDowngradeEnabled = Utilities.enabledHTTPDowngrade();
138 |
139 | DomainSettingsManager.addDomainSettings(
140 | url,
141 | browser,
142 | Constants.BROWSERS_PROTOCOLS.get(browser.name),
143 | Constants.BROWSERS_CIPHERS.get(browser.name),
144 | isHttpDowngradeEnabled
145 | );
146 | }
147 | }
148 | public void addManualSettings(String negotiation){
149 | Utilities.montoyaApi.burpSuite().importProjectOptionsFromJson(negotiation);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/ui/TagsPanel.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.ui;
2 |
3 | import javax.swing.*;
4 | import javax.swing.border.EmptyBorder;
5 | import java.awt.*;
6 | import java.awt.event.MouseAdapter;
7 | import java.awt.event.MouseEvent;
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.function.Consumer;
11 |
12 | public class TagsPanel extends JPanel {
13 | private JPanel tagsPanel;
14 | private JLabel currentSelectedLabel = null;
15 | private final Map resultLabels = new HashMap<>();
16 | private Consumer onTagSelectedListener;
17 |
18 |
19 | private static final Color PRIMARY_COLOR = new Color(60, 141, 188);
20 | private static final Color TEXT_COLOR = new Color(51, 51, 51);
21 | private static final Color BORDER_COLOR = new Color(221, 221, 221);
22 | private static final Color HOVER_COLOR = new Color(240, 248, 255);
23 |
24 | public TagsPanel() {
25 | setLayout(new BorderLayout());
26 | setBackground(Color.WHITE);
27 |
28 | setBorder(BorderFactory.createCompoundBorder(
29 | BorderFactory.createMatteBorder(0, 0, 1, 0, BORDER_COLOR),
30 | new EmptyBorder(8, 15, 8, 15)
31 | ));
32 |
33 | tagsPanel = new JPanel();
34 | tagsPanel.setLayout(new WrapLayout(FlowLayout.LEFT, 10, 3));
35 | tagsPanel.setBackground(Color.WHITE);
36 |
37 |
38 | JLabel allLabel = createTagLabel("全部");
39 | allLabel.setBackground(PRIMARY_COLOR);
40 | allLabel.setForeground(Color.WHITE);
41 | allLabel.setOpaque(true);
42 | currentSelectedLabel = allLabel;
43 | tagsPanel.add(allLabel);
44 |
45 |
46 | JScrollPane tagsScrollPane = new JScrollPane(tagsPanel);
47 | tagsScrollPane.setBorder(null);
48 |
49 | tagsScrollPane.setPreferredSize(new Dimension(0, 35));
50 | tagsScrollPane.setMinimumSize(new Dimension(0, 35));
51 |
52 | tagsScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
53 | tagsScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
54 | tagsScrollPane.getViewport().setBackground(Color.WHITE);
55 |
56 | add(tagsScrollPane, BorderLayout.CENTER);
57 |
58 |
59 | setMinimumSize(new Dimension(0, 50));
60 | setPreferredSize(new Dimension(0, 50));
61 | }
62 |
63 | private JLabel createTagLabel(String text) {
64 | JLabel label = new JLabel(text);
65 | label.setOpaque(false);
66 | label.setForeground(TEXT_COLOR);
67 | label.setFont(new Font(label.getFont().getName(), Font.PLAIN, 13));
68 | label.setBorder(BorderFactory.createCompoundBorder(
69 | BorderFactory.createLineBorder(BORDER_COLOR, 1, true),
70 | new EmptyBorder(3, 8, 3, 8)
71 | ));
72 |
73 |
74 | label.addMouseListener(new MouseAdapter() {
75 | @Override
76 | public void mouseEntered(MouseEvent e) {
77 | if (label != currentSelectedLabel) {
78 | label.setBackground(HOVER_COLOR);
79 | label.setOpaque(true);
80 | }
81 | }
82 |
83 | @Override
84 | public void mouseExited(MouseEvent e) {
85 | if (label != currentSelectedLabel) {
86 | label.setOpaque(false);
87 | }
88 | }
89 |
90 | @Override
91 | public void mouseClicked(MouseEvent e) {
92 |
93 | if (e.getButton() == MouseEvent.BUTTON1) {
94 | if (currentSelectedLabel != null) {
95 | currentSelectedLabel.setBackground(null);
96 | currentSelectedLabel.setForeground(TEXT_COLOR);
97 | currentSelectedLabel.setOpaque(false);
98 | }
99 |
100 | label.setBackground(PRIMARY_COLOR);
101 | label.setForeground(Color.WHITE);
102 | label.setOpaque(true);
103 | currentSelectedLabel = label;
104 |
105 |
106 | if (onTagSelectedListener != null) {
107 | String type = label.getText();
108 | onTagSelectedListener.accept(type.equals("全部") ? null : type);
109 | }
110 | }
111 |
112 | else if (e.getButton() == MouseEvent.BUTTON3 && onRightClickListener != null) {
113 | onRightClickListener.accept(e.getComponent(), e.getX(), e.getY());
114 | }
115 | }
116 | });
117 |
118 | return label;
119 | }
120 |
121 | public void addTag(String type) {
122 | if (!resultLabels.containsKey(type)) {
123 | JLabel typeLabel = createTagLabel(type);
124 | tagsPanel.add(typeLabel);
125 | resultLabels.put(type, typeLabel);
126 | tagsPanel.revalidate();
127 | tagsPanel.repaint();
128 | }
129 | }
130 |
131 | public void clearTags() {
132 | tagsPanel.removeAll();
133 | JLabel allLabel = createTagLabel("全部");
134 | allLabel.setBackground(PRIMARY_COLOR);
135 | allLabel.setForeground(Color.WHITE);
136 | allLabel.setOpaque(true);
137 | tagsPanel.add(allLabel);
138 | currentSelectedLabel = allLabel;
139 |
140 | resultLabels.clear();
141 |
142 | tagsPanel.revalidate();
143 | tagsPanel.repaint();
144 | }
145 |
146 | public void selectTag(String type) {
147 | if (currentSelectedLabel != null) {
148 | currentSelectedLabel.setBackground(null);
149 | currentSelectedLabel.setForeground(TEXT_COLOR);
150 | currentSelectedLabel.setOpaque(false);
151 | }
152 |
153 | JLabel targetLabel = null;
154 | if (type == null || type.equals("全部")) {
155 |
156 | for (Component component : tagsPanel.getComponents()) {
157 | if (component instanceof JLabel && ((JLabel) component).getText().equals("全部")) {
158 | targetLabel = (JLabel) component;
159 | break;
160 | }
161 | }
162 | } else {
163 | targetLabel = resultLabels.get(type);
164 | }
165 |
166 | if (targetLabel != null) {
167 | targetLabel.setBackground(PRIMARY_COLOR);
168 | targetLabel.setForeground(Color.WHITE);
169 | targetLabel.setOpaque(true);
170 | currentSelectedLabel = targetLabel;
171 | }
172 | }
173 |
174 | public void setOnTagSelectedListener(Consumer listener) {
175 | this.onTagSelectedListener = listener;
176 | }
177 |
178 |
179 | private TriConsumer onRightClickListener;
180 |
181 |
182 | @FunctionalInterface
183 | public interface TriConsumer {
184 | void accept(T t, U u, V v);
185 | }
186 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/fingerprint/ui/ControlPanel.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.fingerprint.ui;
2 |
3 | import burp.IBurpExtenderCallbacks;
4 |
5 | import javax.swing.*;
6 | import javax.swing.border.EmptyBorder;
7 | import java.awt.*;
8 | import java.awt.event.MouseAdapter;
9 | import java.awt.event.MouseEvent;
10 |
11 | public class ControlPanel extends JPanel {
12 | private JLabel lbRequestCount;
13 | private JLabel lbSuccessCount;
14 | private JToggleButton scanToggleButton;
15 | private boolean isScanEnabled;
16 | private static final String SCAN_PREF_KEY = "fingerprint_scan_enabled";
17 | private final IBurpExtenderCallbacks callbacks;
18 |
19 |
20 | private static final Color PRIMARY_COLOR = new Color(60, 141, 188);
21 | private static final Color ACCENT_COLOR = new Color(0, 166, 90);
22 | private static final Color LIGHT_TEXT_COLOR = new Color(119, 119, 119);
23 | private static final Color BORDER_COLOR = new Color(221, 221, 221);
24 |
25 |
26 | private Runnable onRefreshListener;
27 | private Runnable onClearListener;
28 |
29 |
30 | private Runnable onScanStateChangedListener;
31 |
32 | public ControlPanel(IBurpExtenderCallbacks callbacks) {
33 | this.callbacks = callbacks;
34 |
35 | setLayout(new BorderLayout(10, 0));
36 | setBackground(Color.WHITE);
37 |
38 | setBorder(BorderFactory.createCompoundBorder(
39 | BorderFactory.createLineBorder(BORDER_COLOR, 1, true),
40 | new EmptyBorder(10, 15, 9, 15)
41 | ));
42 |
43 |
44 | JPanel statsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 35, 0));
45 | statsPanel.setBackground(Color.WHITE);
46 |
47 |
48 | Object[] result = createStatPanel("Total Requests Count: ", "0", PRIMARY_COLOR);
49 | statsPanel.add((JPanel)result[0]);
50 | lbRequestCount = (JLabel)result[1];
51 |
52 |
53 | result = createStatPanel("Success Requests Count: ", "0", ACCENT_COLOR);
54 | statsPanel.add((JPanel)result[0]);
55 | lbSuccessCount = (JLabel)result[1];
56 |
57 | add(statsPanel, BorderLayout.WEST);
58 |
59 |
60 | JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 10));
61 | actionPanel.setBackground(Color.WHITE);
62 |
63 |
64 |
65 | String savedPref = callbacks.loadExtensionSetting(SCAN_PREF_KEY);
66 | isScanEnabled = savedPref != null && savedPref.equals("true");
67 |
68 | scanToggleButton = new JToggleButton(isScanEnabled ? "扫描: 开启" : "扫描: 关闭");
69 | scanToggleButton.setSelected(isScanEnabled);
70 | scanToggleButton.setBackground(isScanEnabled ? ACCENT_COLOR : new Color(221, 75, 57));
71 | scanToggleButton.setForeground(Color.WHITE);
72 | scanToggleButton.setFocusPainted(false);
73 | scanToggleButton.setBorderPainted(false);
74 | scanToggleButton.setFont(new Font(scanToggleButton.getFont().getName(), Font.BOLD, 12));
75 | scanToggleButton.setPreferredSize(new Dimension(100, 25));
76 |
77 | scanToggleButton.addActionListener(e -> {
78 | isScanEnabled = scanToggleButton.isSelected();
79 | scanToggleButton.setText(isScanEnabled ? "扫描: 开启" : "扫描: 关闭");
80 | scanToggleButton.setBackground(isScanEnabled ? ACCENT_COLOR : new Color(221, 75, 57));
81 |
82 | callbacks.saveExtensionSetting(SCAN_PREF_KEY, String.valueOf(isScanEnabled));
83 |
84 |
85 | if (onScanStateChangedListener != null) {
86 | onScanStateChangedListener.run();
87 | }
88 | });
89 |
90 | scanToggleButton.addMouseListener(new MouseAdapter() {
91 | @Override
92 | public void mouseEntered(MouseEvent e) {
93 | scanToggleButton.setBackground(scanToggleButton.isSelected() ?
94 | ACCENT_COLOR.darker() : new Color(221, 75, 57).darker());
95 | }
96 |
97 | @Override
98 | public void mouseExited(MouseEvent e) {
99 | scanToggleButton.setBackground(scanToggleButton.isSelected() ?
100 | ACCENT_COLOR : new Color(221, 75, 57));
101 | }
102 | });
103 |
104 | actionPanel.add(scanToggleButton);
105 |
106 |
107 | JButton refreshButton = createStyledButton("刷新", new Color(60, 141, 188));
108 | refreshButton.addActionListener(e -> {
109 | if (onRefreshListener != null) {
110 | onRefreshListener.run();
111 | }
112 | });
113 | actionPanel.add(refreshButton);
114 |
115 |
116 | JButton clearButton = createStyledButton("清空", new Color(221, 75, 57));
117 | clearButton.addActionListener(e -> {
118 | if (onClearListener != null) {
119 | onClearListener.run();
120 | }
121 | });
122 | actionPanel.add(clearButton);
123 |
124 | add(actionPanel, BorderLayout.EAST);
125 | }
126 |
127 |
128 | private Object[] createStatPanel(String title, String value, Color color) {
129 | JPanel panel = new JPanel();
130 | panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
131 | panel.setBackground(Color.WHITE);
132 |
133 | JLabel titleLabel = new JLabel(title);
134 | titleLabel.setForeground(LIGHT_TEXT_COLOR);
135 | titleLabel.setFont(new Font(titleLabel.getFont().getName(), Font.PLAIN, 12));
136 | panel.add(titleLabel);
137 |
138 |
139 | panel.add(Box.createHorizontalStrut(2));
140 |
141 | JLabel valueLabel = new JLabel(value);
142 | valueLabel.setForeground(color);
143 | valueLabel.setFont(new Font(valueLabel.getFont().getName(), Font.BOLD, 16));
144 | panel.add(valueLabel);
145 |
146 |
147 | return new Object[]{panel, valueLabel};
148 | }
149 |
150 | private JButton createStyledButton(String text, Color color) {
151 | JButton button = new JButton(text);
152 | button.setBackground(color);
153 | button.setForeground(Color.WHITE);
154 | button.setFocusPainted(false);
155 | button.setBorderPainted(false);
156 | button.setFont(new Font(button.getFont().getName(), Font.BOLD, 12));
157 | button.setPreferredSize(new Dimension(80, 30));
158 |
159 |
160 | button.addMouseListener(new MouseAdapter() {
161 | @Override
162 | public void mouseEntered(MouseEvent e) {
163 | button.setBackground(color.darker());
164 | }
165 |
166 | @Override
167 | public void mouseExited(MouseEvent e) {
168 | button.setBackground(color);
169 | }
170 | });
171 |
172 | return button;
173 | }
174 |
175 | public void setRequestCount(int count) {
176 | lbRequestCount.setText(String.valueOf(count));
177 | }
178 |
179 | public void setSuccessCount(int count) {
180 | lbSuccessCount.setText(String.valueOf(count));
181 | }
182 |
183 | public boolean isScanEnabled() {
184 | return isScanEnabled;
185 | }
186 |
187 | public void setOnRefreshListener(Runnable listener) {
188 | this.onRefreshListener = listener;
189 | }
190 |
191 | public void setOnClearListener(Runnable listener) {
192 | this.onClearListener = listener;
193 | }
194 |
195 |
196 | public void setOnScanStateChangedListener(Runnable listener) {
197 | this.onScanStateChangedListener = listener;
198 | }
199 | }
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/generator/PhonePayloadGeneratorFactory.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.generator;
2 |
3 | import burp.*;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class PhonePayloadGeneratorFactory implements IIntruderPayloadGenerator {
9 | private final IExtensionHelpers helpers;
10 | private final IIntruderAttack attack;
11 | private final IBurpExtenderCallbacks callbacks;
12 | private int payloadIndex = 0;
13 | private final List payloads = new ArrayList<>();
14 | private String basePhoneNumber = "18888888888";
15 |
16 | public PhonePayloadGeneratorFactory(IExtensionHelpers helpers, IIntruderAttack attack, IBurpExtenderCallbacks callbacks) {
17 | this.helpers = helpers;
18 | this.attack = attack;
19 | this.callbacks = callbacks;
20 |
21 | initializePayloads(basePhoneNumber.getBytes());
22 | }
23 |
24 |
25 | public void initializePayloads(byte[] selectedValue) {
26 |
27 | if (selectedValue != null && selectedValue.length > 0) {
28 | basePhoneNumber = new String(selectedValue);
29 |
30 | }
31 |
32 |
33 |
34 | payloads.clear();
35 |
36 |
37 | String[] PAYLOAD_PATTERNS = new String[] {
38 | "xxxxxxxxxxx,",
39 | "xxxxxxxxxxx,,",
40 | "xxxxxxxxxxx,,,",
41 | "xxxxxxxxxxx,,,,",
42 | "xxxxxxxxxxx,,,,,",
43 | ",,,,,xxxxxxxxxxx",
44 | ",,,,xxxxxxxxxxx",
45 | ",,,xxxxxxxxxxx",
46 | ",,xxxxxxxxxxx",
47 | ",xxxxxxxxxxx",
48 | " xxxxxxxxxxx",
49 | " xxxxxxxxxxx",
50 | " xxxxxxxxxxx",
51 | "%20xxxxxxxxxxx",
52 | "%20%20xxxxxxxxxxx",
53 | "%20%20%20xxxxxxxxxxx",
54 | "xxxxxxxxxxx ",
55 | "xxxxxxxxxxx ",
56 | "xxxxxxxxxxx ",
57 | "xxxxxxxxxxx%20",
58 | "xxxxxxxxxxx%20%20",
59 | "xxxxxxxxxxx%20%20%20",
60 | "@xxxxxxxxxxx",
61 | "@@xxxxxxxxxxx",
62 | "@@@xxxxxxxxxxx",
63 | "xxxxxxxxxxx@",
64 | "xxxxxxxxxxx@@",
65 | "xxxxxxxxxxx@@@",
66 | "%00xxxxxxxxxxx",
67 | "%00%00xxxxxxxxxxx",
68 | "%00%00%00xxxxxxxxxxx",
69 | "xxxxxxxxxxx%00",
70 | "xxxxxxxxxxx%00%00",
71 | "xxxxxxxxxxx%00%00%00",
72 | "xxxxxxxxxxx\\n",
73 | "xxxxxxxxxxx\\n\\n",
74 | "xxxxxxxxxxx\\n\\n\\n",
75 | "xxxxxxxxxxx\\n\\n\\n\\n",
76 | "\\nxxxxxxxxxxx",
77 | "\\n\\nxxxxxxxxxxx",
78 | "\\n\\n\\nxxxxxxxxxxx",
79 | "\\n\\n\\n\\nxxxxxxxxxxx",
80 | "xxxxxxxxxxx\\r",
81 | "xxxxxxxxxxx\\r\\r",
82 | "xxxxxxxxxxx\\r\\r\\r",
83 | "xxxxxxxxxxx\\r\\r\\r\\r",
84 | "\\rxxxxxxxxxxx",
85 | "\\r\\rxxxxxxxxxxx",
86 | "\\r\\r\\rxxxxxxxxxxx",
87 | "\\r\\r\\r\\rxxxxxxxxxxx",
88 | "xxxxxxxxxxx+",
89 | "xxxxxxxxxxx++",
90 | "xxxxxxxxxxx+++",
91 | "xxxxxxxxxxx++++",
92 | "+xxxxxxxxxxx",
93 | "++xxxxxxxxxxx",
94 | "+++xxxxxxxxxxx",
95 | "++++xxxxxxxxxxx",
96 | "xxxxxxxxxxx-",
97 | "xxxxxxxxxxx--",
98 | "xxxxxxxxxxx---",
99 | "xxxxxxxxxxx----",
100 | "-xxxxxxxxxxx",
101 | "--xxxxxxxxxxx",
102 | "---xxxxxxxxxxx",
103 | "----xxxxxxxxxxx",
104 | "xxxxxxxxxxx*",
105 | "xxxxxxxxxxx**",
106 | "xxxxxxxxxxx***",
107 | "xxxxxxxxxxx****",
108 | "*xxxxxxxxxxx",
109 | "**xxxxxxxxxxx",
110 | "***xxxxxxxxxxx",
111 | "****xxxxxxxxxxx",
112 | "xxxxxxxxxxx/",
113 | "xxxxxxxxxxx//",
114 | "xxxxxxxxxxx///",
115 | "xxxxxxxxxxx////",
116 | "/xxxxxxxxxxx",
117 | "//xxxxxxxxxxx",
118 | "///xxxxxxxxxxx",
119 | "////xxxxxxxxxxx",
120 | "+86xxxxxxxxxxx",
121 | "+86 xxxxxxxxxxx",
122 | "+86%20xxxxxxxxxxx",
123 | "+12xxxxxxxxxxx",
124 | "+12 xxxxxxxxxxx",
125 | "+12%20xxxxxxxxxxx",
126 | "+852xxxxxxxxxxx",
127 | "+852 xxxxxxxxxxx",
128 | "+852%20xxxxxxxxxxx",
129 | "+853xxxxxxxxxxx",
130 | "+853 xxxxxxxxxxx",
131 | "+853%20xxxxxxxxxxx",
132 | "0086xxxxxxxxxxx",
133 | "0086 xxxxxxxxxxx",
134 | "0086%20xxxxxxxxxxx",
135 | "0012xxxxxxxxxxx",
136 | "0012 xxxxxxxxxxx",
137 | "0012%20xxxxxxxxxxx",
138 | "00852xxxxxxxxxxx",
139 | "00852 xxxxxxxxxxx",
140 | "00852%20xxxxxxxxxxx",
141 | "00853xxxxxxxxxxx",
142 | "00853 xxxxxxxxxxx",
143 | "00853%20xxxxxxxxxxx",
144 | "9986xxxxxxxxxxx",
145 | "9986 xxxxxxxxxxx",
146 | "9986%20xxxxxxxxxxx",
147 | "9912xxxxxxxxxxx",
148 | "9912 xxxxxxxxxxx",
149 | "9912%20xxxxxxxxxxx",
150 | "99852xxxxxxxxxxx",
151 | "99852 xxxxxxxxxxx",
152 | "99852%20xxxxxxxxxxx",
153 | "99853xxxxxxxxxxx",
154 | "99853 xxxxxxxxxxx",
155 | "99853%20xxxxxxxxxxx",
156 | "86xxxxxxxxxxx",
157 | "86 xxxxxxxxxxx",
158 | "86%20xxxxxxxxxxx",
159 | "12xxxxxxxxxxx",
160 | "12 xxxxxxxxxxx",
161 | "12%20xxxxxxxxxxx",
162 | "852xxxxxxxxxxx",
163 | "852 xxxxxxxxxxx",
164 | "852%20xxxxxxxxxxx",
165 | "853xxxxxxxxxxx",
166 | "853 xxxxxxxxxxx",
167 | "853%20xxxxxxxxxxx",
168 | "086xxxxxxxxxxx",
169 | "086 xxxxxxxxxxx",
170 | "086%20xxxxxxxxxxx",
171 | "012xxxxxxxxxxx",
172 | "012 xxxxxxxxxxx",
173 | "012%20xxxxxxxxxxx",
174 | "0852xxxxxxxxxxx",
175 | "0852 xxxxxxxxxxx",
176 | "0852%20xxxxxxxxxxx",
177 | "0853xxxxxxxxxxx",
178 | "0853 xxxxxxxxxxx",
179 | "0853%20xxxxxxxxxxx",
180 | "%86xxxxxxxxxxx",
181 | "%86 xxxxxxxxxxx",
182 | "%86%2%xxxxxxxxxxx",
183 | "%12xxxxxxxxxxx",
184 | "%12 xxxxxxxxxxx",
185 | "%12%2%xxxxxxxxxxx",
186 | "%852xxxxxxxxxxx",
187 | "%852 xxxxxxxxxxx",
188 | "%852%2%xxxxxxxxxxx",
189 | "%853xxxxxxxxxxx",
190 | "%853 xxxxxxxxxxx",
191 | "%853%2%xxxxxxxxxxx",
192 | " 0xxxxxxxxxxx",
193 | "%200xxxxxxxxxxx",
194 | "0xxxxxxxxxxx",
195 | "00xxxxxxxxxxx",
196 | "000xxxxxxxxxxx",
197 | "0000xxxxxxxxxxx",
198 | "00000xxxxxxxxxxx",
199 | "+)WAFXR#!Txxxxxxxxxxx",
200 | "xxxxxxxxxxx+)WAFXR#!T",
201 | "xxxxxxxxxxx.0",
202 | "xxxxxxxxxxx.1",
203 | "xxxxxxxxxxx.2",
204 | "xxxxxxxxxxx.3",
205 | "xxxxxxxxxxx,13811111111",
206 | "xxxxxxxxxxx,,13811111111",
207 | "xxxxxxxxxxx,,,13811111111",
208 | "xxxxxxxxxxx&13811111111",
209 | "xxxxxxxxxxx&&13811111111",
210 | "xxxxxxxxxxx&&&13811111111",
211 | "xxxxxxxxxxx&&&&13811111111",
212 | "13811111111&xxxxxxxxxxx",
213 | "13811111111&&xxxxxxxxxxx",
214 | "13811111111&&&xxxxxxxxxxx",
215 | "13811111111&&&&xxxxxxxxxxx",
216 | "13811111111,xxxxxxxxxxx",
217 | "13811111111,,xxxxxxxxxxx",
218 | "13811111111,,,xxxxxxxxxxx",
219 | };
220 |
221 |
222 | for (String pattern : PAYLOAD_PATTERNS) {
223 | String payload = pattern.replace("xxxxxxxxxxx", basePhoneNumber);
224 | payloads.add(payload);
225 | }
226 |
227 |
228 | payloads.add(basePhoneNumber + "/**/");
229 | payloads.add("/**/"+basePhoneNumber);
230 | payloads.add(basePhoneNumber + "||'1'='1");
231 | payloads.add(basePhoneNumber + "' OR '1'='1");
232 | payloads.add(basePhoneNumber + "' AND '1'='1");
233 |
234 |
235 | payloads.add(basePhoneNumber.replace("8", "8"));
236 | payloads.add(basePhoneNumber.replace("1", "1"));
237 |
238 |
239 | payloads.add(basePhoneNumber.replace("8", "八"));
240 | payloads.add(basePhoneNumber.replace("1", "一"));
241 |
242 | }
243 |
244 | @Override
245 | public boolean hasMorePayloads() {
246 | boolean result = payloadIndex < payloads.size();
247 |
248 |
249 |
250 | return result;
251 | }
252 |
253 |
254 |
255 | @Override
256 | public byte[] getNextPayload(byte[] baseValue) {
257 | if (payloadIndex == 0) {
258 | initializePayloads(baseValue);
259 | }
260 |
261 | if (payloadIndex < payloads.size()) {
262 | String currentPayload = payloads.get(payloadIndex);
263 | byte[] payload = currentPayload.getBytes();
264 | payloadIndex++;
265 | return payload;
266 | }
267 |
268 | return baseValue;
269 | }
270 |
271 | @Override
272 | public void reset() {
273 | payloadIndex = 0;
274 | }
275 | }
--------------------------------------------------------------------------------
/src/main/java/AutoBurp/bypass/BypassBotDetection.java:
--------------------------------------------------------------------------------
1 | package AutoBurp.bypass;
2 |
3 | import AutoBurp.fingerprint.FingerPrintScanner;
4 | import AutoBurp.fingerprint.model.FingerPrintRule;
5 | import AutoBurp.fingerprint.ui.FingerPrintTab;
6 | import AutoBurp.fuzzer.phone.PhoneFuzzer;
7 | import AutoBurp.fuzzer.upload.UploadFuzzer;
8 | import burp.*;
9 | import burp.api.montoya.BurpExtension;
10 | import burp.api.montoya.MontoyaApi;
11 | import AutoBurp.bypass.beens.Browsers;
12 | import AutoBurp.bypass.beens.MatchAndReplace;
13 | import com.google.gson.Gson;
14 | import com.google.gson.reflect.TypeToken;
15 |
16 | import java.io.*;
17 | import java.lang.reflect.Type;
18 | import java.nio.charset.StandardCharsets;
19 | import java.util.*;
20 | import java.util.concurrent.BlockingQueue;
21 | import java.util.concurrent.Executors;
22 | import java.util.concurrent.LinkedBlockingQueue;
23 | import java.util.concurrent.ScheduledExecutorService;
24 | import java.util.concurrent.ThreadPoolExecutor;
25 | import java.util.concurrent.TimeUnit;
26 | import java.util.concurrent.atomic.AtomicInteger;
27 |
28 | public class BypassBotDetection implements BurpExtension, IBurpExtender, IIntruderPayloadGeneratorFactory, IProxyListener, IExtensionStateListener {
29 | private MontoyaApi montoyaApi;
30 | private IExtensionHelpers helpers;
31 | private IBurpExtenderCallbacks callbacks;
32 | private PrintWriter stdout;
33 | private PrintWriter stderr;
34 | private FingerPrintTab fingerPrintTab;
35 | private FingerPrintScanner fingerPrintScanner;
36 | private List fingerprintRules;
37 | private Set scannedUrls = Collections.synchronizedSet(new HashSet<>());
38 | private final ScheduledExecutorService memoryMonitor = Executors.newSingleThreadScheduledExecutor();
39 | private final AtomicInteger requestCount = new AtomicInteger(0);
40 | private final AtomicInteger successCount = new AtomicInteger(0);
41 |
42 | @Override
43 | public void initialize(MontoyaApi montoyaApi) {
44 | this.montoyaApi = montoyaApi;
45 | montoyaApi.extension().setName("综合Bypass");
46 | try {
47 | new Utilities(montoyaApi);
48 | BlockingQueue tasks = new LinkedBlockingQueue<>();
49 | ThreadPoolExecutor taskEngine = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, tasks);
50 | Utilities.saveTLSSettings();
51 |
52 |
53 | DomainSettingsManager.initialize(montoyaApi);
54 |
55 |
56 | montoyaApi.userInterface().registerContextMenuItemsProvider(new TLSContextMenuItemsProvider(taskEngine, montoyaApi));
57 |
58 |
59 | DomainSettingsPanel settingsPanel = new DomainSettingsPanel(montoyaApi);
60 | montoyaApi.userInterface().registerSuiteTab("TLS WAF", settingsPanel);
61 |
62 | montoyaApi.extension().registerUnloadingHandler(()-> {
63 | Utilities.unloaded.set(true);
64 | try {
65 | taskEngine.getQueue().clear();
66 | taskEngine.shutdown();
67 |
68 |
69 | memoryMonitor.shutdownNow();
70 | if (fingerPrintScanner != null) {
71 | fingerPrintScanner.shutdown();
72 | }
73 | }finally {
74 | Utilities.loadTLSSettings();
75 |
76 | }
77 | });
78 |
79 | Thread thread = new Thread(() -> {
80 | try {
81 | Thread.sleep(3000);
82 | } catch (InterruptedException e) {
83 | Thread.currentThread().interrupt();
84 | }
85 |
86 | Utilities.updateTLSSettings(Constants.BROWSERS_PROTOCOLS.get(Browsers.FIREFOX.name), Constants.BROWSERS_CIPHERS.get(Browsers.FIREFOX.name));
87 | Utilities.updateProxySettings(MatchAndReplace.create(Browsers.FIREFOX));
88 | });
89 | thread.start();
90 |
91 | montoyaApi.logging().logToOutput("Auto Fuzz & FingerPrint loaded successfully - Author: e0e1 - Version: 2.0");
92 | montoyaApi.logging().logToOutput("github: https://github.com/eeeeeeeeee-code/AutoFuzzBurp");
93 |
94 | } catch (Exception e) {
95 | montoyaApi.logging().logToError(e.getMessage());
96 | }
97 | }
98 |
99 | @Override
100 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
101 | this.callbacks = callbacks;
102 | this.helpers = callbacks.getHelpers();
103 | this.stdout = new PrintWriter(callbacks.getStdout(), true);
104 | this.stderr = new PrintWriter(callbacks.getStderr(), true);
105 | callbacks.setExtensionName("Bot Detection Bypass & Auto Fuzz");
106 |
107 |
108 | callbacks.registerIntruderPayloadGeneratorFactory(this);
109 |
110 |
111 | PhoneFuzzer phoneFuzzer = new PhoneFuzzer(this.helpers, callbacks);
112 | callbacks.registerIntruderPayloadGeneratorFactory(phoneFuzzer);
113 |
114 |
115 | loadFingerPrintRules();
116 |
117 |
118 | fingerPrintTab = new FingerPrintTab(callbacks, helpers);
119 | callbacks.addSuiteTab(fingerPrintTab);
120 |
121 |
122 | fingerPrintTab.setRulePanel(fingerprintRules);
123 |
124 |
125 | fingerPrintScanner = new FingerPrintScanner(callbacks, helpers, fingerprintRules, fingerPrintTab, scannedUrls, requestCount, successCount);
126 |
127 |
128 | fingerPrintTab.setScanner(fingerPrintScanner);
129 |
130 |
131 | callbacks.registerProxyListener(this);
132 |
133 |
134 | callbacks.registerExtensionStateListener(this);
135 |
136 |
137 | startMemoryMonitor();
138 | }
139 |
140 | private void loadFingerPrintRules() {
141 | try {
142 |
143 | File localFile = new File("finger-important.json");
144 | InputStream inputStream = null;
145 |
146 | if (localFile.exists() && localFile.isFile()) {
147 |
148 | inputStream = new FileInputStream(localFile);
149 |
150 | } else {
151 |
152 | ClassLoader classLoader = getClass().getClassLoader();
153 | inputStream = classLoader.getResourceAsStream("conf/finger-important.json");
154 |
155 | if (inputStream != null) {
156 |
157 | try (InputStream resourceStream = classLoader.getResourceAsStream("conf/finger-important.json");
158 | FileOutputStream outputStream = new FileOutputStream(localFile)) {
159 |
160 | if (resourceStream != null) {
161 | byte[] buffer = new byte[1024];
162 | int length;
163 | while ((length = resourceStream.read(buffer)) > 0) {
164 | outputStream.write(buffer, 0, length);
165 | }
166 |
167 |
168 |
169 | inputStream = new FileInputStream(localFile);
170 | }
171 | } catch (Exception e) {
172 | stderr.println("[!] 复制资源文件到当前目录失败: " + e.getMessage());
173 | }
174 | }
175 | }
176 |
177 | if (inputStream == null) {
178 | stderr.println("[!] 无法加载指纹规则文件");
179 | fingerprintRules = new ArrayList<>();
180 | return;
181 | }
182 |
183 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
184 | Gson gson = new Gson();
185 | Type fingerprintRuleListType = new TypeToken