├── .github
└── workflows
│ └── maven.yml
├── assets
├── image-20230618203042865.png
├── image-20230618203856329.png
├── image-20230618204038455.png
├── image-20230725015707104.png
├── image-20230725020323094.png
├── image-20230725020505812.png
├── image-20230725020944991.png
├── image-20230725021057526.png
├── image-20230725021456284.png
├── image-20230725021644567.png
├── image-20230725022525882.png
├── image-20230725023521961.png
├── image-20230725024907874.png
├── image-20230725024938223.png
├── image-20230725025008113.png
├── image-20230725025125794.png
├── image-20230725025220142.png
├── image-20230725025954768.png
├── image-20230725030215013.png
├── image-20230725030530263.png
└── image-20230725030658414.png
├── pom.xml
├── readme.md
└── src
└── main
├── burp
├── BurpExtender.java
├── EditorTabClass.java
├── ITabClass.java
├── MenuFactoryClass.java
└── ProcessorClass.java
├── config
├── activeCryptConfig.java
├── allCryptoConfig.java
└── autoCryptConfig.java
├── lib
├── ActiveCrypt.java
├── AutoCrypt.java
├── Crypto.java
├── CryptoChains.java
└── Cryptos
│ ├── RSACrypto.java
│ └── SM2Crypto.java
└── ui
├── ActiveCryptConfigUI.java
├── AutoCryptConfigUI.java
├── GUI.java
└── MessageEditorUI.java
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | name: Java CI with Maven
2 |
3 | # 检测到 src 文件内 .java 文件有变动执行编译
4 | on:
5 | push:
6 | paths:
7 | - '**/*src/**/*.java'
8 |
9 | jobs:
10 | build:
11 | # 配置权限
12 | permissions: write-all
13 | runs-on: ubuntu-latest
14 | steps:
15 | # 下载代码
16 | - uses: actions/checkout@v3
17 | - name: Set up JDK 16
18 | # 安装 JDK
19 | uses: actions/setup-java@v3
20 | with:
21 | java-version: '16'
22 | distribution: 'temurin'
23 | cache: maven
24 | # Maven 打包
25 | - name: Build with Maven
26 | run: mvn -B package --file pom.xml
27 | # 将打包好的 Jar 包 放到 staging 文件夹
28 | - run: mkdir staging && cp target/*.jar staging
29 | # 设置 jobs Maven pom 版本环境变量
30 | - name: Set Release version env variable
31 | run: |
32 | echo "RELEASE_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
33 | - name: "Build & test"
34 | run: |
35 | echo "done!"
36 | # 上传文件并发布 Release
37 | - uses: "marvinpinto/action-automatic-releases@latest"
38 | with:
39 | repo_token: "${{ secrets.GITHUB_TOKEN }}"
40 | automatic_release_tag: "${{ env.RELEASE_VERSION }}"
41 | prerelease: false
42 | title: "Release ${{ env.RELEASE_VERSION }}"
43 | files: |
44 | staging/*.jar
45 |
--------------------------------------------------------------------------------
/assets/image-20230618203042865.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230618203042865.png
--------------------------------------------------------------------------------
/assets/image-20230618203856329.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230618203856329.png
--------------------------------------------------------------------------------
/assets/image-20230618204038455.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230618204038455.png
--------------------------------------------------------------------------------
/assets/image-20230725015707104.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725015707104.png
--------------------------------------------------------------------------------
/assets/image-20230725020323094.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725020323094.png
--------------------------------------------------------------------------------
/assets/image-20230725020505812.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725020505812.png
--------------------------------------------------------------------------------
/assets/image-20230725020944991.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725020944991.png
--------------------------------------------------------------------------------
/assets/image-20230725021057526.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725021057526.png
--------------------------------------------------------------------------------
/assets/image-20230725021456284.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725021456284.png
--------------------------------------------------------------------------------
/assets/image-20230725021644567.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725021644567.png
--------------------------------------------------------------------------------
/assets/image-20230725022525882.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725022525882.png
--------------------------------------------------------------------------------
/assets/image-20230725023521961.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725023521961.png
--------------------------------------------------------------------------------
/assets/image-20230725024907874.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725024907874.png
--------------------------------------------------------------------------------
/assets/image-20230725024938223.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725024938223.png
--------------------------------------------------------------------------------
/assets/image-20230725025008113.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725025008113.png
--------------------------------------------------------------------------------
/assets/image-20230725025125794.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725025125794.png
--------------------------------------------------------------------------------
/assets/image-20230725025220142.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725025220142.png
--------------------------------------------------------------------------------
/assets/image-20230725025954768.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725025954768.png
--------------------------------------------------------------------------------
/assets/image-20230725030215013.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725030215013.png
--------------------------------------------------------------------------------
/assets/image-20230725030530263.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725030530263.png
--------------------------------------------------------------------------------
/assets/image-20230725030658414.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/burp-ext-CryptoTools/CryptoTools/e514b2fabdda1bff8fa2b9faffe6d95656eee58f/assets/image-20230725030658414.png
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
4 | 4.0.0
5 |
6 | com.burp.ext
7 | cryptoTools
8 | 2.1
9 | jar
10 |
11 |
12 | 16
13 | 16
14 |
15 |
16 |
17 | src/main
18 |
19 |
20 | org.apache.maven.plugins
21 | maven-shade-plugin
22 | 3.3.0
23 |
24 |
25 | package
26 |
27 | shade
28 |
29 |
30 | false
31 |
32 |
33 | *:*
34 |
35 | META-INF/*.SF
36 | META-INF/*.DSA
37 | META-INF/*.RSA
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | net.portswigger.burp.extender
52 | burp-extender-api
53 | 2.3
54 | provided
55 |
56 |
57 | com.tencent.kona
58 | kona-crypto
59 | 1.0.8
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # 致谢
2 |
3 | 非常详细的burp插件开发指南:[bit4woo/burp-api-drops: burp插件开发指南 (github.com)](https://github.com/bit4woo/burp-api-drops)
4 |
5 | 好不容易找到的合适的国密库:[Tencent/TencentKonaSMSuite (github.com)](https://github.com/Tencent/TencentKonaSMSuite)
6 |
7 | 优秀的插件:
8 |
9 | - [PortSwigger/burpcrypto (github.com)](https://github.com/portswigger/burpcrypto)
10 | - [PortSwigger/crypto-messages-handler: CyRadar Interceptor (github.com)](https://github.com/portswigger/crypto-messages-handler)
11 |
12 | # 说明
13 |
14 | 本插件只作为辅助工具,方便对加密的数据包进行重放、爆破,不能破解加密算法。
15 |
16 | 程序中存在诸多bug,希望师傅们能提出宝贵的意见和建议。
17 |
18 | # 环境
19 |
20 | 编译环境: jdk16
21 |
22 | 测试环境: jdk20、burp2023.7
23 |
24 | # 使用说明
25 |
26 |
27 | [下载jar包](https://github.com/burp-ext-CryptoTools/CryptoTools/releases/tag/2.1)或自行编译。
28 |
29 | 经测试openjdk可以直接使用cryptoTools-xx.jar,不会出现类似`Cannot find any provider supporting SM4/ECB/NoPadding`的错误。
30 |
31 | Oracle jdk建议使用original-cryptoTools-xx.jar,然后将kona-crypto库加入到环境中,加入方式如下。
32 |
33 | [下载kona-crypto-1.0.8.jar](https://github.com/Tencent/TencentKonaSMSuite/releases/download/v1.0.8/kona-crypto-1.0.8.jar),将jar包所在目录加入环境,可能需要重启生效。没有依赖将不能使用国密。
34 |
35 | 
36 |
37 | 使用中可能会遇到各种各样的问题,可以在Extensions下查看报错信息
38 |
39 | 
40 |
41 | ## 自动加解密配置
42 |
43 | 这里做了更改,配置页面不再直接选择算法配置密钥,改为了先添加算法链,然后再下拉列表中选择,对数据处理上更加灵活。
44 |
45 | 
46 |
47 | 
48 |
49 | 匹配密文的方式依旧没变,还是通过正则,需要替换的内容使用小括号括起来,内置两个规则,分别匹配所有json参数值和url参数值,鼠标悬停会出现提示。
50 |
51 | 
52 |
53 | ## 加解密链配置
54 |
55 | 在左侧选择需要的算法,点击+号添加到右边,在右边进行一些参数配置,后面的上下按钮可以改变执行顺序。添加按钮合并为了一个,点击”添加到加解密链“,同时添加到右击菜单、爆破模块和自动解密配置选项中。
56 |
57 | 
58 |
59 | 在任意数据包位置可以查看到添加的右击菜单
60 |
61 | 
62 |
63 | 在Intruder模块的payload processing中选择Invoke Burp extension,可以查看到添加的processor
64 |
65 | 
66 |
67 | # 演示
68 |
69 | ## 重放
70 |
71 | 抓取数据包,请求和响应中的数据都已加密,并且请求和响应的密文有区别
72 |
73 | 
74 |
75 | 通过分析js文件获取加密算法,和密钥信息,在配置页面进行配置
76 |
77 | 添加数据包加密的配置,暂时没办法将响应包还原为中间带换行的格式,还好客户端支持不带换行,所以请求包和响应包使用同一个加密配置即可
78 |
79 | 
80 |
81 | 添加请求包解密配置
82 |
83 | 
84 |
85 | 添加响应包解密配置,先将\n替换为空,再进行解密。
86 |
87 | 
88 |
89 | 在自动解密配置中选择对应的加解密链,和配置对应的密文,点击save按钮,弹出提示即可。
90 |
91 | 
92 |
93 | 回到重放模块,点击Crypto tools标签即可查看明文,并且可以直接对明文进行修改。
94 |
95 | 
96 |
97 | ## 爆破
98 |
99 | 如果需要对上述数据包的passwd进行爆破,可以如下操作
100 |
101 | 1、将刚刚的数据包发送到Intruder,删除所有加密数据,添加 § 符号。
102 |
103 | 
104 |
105 | 2、将不需要爆破的内容提取出来,添加prefix和suffix,再加插件生成的processor。
106 |
107 | 
108 |
109 | 查看爆破的payload
110 |
111 | 
112 |
113 | 同时可以在Extensions页面查看payload的变化过程。
114 |
115 | 
116 |
117 | # 关于获取加密算法及参数
118 |
119 | 第一种方式:直接在源码中搜索参数名、"encrypt"、”AES"、"SM4"等关键字。
120 |
121 | 第二种方式(比较通用):在浏览器开发者工具->源代码,左边打下XHR断点,然后通过调用堆栈找到内容没加密之前的位置(过程中可以重复在堆栈下面的函数打断点,然后重新发送请求),再单步调试,这样比较容易找到加密方法
122 |
123 | 
124 |
125 | # 关于加密的几种情况
126 |
127 | 1. 直接使用固定密钥的对称密码(直接找到密钥就行)
128 | 2. 客户端生成动态对称密码的密钥,通过公钥加密传输到服务端
129 |
130 | 这种情况一般将密钥固定即可,方式有事件断点、burp替换、本地文件替换(可能不太好使)等方式。
131 |
132 | 事件断点,右击断点选择最后一个。
133 |
134 | 
135 |
136 | burp自动替换
137 |
138 | 
139 |
140 | 3. 服务端生成对称加密密钥,非对称加密传输(其实不安全),先解密密钥,再用密钥对数据进行解密。本插件用起来会比较麻烦,建议重新写一个。
141 | 4. 非对称加密传输,在加密函数第一行,以及在解密函数最后一行加上`data = prompt(data, data)`,如果是json格式,用`JSON.stringify(data)`和`JSON.parse(data)`转化一下(跟大佬学来的方法)
142 | 5. 存在签名,建议重新写一个插件自动更新签名,最近发现用yakit也不错,可以添加时间戳标签、进行md5等操作。
143 |
144 | # 版本
145 |
146 | | 时间 | 版本 | 备注 |
147 | |:----------:|:---:|:------------------:|
148 | | 2023/06/18 | 1.0 | 新建 |
149 | | 2023/07/25 | 2.0 | 更改自动解密配置方式,修改诸多bug |
150 | | 2023/07/26 | 2.1 | 修改一些体验上的问题 |
151 |
--------------------------------------------------------------------------------
/src/main/burp/BurpExtender.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | public class BurpExtender implements IBurpExtender {
4 | public static IBurpExtenderCallbacks callback;
5 | public static IExtensionHelpers helpers;
6 |
7 | ITabClass iTabClass;
8 | EditorTabClass editorTabClass;
9 | public static MenuFactoryClass menuFactoryClass;
10 |
11 | @Override
12 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
13 |
14 | callback = callbacks;
15 | helpers = callbacks.getHelpers();
16 | callbacks.setExtensionName("Crypto tools"); // 设置插件名称
17 |
18 | iTabClass = new ITabClass();
19 | menuFactoryClass = new MenuFactoryClass();
20 | editorTabClass = new EditorTabClass();
21 |
22 | callbacks.addSuiteTab(iTabClass); // 添加tab
23 | callbacks.registerMessageEditorTabFactory(editorTabClass); // 添加数据包编辑tab
24 | callbacks.registerContextMenuFactory(menuFactoryClass); // 添加右击菜单
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/src/main/burp/EditorTabClass.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import config.autoCryptConfig;
4 | import lib.AutoCrypt;
5 | import ui.AutoCryptConfigUI;
6 | import ui.MessageEditorUI;
7 |
8 | import java.awt.*;
9 | import java.lang.reflect.Field;
10 | import java.util.Arrays;
11 |
12 | public class EditorTabClass implements IMessageEditorTabFactory {
13 | IExtensionHelpers helpers;
14 | IBurpExtenderCallbacks callback;
15 | AutoCryptConfigUI editorTabUI;
16 |
17 | public EditorTabClass() {
18 | this.helpers = BurpExtender.helpers;
19 | this.callback = BurpExtender.callback;
20 | }
21 |
22 | @Override
23 | public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) {
24 | return new PacketCryptTab(controller, editable);
25 | }
26 |
27 | class PacketCryptTab implements IMessageEditorTab {
28 |
29 | boolean editable;
30 | boolean isRequest;
31 | byte[] currentMessage;
32 | IMessageEditor view;
33 | IMessageEditorController controller;
34 |
35 | public PacketCryptTab(IMessageEditorController _controller, boolean _editable) {
36 | editable = _editable;
37 | controller = _controller;
38 |
39 | view = callback.createMessageEditor(new MessageEditorUI(_controller.getHttpService()), true);
40 | }
41 |
42 | @Override
43 | public String getTabCaption() {
44 | return "Crypto tools";
45 | }
46 |
47 | @Override
48 | public Component getUiComponent() {
49 | return view.getComponent();
50 | }
51 |
52 | @Override
53 | // 是否在页面中展示 IMessageEditorTab
54 | public boolean isEnabled(byte[] content, boolean isRequest) {
55 | IHttpService httpService = controller.getHttpService();
56 |
57 | if (httpService == null)
58 | return true;
59 |
60 | /*
61 | 真想不出怎么解决让插件在内层不显示的问题,待添加
62 | */
63 |
64 | String hostReg = autoCryptConfig.hostReg;
65 | String host = httpService.getHost();
66 |
67 | return "".equals(hostReg) || host != null && host.matches(hostReg);
68 | }
69 |
70 | @Override
71 | // 设置 IMessageEditorTab 中的值
72 | public void setMessage(byte[] content, boolean isRequest) {
73 | this.isRequest = isRequest;
74 | this.currentMessage = content;
75 |
76 | if (content != null) {
77 | if (content.length != 0) {
78 | byte[] newContent = AutoCrypt.unpackPacket(content, helpers, isRequest, true);
79 | view.setMessage(newContent, isRequest);
80 | }
81 | }
82 | }
83 |
84 | @Override
85 | // 该方法的返回值将替换原始数据包
86 | public byte[] getMessage() {
87 | if (view.isMessageModified()) {
88 | return AutoCrypt.unpackPacket(view.getMessage(), helpers, isRequest, false);
89 | } else {
90 | return currentMessage;
91 | }
92 | }
93 |
94 | @Override
95 | public boolean isModified() {
96 | return view.isMessageModified();
97 | }
98 |
99 | @Override
100 | public byte[] getSelectedData() {
101 | return view.getSelectedData();
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/burp/ITabClass.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import ui.GUI;
4 |
5 | import java.awt.*;
6 |
7 | public class ITabClass implements ITab{
8 | GUI gui;
9 |
10 | public ITabClass() {
11 | gui = new GUI();
12 | }
13 |
14 | @Override
15 | public String getTabCaption() {
16 | return "Crypto tools";
17 | }
18 |
19 | @Override
20 | public Component getUiComponent() {
21 | return gui.getComponent(0);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/burp/MenuFactoryClass.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import lib.CryptoChains.CryptoChain;
4 |
5 | import javax.swing.*;
6 | import java.awt.*;
7 | import java.awt.event.ActionEvent;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class MenuFactoryClass implements IContextMenuFactory {
12 | public static ArrayList menu_item_list = new ArrayList<>();
13 |
14 | private IContextMenuInvocation invocation;
15 |
16 | @Override
17 | public List createMenuItems(IContextMenuInvocation invocation) {
18 | this.invocation = invocation;
19 | // 返回菜单列表
20 | return menu_item_list;
21 | }
22 |
23 | public void addMenuItem(String itemName, CryptoChain cryptoChain) {
24 | delMenuItem(itemName);
25 |
26 | JMenuItem menuItem = new JMenuItem(itemName);
27 | menuItem.addActionListener(new AbstractAction() {
28 | @Override
29 | public void actionPerformed(ActionEvent e) {
30 | // 获取选中的内容
31 | IHttpRequestResponse[] selectedMessages = invocation.getSelectedMessages();
32 | boolean isRequest = invocation.getInvocationContext() % 2 == 0;
33 |
34 | if (selectedMessages.length > 0) {
35 | IHttpRequestResponse selectedMessage = selectedMessages[0];
36 | byte[] packetBytes;
37 | if (isRequest)
38 | packetBytes = selectedMessage.getRequest();
39 | else
40 | packetBytes = selectedMessage.getResponse();
41 |
42 | int[] selectedIndexRange = invocation.getSelectionBounds();
43 |
44 | String selectedText = "";
45 | boolean isStr;
46 | try {
47 | selectedText = new String(packetBytes).substring(selectedIndexRange[0], selectedIndexRange[1]);
48 | isStr = true;
49 | } catch (Exception ignored) {
50 | byte[] bytes = new byte[selectedIndexRange[1] - selectedIndexRange[0]];
51 | System.arraycopy(packetBytes, selectedIndexRange[0], bytes, 0, selectedIndexRange[1] - selectedIndexRange[0]);
52 | selectedText = new String(bytes);
53 | isStr = false;
54 | }
55 |
56 | try {
57 | String result = cryptoChain.doFinal(selectedText);
58 | byte[] newPacket;
59 |
60 | if (isStr) {
61 | String s = new String(packetBytes).substring(0, selectedIndexRange[0]) + result + new String(packetBytes).substring(selectedIndexRange[1]);
62 | newPacket = s.getBytes();
63 | } else {
64 | byte[] bytes = new byte[packetBytes.length + result.getBytes().length - selectedText.getBytes().length];
65 | System.arraycopy(packetBytes, 0, bytes, 0, selectedIndexRange[0]);
66 | System.arraycopy(result.getBytes(), 0, bytes, selectedIndexRange[0], result.getBytes().length);
67 | System.arraycopy(packetBytes, selectedIndexRange[1], bytes, selectedIndexRange[0] + result.getBytes().length, selectedIndexRange[1] - selectedIndexRange[0]);
68 | newPacket = bytes;
69 | }
70 |
71 | try {
72 | if (isRequest)
73 | selectedMessage.setRequest(newPacket);
74 | else
75 | selectedMessage.setResponse(newPacket);
76 | } catch (UnsupportedOperationException err) {
77 | /*
78 | 创建文本域显示加解密结果,不知道怎么调用burp自带的 Converted text 框框,暂时使用该方式代替
79 | */
80 | // 创建一个JTextArea并设置文本
81 | JTextArea textArea = new JTextArea();
82 | textArea.setText(result);
83 | textArea.setPreferredSize(new Dimension(500, 300));
84 | textArea.setEditable(false); // 不可编辑
85 | textArea.setLineWrap(true); //自动换行
86 | textArea.setWrapStyleWord(true); // 换行时保持单词完整
87 |
88 | // 将JTextArea添加到JScrollPane中
89 | JScrollPane scrollPane = new JScrollPane(textArea);
90 |
91 | // 显示JOptionPane并将JScrollPane添加到其中
92 | JOptionPane jOptionPane = new JOptionPane(scrollPane, JOptionPane.PLAIN_MESSAGE);
93 | JDialog dialog = jOptionPane.createDialog(null, "结果");
94 | dialog.setResizable(true);
95 | dialog.setVisible(true);
96 | }
97 |
98 | } catch (Exception ex) {
99 | BurpExtender.callback.printError(ex.toString());
100 | }
101 | }
102 |
103 | }
104 | });
105 |
106 | menu_item_list.add(menuItem);
107 | }
108 |
109 | public static String delMenuItem(String itemName) {
110 | for (JMenuItem jMenuItem : menu_item_list) {
111 | if (itemName.equals(jMenuItem.getText())) {
112 | menu_item_list.remove(jMenuItem);
113 | return itemName + " 已删除";
114 | }
115 | }
116 | return itemName + " 删除失败";
117 | }
118 |
119 | public static String delAllMenuItem() {
120 | menu_item_list.clear();
121 | return "已全部删除";
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/main/burp/ProcessorClass.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import lib.CryptoChains.CryptoChain;
4 |
5 | import java.util.List;
6 |
7 | public class ProcessorClass implements IIntruderPayloadProcessor {
8 | String name;
9 | CryptoChain cryptoChain;
10 |
11 | public ProcessorClass(String name, CryptoChain cryptoChain) {
12 | this.name = name;
13 | this.cryptoChain = cryptoChain;
14 | }
15 |
16 | @Override
17 | public String getProcessorName() {
18 | return name;
19 | }
20 |
21 | @Override
22 | public byte[] processPayload(byte[] currentPayload, byte[] originalPayload, byte[] baseValue) {
23 | try {
24 | String result = cryptoChain.doFinal(new String(currentPayload));
25 |
26 | BurpExtender.callback.printOutput(new String(originalPayload) + " => " + new String(currentPayload) + " => " + result);
27 |
28 | return result.getBytes();
29 | } catch (Exception e) {
30 | BurpExtender.callback.printError("processPayload error");
31 | }
32 | return currentPayload;
33 | }
34 |
35 | public void add2Processor() {
36 | delProcessor(name);
37 | BurpExtender.callback.registerIntruderPayloadProcessor(this);
38 | }
39 |
40 | public static String delProcessor(String name) {
41 | List processors = BurpExtender.callback.getIntruderPayloadProcessors();
42 | for (IIntruderPayloadProcessor processor : processors) {
43 | if (name.equals(processor.getProcessorName())) {
44 | BurpExtender.callback.removeIntruderPayloadProcessor(processor);
45 | return name + "删除成功";
46 | }
47 | }
48 | return name + "删除失败";
49 | }
50 |
51 | public static String removeAllProcessor() {
52 | for (IIntruderPayloadProcessor processor : BurpExtender.callback.getIntruderPayloadProcessors()) {
53 | BurpExtender.callback.removeIntruderPayloadProcessor(processor);
54 | }
55 |
56 | return "清除成功";
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/config/activeCryptConfig.java:
--------------------------------------------------------------------------------
1 | package config;
2 |
3 | import java.util.ArrayList;
4 |
5 | public class activeCryptConfig {
6 | public static ArrayList optionList = new ArrayList<>();
7 |
8 | static {
9 | optionList.add("urlEncode");
10 | optionList.add("urlDecode");
11 | optionList.add("base64Encode");
12 | optionList.add("base64Decode");
13 | optionList.add("hexEncode");
14 | optionList.add("hexDecode");
15 | optionList.add("htmlEncode");
16 | optionList.add("htmlDecode");
17 | optionList.add("DESEncrypt");
18 | optionList.add("DESDecrypt");
19 | optionList.add("AESEncrypt");
20 | optionList.add("AESDecrypt");
21 | optionList.add("RSAEncrypt");
22 | optionList.add("RSADecrypt");
23 | optionList.add("SM4Encrypt");
24 | optionList.add("SM4Decrypt");
25 | optionList.add("SM2Encrypt");
26 | optionList.add("SM2Decrypt");
27 | // optionList.add("convertCharset");
28 | optionList.add("hash");
29 | optionList.add("stringReplace");
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/config/allCryptoConfig.java:
--------------------------------------------------------------------------------
1 | package config;
2 |
3 | import java.util.LinkedHashMap;
4 | import java.util.Map;
5 |
6 | public class allCryptoConfig {
7 | public static Map cryptoMap = new LinkedHashMap<>();
8 | public static String[] titles4encode = {"raw", "hex", "base64"};
9 | public static String[] titles4location = {"url", "headers", "body"};
10 |
11 | static {
12 | cryptoMap.put("-- 请选择 --", new String[]{});
13 | cryptoMap.put("AES", new String[]{"AES/ECB/NoPadding", "AES/CBC/NoPadding", "AES/ECB/PKCS5Padding", "AES/CBC/PKCS5Padding"});
14 | cryptoMap.put("DES", new String[]{"DES/ECB/NoPadding", "DES/CBC/NoPadding", "DES/ECB/PKCS5Padding", "DES/CBC/PKCS5Padding"});
15 | cryptoMap.put("RSA", new String[]{"RSA/ECB/PKCS1Padding", "RSA/ECB/OAEPWithSHA-1AndGEF1Padding", "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"});
16 | cryptoMap.put("SM4", new String[]{"SM4/ECB/NoPadding", "SM4/CBC/NoPadding", "SM4/ECB/PKCS7Padding", "SM4/CBC/PKCS7Padding"});
17 | cryptoMap.put("SM2", new String[]{"SM2"});
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/config/autoCryptConfig.java:
--------------------------------------------------------------------------------
1 | package config;
2 |
3 | import lib.CryptoChains;
4 |
5 | public class autoCryptConfig {
6 | public static String hostReg = "";
7 | public static CryptoChains.CryptoChain requestEncryptChain;
8 | public static CryptoChains.CryptoChain requestDecryptChain;
9 | public static CryptoChains.CryptoChain responseEncryptChain;
10 | public static CryptoChains.CryptoChain responseDecryptChain;
11 | public static String requestCryptoReg;
12 | public static String responseCryptoReg;
13 | public static String requestCryptoLocation;
14 | public static String responseCryptoLocation;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/lib/ActiveCrypt.java:
--------------------------------------------------------------------------------
1 | package lib;
2 |
3 | import java.io.UnsupportedEncodingException;
4 | import java.net.URLDecoder;
5 | import java.net.URLEncoder;
6 | import java.nio.charset.Charset;
7 | import java.nio.charset.StandardCharsets;
8 | import java.security.MessageDigest;
9 | import java.security.NoSuchAlgorithmException;
10 | import java.util.ArrayList;
11 | import java.util.Base64;
12 | import java.util.regex.Matcher;
13 | import java.util.regex.Pattern;
14 |
15 | public class ActiveCrypt {
16 | CurrentParameter currentParameter;
17 |
18 | public ActiveCrypt(CurrentParameter currentParameter) {
19 | this.currentParameter = currentParameter;
20 | }
21 |
22 | public String handle(String text) throws Exception {
23 | if ("urlEncode".equalsIgnoreCase(currentParameter.codeMethod))
24 | return url_encode(text, currentParameter.url_encode_all, currentParameter.charset);
25 | if ("urlDecode".equalsIgnoreCase(currentParameter.codeMethod))
26 | return url_decode(text, currentParameter.charset);
27 | if ("base64Encode".equalsIgnoreCase(currentParameter.codeMethod))
28 | return base64_encode(text);
29 | if ("base64Decode".equalsIgnoreCase(currentParameter.codeMethod))
30 | return base64_decode(text);
31 | if ("hexEncode".equalsIgnoreCase(currentParameter.codeMethod))
32 | return string2Hex(text,"","","utf-8");
33 | if ("hexDecode".equalsIgnoreCase(currentParameter.codeMethod))
34 | return hex2String(text, Charset.defaultCharset().name());
35 | if ("convertCharset".equalsIgnoreCase(currentParameter.codeMethod))
36 | return convertCharset(text, currentParameter.charset);
37 | if ("htmlEncode".equalsIgnoreCase(currentParameter.codeMethod))
38 | return html_encode(text, currentParameter.charset);
39 | if ("htmlDecode".equalsIgnoreCase(currentParameter.codeMethod))
40 | return html_decode(text, currentParameter.charset);
41 | if ("stringReplace".equalsIgnoreCase(currentParameter.codeMethod))
42 | return stringReplace(currentParameter.isReg, text, currentParameter.original, currentParameter.newString);
43 | if (currentParameter.isCrypt)
44 | if (currentParameter.isDecrypt) {
45 | byte[] key = AutoCrypt.string2byes(currentParameter.key, currentParameter.keyCode);
46 | byte[] IV = AutoCrypt.string2byes(currentParameter.IV, currentParameter.IVCode);
47 | String decrypted = new Crypto(currentParameter.codeMethod, currentParameter.mode, key, IV, currentParameter.inCode).decrypt(text);
48 |
49 | if ("hex".equalsIgnoreCase(currentParameter.outCode))
50 | return AutoCrypt.bytesToHex(decrypted.getBytes());
51 | else if ("base64".equalsIgnoreCase(currentParameter.outCode))
52 | return new String(Base64.getEncoder().encode(decrypted.getBytes()));
53 | else
54 | return decrypted;
55 | } else {
56 | byte[] key = AutoCrypt.string2byes(currentParameter.key, currentParameter.keyCode);
57 | byte[] IV = AutoCrypt.string2byes(currentParameter.IV, currentParameter.IVCode);
58 |
59 | text = new String(AutoCrypt.string2byes(text, currentParameter.inCode));
60 |
61 | return new Crypto(currentParameter.codeMethod, currentParameter.mode, key, IV, currentParameter.outCode).encrypt(text);
62 | }
63 | if (currentParameter.isHash)
64 | return hash(currentParameter.codeMethod, text);
65 | else
66 | return text;
67 | }
68 |
69 | public String url_encode(String text, boolean all, String charset) throws UnsupportedEncodingException {
70 | if (all) {
71 | return string2Hex(text, "%", "", charset);
72 | } else {
73 | return URLEncoder.encode(text, charset);
74 | }
75 | }
76 |
77 | public String url_decode(String text, String charset) throws UnsupportedEncodingException {
78 | return URLDecoder.decode(text, charset);
79 | }
80 |
81 | public String base64_encode(String text) {
82 | return Base64.getEncoder().encodeToString(text.getBytes());
83 | }
84 |
85 | public String base64_decode(String text) {
86 | byte[] decode = Base64.getDecoder().decode(text);
87 | return new String(decode);
88 | }
89 |
90 | public String convertCharset(String text, String charset) throws UnsupportedEncodingException {
91 | return new String(text.getBytes(charset), StandardCharsets.ISO_8859_1);
92 | }
93 |
94 | public String html_encode(String text, String charset) throws UnsupportedEncodingException {
95 | return string2Hex(text, "", ";", charset);
96 | }
97 |
98 | public String html_decode(String text, String charset) throws UnsupportedEncodingException {
99 | return hex2String(text, charset);
100 | }
101 |
102 | public String string2Hex(String text, String prefix, String suffix, String charset) throws UnsupportedEncodingException {
103 | StringBuilder result = new StringBuilder();
104 | byte[] bytes = text.getBytes(charset);
105 |
106 | for (int b : bytes) {
107 | result.append(prefix).append(Integer.toHexString((b + 256) % 256)).append(suffix);
108 | }
109 |
110 | return result.toString();
111 | }
112 |
113 | public String string2Hex(byte[] bytes, String prefix, String suffix, String charset) throws UnsupportedEncodingException {
114 | StringBuilder result = new StringBuilder();
115 |
116 | for (int b : bytes) {
117 | result.append(prefix).append(Integer.toHexString((b + 256) % 256)).append(suffix);
118 | }
119 |
120 | return result.toString();
121 | }
122 |
123 | public String hex2String(String text, String charset) throws UnsupportedEncodingException {
124 | ArrayList integers = new ArrayList<>();
125 |
126 | Pattern compile = Pattern.compile("[0-9a-f]{2}");
127 | Matcher matcher = compile.matcher(text);
128 |
129 | while (matcher.find()) {
130 | String num = matcher.group();
131 | integers.add((byte) Integer.parseInt(num, 16));
132 | }
133 |
134 | byte[] bytes = new byte[integers.size()];
135 | for (int i = 0; i < integers.size(); i++) {
136 | bytes[i] = integers.get(i);
137 | }
138 |
139 | return new String(bytes, charset);
140 | }
141 |
142 | public String hash(String algorithm, String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
143 | MessageDigest instance = MessageDigest.getInstance(algorithm);
144 | instance.update(text.getBytes());
145 | byte[] bytes = instance.digest();
146 | return string2Hex(bytes, "", "", "iso-8859-1");
147 | }
148 |
149 | public String stringReplace(boolean isReg, String text, String original, String newString){
150 | if (isReg){
151 | return text.replaceAll(original, newString);
152 | }else {
153 | return text.replace(original, newString);
154 | }
155 | }
156 |
157 | public static class CurrentParameter {
158 | public String codeMethod;
159 | public String charset = Charset.defaultCharset().name();
160 | public boolean url_encode_all = false;
161 | public boolean isHash = false;
162 | public boolean isCrypt = false;
163 | public boolean isDecrypt = false;
164 | public String key;
165 | public String keyCode;
166 | public String IV;
167 | public String IVCode;
168 | public String mode;
169 | public String inCode;
170 | public String outCode;
171 | public boolean isReg;
172 | public String original;
173 | public String newString;
174 |
175 | public CurrentParameter(String codeMethod) {
176 | this.codeMethod = codeMethod;
177 | }
178 |
179 | public CurrentParameter(String codeMethod, boolean isHash) {
180 | this.codeMethod = codeMethod;
181 | this.isHash = isHash;
182 | }
183 |
184 | public CurrentParameter(String codeMethod, boolean isCrypt, boolean isDecrypt, String key, String IV, String mode, String inCode, String outCode, String keyCode, String IVCode) {
185 | this.codeMethod = codeMethod;
186 | this.isCrypt = isCrypt;
187 | this.isDecrypt = isDecrypt;
188 | this.key = key;
189 | this.IV = IV;
190 | this.mode = mode;
191 | this.inCode = inCode;
192 | this.outCode = outCode;
193 | this.keyCode = keyCode;
194 | this.IVCode = IVCode;
195 | }
196 |
197 | public CurrentParameter(String codeMethod, String charset) {
198 | this.codeMethod = codeMethod;
199 | this.charset = charset;
200 | }
201 |
202 | public CurrentParameter(String codeMethod, String charset, boolean url_encode_all, boolean isHash) {
203 | this.codeMethod = codeMethod;
204 | this.charset = charset;
205 | this.url_encode_all = url_encode_all;
206 | this.isHash = isHash;
207 | }
208 |
209 | public CurrentParameter(String codeMethod, boolean isReg, String original, String newString){
210 | this.codeMethod = codeMethod;
211 | this.isReg = isReg;
212 | this.original = original;
213 | this.newString = newString;
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/src/main/lib/AutoCrypt.java:
--------------------------------------------------------------------------------
1 | package lib;
2 |
3 | import burp.BurpExtender;
4 | import burp.IExtensionHelpers;
5 | import burp.IRequestInfo;
6 | import burp.IResponseInfo;
7 | import config.autoCryptConfig;
8 |
9 | import java.util.Arrays;
10 | import java.util.Base64;
11 | import java.util.List;
12 | import java.util.Objects;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 | public class AutoCrypt {
17 | public static byte[] unpackPacket(byte[] packet, IExtensionHelpers helpers, boolean isRequest, boolean decode) {
18 | List headers;
19 | String urlParameters = "";
20 | String body;
21 | String cryptoLocation;
22 | String cryptoReg;
23 |
24 | if (isRequest) {
25 | IRequestInfo requestInfo = helpers.analyzeRequest(packet);
26 |
27 | // headers
28 | headers = requestInfo.getHeaders();
29 |
30 | // url参数
31 | String[] split = headers.get(0).split("\\?", 2);
32 | urlParameters = split.length > 1 ? split[1] : "";
33 |
34 | // body
35 | int bodyOffset = requestInfo.getBodyOffset();
36 | body = new String(Arrays.copyOfRange(packet, bodyOffset, packet.length));
37 |
38 | // cryptLocation
39 | cryptoLocation = autoCryptConfig.requestCryptoLocation;
40 | // cryptReg
41 | cryptoReg = autoCryptConfig.requestCryptoReg;
42 |
43 | } else {
44 | IResponseInfo responseInfo = helpers.analyzeResponse(packet);
45 |
46 | // headers
47 | headers = responseInfo.getHeaders();
48 |
49 | // body
50 | int bodyOffset = responseInfo.getBodyOffset();
51 | body = new String(Arrays.copyOfRange(packet, bodyOffset, packet.length));
52 |
53 | // cryptLocation
54 | cryptoLocation = autoCryptConfig.responseCryptoLocation;
55 | // cryptoReg
56 | cryptoReg = autoCryptConfig.responseCryptoReg;
57 | }
58 |
59 | if (Objects.equals(cryptoLocation, "url")) {
60 | urlParameters = extractDataWithReg(urlParameters, cryptoReg, isRequest, decode);
61 | if (!"".equals(urlParameters))
62 | headers.set(0, headers.get(0).split("\\?", 2)[0] + urlParameters);
63 | } else if (Objects.equals(cryptoLocation, "headers")) {
64 | for (int i = 1; i < headers.size(); i++) {
65 | headers.set(i, extractDataWithReg(headers.get(i), cryptoReg, isRequest, decode));
66 | }
67 | } else
68 | body = extractDataWithReg(body, cryptoReg, isRequest, decode);
69 |
70 | return helpers.buildHttpMessage(headers, body.getBytes());
71 | }
72 |
73 | public static String extractDataWithReg(String data, String regStr, boolean isRequest, boolean decode) {
74 | if (data == null || "".equals(data) || regStr == null || "".equals(regStr))
75 | return data;
76 |
77 | CryptoChains.CryptoChain encryptChain;
78 | CryptoChains.CryptoChain decryptChain;
79 | if (isRequest) {
80 | encryptChain = autoCryptConfig.requestEncryptChain;
81 | decryptChain = autoCryptConfig.requestDecryptChain;
82 | }else {
83 | encryptChain = autoCryptConfig.responseEncryptChain;
84 | decryptChain = autoCryptConfig.responseDecryptChain;
85 | }
86 |
87 | Pattern pattern = Pattern.compile(regStr, Pattern.DOTALL);
88 | Matcher matcher = pattern.matcher(data);
89 |
90 | StringBuilder buffer = new StringBuilder();
91 |
92 | // 循环获取多次匹配到的结果
93 | while (matcher.find()) {
94 | int start = matcher.start();
95 | StringBuilder replacement = new StringBuilder();
96 |
97 | // 每次匹配到的结果可能有多个分组(多组小括号),如果没有则进行提示
98 | if (matcher.groupCount() < 1)
99 | BurpExtender.callback.printError("Error:自动解密未匹配到任何内容,需要替换的内容请用小括号括起来");
100 |
101 | for (int i = 1; i <= matcher.groupCount(); i++) {
102 | String match = matcher.group(i);
103 | if ("".equals(match))
104 | break;
105 |
106 | // 对匹配到的数据进行加解密
107 | String value;
108 | try {
109 | if (decode && decryptChain != null)
110 | value = decryptChain.doFinal(match);
111 | else if (!decode && encryptChain != null)
112 | value = encryptChain.doFinal(match);
113 | else
114 | value = match;
115 | }catch (Exception e){
116 | BurpExtender.callback.printError(e.toString());
117 | value = match;
118 | }
119 |
120 | replacement.append(data, start, matcher.start(i)).append(value);
121 | start = matcher.end(i);
122 | }
123 | replacement.append(data, start, matcher.end());
124 | matcher.appendReplacement(buffer, Matcher.quoteReplacement(replacement.toString()));
125 | }
126 | matcher.appendTail(buffer);
127 | return buffer.toString();
128 | }
129 |
130 | public static byte[] string2byes(String str, String mode) {
131 | if (str == null || "".equals(str))
132 | return new byte[]{};
133 |
134 | str = str.strip();
135 | if ("hex".equals(mode)) {
136 | byte[] bytes = new byte[str.length() / 2];
137 | for (int i = 0; i < str.length(); i += 2)
138 | bytes[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16));
139 | return bytes;
140 | } else if ("base64".equals(mode)) {
141 | return Base64.getDecoder().decode(str);
142 | } else {
143 | return str.getBytes();
144 | }
145 | }
146 |
147 | public static String bytesToHex(byte[] bytes) {
148 | StringBuilder sb = new StringBuilder();
149 | for (byte b : bytes) {
150 | sb.append(String.format("%02X", (b + 256) % 256 ));
151 | }
152 | return sb.toString();
153 | }
154 |
155 | public static byte[] hexToBytes(String hexString) {
156 | int len = hexString.length();
157 | String hex;
158 | if (len % 2 == 1) {
159 | hex = "0" + hexString;
160 | len += 1;
161 | } else
162 | hex = hexString;
163 |
164 | byte[] data = new byte[len / 2];
165 | for (int i = 0; i < len; i += 2) {
166 | data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
167 | + Character.digit(hex.charAt(i + 1), 16));
168 | }
169 | return data;
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/main/lib/Crypto.java:
--------------------------------------------------------------------------------
1 | package lib;
2 |
3 | import burp.BurpExtender;
4 | import com.tencent.kona.crypto.KonaCryptoProvider;
5 | import lib.Cryptos.RSACrypto;
6 | import lib.Cryptos.SM2Crypto;
7 |
8 | import javax.crypto.Cipher;
9 | import javax.crypto.spec.IvParameterSpec;
10 | import javax.crypto.spec.SecretKeySpec;
11 | import java.security.Security;
12 | import java.util.Base64;
13 |
14 | public class Crypto {
15 | String algorithm;
16 | String method;
17 | byte[] key;
18 | byte[] iv;
19 | String coding;
20 |
21 | public Crypto(String algorithm, String method, byte[] key, byte[] iv, String coding) {
22 | this.algorithm = algorithm;
23 | this.method = method;
24 | this.key = key;
25 | this.iv = iv;
26 | this.coding = coding;
27 |
28 | Security.insertProviderAt(new KonaCryptoProvider(), 1);
29 | }
30 |
31 | public String encrypt(String content) {
32 | if (algorithm == null || method == null)
33 | return content;
34 |
35 | try {
36 | switch (algorithm) {
37 | case "SM2" -> {
38 | byte[] priKey = key;
39 | byte[] pubKey = iv;
40 | return new SM2Crypto(method, priKey, pubKey, coding).encrypt(content);
41 | }
42 | // case "SM4" -> {
43 | // return new SM4Crypto(method, key, iv, coding).encrypt(content);
44 | // }
45 | case "RSA" -> {
46 | byte[] priKey = key;
47 | byte[] pubKey = iv;
48 | return new RSACrypto(method, priKey, pubKey, coding).encrypt(content);
49 | }
50 | // default 包括AES、DES、SM4
51 | default -> {
52 | SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
53 | IvParameterSpec ivSpec = null;
54 | if (iv.length > 0)
55 | ivSpec = new IvParameterSpec(iv);
56 | Cipher cipher = Cipher.getInstance(method);
57 | byte[] encrypted;
58 | if (ivSpec != null)
59 | cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
60 | else
61 | cipher.init(Cipher.ENCRYPT_MODE, keySpec);
62 | encrypted = cipher.doFinal(content.getBytes());
63 | if ("Base64".equalsIgnoreCase(coding))
64 | return Base64.getEncoder().encodeToString(encrypted);
65 | else if ("hex".equalsIgnoreCase(coding))
66 | return AutoCrypt.bytesToHex(encrypted);
67 | else
68 | return new String(encrypted);
69 | }
70 | }
71 | } catch (Exception e) {
72 | String errorStr = "\n加密出错: " + e + "\n" +
73 | "参数: \n\t\t" +
74 | "算法:" + algorithm + "\n\t\t模式:" + method + "\n\t\tkey:" + new String(key) +
75 | "\n\t\tIV:" + new String(iv) + "\n\t\t加密内容:" + content;
76 | BurpExtender.callback.printError(errorStr);
77 | return content;
78 | }
79 | }
80 |
81 | public String decrypt(String content) {
82 | if (algorithm == null || method == null)
83 | return content;
84 |
85 | try {
86 | switch (algorithm) {
87 | case "SM2" -> {
88 | byte[] priKey = key;
89 | byte[] pubKey = iv;
90 | return new SM2Crypto(method, priKey, pubKey, coding).decrypt(content);
91 | }
92 | // case "SM4" -> {
93 | // return new SM4Crypto(method, key, iv, coding).decrypt(content);
94 | // }
95 | case "RSA" -> {
96 | byte[] priKey = key;
97 | byte[] pubKey = iv;
98 | return new RSACrypto(method, priKey, pubKey, coding).decrypt(content);
99 | }
100 | // default 包括 AES、DES、SM4
101 | default -> {
102 | SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
103 | IvParameterSpec ivSpec = null;
104 | if (iv.length > 0)
105 | ivSpec = new IvParameterSpec(iv);
106 | Cipher cipher = Cipher.getInstance(method);
107 | byte[] encrypted;
108 | if ("Base64".equalsIgnoreCase(coding))
109 | encrypted = Base64.getDecoder().decode(content);
110 | else
111 | encrypted = AutoCrypt.hexToBytes(content);
112 | if (ivSpec != null)
113 | cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
114 | else
115 | cipher.init(Cipher.DECRYPT_MODE, keySpec);
116 | return new String(cipher.doFinal(encrypted));
117 | }
118 | }
119 | } catch (Exception e) {
120 | String errorStr = "\n解密出错: " + e + "\n" +
121 | "参数: \n\t\t" +
122 | "算法:" + algorithm + "\n\t\t模式:" + method + "\n\t\tkey:" + new String(key) +
123 | "\n\t\tIV:" + new String(iv) + "\n\t\t解密内容:" + content;
124 | BurpExtender.callback.printError(errorStr);
125 | return content;
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/src/main/lib/CryptoChains.java:
--------------------------------------------------------------------------------
1 | package lib;
2 |
3 | import burp.BurpExtender;
4 | import burp.MenuFactoryClass;
5 | import burp.ProcessorClass;
6 | import ui.AutoCryptConfigUI;
7 |
8 | import javax.swing.*;
9 | import java.nio.charset.Charset;
10 | import java.util.LinkedHashMap;
11 |
12 | public class CryptoChains {
13 | public static LinkedHashMap cryptoChainLinkedHashMap = new LinkedHashMap<>();
14 |
15 | public static String addChain(String chainName, CryptoChain cryptoChain) {
16 | if ("".equals(chainName))
17 | return "菜单名不能为空";
18 | cryptoChain.getCryptChain();
19 | cryptoChainLinkedHashMap.put(chainName, cryptoChain);
20 |
21 | // 添加到右击菜单
22 | MenuFactoryClass menuFactoryClass = BurpExtender.menuFactoryClass;
23 | menuFactoryClass.addMenuItem(chainName, cryptoChain);
24 |
25 | // 添加到processor
26 | ProcessorClass processorClass = new ProcessorClass(chainName, cryptoChain);
27 | processorClass.add2Processor();
28 |
29 | // 添加到主动解密模块
30 | refreshCryptoComboBox();
31 |
32 | return chainName + " 添加成功";
33 | }
34 |
35 | public static void refreshCryptoComboBox() {
36 | AutoCryptConfigUI.requestPanel.refreshCryptoComboBox(cryptoChainLinkedHashMap.keySet().toArray(new String[0]));
37 | AutoCryptConfigUI.responsePanel.refreshCryptoComboBox(cryptoChainLinkedHashMap.keySet().toArray(new String[0]));
38 | }
39 |
40 | public static class CryptoChain {
41 | public LinkedHashMap cardChain = new LinkedHashMap<>();
42 | public LinkedHashMap cryptChain = new LinkedHashMap<>();
43 |
44 | public CryptoChain() {
45 |
46 | }
47 |
48 | private CryptoChain(CryptoChain cryptoChain) {
49 | this.cardChain = new LinkedHashMap<>(cryptoChain.cardChain);
50 | this.cryptChain = new LinkedHashMap<>(cryptoChain.cryptChain);
51 | }
52 |
53 | public void upItem(int index) {
54 | if (index == 1)
55 | return;
56 | JPanel temp = cardChain.get(index);
57 |
58 | cardChain.remove(index);
59 | cardChain.put(index, cardChain.get(index - 1));
60 |
61 | cardChain.remove(index - 1);
62 | cardChain.put(index - 1, temp);
63 | }
64 |
65 | public void downItem(int index) {
66 | if (index == cardChain.size())
67 | return;
68 |
69 | JPanel temp = cardChain.get(index);
70 |
71 | cardChain.remove(index);
72 | cardChain.put(index, cardChain.get(index + 1));
73 |
74 | cardChain.remove(index + 1);
75 | cardChain.put(index + 1, temp);
76 | }
77 |
78 | public void delItem(int index) {
79 | for (int i = index; i <= cardChain.size(); i++) {
80 | if (i != cardChain.size()) {
81 | cardChain.remove(i);
82 | cardChain.put(i, cardChain.get(i + 1));
83 | }
84 | }
85 | cardChain.remove(cardChain.size());
86 | }
87 |
88 | public void clear() {
89 | cardChain.clear();
90 | }
91 |
92 | public void getCryptChain() {
93 | cryptChain.clear();
94 | for (JPanel panel : cardChain.values()) {
95 | JPanel leftPanel = (JPanel) panel.getComponent(0);
96 | JPanel labelPanel = (JPanel) leftPanel.getComponent(0);
97 | JLabel label = (JLabel) labelPanel.getComponent(0);
98 | String cryptName = label.getText();
99 |
100 |
101 | if ("urlEncode".equalsIgnoreCase(cryptName)) {
102 | JPanel dataPanel = (JPanel) leftPanel.getComponent(1);
103 | JCheckBox all_encode = (JCheckBox) dataPanel.getComponent(0);
104 | boolean selected = all_encode.isSelected();
105 | ActiveCrypt.CurrentParameter parameter = new ActiveCrypt.CurrentParameter(cryptName, Charset.defaultCharset().name(), selected, false);
106 | cryptChain.put(cryptChain.size() + 1, new ActiveCrypt(parameter));
107 | } else if (cryptName.contains("crypt")) {
108 | JPanel dataPanel = (JPanel) leftPanel.getComponent(1);
109 |
110 | JPanel jPanel1 = (JPanel) dataPanel.getComponent(0);
111 | JPanel jPanel2 = (JPanel) dataPanel.getComponent(1);
112 |
113 | JPanel keyPanel = (JPanel) jPanel1.getComponent(0);
114 | JPanel IVPanel = (JPanel) jPanel1.getComponent(1);
115 |
116 | JPanel algorithmPanel = (JPanel) jPanel2.getComponent(0);
117 | JPanel inputEncodePanel = (JPanel) jPanel2.getComponent(1);
118 | JPanel outputEncodePanel = (JPanel) jPanel2.getComponent(2);
119 |
120 |
121 | JTextField keyTextField = (JTextField) keyPanel.getComponent(2);
122 | JComboBox keyCodeComboBox = (JComboBox) keyPanel.getComponent(4);
123 |
124 | String key = keyTextField.getText();
125 | String keyCode = (String) keyCodeComboBox.getSelectedItem();
126 |
127 | JTextField IVTextField = (JTextField) IVPanel.getComponent(2);
128 | JComboBox IVCodeComboBox = (JComboBox) IVPanel.getComponent(4);
129 |
130 | String IV = IVTextField.getText();
131 | String IVCode = (String) IVCodeComboBox.getSelectedItem();
132 |
133 | JComboBox algorithmComboBox = (JComboBox) algorithmPanel.getComponent(1);
134 | String algorithm = (String) algorithmComboBox.getSelectedItem();
135 |
136 | JComboBox inputCodeComboBox = (JComboBox) inputEncodePanel.getComponent(1);
137 | String inputCode = (String) inputCodeComboBox.getSelectedItem();
138 |
139 | JComboBox outputCodeComboBox = (JComboBox) outputEncodePanel.getComponent(1);
140 | String outputCode = (String) outputCodeComboBox.getSelectedItem();
141 |
142 | ActiveCrypt.CurrentParameter parameter = new ActiveCrypt.CurrentParameter(algorithm.split("/")[0], true, cryptName.contains("Decrypt"), key, IV, algorithm, inputCode, outputCode, keyCode, IVCode);
143 | cryptChain.put(cryptChain.size() + 1, new ActiveCrypt(parameter));
144 | } else if ("convertCharset".equalsIgnoreCase(cryptName)) {
145 | JPanel dataPanel = (JPanel) leftPanel.getComponent(1);
146 |
147 | JComboBox charsetComboBox = (JComboBox) dataPanel.getComponent(0);
148 | String charset = (String) charsetComboBox.getSelectedItem();
149 |
150 | ActiveCrypt.CurrentParameter parameter = new ActiveCrypt.CurrentParameter(cryptName, charset);
151 | cryptChain.put(cryptChain.size() + 1, new ActiveCrypt(parameter));
152 | } else if ("hash".equalsIgnoreCase(cryptName)) {
153 | JPanel dataPanel = (JPanel) leftPanel.getComponent(1);
154 |
155 | JComboBox hashComboBox = (JComboBox) dataPanel.getComponent(0);
156 | String hash = (String) hashComboBox.getSelectedItem();
157 |
158 | ActiveCrypt.CurrentParameter parameter = new ActiveCrypt.CurrentParameter(hash, true);
159 | cryptChain.put(cryptChain.size() + 1, new ActiveCrypt(parameter));
160 | } else if ("stringReplace".equalsIgnoreCase(cryptName)) {
161 | JPanel dataPanel = (JPanel) leftPanel.getComponent(1);
162 |
163 | JPanel checkPanel = (JPanel) dataPanel.getComponent(0);
164 | JCheckBox checkBox = (JCheckBox) checkPanel.getComponent(0);
165 | boolean isReg = checkBox.isSelected();
166 |
167 | JPanel inputPanel = (JPanel) dataPanel.getComponent(1);
168 | JTextField findTextField = (JTextField) inputPanel.getComponent(1);
169 | JTextField replaceTextField = (JTextField) inputPanel.getComponent(3);
170 |
171 | String oldString = findTextField.getText();
172 | String newString = replaceTextField.getText();
173 |
174 | ActiveCrypt.CurrentParameter parameter = new ActiveCrypt.CurrentParameter(cryptName, isReg, oldString, newString);
175 | cryptChain.put(cryptChain.size() + 1, new ActiveCrypt(parameter));
176 | } else {
177 | ActiveCrypt.CurrentParameter parameter = new ActiveCrypt.CurrentParameter(cryptName);
178 | cryptChain.put(cryptChain.size() + 1, new ActiveCrypt(parameter));
179 | }
180 | }
181 | }
182 |
183 | public String doFinal(String text) throws Exception {
184 | for (ActiveCrypt cryptTool : cryptChain.values()) {
185 | text = cryptTool.handle(text);
186 | }
187 | return text;
188 | }
189 |
190 | public CryptoChain copy() {
191 | return new CryptoChain(this);
192 | }
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/src/main/lib/Cryptos/RSACrypto.java:
--------------------------------------------------------------------------------
1 | package lib.Cryptos;
2 |
3 | import lib.AutoCrypt;
4 |
5 | import javax.crypto.Cipher;
6 | import javax.crypto.NoSuchPaddingException;
7 | import java.security.KeyFactory;
8 | import java.security.NoSuchAlgorithmException;
9 | import java.security.PrivateKey;
10 | import java.security.PublicKey;
11 | import java.security.spec.PKCS8EncodedKeySpec;
12 | import java.security.spec.X509EncodedKeySpec;
13 | import java.util.Base64;
14 |
15 | public class RSACrypto {
16 | private final String coding;
17 | private final KeyFactory keyFactory;
18 | private final Cipher cipher;
19 | private final byte[] priKey;
20 | private final byte[] pubKey;
21 |
22 | public RSACrypto(String method, byte[] priKey, byte[] pubKey, String coding) throws NoSuchAlgorithmException, NoSuchPaddingException {
23 | this.coding = coding;
24 | this.priKey = priKey;
25 | this.pubKey = pubKey;
26 |
27 | keyFactory = KeyFactory.getInstance("RSA");
28 | cipher = Cipher.getInstance(method);
29 | }
30 |
31 | public String encrypt(String plainText) throws Exception {
32 |
33 | X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKey);
34 | PublicKey publicKey = keyFactory.generatePublic(keySpec);
35 |
36 | cipher.init(Cipher.ENCRYPT_MODE, publicKey);
37 | byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
38 |
39 | if ("Base64".equalsIgnoreCase(coding))
40 | return Base64.getEncoder().encodeToString(encryptedBytes);
41 | else if ("hex".equalsIgnoreCase(coding))
42 | return AutoCrypt.bytesToHex(encryptedBytes);
43 | else
44 | return new String(encryptedBytes);
45 | }
46 |
47 | public String decrypt(String encryptedText) throws Exception {
48 |
49 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priKey);
50 | PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
51 | cipher.init(Cipher.DECRYPT_MODE, privateKey);
52 |
53 | byte[] encryptedBytes;
54 | if ("Base64".equalsIgnoreCase(coding))
55 | encryptedBytes = Base64.getDecoder().decode(encryptedText);
56 | else if ("hex".equalsIgnoreCase(coding))
57 | encryptedBytes = AutoCrypt.hexToBytes(encryptedText);
58 | else
59 | encryptedBytes = encryptedText.getBytes();
60 |
61 | byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
62 | return new String(decryptedBytes);
63 | }
64 | }
--------------------------------------------------------------------------------
/src/main/lib/Cryptos/SM2Crypto.java:
--------------------------------------------------------------------------------
1 | package lib.Cryptos;
2 |
3 | import burp.BurpExtender;
4 | import com.tencent.kona.crypto.spec.SM2PrivateKeySpec;
5 | import com.tencent.kona.crypto.spec.SM2PublicKeySpec;
6 | import lib.AutoCrypt;
7 |
8 | import javax.crypto.Cipher;
9 | import javax.crypto.NoSuchPaddingException;
10 | import java.security.KeyFactory;
11 | import java.security.NoSuchAlgorithmException;
12 | import java.security.PrivateKey;
13 | import java.security.PublicKey;
14 | import java.util.Base64;
15 |
16 | public class SM2Crypto {
17 | private final String coding;
18 | private final Cipher cipher;
19 | private PublicKey pubKey = null;
20 | private PrivateKey priKey = null;
21 |
22 | public SM2Crypto(String method, byte[] priKey, byte[] pubKey, String coding) throws NoSuchAlgorithmException, NoSuchPaddingException {
23 | this.coding = coding;
24 |
25 | cipher = Cipher.getInstance("SM2");
26 |
27 | KeyFactory keyFactory = KeyFactory.getInstance("SM2");
28 |
29 | if (pubKey.length > 0) {
30 | try {
31 | this.pubKey = keyFactory.generatePublic(new SM2PublicKeySpec(pubKey));
32 | } catch (Exception e) {
33 | BurpExtender.callback.printError("SM2 公钥错误");
34 | }
35 | }
36 |
37 | if (priKey.length > 0) {
38 | try {
39 | this.priKey = keyFactory.generatePrivate(new SM2PrivateKeySpec(priKey));
40 | } catch (Exception e) {
41 | BurpExtender.callback.printError("SM2 私钥错误");
42 | }
43 | }
44 | }
45 |
46 | public String encrypt(String plainText) throws Exception {
47 | cipher.init(Cipher.ENCRYPT_MODE, pubKey);
48 | byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
49 |
50 | if ("Base64".equalsIgnoreCase(coding))
51 | return Base64.getEncoder().encodeToString(encryptedBytes);
52 | else if ("hex".equalsIgnoreCase(coding))
53 | return AutoCrypt.bytesToHex(encryptedBytes);
54 | else
55 | return new String(encryptedBytes);
56 | }
57 |
58 | public String decrypt(String encryptedText) throws Exception {
59 | byte[] encryptedBytes;
60 | if ("Base64".equalsIgnoreCase(coding))
61 | encryptedBytes = Base64.getDecoder().decode(encryptedText);
62 | else if ("hex".equalsIgnoreCase(coding))
63 | encryptedBytes = AutoCrypt.hexToBytes(encryptedText);
64 | else
65 | encryptedBytes = encryptedText.getBytes();
66 |
67 | cipher.init(Cipher.DECRYPT_MODE, priKey);
68 | byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
69 |
70 | return new String(decryptedBytes);
71 | }
72 | }
--------------------------------------------------------------------------------
/src/main/ui/ActiveCryptConfigUI.java:
--------------------------------------------------------------------------------
1 | package ui;
2 |
3 | import burp.MenuFactoryClass;
4 | import burp.ProcessorClass;
5 | import config.activeCryptConfig;
6 | import config.allCryptoConfig;
7 | import lib.CryptoChains;
8 | import lib.CryptoChains.CryptoChain;
9 |
10 | import javax.swing.*;
11 | import java.awt.*;
12 | import java.awt.event.MouseAdapter;
13 | import java.awt.event.MouseEvent;
14 | import java.lang.reflect.Method;
15 | import java.nio.charset.Charset;
16 | import java.security.Security;
17 | import java.util.Objects;
18 |
19 | /**
20 | * 添加加解密链的UI,包括左侧选择列表和右侧已选择的加解密算法的卡片
21 | */
22 | public class ActiveCryptConfigUI extends JPanel {
23 | public CryptoChain cryptoChain = new CryptoChain();
24 | public JPanel selectedPanel;
25 |
26 | public ActiveCryptConfigUI() {
27 | init();
28 | }
29 |
30 | public void init() {
31 | setLayout(new BorderLayout());
32 |
33 | // 上方,接收添加的菜单的命名
34 | JPanel topPanel = new JPanel();
35 |
36 | JLabel nameLabel = new JLabel("命名: ");
37 | JTextField nameTextField = new JTextField(30);
38 |
39 | topPanel.add(nameLabel);
40 | topPanel.add(nameTextField);
41 |
42 | // 中部,主题窗口
43 | JPanel centerPanel = new JPanel(new GridBagLayout());
44 | GridBagConstraints gbc = new GridBagConstraints();
45 | gbc.fill = GridBagConstraints.BOTH;
46 |
47 | // 中左部分,可选择的加解密和编码列表
48 | gbc.gridx = 0;
49 | gbc.weightx = gbc.weighty = 20;
50 |
51 | centerPanel.add(optionListJPanel(), gbc);
52 |
53 | // 中中部分,已选择的列表
54 | gbc.gridx = 20;
55 | gbc.weightx = 80;
56 |
57 | selectedPanel = new JPanel(new GridLayout(0, 1, 0, 0));
58 | JScrollPane selectedScrollPanel = new JScrollPane(selectedPanel);
59 | selectedScrollPanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
60 |
61 |
62 | centerPanel.add(selectedScrollPanel, gbc);
63 |
64 | // 中右部分,输入输出窗口(暂时去掉)
65 | // gbc.gridx = 2;
66 | // gbc.weightx = 60;
67 | //
68 | // JPanel IOPanel = new JPanel();
69 | // IOPanel.setBackground(new Color(2000000000));
70 | //
71 | // centerPanel.add(IOPanel, gbc);
72 |
73 | // 底部,保存按钮
74 | JPanel bottomPanel = new JPanel();
75 |
76 | JButton addChainjButton = new JButton("添加到加解密链");
77 | JButton manageButton = new JButton("管理加解密链");
78 | JButton clearMenuButton = new JButton("清除所有加解密链");
79 |
80 | bottomPanel.add(addChainjButton);
81 | bottomPanel.add(manageButton);
82 | bottomPanel.add(clearMenuButton);
83 |
84 | add(topPanel, BorderLayout.NORTH);
85 | add(centerPanel, BorderLayout.CENTER);
86 | add(bottomPanel, BorderLayout.SOUTH);
87 |
88 | // 管理所有菜单
89 | manageButton.addMouseListener(new MouseAdapter() {
90 | @Override
91 | public void mouseClicked(MouseEvent e) {
92 | JDialog jDialog = new JDialog();
93 | jDialog.setSize(400, 300);
94 | jDialog.setPreferredSize(new Dimension(400, 300));
95 |
96 | JPanel leftElements = new JPanel(new GridLayout(0, 1, 0, 5));
97 | for (String cryptoName : CryptoChains.cryptoChainLinkedHashMap.keySet()) {
98 | JLabel label = new JLabel(cryptoName);
99 | JButton delButton = new JButton("×");
100 | JPanel element = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));
101 | element.add(label);
102 | element.add(delButton);
103 | leftElements.add(element);
104 |
105 | delButton.addMouseListener(new MouseAdapter() {
106 | @Override
107 | public void mouseClicked(MouseEvent e) {
108 | // 删除右击菜单
109 | MenuFactoryClass.delMenuItem(cryptoName);
110 |
111 | // 删除Processor
112 | ProcessorClass.delProcessor(cryptoName);
113 |
114 | // 删除自动加解密选择项
115 | CryptoChains.cryptoChainLinkedHashMap.remove(cryptoName);
116 | CryptoChains.refreshCryptoComboBox();
117 |
118 | // 更新管理框的条目
119 | leftElements.remove(element);
120 | leftElements.repaint();
121 | }
122 | });
123 | }
124 |
125 | JScrollPane leftScrollPane = new JScrollPane(leftElements);
126 | leftScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
127 | jDialog.add(leftScrollPane, BorderLayout.CENTER);
128 |
129 | jDialog.setVisible(true);
130 | }
131 | });
132 |
133 | // 添加到加解密链
134 | addChainjButton.addMouseListener(new MouseAdapter() {
135 | @Override
136 | public void mouseClicked(MouseEvent e) {
137 | String itemName = nameTextField.getText();
138 |
139 | if ("".equals(itemName)) {
140 | itemName = JOptionPane.showInputDialog("请输入菜单名");
141 | nameTextField.setText(itemName);
142 | }
143 |
144 | String msg = CryptoChains.addChain(itemName, cryptoChain.copy());
145 | JOptionPane.showMessageDialog(null, msg, "提示", JOptionPane.INFORMATION_MESSAGE);
146 |
147 |
148 | }
149 | });
150 |
151 | // 清除所有加解密链
152 | clearMenuButton.addMouseListener(new MouseAdapter() {
153 | @Override
154 | public void mouseClicked(MouseEvent e) {
155 | int option = JOptionPane.showConfirmDialog(centerPanel, "是否清除所有加解密链", "清除所有", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
156 | if (option == JOptionPane.YES_OPTION) {
157 |
158 | // 删除所有 右击菜单
159 | MenuFactoryClass.delAllMenuItem();
160 |
161 | // 删除所有 processor
162 | ProcessorClass.removeAllProcessor();
163 |
164 | // 删除所有自动加解密选择项
165 | CryptoChains.cryptoChainLinkedHashMap.clear();
166 | CryptoChains.refreshCryptoComboBox();
167 | }
168 | }
169 | });
170 | }
171 |
172 | /**
173 | * 左侧选择列表,所有可用的加解密方式
174 | */
175 | public JScrollPane optionListJPanel() {
176 | JPanel mainPanel = new JPanel();
177 | mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
178 |
179 | for (String option : activeCryptConfig.optionList) {
180 | JPanel singlePanel = new JPanel();
181 |
182 | JLabel nameLabel = new JLabel(option);
183 | JButton addButton = new JButton("+");
184 |
185 | addButton.addMouseListener(new MouseAdapter() {
186 | @Override
187 | public void mouseClicked(MouseEvent e) {
188 | int index = cryptoChain.cardChain.size() + 1;
189 |
190 | try {
191 | Method getCard = CryptoCards.class.getMethod(option + "Card");
192 | JPanel card = (JPanel) getCard.invoke(new CryptoCards());
193 |
194 | cryptoChain.cardChain.put(index, card);
195 |
196 | // 刷新已选择的列表
197 | refreshSelectedPanel();
198 |
199 | } catch (Exception ex) {
200 | throw new RuntimeException(ex);
201 | }
202 | }
203 | });
204 |
205 | singlePanel.add(nameLabel);
206 | singlePanel.add(addButton);
207 |
208 | mainPanel.add(singlePanel);
209 | }
210 |
211 | JScrollPane listScrollPane = new JScrollPane(mainPanel);
212 | listScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
213 | return listScrollPane;
214 | }
215 |
216 | /**
217 | * 上移、下移、删除卡片后更新UI
218 | */
219 | public void refreshSelectedPanel() {
220 | int size = cryptoChain.cardChain.size();
221 | selectedPanel.removeAll();
222 |
223 | for (int i = 1; i <= size; i++) {
224 | JPanel card = cryptoChain.cardChain.get(i);
225 | selectedPanel.add(card);
226 | }
227 |
228 | for (int i = 0; i < 10; i++) {
229 | selectedPanel.add(new JPanel());
230 | }
231 |
232 | selectedPanel.requestFocus();
233 | }
234 |
235 | /**
236 | * 创建加解密卡片,通过反射调用
237 | */
238 | public class CryptoCards {
239 | public JPanel urlDecodeCard() {
240 | return baseCard("urlDecode", null, ActiveCryptConfigUI.this);
241 | }
242 |
243 | public JPanel urlEncodeCard() {
244 | JCheckBox checkBox = new JCheckBox("all encode");
245 | JPanel jPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
246 | jPanel.add(checkBox);
247 |
248 | return baseCard("urlEncode", jPanel, ActiveCryptConfigUI.this);
249 | }
250 |
251 | public JPanel base64DecodeCard() {
252 | return baseCard("base64Decode", null, ActiveCryptConfigUI.this);
253 | }
254 |
255 | public JPanel base64EncodeCard() {
256 | return baseCard("base64Encode", null, ActiveCryptConfigUI.this);
257 | }
258 |
259 | public JPanel hexDecodeCard() {
260 | return baseCard("hexDecode", null, ActiveCryptConfigUI.this);
261 | }
262 |
263 | public JPanel hexEncodeCard() {
264 | return baseCard("hexEncode", null, ActiveCryptConfigUI.this);
265 | }
266 |
267 | public JPanel htmlDecodeCard() {
268 | return baseCard("htmlDecode", null, ActiveCryptConfigUI.this);
269 | }
270 |
271 | public JPanel htmlEncodeCard() {
272 | return baseCard("htmlEncode", null, ActiveCryptConfigUI.this);
273 | }
274 |
275 | public JPanel convertCharsetCard() {
276 | JPanel jPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
277 |
278 | String[] values = Charset.availableCharsets().keySet().toArray(new String[0]);
279 |
280 | JComboBox box = new JComboBox<>(values);
281 | jPanel.add(box);
282 |
283 | return baseCard("convertCharset", jPanel, ActiveCryptConfigUI.this);
284 | }
285 |
286 | public JPanel hashCard() {
287 | JPanel jPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
288 | String[] values = Security.getAlgorithms("MessageDigest").toArray(new String[0]);
289 | JComboBox box = new JComboBox<>(values);
290 | jPanel.add(box);
291 |
292 | return baseCard("hash", jPanel, ActiveCryptConfigUI.this);
293 | }
294 |
295 | public JPanel stringReplaceCard() {
296 | JPanel jPanel = new JPanel();
297 | jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.PAGE_AXIS));
298 |
299 | JPanel checkPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
300 | JCheckBox regCheckBox = new JCheckBox("使用正则");
301 |
302 | checkPanel.add(regCheckBox);
303 |
304 | JPanel inputPanel = new JPanel();
305 | inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.LINE_AXIS));
306 |
307 | JLabel findLabel = new JLabel("查找内容: ");
308 | JTextField findTextField = new JTextField();
309 | findTextField.setPreferredSize(new Dimension(findTextField.getPreferredSize().width, 5));
310 |
311 | JLabel replaceLabel = new JLabel("替换为: ");
312 | JTextField replaceTextField = new JTextField();
313 | replaceTextField.setPreferredSize(new Dimension(replaceTextField.getPreferredSize().width, 5));
314 |
315 | inputPanel.add(findLabel);
316 | inputPanel.add(findTextField);
317 | inputPanel.add(replaceLabel);
318 | inputPanel.add(replaceTextField);
319 |
320 | jPanel.add(checkPanel);
321 | jPanel.add(inputPanel);
322 |
323 | return baseCard("stringReplace", jPanel, ActiveCryptConfigUI.this);
324 | }
325 |
326 | public JPanel AESDecryptCard() {
327 | return cryptoCard("AES", "AESDecrypt", ActiveCryptConfigUI.this);
328 | }
329 |
330 | public JPanel AESEncryptCard() {
331 | return cryptoCard("AES", "AESEncrypt", ActiveCryptConfigUI.this);
332 | }
333 |
334 | public JPanel DESDecryptCard() {
335 | return cryptoCard("DES", "DESDecrypt", ActiveCryptConfigUI.this);
336 | }
337 |
338 | public JPanel DESEncryptCard() {
339 | return cryptoCard("DES", "DESEncrypt", ActiveCryptConfigUI.this);
340 | }
341 |
342 | public JPanel SM4DecryptCard() {
343 | return cryptoCard("SM4", "SM4Decrypt", ActiveCryptConfigUI.this);
344 | }
345 |
346 | public JPanel SM4EncryptCard() {
347 | return cryptoCard("SM4", "SM4Encrypt", ActiveCryptConfigUI.this);
348 | }
349 |
350 | public JPanel RSADecryptCard() {
351 | return cryptoCard("RSA", "RSADecrypt", ActiveCryptConfigUI.this);
352 | }
353 |
354 | public JPanel RSAEncryptCard() {
355 | return cryptoCard("RSA", "RSAEncrypt", ActiveCryptConfigUI.this);
356 | }
357 |
358 | public JPanel SM2DecryptCard() {
359 | return cryptoCard("SM2", "SM2Decrypt", ActiveCryptConfigUI.this);
360 | }
361 |
362 | public JPanel SM2EncryptCard() {
363 | return cryptoCard("SM2", "SM2Encrypt", ActiveCryptConfigUI.this);
364 | }
365 |
366 | public static JPanel baseCard(String title, JPanel panel, ActiveCryptConfigUI activeCryptConfigUI) {
367 | // 新建JPanel,作为整体框架
368 | JPanel basePanel = new JPanel(new GridBagLayout());
369 | basePanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(0, 0, 0)));
370 | basePanel.setPreferredSize(new Dimension(0, 120));
371 |
372 | // 页面标签
373 | JPanel labelPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
374 | JLabel label = new JLabel(title);
375 | label.setBorder(BorderFactory.createEmptyBorder(5, 5, 20, 0));
376 | labelPanel.add(label);
377 |
378 | // 新建功能区,包括上移、下移、删除
379 | JPanel funcPanel = new JPanel();
380 | funcPanel.setLayout(new GridLayout());
381 | funcPanel.setBackground(new Color(230, 230, 230));
382 |
383 | JButton upButton = getButton("↑");
384 | JButton downButton = getButton("↓");
385 | JButton delButton = getButton("×");
386 |
387 | // 功能区按钮事件
388 | upButton.addMouseListener(new MouseAdapter() {
389 | @Override
390 | public void mouseClicked(MouseEvent e) {
391 | for (int i = 1; i <= activeCryptConfigUI.cryptoChain.cardChain.size(); i++) {
392 | if (basePanel.equals(activeCryptConfigUI.cryptoChain.cardChain.get(i))) {
393 | activeCryptConfigUI.cryptoChain.upItem(i);
394 | activeCryptConfigUI.refreshSelectedPanel();
395 | return;
396 | }
397 | }
398 | }
399 | });
400 |
401 | downButton.addMouseListener(new MouseAdapter() {
402 | @Override
403 | public void mouseClicked(MouseEvent e) {
404 | for (int i = 1; i <= activeCryptConfigUI.cryptoChain.cardChain.size(); i++) {
405 | if (basePanel.equals(activeCryptConfigUI.cryptoChain.cardChain.get(i))) {
406 | activeCryptConfigUI.cryptoChain.downItem(i);
407 | activeCryptConfigUI.refreshSelectedPanel();
408 | return;
409 | }
410 | }
411 | }
412 | });
413 |
414 | delButton.addMouseListener(new MouseAdapter() {
415 | @Override
416 | public void mouseClicked(MouseEvent e) {
417 | for (int i = 1; i <= activeCryptConfigUI.cryptoChain.cardChain.size(); i++) {
418 | if (basePanel.equals(activeCryptConfigUI.cryptoChain.cardChain.get(i))) {
419 | activeCryptConfigUI.cryptoChain.delItem(i);
420 | activeCryptConfigUI.selectedPanel.remove(i - 1);
421 | activeCryptConfigUI.refreshSelectedPanel();
422 | return;
423 | }
424 | }
425 | }
426 | });
427 |
428 | funcPanel.add(upButton);
429 | funcPanel.add(downButton);
430 | funcPanel.add(delButton);
431 |
432 | // 组装左边区域,如果有传入panel,将其放入左下方
433 | JPanel leftPanel = new JPanel();
434 | leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
435 |
436 | leftPanel.add(labelPanel);
437 |
438 | if (panel != null) {
439 | leftPanel.add(panel);
440 | }
441 |
442 | GridBagConstraints gbc = new GridBagConstraints();
443 | gbc.fill = GridBagConstraints.BOTH;
444 |
445 | gbc.weightx = gbc.weighty = 999;
446 | gbc.gridx = gbc.gridy = 0;
447 |
448 | basePanel.add(leftPanel, gbc);
449 |
450 | gbc.gridx = 1;
451 | gbc.weightx = 1;
452 | basePanel.add(funcPanel, gbc);
453 |
454 | return basePanel;
455 | }
456 |
457 | public JPanel cryptoCard(String cipherName, String title, ActiveCryptConfigUI activeCryptConfigUI) {
458 | JPanel jPanel = new JPanel();
459 | jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.PAGE_AXIS));
460 |
461 | // 密钥组
462 | JPanel keyPanel = new JPanel();
463 | keyPanel.setLayout(new BoxLayout(keyPanel, BoxLayout.LINE_AXIS));
464 |
465 | JLabel keyLabel;
466 | if ("RSA".equalsIgnoreCase(cipherName) || "SM2".equalsIgnoreCase(cipherName))
467 | keyLabel = new JLabel("私钥");
468 | else
469 | keyLabel = new JLabel("密钥");
470 | JTextField keyTextField = new JTextField(15);
471 | JComboBox keyEncodeComboBox = new JComboBox<>(allCryptoConfig.titles4encode);
472 |
473 | keyPanel.add(keyLabel);
474 | keyPanel.add(Box.createHorizontalStrut(0));
475 | keyPanel.add(keyTextField);
476 | keyPanel.add(Box.createHorizontalStrut(0));
477 | keyPanel.add(keyEncodeComboBox);
478 | keyPanel.add(Box.createHorizontalStrut(0));
479 |
480 | int height = Math.max(keyTextField.getPreferredSize().height, keyEncodeComboBox.getPreferredSize().height);
481 | keyTextField.setPreferredSize(new Dimension(keyTextField.getPreferredSize().width, height));
482 | keyEncodeComboBox.setPreferredSize(new Dimension(keyEncodeComboBox.getPreferredSize().width, height));
483 |
484 | // IV组
485 | JPanel IVPanel = new JPanel();
486 | IVPanel.setLayout(new BoxLayout(IVPanel, BoxLayout.LINE_AXIS));
487 |
488 | JLabel IVLabel;
489 | if ("RSA".equalsIgnoreCase(cipherName) || "SM2".equalsIgnoreCase(cipherName))
490 | IVLabel = new JLabel("公钥");
491 | else
492 | IVLabel = new JLabel("IV");
493 | JTextField IVTextField = new JTextField(15);
494 | JComboBox IVEncodeComboBox = new JComboBox<>(allCryptoConfig.titles4encode);
495 |
496 | IVPanel.add(IVLabel);
497 | IVPanel.add(Box.createHorizontalStrut(0));
498 | IVPanel.add(IVTextField);
499 | IVPanel.add(Box.createHorizontalStrut(0));
500 | IVPanel.add(IVEncodeComboBox);
501 | IVPanel.add(Box.createHorizontalStrut(0));
502 |
503 | IVTextField.setPreferredSize(new Dimension(IVTextField.getPreferredSize().width, height));
504 | IVEncodeComboBox.setPreferredSize(new Dimension(IVEncodeComboBox.getPreferredSize().width, height));
505 |
506 | // 算法选择
507 | JPanel algorithmPanel = new JPanel();
508 | JLabel algorithmLabel = new JLabel("加密方式");
509 | JComboBox algorithmComboBox = new JComboBox<>(allCryptoConfig.cryptoMap.get(cipherName));
510 | algorithmComboBox.setEditable(true);
511 | algorithmPanel.add(algorithmLabel);
512 | algorithmPanel.add(algorithmComboBox);
513 |
514 | // 输入格式
515 | JPanel inputEncodePanel = new JPanel();
516 | JLabel inputEncodeLabel = new JLabel("输入格式");
517 | JComboBox inputEncodeComboBox = new JComboBox<>(allCryptoConfig.titles4encode);
518 | inputEncodePanel.add(inputEncodeLabel);
519 | inputEncodePanel.add(inputEncodeComboBox);
520 |
521 | // 输出格式
522 | JPanel outputEncodePanel = new JPanel();
523 | JLabel outputEncodeLabel = new JLabel("输出格式");
524 | JComboBox outputEncodeComboBox = new JComboBox<>(allCryptoConfig.titles4encode);
525 | outputEncodePanel.add(outputEncodeLabel);
526 | outputEncodePanel.add(outputEncodeComboBox);
527 |
528 | JPanel jPanel1 = new JPanel();
529 | jPanel1.setLayout(new BoxLayout(jPanel1, BoxLayout.LINE_AXIS));
530 | JPanel jPanel2 = new JPanel();
531 | jPanel2.setLayout(new BoxLayout(jPanel2, BoxLayout.LINE_AXIS));
532 |
533 | jPanel1.add(keyPanel);
534 | jPanel1.add(IVPanel);
535 |
536 | jPanel2.add(algorithmPanel);
537 | jPanel2.add(inputEncodePanel);
538 | jPanel2.add(outputEncodePanel);
539 |
540 | jPanel.add(jPanel1);
541 | jPanel.add(jPanel2);
542 |
543 | return baseCard(title, jPanel, activeCryptConfigUI);
544 | }
545 |
546 | private static JButton getButton(String text) {
547 | JButton jButton = new JButton(text);
548 | jButton.setContentAreaFilled(false);
549 | jButton.setBorderPainted(false);
550 | jButton.setMargin(new Insets(0, 2, 0, 2));
551 | jButton.setFont(new Font("Arial", Font.BOLD, 13));
552 |
553 | return jButton;
554 | }
555 | }
556 |
557 | }
558 |
--------------------------------------------------------------------------------
/src/main/ui/AutoCryptConfigUI.java:
--------------------------------------------------------------------------------
1 | package ui;
2 |
3 | import config.autoCryptConfig;
4 | import lib.CryptoChains;
5 |
6 | import javax.swing.*;
7 | import javax.swing.border.MatteBorder;
8 | import javax.swing.border.TitledBorder;
9 | import java.awt.*;
10 | import java.awt.event.FocusAdapter;
11 | import java.awt.event.FocusEvent;
12 | import java.awt.event.MouseAdapter;
13 | import java.awt.event.MouseEvent;
14 | import java.util.Enumeration;
15 |
16 | /**
17 | * ITab的第一个页面,获取用户输入的配置信息
18 | * 加解密在这里做个中转,方便获取到的配置的传递
19 | */
20 | public class AutoCryptConfigUI extends JPanel {
21 | public static GetContentPanel requestPanel;
22 | public static GetContentPanel responsePanel;
23 | JTextField hostTextField;
24 | static boolean REQUEST = true;
25 | static boolean RESPONSE = false;
26 |
27 | public AutoCryptConfigUI() {
28 | init();
29 | }
30 |
31 | private void init() {
32 | setLayout(new BorderLayout());
33 |
34 | JLabel hostLabel = new JLabel("host匹配(正则): ");
35 | hostTextField = new JTextField(30);
36 |
37 | JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
38 | topPanel.add(hostLabel);
39 | topPanel.add(hostTextField);
40 |
41 | JButton saveButton = new JButton("save");
42 | JPanel bottomPanel = new JPanel();
43 | bottomPanel.add(saveButton);
44 |
45 | JPanel centerPanel = new JPanel();
46 | centerPanel.setLayout(new GridLayout(1, 2));
47 |
48 | requestPanel = new GetContentPanel(REQUEST);
49 | responsePanel = new GetContentPanel(RESPONSE);
50 |
51 | // 点击保存按钮,保存数据
52 | saveButton.addMouseListener(new MouseAdapter() {
53 | @Override
54 | public void mouseClicked(MouseEvent e) {
55 | save();
56 | JOptionPane.showMessageDialog(null, "保存成功", "提示", JOptionPane.INFORMATION_MESSAGE);
57 | }
58 | });
59 |
60 | centerPanel.add(requestPanel);
61 | centerPanel.add(responsePanel);
62 |
63 | add(topPanel, BorderLayout.NORTH);
64 | add(centerPanel, BorderLayout.CENTER);
65 | add(bottomPanel, BorderLayout.SOUTH);
66 | }
67 |
68 | private void save() {
69 | autoCryptConfig.hostReg = hostTextField.getText();
70 | autoCryptConfig.requestCryptoReg = getJComboBoxSelected(requestPanel.cryptRegComboBox);
71 | autoCryptConfig.responseCryptoReg = getJComboBoxSelected(responsePanel.cryptRegComboBox);
72 | autoCryptConfig.requestCryptoLocation = getButtonGroupSelected(requestPanel.locationButtonGroup);
73 | autoCryptConfig.responseCryptoLocation = getButtonGroupSelected(responsePanel.locationButtonGroup);
74 |
75 | autoCryptConfig.requestEncryptChain = CryptoChains.cryptoChainLinkedHashMap.get(getJComboBoxSelected(requestPanel.encryptoComboBox));
76 | autoCryptConfig.requestDecryptChain = CryptoChains.cryptoChainLinkedHashMap.get(getJComboBoxSelected(requestPanel.decryptoComboBox));
77 | autoCryptConfig.responseEncryptChain = CryptoChains.cryptoChainLinkedHashMap.get(getJComboBoxSelected(responsePanel.encryptoComboBox));
78 | autoCryptConfig.responseDecryptChain = CryptoChains.cryptoChainLinkedHashMap.get(getJComboBoxSelected(responsePanel.decryptoComboBox));
79 | }
80 |
81 | private String getJComboBoxSelected(JComboBox jComboBox) {
82 | return jComboBox.getSelectedItem().toString();
83 | }
84 |
85 | private String getButtonGroupSelected(ButtonGroup buttonGroup) {
86 | Enumeration elements = buttonGroup.getElements();
87 | while (elements.hasMoreElements()) {
88 | AbstractButton button = elements.nextElement();
89 | if (button.isSelected())
90 | return button.getText();
91 | }
92 | return "";
93 | }
94 |
95 | public class GetContentPanel extends JPanel {
96 | boolean isRequest;
97 | JComboBox encryptoComboBox;
98 | JComboBox decryptoComboBox;
99 | JComboBox cryptRegComboBox;
100 | ButtonGroup locationButtonGroup;
101 |
102 | public GetContentPanel(boolean isRequest) {
103 | this.isRequest = isRequest;
104 | init();
105 | }
106 |
107 | private void init() {
108 | setLayout(new GridLayout(10, 1, 20, 1));
109 |
110 | // 第一行,加密链选择
111 | JPanel jPanel1 = new JPanel();
112 | JLabel encryptoLabel = new JLabel("加密链: ");
113 | encryptoComboBox = getCryptoComboBox();
114 | encryptoComboBox.setPreferredSize(new Dimension(300, encryptoComboBox.getPreferredSize().height));
115 | jPanel1.add(encryptoLabel);
116 | jPanel1.add(encryptoComboBox);
117 |
118 | // 第二行,解密链选择
119 | JPanel jPanel2 = new JPanel();
120 | JLabel decryptoLabel = new JLabel("解密链: ");
121 | decryptoComboBox = getCryptoComboBox();
122 | decryptoComboBox.setPreferredSize(new Dimension(300, decryptoComboBox.getPreferredSize().height));
123 | jPanel2.add(decryptoLabel);
124 | jPanel2.add(decryptoComboBox);
125 |
126 | // 第三行,密文位置
127 | JPanel jPanel3 = new JPanel();
128 | JLabel cryptLocationLabel = new JLabel("密文位置: ");
129 | jPanel3.add(cryptLocationLabel);
130 |
131 |
132 | JRadioButton urlRadio = new JRadioButton("url");
133 | JRadioButton headerRadio = new JRadioButton("header");
134 | JRadioButton bodyRadio = new JRadioButton("body");
135 |
136 | toSilky(new JRadioButton[]{urlRadio, headerRadio, bodyRadio});
137 |
138 | locationButtonGroup = new ButtonGroup();
139 | if (isRequest) {
140 | locationButtonGroup.add(urlRadio);
141 | jPanel3.add(urlRadio);
142 | }
143 | jPanel3.add(headerRadio);
144 | jPanel3.add(bodyRadio);
145 | locationButtonGroup.add(headerRadio);
146 | locationButtonGroup.add(bodyRadio);
147 | bodyRadio.setSelected(true);
148 |
149 | // 第四行,密文正则
150 | JPanel jPanel4 = new JPanel();
151 | JLabel cryptLabel = new JLabel("密文匹配(正则): ");
152 |
153 | cryptRegComboBox = new JComboBox<>();
154 | cryptRegComboBox.setEditable(true);
155 | cryptRegComboBox.setPreferredSize(new Dimension(300, cryptRegComboBox.getPreferredSize().height));
156 |
157 | cryptRegComboBox.addItem(":.?\"([^,}]*)\"");
158 | cryptRegComboBox.addItem("=([^&]*)");
159 | cryptRegComboBox.setRenderer(new DefaultListCellRenderer() {
160 | @Override
161 | public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
162 | super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
163 | if (value != null)
164 | if (":.?\"([^,}]*)\"".equals(value))
165 | setToolTipText("匹配json格式的所有值");
166 | else if ("=([^&]*)".equals(value))
167 | setToolTipText("匹配url传参的所有值");
168 | else
169 | setToolTipText("");
170 | return this;
171 | }
172 | });
173 |
174 | jPanel4.add(cryptLabel);
175 | jPanel4.add(cryptRegComboBox);
176 |
177 | // 让panel1不顶格
178 | // 添加不上 Bounds,就加一个20像素的透明边框吧
179 | jPanel1.setBorder(BorderFactory.createMatteBorder(20, 0, 1, 0, new Color(0, 0, 0, 0)));
180 |
181 | if (isRequest) {
182 | MatteBorder border = BorderFactory.createMatteBorder(1, 0, 0, 1, new Color(64, 64, 64, 64));
183 | setBorder(new TitledBorder(border, "request", TitledBorder.CENTER, TitledBorder.TOP, new Font(null, Font.PLAIN, 18)));
184 | } else {
185 | MatteBorder border = BorderFactory.createMatteBorder(1, 0, 0, 0, new Color(64, 64, 64, 64));
186 | setBorder(new TitledBorder(border, "response", TitledBorder.CENTER, TitledBorder.TOP, new Font(null, Font.PLAIN, 18)));
187 | }
188 |
189 | add(jPanel1);
190 | add(jPanel2);
191 | add(jPanel3);
192 | add(jPanel4);
193 | }
194 |
195 | private JComboBox getCryptoComboBox() {
196 | JComboBox jComboBox = new JComboBox<>();
197 | jComboBox.addItem("暂无选择, 请添加");
198 |
199 | return jComboBox;
200 | }
201 |
202 | /**
203 | * 让JRadioButton失去焦点,使体验更丝滑
204 | */
205 | private void toSilky(JRadioButton[] radioArray) {
206 | for (JRadioButton radio : radioArray) {
207 | radio.addFocusListener(new FocusAdapter() {
208 | @Override
209 | public void focusGained(FocusEvent e) {
210 | radio.setFocusable(false);
211 | }
212 | });
213 | }
214 | }
215 |
216 | /**
217 | * 更新加解密链的JComboBox
218 | * @param items JComboBox展示的内容
219 | */
220 | public void refreshCryptoComboBox(String[] items){
221 | String encryptoSelected = (String) encryptoComboBox.getSelectedItem();
222 | String decryptoSelected = (String) decryptoComboBox.getSelectedItem();
223 |
224 | encryptoComboBox.removeAllItems();
225 | decryptoComboBox.removeAllItems();
226 |
227 | if (items.length > 0) {
228 | encryptoComboBox.addItem("---请下拉选择---");
229 | decryptoComboBox.addItem("---请下拉选择---");
230 |
231 | for (String item : items) {
232 | encryptoComboBox.addItem(item);
233 | decryptoComboBox.addItem(item);
234 |
235 | if (item.equals(encryptoSelected)) {
236 | encryptoComboBox.setSelectedItem(item);
237 | }
238 | if (item.equals(decryptoSelected)) {
239 | decryptoComboBox.setSelectedItem(item);
240 | }
241 | }
242 | }else {
243 | encryptoComboBox.addItem("暂无选择, 请添加");
244 | decryptoComboBox.addItem("暂无选择, 请添加");
245 | }
246 | }
247 | }
248 |
249 | }
250 |
--------------------------------------------------------------------------------
/src/main/ui/GUI.java:
--------------------------------------------------------------------------------
1 | package ui;
2 |
3 | import javax.swing.*;
4 | import java.awt.*;
5 | import java.awt.event.*;
6 |
7 | public class GUI extends JFrame {
8 | JTabbedPane tabbedPane;
9 | int newIndex = 0;
10 | public AutoCryptConfigUI autoCryptConfigUI;
11 |
12 | public GUI() {
13 | init();
14 |
15 | setContentPane(tabbedPane);
16 | pack();
17 | }
18 |
19 | /**
20 | * 初始化整个配置页面(ITab)的基本框架
21 | */
22 | public void init() {
23 | tabbedPane = new JTabbedPane(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
24 |
25 | autoCryptConfigUI = new AutoCryptConfigUI();
26 | tabbedPane.addTab("自动解密配置", autoCryptConfigUI);
27 | tabbedPane.add("+", null);
28 |
29 | /*
30 | 鼠标事件,点击+添加新标签、双击改名等
31 | */
32 | tabbedPane.addMouseListener(new MouseAdapter() {
33 | @Override
34 | public void mousePressed(MouseEvent e) {
35 | if (e.getSource() instanceof JTabbedPane) {
36 | int tabCount = tabbedPane.getTabCount();
37 | int selectedIndex = tabbedPane.getSelectedIndex();
38 |
39 | // 如果选中的是最后的选项(即+),则添加新tab
40 | if (selectedIndex == tabCount - 1) {
41 | addNewTable(tabCount);
42 | }
43 | // 双击鼠标,改名
44 | else if (e.getClickCount() == 2 && selectedIndex != 0) {
45 | JTabbedPane pane = (JTabbedPane) e.getSource();
46 | int doubleClickIndex = pane.getSelectedIndex();
47 | NewComponent doubleClickComponent = (NewComponent) tabbedPane.getTabComponentAt(doubleClickIndex);
48 |
49 | JLabel titleLabel = doubleClickComponent.titleLabel;
50 | JTextField titleTextField = doubleClickComponent.titleTextField;
51 |
52 | titleLabel.setVisible(false);
53 | titleTextField.setVisible(true);
54 |
55 | titleTextField.setText(titleLabel.getText());
56 | titleTextField.requestFocusInWindow();
57 | titleTextField.setCaretPosition(titleTextField.getText().length());
58 | } else {
59 | ((JTabbedPane) e.getSource()).requestFocusInWindow();
60 | }
61 | }
62 | }
63 |
64 | @Override
65 | // 鼠标拖动,准备实现个拖动改变标签位置的功能
66 | public void mouseDragged(MouseEvent e) {
67 | super.mouseDragged(e);
68 | }
69 | });
70 | }
71 |
72 | /**
73 | * 添加新tab,配置多个右击菜单
74 | * @param count 计数器,表示新增tab的个数
75 | */
76 | public void addNewTable(int count) {
77 | newIndex += 1;
78 | String title = "加解密链配置" + newIndex;
79 |
80 | tabbedPane.insertTab(title, null, new ActiveCryptConfigUI(), null, count - 1);
81 |
82 | NewComponent newComponent = new NewComponent(title);
83 |
84 | tabbedPane.setTabComponentAt(count - 1, newComponent);
85 | tabbedPane.setSelectedIndex(count - 1);
86 | }
87 |
88 | /**
89 | * 用于新建Tab,在顶部菜单栏展示的Component
90 | */
91 | private class NewComponent extends JPanel {
92 | String title;
93 | JButton closeButton;
94 | JLabel titleLabel;
95 | JTextField titleTextField;
96 |
97 | public NewComponent(String title) {
98 | this.title = title;
99 | init();
100 | }
101 |
102 | private void init() {
103 | closeButton = new JButton();
104 | closeButton.setText("×");
105 | closeButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
106 | closeButton.setBorderPainted(false);
107 | closeButton.setContentAreaFilled(false);
108 | closeButton.setFocusable(false);
109 |
110 | closeButton.addMouseListener(new MouseAdapter() {
111 | @Override
112 | public void mouseEntered(MouseEvent e) {
113 | closeButton.setForeground(Color.red);
114 | }
115 |
116 | @Override
117 | public void mouseExited(MouseEvent e) {
118 | closeButton.setForeground(Color.black);
119 | }
120 | });
121 |
122 | closeButton.addActionListener(e -> {
123 | JButton button = (JButton) e.getSource();
124 | NewComponent component = (NewComponent) SwingUtilities.getAncestorOfClass(NewComponent.class, button);
125 |
126 | int index = tabbedPane.indexOfTabComponent(component);
127 | if (index == tabbedPane.getTabCount() - 2) {
128 | tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 3);
129 | }
130 |
131 | tabbedPane.remove(index);
132 | });
133 |
134 | titleLabel = new JLabel(title);
135 | titleTextField = new JTextField();
136 |
137 | titleTextField.setBackground(new Color(0, 0, 0, 0));
138 | titleTextField.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
139 | titleTextField.setOpaque(false);
140 |
141 | titleTextField.addFocusListener(new FocusAdapter() {
142 | @Override
143 | public void focusLost(FocusEvent e) {
144 | saveTitle();
145 | }
146 | });
147 | titleTextField.addKeyListener(new KeyAdapter() {
148 | @Override
149 | public void keyPressed(KeyEvent e) {
150 | if (e.getKeyCode() == KeyEvent.VK_ENTER)
151 | saveTitle();
152 | }
153 | });
154 |
155 | add(titleLabel);
156 | add(titleTextField);
157 | add(closeButton);
158 | }
159 |
160 | public String getTitle() {
161 | return title;
162 | }
163 |
164 | public void saveTitle() {
165 | titleLabel.setText(titleTextField.getText());
166 |
167 | titleLabel.setVisible(true);
168 | titleTextField.setVisible(false);
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/main/ui/MessageEditorUI.java:
--------------------------------------------------------------------------------
1 | package ui;
2 |
3 | import burp.IHttpService;
4 | import burp.IMessageEditorController;
5 |
6 | import javax.swing.*;
7 | import java.awt.*;
8 |
9 |
10 | public class MessageEditorUI extends JPanel implements IMessageEditorController {
11 | IHttpService iHttpService;
12 | public MessageEditorUI(IHttpService _iHttpService) {
13 | iHttpService = _iHttpService;
14 | }
15 |
16 | @Override
17 | public IHttpService getHttpService() {
18 | return iHttpService;
19 | }
20 |
21 | @Override
22 | public byte[] getRequest() {
23 | return null;
24 | }
25 |
26 | @Override
27 | public byte[] getResponse() {
28 | return null;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------