Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.

Commit 18424cb

Browse files
author
vaycore
committed
添加主域名{{mdomain}}动态变量;新增QPS限制,限制每秒的请求数;优化配置面板,页面支持上下滚动;版本号更新至0.4.3版本。
1 parent 839e6fd commit 18424cb

File tree

18 files changed

+515
-49
lines changed

18 files changed

+515
-49
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ Request配置界面如下
7373
```text
7474
{{host}} - 原请求头中的Host
7575
{{domain}} - 原请求头中的Host(不包含端口号)
76+
{{mdomain}} - 主域名(如果domain是IP地址,那么该值也是IP地址)
7677
{{protocol}} - 原请求头中的协议(http、https)
7778
{{timestamp}} - Unix时间戳(单位:秒)
7879
{{random.ip}} - 随机IPv4值
@@ -94,6 +95,7 @@ Other配置界面如下
9495

9596
![](imgs/config_other.png)
9697

98+
- `QPS` QPS限制,限制每秒请求的数量,最大值 `9999`
9799
- `Web name collect` Web目录名收集(例如:`http://xxx.com/wapi/xxx.html` 会将该 url 中的 `wapi` 写入到指定的文件中)
98100
- `Json field collect` Json字段收集(收集json格式响应包中的所有key值,保存到指定目录)
99101
- `Exclude suffix` 排除指定后缀的数据包

imgs/config_other.png

19.1 KB
Loading

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>burp.vaycore</groupId>
88
<artifactId>onescan</artifactId>
9-
<version>0.4.2</version>
9+
<version>0.4.3</version>
1010

1111
<properties>
1212
<jdk.version>8</jdk.version>

src/main/java/burp/BurpExtender.java

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
package burp;
22

33
import burp.vaycore.common.helper.DomainHelper;
4+
import burp.vaycore.common.helper.QpsLimiter;
45
import burp.vaycore.common.log.Logger;
56
import burp.vaycore.common.utils.*;
67
import burp.vaycore.hae.HaE;
78
import burp.vaycore.onescan.OneScan;
89
import burp.vaycore.onescan.bean.TaskData;
910
import burp.vaycore.onescan.common.Config;
1011
import burp.vaycore.onescan.common.Constants;
12+
import burp.vaycore.onescan.common.OnTabEventListener;
1113
import burp.vaycore.onescan.ui.payloadlist.PayloadItem;
1214
import burp.vaycore.onescan.ui.payloadlist.PayloadRule;
15+
import burp.vaycore.onescan.ui.tab.ConfigPanel;
1316
import burp.vaycore.onescan.ui.tab.DataBoardTab;
17+
import burp.vaycore.onescan.ui.tab.config.OtherTab;
1418
import burp.vaycore.onescan.ui.widget.TaskTable;
19+
import org.json.HTTP;
1520
import org.json.JSONArray;
1621
import org.json.JSONObject;
1722

