Compare commits

...

34 Commits
1.4 ... 2.0.5

Author SHA1 Message Date
AnonymousUser
43fbc46b65 Version: 2.0.5 Fixed Bug 2021-07-06 18:33:11 +08:00
AnonymousUser
00a4a835b2 Update 2021-06-25 12:41:25 +08:00
AnonymousUser
f872dadf46 Version: 2.0.4 Fixed Bug 2021-06-14 23:06:03 +08:00
0chen
15bbb9f1a0 修复一处bug
close #18
感谢#18 问题已经修复
2021-06-14 15:33:22 +08:00
AnonymousUser
89f3f6cf09 Version 2.0.3 Fixed Match Scope Bug 2021-06-12 15:24:19 +08:00
AnonymousUser
cf9f434ff8 Version 2.0.3 Fixed Match Scope Bug 2021-06-12 15:19:39 +08:00
AnonymousUser
37a907d6df Version: 2.0.2 Fixed UI BUG 2021-06-11 18:27:14 +08:00
AnonymousUser
83e5da2f7e Version: 2.0.2 Fixed UI BUG 2021-06-11 18:25:36 +08:00
AnonymousUser
e43a96b8ad Version: 2.0.1 Fixed bug 2021-06-11 12:36:30 +08:00
AnonymousUser
a7112ad297 Version: 2.0 Update 2021-06-11 08:22:45 +08:00
AnonymousUser
efc7a2d7e3 Version: 2.0 Update 2021-06-10 23:20:46 +08:00
AnonymousUser
0cfebb8464 Version: 2.0 Update 2021-06-10 23:02:51 +08:00
AnonymousUser
2b4e56ea8c Version: 2.0 Update 2021-06-10 22:59:27 +08:00
AnonymousUser
4bdb576448 Add Public Rules 2020-12-11 23:55:11 +08:00
Key
e7a7f823df Merge pull request #11 from PortSwigger/master
BApp
2020-12-04 23:02:57 +08:00
PortSwigger Support
a0d33f8c58 1.5.1 update 2020-12-04 14:51:33 +00:00
Uthman Eqbal
72511d9f14 Merge pull request #7 from gh0stkey/master
HaE 1.5.1
2020-12-04 12:02:26 +00:00
Uthman Eqbal
2336a49023 Merge branch 'master' into master 2020-12-04 12:02:16 +00:00
AnonymousUser
d89bec65e3 Update 2020-12-04 19:52:36 +08:00
AnonymousUser
2239ca1e90 Update 2020-12-04 19:48:22 +08:00
AnonymousUser
27fbf465b7 update 2020-12-04 16:00:40 +08:00
AnonymousUser
2879a1494c update 2020-12-04 02:46:19 +08:00
AnonymousUser
d9e0bf4714 Update: Customize HaE's Regex Engine
Now you can customize HaE's regex engine: NFA/DFA, but the premise is that you need to test your regex is running ok under the engine you choose.
2020-12-04 02:43:34 +08:00
AnonymousUser
170ed412b3 Add gitignore 2020-11-27 21:31:54 +08:00
PortSwigger Support
91009337c1 BApp update v1.5 2020-11-27 10:24:49 +00:00
Uthman Eqbal
a0127d75a9 Merge pull request #5 from gh0stkey/master
HaE 1.5
2020-11-27 09:17:41 +00:00
AnonymousUser
2ce57f8ee1 Rebuild code and add default filter. 2020-11-27 03:48:28 +08:00
AnonymousUser
7b5027a528 Update: Replace java.util.regex with jregex 2020-11-12 22:54:34 +08:00
PortSwigger Support
df0f4bd41b BApp update 2020-11-12 14:22:18 +00:00
HannahLaw-Portswigger
d0a61ba9ac Merge pull request #4 from gh0stkey/master
HaE 1.4.1
2020-11-12 11:26:34 +00:00
AnonymousUser
c632782bc6 Add Scope Column: any 2020-11-11 23:59:27 +08:00
AnonymousUser
503fea6f55 Update: Support request messages 2020-11-11 03:32:42 +08:00
AnonymousUser
db1f8b9cc9 Update 2020-11-11 03:22:31 +08:00
PortSwigger Support
78628b03d1 BApp preparation 2020-10-08 10:06:10 +00:00
28 changed files with 1784 additions and 779 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.DS_Store
.idea
.gradle

View File

@@ -1,99 +1,95 @@
# HaE - Highlighter and Extractor
Note: My english is not very good, Thanks!
HaE相关作者 (来自米斯特安全团队 www.acmesec.cn)
Read Chinese simplified version ([README_zh](README_zh.md)).
架构作者: [@0chencc](https://github.com/0Chencc)
核心功能作者: [@EvilChen](https://github.com/gh0stkey)
## Introduction
## 公共规则网站
**HaE** is used to highlight HTTP requests and extract information from HTTP `response messages` or `request messages`.
https://gh0st.cn/HaE/
## 介绍
**HaE**是基于 `BurpSuite` 插件 `JavaAPI` 开发的请求高亮标记与信息提取的辅助型插件。
![-w1070](images/16000706401522.jpg)
The plugin can custom regular expression to match HTTP response messages. You can decide for yourself whether the corresponding request that meets the custom regular expression match needs to be highlighted and information extracted.
该插件可以通过自定义正则的方式匹配**响应报文或请求报文**,可以自行决定符合该自定义正则匹配的相应请求是否需要高亮标记、信息提取。
**Note**: The use of HaE requires a basic regular expression foundation for testers. Since the Java regular expression library is not as elegant or convenient as Python, when using regular expressions, HaE requires users to use `()` to extract what they need The expression content contains; for example, if you want to match a response message of a Shiro application, the normal matching rule is `rememberMe=delete`, if you want to extract this content, you need to become `(rememberMe=delete)`.
****: `HaE`的使用,对测试人员来说需要基本的正则表达式基础,由于`Java`正则表达式的库并没有`Python`的优雅或方便在使用正则的HaE要求使用者必须使用`()`将所需提取的表达式内容包含;例如你要匹配一个**Shiro应用**的响应报文,正常匹配规则为`rememberMe=delete`,如果你要提取这段内容的话就需要变成`(rememberMe=delete)`
## Instructions
## 使用方法
Load: `Extender - Extensions - Add - Select File - Next`
插件装载: `Extender - Extensions - Add - Select File - Next`
The configuration file is initialized when HaE is loaded for the first time. The default configuration file has a built-in regular expression: `Email`. The initialized configuration file will be placed in the same directory as the BurpSuite Jar package.
初次装载`HaE`会初始化配置文件,默认配置文件内置一个正则: `Email`,初始化的配置文件会放在与`BurpSuite Jar`包同级目录下。
![-w330](images/16000708493657.jpg)
In addition to the initial configuration file, there is `init.hae`, which is used to store the configuration file path; `HaE` supports custom configuration file paths, and you can select a custom configuration file by clicking the `Select File` button.
除了初始化的配置文件外,还有`Setting.yml`,该文件用于存储配置文件路径;`HaE`支持自定义配置文件路径,你可以通过点击`Select File`按钮进行选择自定义配置文件。
![-w477](images/16000710069404.jpg)
HaE supports three actions:
## 插件优点
1. Reload: It can be used when you do not use the HaE UI interface to modify the rules in the configuration file, but directly modify the rules based on the configuration file;
2. New: Add a new rule will automatically add a row of table data, click or double-click to modify the data to automatically save;
3. Delete: When you click to select a rule, press this button to delete the rule.
1. 多选项自定义控制适配需求
2. 多颜色高亮分类将BurpSuite的所有高亮颜色集成: `red, orange, yellow, green, cyan, blue, pink, magenta, gray`
3. **颜色升级算法**: 利用下标的方式进行优先级排序当满足2个同颜色条件则以优先级顺序上升颜色例如: **两个正则,颜色为橘黄色,该请求两个正则都匹配到了,那么将升级为红色**
4. 配置文件采用YAML格式存储更加便于阅读和修改
5. 内置简单缓存,在“多正则、大数据”的场景下减少卡顿现象
6. **支持标签分页**,点击`...`即可添加新的标签页,对着标签页右键即可删除
**Note**: `HaE's operations` are based on the form UI, and all operations will be automatically saved.
![-w477](images/16000720732851.jpg)
## Plugin Advantages
## 实际使用
1. Multi-option custom adaptation requirements;
2. Multi-color classification (colors of BurpSuite): `red, orange, yellow, green, cyan, blue, pink, magenta, gray`;
3. Color upgrade algorithm: **Two regulars expression, the colors are both orange, if the request are matched these, it will be upgraded to red.**
4. The configuration file format uses JSON format, the format is
```
{name: {"loaded": isLoaded,"regex": regexText, "highlight": isHighlight, "extract": isExtract, "color": colorText}}
```
5. Built-in simple cache to reduce the stuttering phenomenon in the `multi-regular, big data scenario`.
## Actual Use
Use RGPerson to generate test data and put it in the root directory file of the website:
使用 RGPerson 生成测试数据,放入网站根目录文件中:
![-w467](images/16000719723284.jpg)
Visit the address, you can see the highlighted request in the `Proxy-HTTP History`, and you can see the response tab contains the `MarkINFO` tag, which extracts the matched information.
访问该地址,在`Proxy - HTTP History`中可以看见高亮请求,响应标签页中含有`MarkINFO`标签,其中将匹配到的信息提取了出来。
![-w1047](images/16000720732854.jpg)
## Regular Expression Optimization
## 正则优化
Some regular expression are not ideal in actual combat application scenarios.
有些正则在实战应用场景中并不理想
There will be some false positives when regular expression matching mobile phone numbers (pure numbers), the mobile phone number processing can be solved:
在正则匹配手机号、身份证号码的时候(纯数字类)会存在一些误报(这里匹配身份证号码无法进行校验,误报率很高),但手机号处理这一块可以解决:
Original regular expression:
原正则:
```
1[3-9]\d{9}
```
False positive scenario: `12315188888888123`, it will match `15188888888`, but this paragraph is not a mobile phone number, so the modification rule is:
误报场景: `12315188888888123`,这时候会匹配到`15188888888`,而实际上这一段并不是手机号,所以修改正则为:
```
[^0-9]+(1[3-9]\d{9})[^0-9]+
```
The mobile phone number required to be matched cannot be a number from 0-9.
也就是要求匹配的手机号前后不能为0-9的数字。
## 实战用法
### Include Regular Expression List
1. CMS指纹识别Discuz正则: `(Powered by Discuz!)`
2. OSS对象存储信息泄露正则: `([A|a]ccess[K|k]ey[I|i]d|[A|a]ccess[K|k]ey[S|s]ecret)`
3. 内网地址信息提取,正则: `(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:172\.(?:(?:1[6-9])|(?:2\d)|(?:3[01]))\.\d{1,3}\.\d{1,3})|(?:192\.168\.\d{1,3}\.\d{1,3})`
4. 实战插件关联搭配,漏洞挖掘案例: https://mp.weixin.qq.com/s/5vNn7dMRZBtv0ojPBAHV7Q
Chinese ID-Number(From: https://github.com/gh0stkey/HaE/issues/3):
...还有诸多使用方法等待大家去发掘。
```
[^0-9]([1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx])|([1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}[0-9Xx])[^0-9]
```
## 文末
Email Address:
随笔: 正义感是一个不可丢失的东西。
```
([\w-]+(?:\.[\w-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?)
```
Github项目地址BUG、需求、正则欢迎提交: https://github.com/gh0stkey/HaE
Elasticsearch Unauthorized Access(From: https://github.com/gh0stkey/HaE/issues/7):
## 404StarLink 2.0 - Galaxy
```
("cluster_uuid"\s*:\s*"[A-Za-z0-9_-]{22}")
```
![404StarLink Logo](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png)
`HaE` 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-Galaxy) 中的一环,如果对 `HaE` 有任何疑问又或是想要找小伙伴交流,可以参考星链计划的加群方式。
- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community)

View File

@@ -1,108 +0,0 @@
# HaE - Highlighter and Extractor
## 介绍
**HaE**是基于 `BurpSuite` 插件 `JavaAPI` 开发的请求高亮标记与信息提取的辅助型插件。
![-w1070](images/16000706401522.jpg)
该插件可以通过自定义正则的方式匹配**响应报文或请求报文**,可以自行决定符合该自定义正则匹配的相应请求是否需要高亮标记、信息提取。
**注**: `HaE`的使用,对测试人员来说需要基本的正则表达式基础,由于`Java`正则表达式的库并没有`Python`的优雅或方便在使用正则的HaE要求使用者必须使用`()`将所需提取的表达式内容包含;例如你要匹配一个**Shiro应用**的响应报文,正常匹配规则为`rememberMe=delete`,如果你要提取这段内容的话就需要变成`(rememberMe=delete)`
## 使用方法
插件装载: `Extender - Extensions - Add - Select File - Next`
初次装载`HaE`会初始化配置文件,默认配置文件内置一个正则: `Email`,初始化的配置文件会放在与`BurpSuite Jar`包同级目录下。
![-w330](images/16000708493657.jpg)
除了初始化的配置文件外,还有`init.hae`,该文件用于存储配置文件路径;`HaE`支持自定义配置文件路径,你可以通过点击`Select File`按钮进行选择自定义配置文件。
![-w477](images/16000710069404.jpg)
HaE支持三个动作:
1. 重载规则Reload: 当你不使用HaE UI界面去修改配置文件内的规则时而是直接基于配置文件进行修改规则时可使用
2. 新建规则New: 新建规则会自动添加一行表格数据,单击或双击进行修改数据即可自动保存;
3. 删除规则Delete: 单击选中某条规则时,按下该按钮即可删除规则。
**注**: HaE的操作都是基于表单UI的方式操作即会自动保存。
## 插件优点
1. 多选项自定义控制适配需求;
2. 多颜色高亮分类将BurpSuite的所有高亮颜色集成: `red, orange, yellow, green, cyan, blue, pink, magenta, gray`
3. 颜色升级算法: 利用下标的方式进行优先级排序当满足2个同颜色条件则以优先级顺序上升颜色。例如: **两个正则,颜色为橘黄色,该请求两个正则都匹配到了,那么将升级为红色**
4. 简单的配置文件格式选用JSON格式格式为
```
{name: {"loaded": isLoaded,"regex": regexText, "highlight": isHighlight, "extract": isExtract, "color": colorText}}
```
5. 内置简单缓存,在“多正则、大数据”的场景下减少卡顿现象。
## 实际使用
使用 RGPerson 生成测试数据,放入网站根目录文件中:
![-w467](images/16000719723284.jpg)
访问该地址,在`Proxy - HTTP History`中可以看见高亮请求,响应标签页中含有`MarkINFO`标签,其中将匹配到的信息提取了出来。
![-w1047](images/16000720732854.jpg)
## 正则优化
有些正则在实战应用场景中并不理想
在正则匹配手机号、身份证号码的时候(纯数字类)会存在一些误报(这里匹配身份证号码无法进行校验,误报率很高),但手机号处理这一块可以解决:
原正则:
```
1[3-9]\d{9}
```
误报场景: `12315188888888123`,这时候会匹配到`15188888888`,而实际上这一段并不是手机号,所以修改正则为:
```
[^0-9]+(1[3-9]\d{9})[^0-9]+
```
也就是要求匹配的手机号前后不能为0-9的数字。
## 实战用法
1. CMS指纹识别Discuz正则: `(Powered by Discuz!)`
2. OSS对象存储信息泄露正则: `([A|a]ccess[K|k]ey[I|i]d|[A|a]ccess[K|k]ey[S|s]ecret)`
3. 内网地址信息提取,正则: `(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:172\.(?:(?:1[6-9])|(?:2\d)|(?:3[01]))\.\d{1,3}\.\d{1,3})|(?:192\.168\.\d{1,3}\.\d{1,3})`
4. 实战插件关联搭配,漏洞挖掘案例: https://mp.weixin.qq.com/s/5vNn7dMRZBtv0ojPBAHV7Q
...还有诸多使用方法等待大家去发掘。
## 文末
随笔: 正义感是一个不可丢失的东西。
Github项目地址BUG、需求、正则欢迎提交: https://github.com/gh0stkey/HaE
### 收录正则列表
身份证号码(来自: https://github.com/gh0stkey/HaE/issues/3):
```
[^0-9]([1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx])|([1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}[0-9Xx])[^0-9]
```
邮箱地址:
```
([\w-]+(?:\.[\w-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?)
```
Elasticsearch未授权访问匹配(来自: https://github.com/gh0stkey/HaE/issues/7):
```
("cluster_uuid"\s*:\s*"[A-Za-z0-9_-]{22}")
```

View File

@@ -1,24 +1,33 @@
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'net.portswigger.burp.extender:burp-extender-api:1.7.13'
compile 'org.json:json:20200518'
}
sourceSets {
main {
java {
srcDir '.'
}
}
}
task fatJar(type: Jar) {
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
plugins {
id 'java'
}
repositories {
mavenCentral()
}
compileJava {
options.encoding = "UTF-8"
}
sourceSets {
main {
java {
srcDir './src/main/java'
}
}
}
task fatJar(type: Jar) {
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
dependencies {
compile 'net.portswigger.burp.extender:burp-extender-api:1.7.13'
compile 'org.jetbrains:annotations:16.0.2'
compile group: 'org.yaml', name: 'snakeyaml', version: '1.28'
compile 'net.sourceforge.jregex:jregex:1.2_01'
compile 'dk.brics.automaton:automaton:1.11-8'
}

View File

@@ -1,597 +0,0 @@
package burp;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.*;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.DefaultCellEditor;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.awt.event.ActionEvent;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.JLabel;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEditorTabFactory, ITab {
private JFrame frame;
private JPanel panel;
private JTable table;
private JTextField textField;
private IBurpExtenderCallbacks callbacks;
private static String configFilePath = "config.json";
private static String initFilePath = "init.hae";
private static String initConfigContent = "{\"Email\":{\"loaded\":true,\"highlight\":true,\"regex\":\"([\\\\w-]+(?:\\\\.[\\\\w-]+)*@(?:[\\\\w](?:[\\\\w-]*[\\\\w])?\\\\.)+[\\\\w](?:[\\\\w-]*[\\\\w])?)\",\"extract\":true,\"color\":\"yellow\"}}";
private static String endColor = "";
private static String[] colorArray = new String[] {"red", "orange", "yellow", "green", "cyan", "blue", "pink", "magenta", "gray"};
private static String[] scopeArray = new String[] {"response", "request"};
private static String[] actionArray = new String[] {"any", "extract", "highight"};
private static IMessageEditorTab HaETab;
private static PrintWriter stdout;
@Override
public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks)
{
this.callbacks = callbacks;
// 设置插件名字和版本
String version = "1.4";
callbacks.setExtensionName(String.format("HaE (%s) - Highlighter and Extractor", version));
// 定义输出
stdout = new PrintWriter(callbacks.getStdout(), true);
stdout.println("@Author: EvilChen");
// UI
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// 判断"config.json"文件是否具备内容,如若不具备则进行初始化
if (configFilePath.equals("config.json")) {
if (readFileContent(configFilePath).equals("")) {
writeFileContent(configFilePath, initConfigContent);
writeFileContent(initFilePath, configFilePath);
}
}
// 判断配置文件是否存在
if (fileExists(configFilePath)) {
configFilePath = readFileContent(initFilePath);
} else {
JOptionPane.showMessageDialog(null, "Config File Not Found!", "Error", JOptionPane.ERROR_MESSAGE);
}
initialize();
fillTable();
}
});
callbacks.registerHttpListener(BurpExtender.this);
callbacks.registerMessageEditorTabFactory(BurpExtender.this);
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 526, 403);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(new BorderLayout(0, 0));
JPanel panel_3 = new JPanel();
panel.add(panel_3, BorderLayout.NORTH);
JLabel lblNewLabel_1 = new JLabel("Config File:");
panel_3.add(lblNewLabel_1);
textField = new JTextField();
textField.setEditable(false);
panel_3.add(textField);
textField.setColumns(20);
textField.setText(configFilePath);
JButton btnNewButton = new JButton("Select File ...");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser jfc = new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
jfc.showDialog(new JLabel(), "Choose");
File file = jfc.getSelectedFile();
textField.setText(file.getAbsolutePath());
configFilePath = textField.getText();
writeFileContent(initFilePath, configFilePath);
fillTable();
}
});
panel_3.add(btnNewButton);
JPanel panel_2 = new JPanel();
panel.add(panel_2, BorderLayout.CENTER);
panel_2.setLayout(new BorderLayout(0, 0));
JPanel panel_1 = new JPanel();
panel_2.add(panel_1, BorderLayout.NORTH);
panel_1.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "Actions", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
JButton btnReloadRule = new JButton("Reload");
btnReloadRule.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fillTable();
}
});
panel_1.add(btnReloadRule);
JButton btnNewRule = new JButton("New");
btnNewRule.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
Vector rules = new Vector();
rules.add(true);
rules.add("New Rule");
rules.add("New Regex");
rules.add("red");
rules.add("response");
rules.add("any");
dtm.addRow(rules);
}
});
panel_1.add(btnNewRule);
JButton btnDeleteRule = new JButton("Delete");
btnDeleteRule.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectRows = table.getSelectedRows().length;
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
if (selectRows == 1) {
int selectedRowIndex = table.getSelectedRow();
// 在配置文件中删除数据
String cellValue = (String) dtm.getValueAt(selectedRowIndex, 1);
// System.out.println(cellValue);
removeConfig(cellValue);
// 在表格中删除数据
dtm.removeRow(selectedRowIndex);
}
}
});
panel_1.add(btnDeleteRule);
JScrollPane scrollPane = new JScrollPane();
panel_2.add(scrollPane, BorderLayout.CENTER);
table = new JTable();
table.setModel(new DefaultTableModel(
new Object[][] {
},
new String[] {
"Loaded", "Name", "Regex", "Color", "Scope", "Action"
}
));
scrollPane.setViewportView(table);
table.getColumnModel().getColumn(2).setPreferredWidth(172);
table.getColumnModel().getColumn(3).setCellEditor(new DefaultCellEditor(new JComboBox(colorArray)));
table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(new JCheckBox()));
table.getColumnModel().getColumn(4).setCellEditor(new DefaultCellEditor(new JComboBox(scopeArray)));
table.getColumnModel().getColumn(5).setCellEditor(new DefaultCellEditor(new JComboBox(actionArray)));
JLabel lblNewLabel = new JLabel("@EvilChen Love YuChen.");
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(lblNewLabel, BorderLayout.SOUTH);
table.getModel().addTableModelListener(
new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.INSERT || e.getType() == TableModelEvent.UPDATE) {
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
int rows = dtm.getRowCount();
JSONObject jsonObj = new JSONObject();
for (int i = 0; i < rows; i++) {
JSONObject jsonObj1 = new JSONObject();
jsonObj1.put("loaded", (boolean) dtm.getValueAt(i, 0));
jsonObj1.put("regex", (String) dtm.getValueAt(i, 2));
jsonObj1.put("color", (String) dtm.getValueAt(i, 3));
jsonObj1.put("scope", (String) dtm.getValueAt(i, 4));
jsonObj1.put("action", (String) dtm.getValueAt(i, 5));
// 添加数据
jsonObj.put((String) dtm.getValueAt(i, 1), jsonObj1);
}
writeFileContent(configFilePath, jsonObj.toString());
}
}
}
);
callbacks.customizeUiComponent(panel);
callbacks.customizeUiComponent(panel_1);
callbacks.customizeUiComponent(panel_2);
callbacks.customizeUiComponent(panel_3);
callbacks.customizeUiComponent(scrollPane);
callbacks.addSuiteTab(BurpExtender.this);
}
@Override
public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) {
HaETab = new MarkInfoTab(controller, editable);
return HaETab;
}
@Override
public String getTabCaption() {
return "HaE";
}
@Override
public Component getUiComponent() {
return panel;
}
/*
* 使用processHttpMessage用来做Highlighter
*/
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
// 判断是否是响应且该代码作用域为REPEATER、INTRUDER、PROXY分别对应toolFlag 64、32、4
if (toolFlag == 64 || toolFlag == 32 || toolFlag == 4) {
JSONObject jsonObj = new JSONObject();
if (messageIsRequest) {
byte[] content = messageInfo.getRequest();
try {
String c = new String(content, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
jsonObj = matchRegex(content, "request", "highlight");
} else {
byte[] content = messageInfo.getResponse();
try {
String c = new String(content, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
jsonObj = matchRegex(content, "response", "highlight");
}
List<String> colorList = highlightList(jsonObj);
if (colorList.size() != 0) {
colorUpgrade(getColorKeys(colorList));
String color = endColor;
messageInfo.setHighlight(color);
}
}
}
class MarkInfoTab implements IMessageEditorTab {
private ITextEditor markInfoText;
private byte[] currentMessage;
public MarkInfoTab(IMessageEditorController controller, boolean editable) {
markInfoText = callbacks.createTextEditor();
markInfoText.setEditable(editable);
}
@Override
public String getTabCaption() {
return "MarkInfo";
}
@Override
public Component getUiComponent() {
return markInfoText.getComponent();
}
@Override
public boolean isEnabled(byte[] content, boolean isRequest) {
if (isRequest && matchRegex(content, "request", "extract").length() != 0) {
return true;
} else if (!isRequest && matchRegex(content, "response", "extract").length() != 0) {
return true;
}
return false;
}
@Override
public byte[] getMessage() {
return currentMessage;
}
@Override
public boolean isModified() {
return markInfoText.isTextModified();
}
@Override
public byte[] getSelectedData() {
return markInfoText.getSelectedText();
}
/*
* 使用setMessage用来做Extractor
*/
@Override
public void setMessage(byte[] content, boolean isRequest) {
try {
String c = new String(content, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (content.length > 0) {
if (isRequest) {
JSONObject jsonObj = matchRegex(content, "request", "extract");
if (jsonObj.length() != 0) {
String result = extractString(jsonObj);
markInfoText.setText(result.getBytes());
}
} else {
JSONObject jsonObj = matchRegex(content, "response", "extract");
if (jsonObj.length() != 0) {
String result = extractString(jsonObj);
markInfoText.setText(result.getBytes());
}
}
}
currentMessage = content;
}
}
private String extractString(JSONObject jsonObj) {
String result = "";
Iterator<String> k = jsonObj.keys();
while (k.hasNext()) {
String name = k.next();
JSONObject jsonObj1 = new JSONObject(jsonObj.get(name).toString());
String tmpStr = String.format("[%s]\n%s\n\n", name, jsonObj1.getString("data")).intern();
result += tmpStr;
}
return result;
}
private List<String> highlightList(JSONObject jsonObj) {
List<String> colorList = new ArrayList<String>();
Iterator<String> k = jsonObj.keys();
while (k.hasNext()) {
String name = k.next();
JSONObject jsonObj2 = new JSONObject(jsonObj.get(name).toString());
colorList.add(jsonObj2.getString("color"));
}
return colorList;
}
private JSONObject matchRegex(byte[] content, String scopeString, String actionString) {
JSONObject tabContent = new JSONObject();
// 正则匹配提取内容
try {
String jsonStr = readFileContent(configFilePath);
JSONObject jsonObj = new JSONObject(jsonStr);
Iterator<String> k = jsonObj.keys();
// 遍历json数组
while (k.hasNext()) {
String contentString = new String(content, "UTF-8").intern();
String name = k.next();
JSONObject jsonObj1 = new JSONObject(jsonObj.get(name).toString());
JSONObject jsonData = new JSONObject();
String regex = jsonObj1.getString("regex");
boolean isLoaded = jsonObj1.getBoolean("loaded");
String scope = jsonObj1.getString("scope");
String action = jsonObj1.getString("action");
String color = jsonObj1.getString("color");
List<String> result = new ArrayList<String>();
if(isLoaded && scope.equals(scopeString) && (action.equals(actionString) || action.equals("any"))) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(contentString);
while (matcher.find()) {
// 添加匹配数据至list
// 强制用户使用()包裹正则
result.add(matcher.group(1));
}
// 去除重复内容
HashSet tmpList = new HashSet(result);
result.clear();
result.addAll(tmpList);
if (!result.isEmpty()) {
jsonData.put("color", color);
jsonData.put("data", String.join("\n", result));
jsonData.put("loaded", isLoaded);
// 初始化格式
tabContent.put(name, jsonData);
}
}
}
return tabContent;
} catch (Exception e) {
return new JSONObject();
}
}
/*
* 颜色下标获取
*/
private List<Integer> getColorKeys(List<String> keys){
List<Integer> result = new ArrayList<Integer>();
int size = colorArray.length;
// 根据颜色获取下标
for (int x = 0; x < keys.size(); x++) {
for (int v = 0; v < size; v++) {
if (colorArray[v].equals(keys.get(x))) {
result.add(v);
}
}
}
return result;
}
/*
* 颜色升级递归算法
*/
private static String colorUpgrade(List<Integer> colorList) {
int colorSize = colorList.size();
colorList.sort(Comparator.comparingInt(Integer::intValue));
int i = 0;
List<Integer> stack = new ArrayList<Integer>();
while (i < colorSize) {
if (stack.isEmpty()) {
stack.add(colorList.get(i));
i++;
} else {
if (colorList.get(i) != stack.stream().reduce((first, second) -> second).orElse(99999999)) {
stack.add(colorList.get(i));
i++;
} else {
stack.set(stack.size() - 1, stack.get(stack.size() - 1) - 1);
i++;
}
}
}
// 利用HashSet删除重复元素
HashSet tmpList = new HashSet(stack);
if (stack.size() == tmpList.size()) {
stack.sort(Comparator.comparingInt(Integer::intValue));
if(stack.get(0).equals(-1)) {
endColor = colorArray[0];
} else {
endColor = colorArray[stack.get(0)];
}
} else {
colorUpgrade(stack);
}
return "";
}
/*
* 判断文件是否存在
*/
private Boolean fileExists(String fileName) {
File file = new File(fileName);
if(file.exists()){
return true;
}
return false;
}
/*
* 获取文件内容
*/
private String readFileContent(String fileName) {
File file = new File(fileName);
BufferedReader reader = null;
StringBuffer sbf = new StringBuffer();
try {
reader = new BufferedReader(new FileReader(file));
String tempStr;
while ((tempStr = reader.readLine()) != null) {
sbf.append(tempStr);
}
reader.close();
return sbf.toString();
} catch (IOException e) {
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException err) {
err.printStackTrace();
}
}
}
return sbf.toString();
}
/*
* 写入文件内容
*/
private boolean writeFileContent(String fileName, String fileContent) {
try {
BufferedWriter out = new BufferedWriter(new FileWriter(fileName));
out.write(fileContent);
out.close();
return true;
} catch (IOException e) {
stdout.println(e);
return false;
}
}
/*
* 删除单条配置内容
*/
private void removeConfig(String key) {
String jsonStr = readFileContent(configFilePath);
JSONObject jsonObj = new JSONObject(jsonStr);
jsonObj.remove(key);
if (writeFileContent(configFilePath, jsonObj.toString())) {
JOptionPane.showMessageDialog(null, "Delete Successfully!", "Info", JOptionPane.INFORMATION_MESSAGE);
}
}
/*
* 初始化表格内容
*/
private void fillTable() {
DefaultTableModel dtm=(DefaultTableModel) table.getModel();
dtm.setRowCount(0);
String jsonStr = readFileContent(configFilePath);
JSONObject jsonObj = new JSONObject(jsonStr);
Iterator<String> k = jsonObj.keys();
// 遍历json数组
while (k.hasNext()) {
String name = k.next();
JSONObject jsonObj1 = new JSONObject(jsonObj.get(name).toString());
boolean loaded = jsonObj1.getBoolean("loaded");
String regex = jsonObj1.getString("regex");
String color = jsonObj1.getString("color");
String scope = jsonObj1.getString("scope");
String action = jsonObj1.getString("action");
// 填充数据
Vector rules = new Vector();
rules.add(loaded);
rules.add(name);
rules.add(regex);
rules.add(color);
rules.add(scope);
rules.add(action);
dtm.addRow(rules);
}
}
public static void main(String[] args) {
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 144 KiB

BIN
images/16000720732851.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

After

Width:  |  Height:  |  Size: 297 KiB

View File

@@ -1 +1,2 @@
rootProject.name = 'HaE'
rootProject.name = 'HaE'

View File

@@ -0,0 +1,235 @@
package burp;
import burp.action.*;
import burp.ui.MainUI;
import javax.swing.*;
import java.awt.*;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;
import java.io.PrintWriter;
import java.util.Map;
/*
* @author EvilChen
*/
public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEditorTabFactory, ITab {
private MainUI main = new MainUI();
private static PrintWriter stdout;
private IBurpExtenderCallbacks callbacks;
private static IExtensionHelpers helpers;
private static IMessageEditorTab HaETab;
MatchHTTP mh = new MatchHTTP();
ExtractContent ec = new ExtractContent();
DoAction da = new DoAction();
GetColorKey gck = new GetColorKey();
UpgradeColor uc = new UpgradeColor();
@Override
public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks)
{
this.callbacks = callbacks;
BurpExtender.helpers = callbacks.getHelpers();
String version = "2.0.5";
callbacks.setExtensionName(String.format("HaE (%s) - Highlighter and Extractor", version));
// 定义输出
stdout = new PrintWriter(callbacks.getStdout(), true);
stdout.println("@UI Author: 0chencc");
stdout.println("@Core Author: EvilChen");
stdout.println("@Github: https://github.com/gh0stkey/HaE");
// UI
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
initialize();
}
});
callbacks.registerHttpListener(BurpExtender.this);
callbacks.registerMessageEditorTabFactory(BurpExtender.this);
}
private void initialize(){
callbacks.customizeUiComponent(main);
callbacks.addSuiteTab(BurpExtender.this);
}
@Override
public String getTabCaption(){
return "HaE";
}
@Override
public Component getUiComponent() {
return main;
}
/*
* 使用processHttpMessage用来做Highlighter
*/
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
// 判断是否是响应且该代码作用域为REPEATER、INTRUDER、PROXY分别对应toolFlag 64、32、4
if (toolFlag == 64 || toolFlag == 32 || toolFlag == 4) {
Map<String, Map<String, Object>> obj;
byte[] content = messageInfo.getRequest();
// 流量清洗
String urlString = helpers.analyzeRequest(messageInfo.getHttpService(), content).getUrl().toString();
urlString = urlString.indexOf("?") > 0 ? urlString.substring(0, urlString.indexOf("?")) : urlString;
// 正则判断
if (mh.matchSuffix(urlString)) {
return;
}
if (messageIsRequest) {
// 获取报文头
List<String> requestTmpHeaders = helpers.analyzeRequest(messageInfo.getHttpService(), content).getHeaders();
String requestHeaders = String.join("\n", requestTmpHeaders);
// 获取报文主体
int requestBodyOffset = helpers.analyzeRequest(messageInfo.getHttpService(), content).getBodyOffset();
byte[] byteRequest = messageInfo.getRequest();
byte[] requestBody = Arrays.copyOfRange(byteRequest, requestBodyOffset, byteRequest.length);
obj = ec.matchRegex(content, requestHeaders, requestBody, "request");
} else {
// 获取报文头
List<String> responseTmpHeaders = helpers.analyzeRequest(messageInfo.getHttpService(), content).getHeaders();
String responseHeaders = String.join("\n", responseTmpHeaders);
// 获取报文主体
int responseBodyOffset = helpers.analyzeResponse(content).getBodyOffset();
byte[] byteResponse = messageInfo.getResponse();
byte[] responseBody = Arrays.copyOfRange(byteResponse, responseBodyOffset, byteResponse.length);
content = messageInfo.getResponse();
obj = ec.matchRegex(content, responseHeaders, responseBody, "response");
}
List<String> colorList = da.highlightList(obj);
if (colorList.size() != 0) {
String color = uc.getEndColor(gck.getColorKeys(colorList, Config.colorArray), Config.colorArray);
messageInfo.setHighlight(color);
}
}
}
class MarkInfoTab implements IMessageEditorTab {
private ITextEditor markInfoText;
private byte[] currentMessage;
private final IMessageEditorController controller;
private byte[] extractRequestContent;
private byte[] extractResponseContent;
public MarkInfoTab(IMessageEditorController controller, boolean editable) {
this.controller = controller;
markInfoText = callbacks.createTextEditor();
markInfoText.setEditable(editable);
}
@Override
public String getTabCaption() {
return "MarkInfo";
}
@Override
public Component getUiComponent() {
return markInfoText.getComponent();
}
@Override
public boolean isEnabled(byte[] content, boolean isRequest) {
Map<String, Map<String, Object>> obj;
if (isRequest) {
try {
// 流量清洗
String urlString = helpers.analyzeRequest(controller.getHttpService(), controller.getRequest()).getUrl().toString();
urlString = urlString.indexOf("?") > 0 ? urlString.substring(0, urlString.indexOf("?")) : urlString;
// 正则判断
if (mh.matchSuffix(urlString)) {
return false;
}
} catch (Exception e) {
return false;
}
// 获取报文头
List<String> requestTmpHeaders = helpers.analyzeRequest(controller.getHttpService(), content).getHeaders();
String requestHeaders = String.join("\n", requestTmpHeaders);
// 获取报文主体
int requestBodyOffset = helpers.analyzeRequest(controller.getHttpService(), content).getBodyOffset();
byte[] byteRequest = controller.getRequest();
byte[] requestBody = Arrays.copyOfRange(byteRequest, requestBodyOffset, byteRequest.length);
obj = ec.matchRegex(content, requestHeaders, requestBody, "request");
if (obj.size() > 0) {
String result = da.extractString(obj);
extractRequestContent = result.getBytes();
return true;
}
} else {
// 获取报文头
List<String> responseTmpHeaders = helpers.analyzeResponse(content).getHeaders();
String responseHeaders = String.join("\n", responseTmpHeaders);
// 获取报文主体
int responseBodyOffset = helpers.analyzeResponse(content).getBodyOffset();
byte[] byteResponse = controller.getResponse();
byte[] responseBody = Arrays.copyOfRange(byteResponse, responseBodyOffset, byteResponse.length);
obj = ec.matchRegex(content, responseHeaders, responseBody, "response");
if (obj.size() > 0) {
String result = da.extractString(obj);
extractResponseContent = result.getBytes();
return true;
}
}
return false;
}
@Override
public byte[] getMessage() {
return currentMessage;
}
@Override
public boolean isModified() {
return markInfoText.isTextModified();
}
@Override
public byte[] getSelectedData() {
return markInfoText.getSelectedText();
}
/*
* 使用setMessage用来做Extractor
*/
@Override
public void setMessage(byte[] content, boolean isRequest) {
try {
String c = new String(content, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
stdout.println(e);
}
if (content.length > 0) {
if (isRequest) {
markInfoText.setText(extractRequestContent);
} else {
markInfoText.setText(extractResponseContent);
}
}
currentMessage = content;
}
}
@Override
public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) {
HaETab = new MarkInfoTab(controller, editable);
return HaETab;
}
}