@@ -32,23 +37,25 @@
3237
* Created by vaycore on 2022-08-07.
3338
*/
3439
public class BurpExtender implements IBurpExtender, IProxyListener, IMessageEditorController,
35-
TaskTable.OnTaskTableEventListener, ITab {
40+
TaskTable.OnTaskTableEventListener, ITab, OnTabEventListener {
3641

3742
private IBurpExtenderCallbacks mCallbacks;
3843
private OneScan mOneScan;
3944
private DataBoardTab mDataBoardTab;
45+
private ConfigPanel mConfigTab;
4046
private IMessageEditor mRequestTextEditor;
4147
private IMessageEditor mResponseTextEditor;
4248
private ExecutorService mThreadPool;
4349
private IHttpRequestResponse mCurrentReqResp;
4450
private static final Vector<String> sRepeatFilter = new Vector<>();
51+
private QpsLimiter mQpsLimit;
4552

4653
@Override
4754
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
4855
initData(callbacks);
4956
initView();
5057
initEvent();
51-
Logger.debug("register Extender ok! Log: " + Constants.PLUGIN_VERSION.contains("debug"));
58+
Logger.debug("register Extender ok! Log: " + Constants.DEBUG);
5259
// 加载HaE插件
5360
HaE.loadPlugin(Config.getFilePath(Config.KEY_HAE_PLUGIN_PATH));
5461
}
@@ -58,24 +65,37 @@ private void initData(IBurpExtenderCallbacks callbacks) {
5865
this.mThreadPool = Executors.newFixedThreadPool(50);
5966
this.mCallbacks.setExtensionName(Constants.PLUGIN_NAME + " v" + Constants.PLUGIN_VERSION);
6067
// 初始化日志打印
61-
Logger.init(Constants.PLUGIN_VERSION.contains("debug"), mCallbacks.getStdout(), mCallbacks.getStderr());
68+
Logger.init(Constants.DEBUG, mCallbacks.getStdout(), mCallbacks.getStderr());
6269
// 初始化默认配置
6370
Config.init();
6471
// 初始化域名辅助类
6572
DomainHelper.init("public_suffix_list.json");
6673
// 初始化HaE插件
6774
HaE.init(this);
75+
// 初始化QPS限制器
76+
initQpsLimiter();
77+
}
78+
79+
private void initQpsLimiter() {
80+
// 检测范围,如果不符合条件,不创建限制器
81+
int limit = StringUtils.parseInt(Config.get(Config.KEY_QPS_LIMIT));
82+
if (limit > 0 && limit <= 9999) {
83+
this.mQpsLimit = new QpsLimiter(limit);
84+
}
6885
}
6986

7087
private void initView() {
7188
mOneScan = new OneScan();
7289
mDataBoardTab = mOneScan.getDataBoardTab();
90+
mConfigTab = mOneScan.getConfigPanel();
7391
mCallbacks.addSuiteTab(this);
7492
// 创建请求和响应控件
7593
mRequestTextEditor = mCallbacks.createMessageEditor(this, false);
7694
mResponseTextEditor = mCallbacks.createMessageEditor(this, false);
7795
mDataBoardTab.init(mRequestTextEditor.getComponent(), mResponseTextEditor.getComponent());
7896
mDataBoardTab.getTaskTable().setOnTaskTableEventListener(this);
97+
// 注册事件
98+
mConfigTab.getOtherTab().setOnTabEventListener(this);
7999
}
80100

81101
private void initEvent() {
@@ -301,6 +321,10 @@ private void doBurpRequest(IHttpRequestResponse httpReqResp, byte[] request) {
301321
sRepeatFilter.add(url);
302322
// 给每个任务创建线程
303323
mThreadPool.execute(() -> {
324+
// 限制QPS
325+
if (mQpsLimit != null) {
326+
mQpsLimit.limit();
327+
}
304328
Logger.debug("Do Send Request url: " + url);
305329
// 发起请求
306330
IHttpRequestResponse newReqResp = mCallbacks.makeHttpRequest(service, requestBytes);
@@ -322,7 +346,7 @@ private String buildRequestHeader(IHttpService service, String urlPath) {
322346
ArrayList<String> headerList = getHeaderList();
323347
StringBuilder request = new StringBuilder();
324348
// 请求头构造
325-
request.append("GET ").append(urlPath).append(" HTTP/1.1").append("\r\n");
349+
request.append("GET ").append(urlPath).append(" HTTP/1.1").append(HTTP.CRLF);
326350
// 如果存在配置,直接加载配置的值,否则使用默认值
327351
if (headerList.size() > 0) {
328352
for (String headerItem : headerList) {
@@ -332,20 +356,20 @@ private String buildRequestHeader(IHttpService service, String urlPath) {
332356
}
333357
String headerKey = headerItem.substring(0, splitIndex);
334358
String headerValue = headerItem.substring(splitIndex + 2);
335-
request.append(headerKey).append(": ").append(headerValue).append("\r\n");
359+
request.append(headerKey).append(": ").append(headerValue).append(HTTP.CRLF);
336360
}
337361
} else {
338362
String referer = getHostByIHttpService(service) + "/";
339-
request.append("Host: {{host}}").append("\r\n");
340-
request.append("User-Agent: ").append("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4495.0 Safari/537.36").append("\r\n");
341-
request.append("Referer: ").append(referer).append("\r\n");
342-
request.append("Accept: ").append("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9").append("\r\n");
343-
request.append("Accept-Language: ").append("zh-CN,zh;q=0.9,en;q=0.8").append("\r\n");
344-
request.append("Accept-Encoding: ").append("gzip, deflate").append("\r\n");
345-
request.append("Origin: ").append("https://www.baidu.com").append("\r\n");
346-
request.append("Cache-Control: ").append("max-age=0").append("\r\n");
347-
}
348-
request.append("\r\n");
363+
request.append("Host: {{host}}").append(HTTP.CRLF);
364+
request.append("User-Agent: ").append("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4495.0 Safari/537.36").append(HTTP.CRLF);
365+
request.append("Referer: ").append(referer).append(HTTP.CRLF);
366+
request.append("Accept: ").append("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9").append(HTTP.CRLF);
367+
request.append("Accept-Language: ").append("zh-CN,zh;q=0.9,en;q=0.8").append(HTTP.CRLF);
368+
request.append("Accept-Encoding: ").append("gzip, deflate").append(HTTP.CRLF);
369+
request.append("Origin: ").append("https://www.baidu.com").append(HTTP.CRLF);
370+
request.append("Cache-Control: ").append("max-age=0").append(HTTP.CRLF);
371+
}
372+
request.append(HTTP.CRLF);
349373
// 请求头构建完成后,设置里面包含的变量
350374
return setupVariable(service, request.toString());
351375
}
@@ -360,9 +384,11 @@ private String setupVariable(IHttpService service, String request) {
360384
String timestamp = String.valueOf(DateUtils.getTimestamp());
361385
String randomIP = IPUtils.randomIPv4();
362386
String randomUA = Utils.getRandomItem(Config.getList(Config.KEY_UA_LIST));
387+
String mainDomain = DomainHelper.getDomain(domain);
363388
// 替换变量
364389
request = request.replace("{{host}}", host);
365390
request = request.replace("{{domain}}", domain);
391+
request = request.replace("{{mdomain}}", mainDomain);
366392
request = request.replace("{{protocol}}", protocol);
367393
request = request.replace("{{timestamp}}", timestamp);
368394
request = request.replace("{{random.ip}}", randomIP);
@@ -641,4 +667,15 @@ public void onSendToRepeater(ArrayList<TaskData> list) {
641667
}
642668
}
643669
}
670+
671+
@Override
672+
public void onTabEventMethod(String action, Object... params) {
673+
switch (action) {
674+
case OtherTab.EVENT_QPS_LIMIT:
675+
String limit = (String) params[0];
676+
mQpsLimit = new QpsLimiter(StringUtils.parseInt(limit));
677+
Logger.debug("Event: change qps limit: " + limit);
678+
break;
679+
}
680+
}
644681
}

src/main/java/burp/vaycore/common/config/ConfigContextImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import java.io.File;
99
import java.util.HashMap;
10-
import java.util.LinkedHashMap;
1110
import java.util.Map;
1211

1312
/**
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package burp.vaycore.common.helper;
2+
3+
/**
4+
* QPS 限制器
5+
* <p>
6+
* Created by vaycore on 2023-02-23.
7+
*/
8+
public class QpsLimiter {
9+
10+
/**
11+
* 以每秒的间隔计算
12+
*/
13+
private static final long PERIOD = 1000;
14+
15+
/**
16+
* 接受请求时间窗口
17+
*/
18+
private final long[] accessTime;
19+
20+
/**
21+
* 限制数量,最低为1
22+
*/
23+
private final int limit;
24+
25+
/**
26+
* 指向最早请求时间的位置
27+
*/
28+
private int position;
29+
30+
public QpsLimiter(int limit) {
31+
if (limit <= 0) {
32+
throw new IllegalArgumentException("Illegal limit value: " + limit);
33+
}
34+
this.position = 0;
35+
this.limit = limit;
36+
this.accessTime = new long[limit];
37+
}
38+
39+
/**
40+
* 对执行点进行限制
41+
*/
42+
public void limit() {
43+
long sleepMillis = 0;
44+
synchronized (QpsLimiter.class) {
45+
long curTime = System.currentTimeMillis();
46+
if (curTime - this.accessTime[this.position] < PERIOD) {
47+
// 未达到处理间隔, 计算休眠间隔剩余时间
48+
sleepMillis = PERIOD - (curTime - this.accessTime[this.position]) + 1;
49+
curTime = System.currentTimeMillis() + sleepMillis;
50+
}
51+
this.accessTime[this.position++] = curTime;
52+
this.position = this.position % this.limit;
53+
}
54+
// 如果为0,没必要sleep
55+
if (sleepMillis > 0) {
56+
try {
57+
Thread.sleep(sleepMillis);
58+
} catch (InterruptedException e) {
59+
e.printStackTrace();
60+
}
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)