View File

@@ -0,0 +1,38 @@
package burp;
/*
* @author EvilChen
*/
public class Config {
public static String excludeSuffix = "3g2|3gp|7z|aac|abw|aif|aifc|aiff|arc|au|avi|azw|bin|bmp|bz|bz2|cmx|cod|csh|css|csv|doc|docx|eot|epub|gif|gz|ico|ics|ief|jar|jfif|jpe|jpeg|jpg|m3u|mid|midi|mjs|mp2|mp3|mpa|mpe|mpeg|mpg|mpkg|mpp|mpv2|odp|ods|odt|oga|ogv|ogx|otf|pbm|pdf|pgm|png|pnm|ppm|ppt|pptx|ra|ram|rar|ras|rgb|rmi|rtf|snd|svg|swf|tar|tif|tiff|ttf|vsd|wav|weba|webm|webp|woff|woff2|xbm|xls|xlsx|xpm|xul|xwd|zip|zip";
public static String[] scopeArray = new String[] {
"any",
"response",
"response header",
"response body",
"request",
"request header",
"request body"
};
public static String[] engineArray = new String[] {
"nfa",
"dfa"
};
public static String outputTplString = "[%s]\n%s\n\n";
public static String[] colorArray = new String[] {
"red",
"orange",
"yellow",
"green",
"cyan",
"blue",
"pink",
"magenta",
"gray"
};
}

View File

@@ -0,0 +1,33 @@
package burp.action;
import java.util.Map;
import burp.Config;
import java.util.ArrayList;
import java.util.List;
/*
* @author EvilChen
*/
public class DoAction {
public String extractString(Map<String, Map<String, Object>> obj) {
String[] result = {""};
obj.keySet().forEach(i->{
Map<String, Object> tmpMap = obj.get(i);
String data = tmpMap.get("data").toString();
String tmpStr = String.format(Config.outputTplString, i, data).intern();
result[0] += tmpStr;
});
return result[0];
}
public List<String> highlightList(Map<String, Map<String, Object>> obj) {
List<String> colorList = new ArrayList<String>();
obj.keySet().forEach(i->{
Map<String, Object> tmpMap = obj.get(i);
String color = tmpMap.get("color").toString();
colorList.add(color);
});
return colorList;
}
}

View File

@@ -0,0 +1,103 @@
package burp.action;
import java.io.UnsupportedEncodingException;
import java.util.*;
import dk.brics.automaton.Automaton;
import dk.brics.automaton.AutomatonMatcher;
import dk.brics.automaton.RegExp;
import dk.brics.automaton.RunAutomaton;
import jregex.Matcher;
import jregex.Pattern;
import burp.yaml.LoadRule;
import burp.yaml.LoadConfigFile;
/*
* @author EvilChen
*/
public class ExtractContent {
private LoadConfigFile lcf = new LoadConfigFile();
private LoadRule lr = new LoadRule(lcf.getConfigPath());
public Map<String, Map<String, Object>> matchRegex(byte[] content, String headers, byte[] body, String scopeString) {
Map<String, Map<String, Object>> map = new HashMap<>(); // 最终返回的结果
Map<String,Object[][]> rules = lr.getConfig();
rules.keySet().forEach(i -> {
String matchContent = "";
for (Object[] objects : rules.get(i)) {
// 遍历获取规则
List<String> result = new ArrayList<>();
Map<String, Object> tmpMap = new HashMap<>();
String name = objects[1].toString();
boolean loaded = (Boolean) objects[0];
String regex = objects[2].toString();
String color = objects[3].toString();
String scope = objects[4].toString();
String engine = objects[5].toString();
// 判断规则是否开启与作用域
if (loaded && (scope.contains(scopeString) || scope.equals("any"))) {
switch (scope) {
case "any":
case "request":
case "response":
try {
matchContent = new String(content, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
break;
case "request header":
case "response header":
matchContent = headers;
break;
case "request body":
case "response body":
try {
matchContent = new String(body, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
break;
}
if (engine.equals("nfa")) {
Pattern pattern = new Pattern(regex);
Matcher matcher = pattern.matcher(matchContent);
while (matcher.find()) {
// 添加匹配数据至list
// 强制用户使用()包裹正则
result.add(matcher.group(1));
}
} else {
RegExp regexpr = new RegExp(regex);
Automaton auto = regexpr.toAutomaton();
RunAutomaton runAuto = new RunAutomaton(auto, true);
AutomatonMatcher autoMatcher = runAuto.newMatcher(matchContent);
while (autoMatcher.find()) {
// 添加匹配数据至list
// 强制用户使用()包裹正则
result.add(autoMatcher.group());
}
}
// 去除重复内容
HashSet tmpList = new HashSet(result);
result.clear();
result.addAll(tmpList);
if (!result.isEmpty()) {
tmpMap.put("color", color);
tmpMap.put("data", String.join("\n", result));
// 初始化格式
map.put(name, tmpMap);
}
}
}
});
return map;
}
}

View File

@@ -0,0 +1,27 @@
package burp.action;
import java.util.ArrayList;
import java.util.List;
/*
* @author EvilChen
*/
public class GetColorKey {
/*
* 颜色下标获取
*/
public List<Integer> getColorKeys(List<String> keys, String[] colorArray){
List<Integer> result = new ArrayList<Integer>();
int size = colorArray.length;
// 根据颜色获取下标
for (int x = 0; x < keys.size(); x++) {
for (int v = 0; v < size; v++) {
if (colorArray[v].equals(keys.get(x))) {
result.add(v);
}
}
}
return result;
}
}

View File

@@ -0,0 +1,24 @@
package burp.action;
import jregex.Matcher;
import jregex.Pattern;
import jregex.REFlags;
import burp.yaml.LoadConfigFile;
/*
* @author EvilChen
*/
public class MatchHTTP {
// 匹配后缀
LoadConfigFile lc = new LoadConfigFile();
public boolean matchSuffix(String str) {
Pattern pattern = new Pattern(String.format("[\\w]+[\\.](%s)", lc.getExcludeSuffix()), REFlags.IGNORE_CASE);
Matcher matcher = pattern.matcher(str);
if(matcher.find()){
return true;
}else{
return false;
}
}
}

View File

@@ -0,0 +1,56 @@
package burp.action;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
/*
* @author EvilChen
*/
public class UpgradeColor {
private String endColor = "";
/*
* 颜色升级递归算法
*/
private String colorUpgrade(List<Integer> colorList, String[] colorArray) {
int colorSize = colorList.size();
colorList.sort(Comparator.comparingInt(Integer::intValue));
int i = 0;
List<Integer> stack = new ArrayList<Integer>();
while (i < colorSize) {
if (stack.isEmpty()) {
stack.add(colorList.get(i));
i++;
} else {
if (colorList.get(i) != stack.stream().reduce((first, second) -> second).orElse(99999999)) {
stack.add(colorList.get(i));
i++;
} else {
stack.set(stack.size() - 1, stack.get(stack.size() - 1) - 1);
i++;
}
}
}
// 利用HashSet删除重复元素
HashSet tmpList = new HashSet(stack);
if (stack.size() == tmpList.size()) {
stack.sort(Comparator.comparingInt(Integer::intValue));
if(stack.get(0).equals(-1)) {
this.endColor = colorArray[0];
} else {
this.endColor = colorArray[stack.get(0)];
}
} else {
this.colorUpgrade(stack, colorArray);
}
return "";
}
public String getEndColor(List<Integer> colorList, String[] colorArray) {
colorUpgrade(colorList, colorArray);
return endColor;
}
}

View File

@@ -0,0 +1,117 @@
package burp.ui;
import javax.swing.*;
import javax.swing.plaf.metal.MetalIconFactory;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/*
* @author 6dc
*
* A class which creates a JTabbedPane and auto sets a close button when you add a tab
*/
public class JTabbedPaneCloseButton extends JTabbedPane {
public JTabbedPaneCloseButton() {
super();
}
/* Override Addtab in order to add the close Button everytime */
@Override
public void addTab(String title, Icon icon, Component component, String tip) {
super.addTab(title, icon, component, tip);
int count = this.getTabCount() - 1;
setTabComponentAt(count, new CloseButtonTab(component, title, icon));
}
@Override
public void addTab(String title, Icon icon, Component component) {
addTab(title, icon, component, null);
}
@Override
public void addTab(String title, Component component) {
addTab(title, null, component);
}
public void addTab(String title,Component component,Boolean closewith){
if (closewith){
addTab(title,component);
}else{
super.addTab(title,null,component,null);
}
}
/* addTabNoExit */
public void addTabNoExit(String title, Icon icon, Component component, String tip) {
super.addTab(title, icon, component, tip);
}
public void addTabNoExit(String title, Icon icon, Component component) {
addTabNoExit(title, icon, component, null);
}
public void addTabNoExit(String title, Component component) {
addTabNoExit(title, null, component);
}
/* Button */
public class CloseButtonTab extends JPanel {
private Component tab;
public CloseButtonTab(final Component tab, String title, Icon icon) {
this.tab = tab;
setOpaque(false);
FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 3, 3);
setLayout(flowLayout);
JLabel jLabel = new JLabel(title);
jLabel.setIcon(icon);
add(jLabel);
JButton button = new JButton(MetalIconFactory.getInternalFrameCloseIcon(2));
button.setMargin(new Insets(0, 0, 0, 0));
button.addMouseListener(new CloseListener(tab));
add(button);
}
}
/* ClickListener */
public class CloseListener implements MouseListener
{
private Component tab;
public CloseListener(Component tab){
this.tab=tab;
}
@Override
public void mouseClicked(MouseEvent e) {
if(e.getSource() instanceof JButton){
JButton clickedButton = (JButton) e.getSource();
JTabbedPane tabbedPane = (JTabbedPane) clickedButton.getParent().getParent().getParent();
tabbedPane.remove(tab);
}
}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {
if(e.getSource() instanceof JButton){
JButton clickedButton = (JButton) e.getSource();
}
}
@Override
public void mouseExited(MouseEvent e) {
if(e.getSource() instanceof JButton){
JButton clickedButton = (JButton) e.getSource();
}
}
}
}

View File

@@ -0,0 +1,347 @@
package burp.ui;
import org.jetbrains.annotations.NotNull;
import burp.yaml.LoadConfigFile;
import burp.yaml.LoadRule;
import burp.yaml.SetRuleConfig;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.*;
import java.util.Map;
/*
* @author LinChen
*/
public class MainUI extends JPanel{
public MainUI() {
initComponents();
}
public void closeTabActionPerformed(ActionEvent e){
if (tabbedPane1.getTabCount()>2){
if (tabbedPane1.getSelectedIndex()!=0){
SetRuleConfig setruleconfig = new SetRuleConfig();
setruleconfig.deleteRules(tabbedPane1.getTitleAt(tabbedPane1.getSelectedIndex()));
tabbedPane1.remove(tabbedPane1.getSelectedIndex());
tabbedPane1.setSelectedIndex(tabbedPane1.getSelectedIndex()-1);
}else{
SetRuleConfig setruleconfig = new SetRuleConfig();
setruleconfig.deleteRules(tabbedPane1.getTitleAt(tabbedPane1.getSelectedIndex()));
tabbedPane1.remove(tabbedPane1.getSelectedIndex());
tabbedPane1.setSelectedIndex(tabbedPane1.getSelectedIndex());
}
}
}
private void SelectFileMouseClicked(MouseEvent e) {
JFileChooser chooseconfig = new JFileChooser();
chooseconfig.setFileSelectionMode(JFileChooser.FILES_ONLY);
FileNameExtensionFilter filter = new FileNameExtensionFilter("Yaml File (.yml/.yaml)","yaml", "yml");
chooseconfig.setFileFilter(filter);
int selectframe = chooseconfig.showDialog(new JLabel(),"Select");
if (selectframe == JFileChooser.APPROVE_OPTION){
String configpath = chooseconfig.getSelectedFile().toString();
reloadRule(configpath);
loadfile.setConfigPath(configpath);
}
configfilepathtext.setText(loadfile.getConfigPath());
}
private void reloadRule(String configfile){
tabbedPane1.removeAll();
LoadRule loadrule = new LoadRule(configfile);
Map<String,Object[][]> config = loadrule.getConfig();
ruleSwitch.setListen(false);
config.keySet().forEach(i->tabbedPane1.addTab(i,new RulePane(config.get(i),tabbedPane1)));
tabbedPane1.addTab("...",new JLabel());
ruleSwitch.setListen(true);
}
private void reloadRule(){
tabbedPane1.removeAll();
LoadRule loadrule = new LoadRule(loadfile.getConfigPath());
Map<String,Object[][]> config = loadrule.getConfig();
ruleSwitch.setListen(false);
config.keySet().forEach(i->tabbedPane1.addTab(i,new RulePane(config.get(i),tabbedPane1))
);
tabbedPane1.addTab("...",new JLabel());
ruleSwitch.setListen(true);
}
private void reloadMouseClicked(MouseEvent e) {
reloadRule();
}
private void ESSaveMouseClicked(MouseEvent e) {
// TODO add your code here
LoadConfigFile lcf = new LoadConfigFile();
lcf.setExcludeSuffix(EStext.getText());
}
private void initComponents() {
tabbedPane2 = new JTabbedPane();
tabbedPane1 = new JTabbedPane();
panel3 = new JPanel();
configfilepathtext = new JTextField();
label1 = new JLabel();
SelectFile = new JButton();
reload = new JButton();
label2 = new JLabel();
EStext = new JTextField();
ESSave = new JButton();
//======== this ========
setLayout(new GridBagLayout());
((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0};
((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0};
((GridBagLayout)getLayout()).columnWeights = new double[] {1.0, 1.0E-4};
((GridBagLayout)getLayout()).rowWeights = new double[] {1.0, 1.0E-4};
//======== tabbedPane2 ========
{
tabbedPane2.addTab("Rules", tabbedPane1);
//======== panel3 ========
{
panel3.setLayout(new GridBagLayout());
((GridBagLayout)panel3.getLayout()).columnWidths = new int[] {0, 0, 0, 0, 0};
((GridBagLayout)panel3.getLayout()).rowHeights = new int[] {0, 0, 0};
((GridBagLayout)panel3.getLayout()).columnWeights = new double[] {0.0, 1.0, 0.0, 0.0, 1.0E-4};
((GridBagLayout)panel3.getLayout()).rowWeights = new double[] {0.0, 0.0, 1.0E-4};
//---- configfilepathtext ----
configfilepathtext.setEditable(false);
panel3.add(configfilepathtext, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(5, 0, 5, 5), 0, 0));
//---- label1 ----
label1.setText("Config File Path:");
panel3.add(label1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.WEST, GridBagConstraints.VERTICAL,
new Insets(5, 5, 5, 5), 0, 0));
//---- SelectFile ----
SelectFile.setText("Select File ...");
SelectFile.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
SelectFileMouseClicked(e);
}
});
panel3.add(SelectFile, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(5, 0, 5, 5), 0, 0));
//---- reload ----
reload.setText("Reload");
reload.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
reloadMouseClicked(e);
}
});
panel3.add(reload, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(5, 0, 5, 5), 0, 0));
//---- label2 ----
label2.setText("ExcludeSuffix:");
panel3.add(label2, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE,
new Insets(0, 5, 5, 5), 0, 0));
panel3.add(EStext, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 5), 0, 0));
//---- ESSave ----
ESSave.setText("Save");
ESSave.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
ESSaveMouseClicked(e);
}
});
panel3.add(ESSave, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 5), 0, 0));
}
tabbedPane2.addTab("Config", panel3);
}
add(tabbedPane2, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0));
// JFormDesigner - End of component initialization //GEN-END:initComponents
LoadRule loadRule = new LoadRule(loadfile.getConfigPath());
Map<String,Object[][]> config = loadRule.getConfig();
config.keySet().forEach(i->tabbedPane1.addTab(i,new RulePane(config.get(i),tabbedPane1)));
tabbedPane1.addTab("...",new JLabel());
//TabTitleEditListener ruleSwitch = new TabTitleEditListener(tabbedPane1);
configfilepathtext.setText(loadfile.getConfigPath());
LoadConfigFile lcf =new LoadConfigFile();
EStext.setText(lcf.getExcludeSuffix());
ruleSwitch = new TabTitleEditListener(tabbedPane1);
tabbedPane1.addChangeListener(ruleSwitch);
tabbedPane1.addMouseListener(ruleSwitch);
closeTab.addActionListener(e -> closeTabActionPerformed(e));
tabMenu.add(closeTab);
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JTabbedPane tabbedPane2;
private JTabbedPane tabbedPane1;
private JPanel panel3;
private JTextField configfilepathtext;
private JLabel label1;
private JButton SelectFile;
private JButton reload;
private JLabel label2;
private JTextField EStext;
private JButton ESSave;
// JFormDesigner - End of variables declaration //GEN-END:variables
protected static JPopupMenu tabMenu = new JPopupMenu();
private JMenuItem closeTab = new JMenuItem("Delete");
private TabTitleEditListener ruleSwitch;
private LoadConfigFile loadfile = new LoadConfigFile();
}
class TabTitleEditListener extends MouseAdapter implements ChangeListener, DocumentListener {
protected final JTextField editor = new JTextField();
protected final JTabbedPane tabbedPane;
protected int editingIdx = -1;
protected int len = -1;
protected Boolean listen = true;
protected Dimension dim;
protected Component tabComponent;
protected Boolean isRenamesucc = false;
protected LoadConfigFile loadfile = new LoadConfigFile();
protected LoadRule lr = new LoadRule(loadfile.getConfigPath());
protected SetRuleConfig setRuleConfig = new SetRuleConfig();
protected final Action startEditing = new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
editingIdx = tabbedPane.getSelectedIndex();
tabComponent = tabbedPane.getTabComponentAt(editingIdx);
tabbedPane.setTabComponentAt(editingIdx, editor);
isRenamesucc = true;
editor.setVisible(true);
editor.setText(tabbedPane.getTitleAt(editingIdx));
editor.selectAll();
editor.requestFocusInWindow();
len = editor.getText().length();
dim = editor.getPreferredSize();
editor.setMinimumSize(dim);
}
};
protected final Action renameTabTitle = new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
String title = editor.getText().trim();
if (editingIdx >= 0 && !title.isEmpty()) {
String oldname = tabbedPane.getTitleAt(editingIdx);
tabbedPane.setTitleAt(editingIdx, title);
setRuleConfig.rename(oldname,title);
}
cancelEditing.actionPerformed(null);
}
};
protected final Action cancelEditing = new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
if (editingIdx >= 0) {
tabbedPane.setTabComponentAt(editingIdx, tabComponent);
editor.setVisible(false);
editingIdx = -1;
len = -1;
tabComponent = null;
editor.setPreferredSize(null);
tabbedPane.requestFocusInWindow();
}
}
};
protected TabTitleEditListener(JTabbedPane tabbedPane) {
super();
this.tabbedPane = tabbedPane;
editor.setBorder(BorderFactory.createEmptyBorder());
editor.addFocusListener(new FocusAdapter() {
@Override public void focusLost(FocusEvent e) {
renameTabTitle.actionPerformed(null);
}
});
InputMap im = editor.getInputMap(JComponent.WHEN_FOCUSED);
ActionMap am = editor.getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel-editing");
am.put("cancel-editing", cancelEditing);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "rename-tab-title");
am.put("rename-tab-title", renameTabTitle);
editor.getDocument().addDocumentListener(this);
tabbedPane.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "start-editing");
tabbedPane.getActionMap().put("start-editing", startEditing);
}
@Override public void stateChanged(ChangeEvent e) {
if (e.getSource() instanceof JTabbedPane && listen) {
JTabbedPane pane = (JTabbedPane) e.getSource();
if (!isRenamesucc){
if (pane.getSelectedIndex() == pane.getComponentCount()-1){
newTab();
}
}else{
if (pane.getSelectedIndex() == pane.getComponentCount()-2){
newTab();
}
}
}
renameTabTitle.actionPerformed(null);
}
public void newTab(){
Object[][] data = new Object[][]{{false, "New Name", "(New Regex)", "gray", "any", "nfa"}};
insertTab(tabbedPane,setRuleConfig.newRules(),data);
}
public void insertTab(@NotNull JTabbedPane pane,String title,Object[][] data){
pane.addTab(title,new RulePane(data,pane));
pane.remove(pane.getSelectedIndex());
pane.addTab("...",new JLabel());
}
public void setListen(Boolean listen){
this.listen = listen;
}
@Override public void insertUpdate(DocumentEvent e) {
updateTabSize();
}
@Override public void removeUpdate(DocumentEvent e) {
updateTabSize();
}
@Override public void changedUpdate(DocumentEvent e) {}
@Override public void mouseClicked(MouseEvent e) {
switch (e.getButton()){
case 1:
{
Rectangle r = tabbedPane.getBoundsAt(tabbedPane.getSelectedIndex());
boolean isDoubleClick = e.getClickCount() >= 2;
if (isDoubleClick && r.contains(e.getPoint())) {
startEditing.actionPerformed(null);
} else {
renameTabTitle.actionPerformed(null);
}
break;
}
case 3:{
MainUI.tabMenu.show(e.getComponent(),e.getX(),e.getY());
break;
}
default:
break;
}
}
protected void updateTabSize() {
editor.setPreferredSize(editor.getText().length() > len ? null : dim);
tabbedPane.revalidate();
}
}

View File

@@ -0,0 +1,197 @@
package burp.ui;
import burp.yaml.SetRuleConfig;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Vector;
/*
* @author LinChen
*/
public class RulePane extends JPanel {
public RulePane(Object[][] data,JTabbedPane pane) {
initComponents(data,pane);
}
private SetRuleConfig setruleconfig = new SetRuleConfig();
private Boolean isEdit = false;
private void RuleAddMouseClicked(MouseEvent e, JTabbedPane pane) {
// TODO add your code here
RuleSetting add = new RuleSetting();
int isOk = JOptionPane.showConfirmDialog(null,add,"RuleSetting - Add Rule",JOptionPane.OK_OPTION);
if(isOk == 0){
Vector data = new Vector();
data.add(false);
data.add(add.Name.getText());
data.add(add.Regex.getText());
data.add(add.ColorSelect.getSelectedItem().toString());
data.add(add.ScopeSelect.getSelectedItem().toString());
data.add(add.EngineSelect.getSelectedItem().toString());
model.insertRow(model.getRowCount(),data);
model = (DefaultTableModel) table.getModel();
setruleconfig.add(data,pane.getTitleAt(pane.getSelectedIndex()));
}
}
private void RuleEditMouseClicked(MouseEvent e,JTabbedPane pane){
if (table.getSelectedRowCount()>=1){
RuleSetting edit = new RuleSetting();
edit.Name.setText(table.getValueAt(table.getSelectedRow(),1).toString());
edit.Regex.setText(table.getValueAt(table.getSelectedRow(),2).toString());
edit.ColorSelect.setSelectedItem(table.getValueAt(table.getSelectedRow(),3).toString());
edit.ScopeSelect.setSelectedItem(table.getValueAt(table.getSelectedRow(),4).toString());
edit.EngineSelect.setSelectedItem(table.getValueAt(table.getSelectedRow(),5).toString());
int isOk = JOptionPane.showConfirmDialog(null,edit,"RuleSetting - Edit Rule",JOptionPane.OK_OPTION);
if (isOk ==0){
int select = table.convertRowIndexToModel(table.getSelectedRow());
model.setValueAt(edit.Name.getText(),select,1);
model.setValueAt(edit.Regex.getText(),select,2);
model.setValueAt(edit.ColorSelect.getSelectedItem().toString(),select,3);
model.setValueAt(edit.ScopeSelect.getSelectedItem().toString(),select,4);
model.setValueAt(edit.EngineSelect.getSelectedItem().toString(),select,5);
model = (DefaultTableModel) table.getModel();
setruleconfig.edit((Vector) model.getDataVector().get(select),select,pane.getTitleAt(pane.getSelectedIndex()));
}
}
}
private void RuleRemoveMouseClicked(MouseEvent e,JTabbedPane pane){
if (table.getSelectedRowCount()>=1){
int isOk = JOptionPane.showConfirmDialog(null,"Are your sure?","RuleSetting - Delete Rule",JOptionPane.OK_OPTION);
if (isOk==0){
int select = table.convertRowIndexToModel(table.getSelectedRow());
model.removeRow(select);
model = (DefaultTableModel) table.getModel();
setruleconfig.remove(select,pane.getTitleAt(pane.getSelectedIndex()));
}
}
}
private void RuleTableChange(TableModelEvent e,JTabbedPane pane) {
if (e.getColumn()==0&&table.getSelectedRow()!=-1&&!isEdit){
model = (DefaultTableModel) table.getModel();
int select = table.convertRowIndexToModel(table.getSelectedRow());
setruleconfig.edit((Vector) model.getDataVector().get(select),select,pane.getTitleAt(pane.getSelectedIndex()));
}
}
private void initComponents(Object[][] data,JTabbedPane pane) {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
RuleAdd = new JButton();
RuleEdit = new JButton();
scrollPane = new JScrollPane();
table = new JTable();
Remove = new JButton();
//======== this ========
setLayout(new GridBagLayout());
((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0, 0};
((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0, 0, 0, 0};
((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 1.0, 1.0E-4};
((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 0.0, 0.0, 1.0, 1.0E-4};
//---- RuleAdd ----
RuleAdd.setText("Add");
RuleAdd.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
isEdit = true;
RuleAddMouseClicked(e,pane);
model = (DefaultTableModel) table.getModel();
isEdit = false;
}
});
add(RuleAdd, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(15, 5, 3, 2), 0, 0));
//---- RuleEdit ----
RuleEdit.setText("Edit");
RuleEdit.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
isEdit = true;
RuleEditMouseClicked(e,pane);
model = (DefaultTableModel) table.getModel();
isEdit = false;
}
});
add(RuleEdit, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 5, 3, 2), 0, 0));
//======== scrollPane ========
{
//---- table ----
table.setShowVerticalLines(false);
table.setVerifyInputWhenFocusTarget(false);
table.setUpdateSelectionOnSort(false);
table.setShowHorizontalLines(false);
table.setModel(new DefaultTableModel());
table.setSurrendersFocusOnKeystroke(true);
scrollPane.setViewportView(table);
}
add(scrollPane, new GridBagConstraints(1, 0, 1, 4, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(15, 5, 5, 5), 0, 0));
//---- Remove ----
Remove.setText("Remove");
Remove.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
isEdit = true;
RuleRemoveMouseClicked(e,pane);
model = (DefaultTableModel) table.getModel();
isEdit = false;
}
});
add(Remove, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 5, 3, 2), 0, 0));
// JFormDesigner - End of component initialization //GEN-END:initComponents
table.setModel(model);
model.setDataVector(data,title);
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
RuleTableChange(e,pane);
}
});
table.setRowSorter(new TableRowSorter(model));
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
public JButton RuleAdd;
public JButton RuleEdit;
public JScrollPane scrollPane;
public JTable table;
public JButton Remove;
// JFormDesigner - End of variables declaration //GEN-END:variables
private final String[] title = new String[]{"Loaded", "Name", "Regex", "Color", "Scope", "Engine"};
private DefaultTableModel model = new DefaultTableModel() {
public Class<?> getColumnClass ( int column){
if (column == 0) {
return Boolean.class;
}else{
return String.class;
}
}
public boolean isCellEditable(int row,int column){
if (column ==0){
return true;
}else {
return false;
}
}
};
}

View File

@@ -0,0 +1,105 @@
package burp.ui;
import javax.swing.*;
import java.awt.*;
import burp.Config;
/*
* @author LinChen
*/
public class RuleSetting extends JPanel {
public RuleSetting() {
initComponents();
}
public void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
label5 = new JLabel();
label4 = new JLabel();
Regex = new JTextField();
label3 = new JLabel();
label2 = new JLabel();
Name = new JTextField();
ScopeSelect = new JComboBox<>();
EngineSelect = new JComboBox<>();
label6 = new JLabel();
ColorSelect = new JComboBox<>();
//======== this ========
setLayout(null);
//---- label5 ----
label5.setText("Engine:");
add(label5);
label5.setBounds(new Rectangle(new Point(10, 175), label5.getPreferredSize()));
//---- label4 ----
label4.setText("Scope:");
add(label4);
label4.setBounds(new Rectangle(new Point(10, 135), label4.getPreferredSize()));
add(Regex);
Regex.setBounds(70, 50, 265, 30);
//---- label3 ----
label3.setText("Regex:");
add(label3);
label3.setBounds(new Rectangle(new Point(10, 55), label3.getPreferredSize()));
//---- label2 ----
label2.setText("Name:");
add(label2);
label2.setBounds(new Rectangle(new Point(10, 15), label2.getPreferredSize()));
add(Name);
Name.setBounds(70, 10, 265, 30);
//---- ScopeSelect ----
ScopeSelect.setModel(new DefaultComboBoxModel<>(Config.scopeArray));
add(ScopeSelect);
ScopeSelect.setBounds(70, 130, 265, ScopeSelect.getPreferredSize().height);
//---- EngineSelect ----
EngineSelect.setModel(new DefaultComboBoxModel<>(Config.engineArray));
add(EngineSelect);
EngineSelect.setBounds(70, 170, 265, EngineSelect.getPreferredSize().height);
//---- label7 ----
label6.setText("Color:");
add(label6);
label6.setBounds(new Rectangle(new Point(10, 95), label6.getPreferredSize()));
//---- ColorSelect ----
ColorSelect.setModel(new DefaultComboBoxModel<>(Config.colorArray));
add(ColorSelect);
ColorSelect.setBounds(70, 90, 265, ColorSelect.getPreferredSize().height);
{
// compute preferred size
Dimension preferredSize = new Dimension();
for(int i = 0; i < getComponentCount(); i++) {
Rectangle bounds = getComponent(i).getBounds();
preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width);
preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height);
}
Insets insets = getInsets();
preferredSize.width += insets.right;
preferredSize.height += insets.bottom;
setMinimumSize(preferredSize);
setPreferredSize(preferredSize);
}
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JLabel label5;
private JLabel label4;
public JTextField Regex;
private JLabel label3;
private JLabel label2;
public JTextField Name;
public JComboBox<String> ScopeSelect;
public JComboBox<String> EngineSelect;
private JLabel label6;
public JComboBox<String> ColorSelect;
// JFormDesigner - End of variables declaration //GEN-END:variables
}

View File

@@ -0,0 +1,19 @@
package burp.yaml;
import java.util.List;
/*
* @author LinChen
*/
public class Config {
public List<Rules> rules;
public List<Rules> getRules() {
return rules;
}
public void setRules(List<Rules> rules) {
this.rules = rules;
}
}

View File

@@ -0,0 +1,86 @@
package burp.yaml;
import org.jetbrains.annotations.NotNull;
import org.yaml.snakeyaml.Yaml;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
/*
* @author LinChen
*/
public class LoadConfigFile {
private static Yaml yaml = new Yaml();
private static final String SettingPath = "Setting.yml";
private static final String ConfigPath = "Config.yml";
public LoadConfigFile(){
init();
}
// 初始化配置
public void init(){
File yamlSetting = new File(SettingPath);
if (!(yamlSetting.exists() && yamlSetting.isFile())) {
Map<String,Object> r = new HashMap<>();
r.put("configPath", ConfigPath);
r.put("excludeSuffix", getExcludeSuffix());
try{
Writer ws = new OutputStreamWriter(new FileOutputStream(SettingPath),"UTF-8");
yaml.dump(r, ws);
}catch (Exception ex){
ex.printStackTrace();
}
}
}
public String getExcludeSuffix(){
try {
InputStream inorder = new FileInputStream(SettingPath);
Map<String,Object> r;
r = yaml.load(inorder);
return r.get("excludeSuffix").toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
return "css|jpeg|gif|jpg|png|pdf|rar|zip|docx|doc|svg|jpeg|ico|woff|woff2|ttf|otf";
}
}
public String getConfigPath(){
try {
InputStream inorder = new FileInputStream(SettingPath);
Map<String,Object> r;
r = yaml.load(inorder);
return r.get("configPath").toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
return ConfigPath;
}
}
public void setExcludeSuffix(@NotNull String excludeSuffix){
Map<String,Object> r = new HashMap<>();
r.put("excludeSuffix", excludeSuffix);
r.put("configPath", getConfigPath());
try{
Writer ws = new OutputStreamWriter(new FileOutputStream(SettingPath),"UTF-8");
yaml.dump(r, ws);
}catch (Exception ex){
ex.printStackTrace();
}
}
public void setConfigPath(@NotNull String filePath){
Map<String,Object> r = new HashMap<>();
r.put("configPath", filePath);
r.put("excludeSuffix", getExcludeSuffix());
try{
Writer ws = new OutputStreamWriter(new FileOutputStream(SettingPath),"UTF-8");
yaml.dump(r, ws);
}catch (Exception ex){
ex.printStackTrace();
}
}
}

View File

@@ -0,0 +1,89 @@
package burp.yaml;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.nodes.Tag;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/*
* @author LinChen
*/
public class LoadRule {
private static String filePath = "Config.yml";
public LoadRule(String configfile){
filePath = configfile;
init();
}
// 初始化配置
public void init(){
File settingyaml = new File(filePath);
if (!(settingyaml.exists() && settingyaml.isFile())){
Map<String,Object[][]> r = new HashMap<>();
Rule rule = new Rule();
rule.setLoaded(true);
rule.setName("Email");
rule.setColor("yellow");
rule.setEngine("nfa");
rule.setScope("response");
rule.setRegex("(([a-zA-Z0-9][_|\\.])*[a-zA-Z0-9]+@([a-zA-Z0-9][-|_|\\.])*[a-zA-Z0-9]+\\.((?!js|css|jpg|jpeg|png|ico)[a-zA-Z]{2,}))");
Rules rules = new Rules();
rules.setType("Basic Information");
ArrayList<Rule> rl = new ArrayList<>();
rl.add(rule);
rules.setRule(rl);
ArrayList<Rules> rls = new ArrayList<>();
rls.add(rules);
Config config = new Config();
config.setRules(rls);
DumperOptions dop = new DumperOptions();
dop.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Representer representer = new Representer();
representer.addClassTag(Config.class, Tag.MAP);
Yaml yaml = new Yaml(new Constructor(),representer,dop);
LoadConfigFile loadfile = new LoadConfigFile();
File f = new File(loadfile.getConfigPath());
try{
Writer ws = new OutputStreamWriter(new FileOutputStream(f),"UTF-8");
yaml.dump(config,ws);
}catch (Exception ex){
ex.printStackTrace();
}
}
}
public static Map<String,Object[][]> getConfig(){
InputStream inorder = null;
{
try {
inorder = new FileInputStream(new File(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Yaml yaml = new Yaml(new Constructor(Config.class));
Config plugin = yaml.loadAs(inorder, Config.class);
Map<String,Object[][]> config = new HashMap<>();
plugin.rules.forEach(i->{
ArrayList<Object[]> data = new ArrayList<>();
i.rule.forEach(j->{
try {
data.add(j.getRuleObject());
}catch (Exception e){
e.printStackTrace();
}
});
config.put(i.getType(), data.toArray(new Object[data.size()][]));
});
return config;
}
}

View File

@@ -0,0 +1,81 @@
package burp.yaml;
import java.util.HashMap;
import java.util.Map;
/*
* @author LinChen
*/
public class Rule {
private String Name;
private Boolean Loaded;
private String Regex;
private String Color;
private String Engine;
private String Scope;
public Boolean getLoaded() {
return Loaded;
}
public String getColor() {
return Color;
}
public String getEngine() {
return Engine;
}
public String getName() {
return Name;
}
public String getRegex() {
return Regex;
}
public String getScope() {
return Scope;
}
public void setLoaded(Boolean loaded) {
this.Loaded = loaded;
}
public void setColor(String color) {
this.Color = color;
}
public void setEngine(String engine) {
this.Engine = engine;
}
public void setName(String name) {
this.Name = name;
}
public void setRegex(String regex) {
this.Regex = regex;
}
public void setScope(String scope) {
this.Scope = scope;
}
public Object[] getRuleObject(){
return new Object[]{Loaded, Name, Regex, Color, Scope, Engine};
}
public Map<String,Object> getRuleObjMap(){
Map<String,Object> r = new HashMap<>();
r.put("Loaded",Loaded);
r.put("Name",Name);
r.put("Regex",Regex);
r.put("Color",Color);
r.put("Scope",Scope);
r.put("Engine",Engine);
return r;
}
public String toString(){
return "{ \nLoaded: "+Loaded+"\nName: "+Name+"\nRegex: "+Regex+"\nColor: "+Color+"\nScope: "+Scope+"\nEngine: "+Engine+"\n}";
}
}

View File

@@ -0,0 +1,35 @@
package burp.yaml;
import java.util.List;
/*
* @author LinChen
*/
public class Rules {
private String type;
public List<Rule> rule;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<Rule> getRule() {
return rule;
}
public void setRule(List<Rule> rule) {
this.rule = rule;
}
public void setRuleObj(){
}
public String toString(){
return "{ type: "+type+"\n config: "+ rule +"}\n";
}
}

View File

@@ -0,0 +1,109 @@
package burp.yaml;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.*;
public class SetRuleConfig {
private static Yaml yaml;
private static LoadConfigFile loadfile;
private static LoadRule lr;
private Map<String,Object[][]> config = lr.getConfig();
public void format(){
DumperOptions dop = new DumperOptions();
dop.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Representer representer = new Representer();
representer.addClassTag(Config.class, Tag.MAP);
yaml = new Yaml(new Constructor(),representer,dop);
Config con = new Config();
List<Rules> rls = new ArrayList<>();
config.keySet().forEach(i->
{
Rules rlstmp = new Rules();
rlstmp.setType(i);
List<Rule> rl = new ArrayList<>();
for (Object[] objects : config.get(i)) {
Rule rltmp = new Rule();
rltmp.setName((String) objects[1]);
rltmp.setLoaded((Boolean) objects[0]);
rltmp.setRegex((String) objects[2]);
rltmp.setColor((String) objects[3]);
rltmp.setScope((String) objects[4]);
rltmp.setEngine((String) objects[5]);
rl.add(rltmp);
}
rlstmp.setRule(rl);
rls.add(rlstmp);
});
con.setRules(rls);
File f = new File(loadfile.getConfigPath());
try{
Writer ws = new OutputStreamWriter(new FileOutputStream(f),"UTF-8");
yaml.dump(con,ws);
}catch (Exception ex){
ex.printStackTrace();
}
}
public void edit(Vector data,int select, String type){
loadfile = new LoadConfigFile();
lr = new LoadRule(loadfile.getConfigPath());
config = lr.getConfig();
config.get(type)[select] = data.toArray();
this.format();
}
public void add(Vector data,String type){
loadfile = new LoadConfigFile();
lr = new LoadRule(loadfile.getConfigPath());
config = lr.getConfig();
ArrayList<Object[]> x = new ArrayList<Object[]>(Arrays.asList(config.get(type)));
x.add(data.toArray());
config.put(type,x.toArray(new Object[x.size()][]));
this.format();
}
public void remove(int select,String type){
loadfile = new LoadConfigFile();
lr = new LoadRule(loadfile.getConfigPath());
config = lr.getConfig();
ArrayList<Object[]> x = new ArrayList<Object[]>(Arrays.asList(config.get(type)));
x.remove(select);
config.put(type,x.toArray(new Object[x.size()][]));
this.format();
}
public void rename(String oldname,String newname){
loadfile = new LoadConfigFile();
lr = new LoadRule(loadfile.getConfigPath());
config = lr.getConfig();
config.put(newname,config.remove(oldname));
this.format();
}
public void deleteRules(String Rules){
loadfile = new LoadConfigFile();
lr = new LoadRule(loadfile.getConfigPath());
config = lr.getConfig();
config.remove(Rules);
this.format();
}
public String newRules(){
int i = 0;
loadfile = new LoadConfigFile();
lr = new LoadRule(loadfile.getConfigPath());
config = lr.getConfig();
String name = "New ";
Object[][] data = new Object[][]{{false, "New Name", "(New Regex)", "gray", "any", "nfa"}};
while (config.containsKey(name+i)){
i++;
}
config.put(name+i,data);
this.format();
return name+i;
}
}