├── .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 | ![image-20230725015707104](./assets/image-20230725015707104.png) 36 | 37 | 使用中可能会遇到各种各样的问题,可以在Extensions下查看报错信息 38 | 39 | ![image-20230725022525882](./assets/image-20230725022525882.png) 40 | 41 | ## 自动加解密配置 42 | 43 | 这里做了更改,配置页面不再直接选择算法配置密钥,改为了先添加算法链,然后再下拉列表中选择,对数据处理上更加灵活。 44 | 45 | ![image-20230725020323094](./assets/image-20230725020323094.png) 46 | 47 | ![image-20230725020505812](./assets/image-20230725020505812.png) 48 | 49 | 匹配密文的方式依旧没变,还是通过正则,需要替换的内容使用小括号括起来,内置两个规则,分别匹配所有json参数值和url参数值,鼠标悬停会出现提示。 50 | 51 | ![image-20230725020944991](./assets/image-20230725020944991.png) 52 | 53 | ## 加解密链配置 54 | 55 | 在左侧选择需要的算法,点击+号添加到右边,在右边进行一些参数配置,后面的上下按钮可以改变执行顺序。添加按钮合并为了一个,点击”添加到加解密链“,同时添加到右击菜单、爆破模块和自动解密配置选项中。 56 | 57 | ![image-20230725021057526](./assets/image-20230725021057526.png) 58 | 59 | 在任意数据包位置可以查看到添加的右击菜单 60 | 61 | ![image-20230725021456284](./assets/image-20230725021456284.png) 62 | 63 | 在Intruder模块的payload processing中选择Invoke Burp extension,可以查看到添加的processor 64 | 65 | ![image-20230725021644567](./assets/image-20230725021644567.png) 66 | 67 | # 演示 68 | 69 | ## 重放 70 | 71 | 抓取数据包,请求和响应中的数据都已加密,并且请求和响应的密文有区别 72 | 73 | ![image-20230725023521961](./assets/image-20230725023521961.png) 74 | 75 | 通过分析js文件获取加密算法,和密钥信息,在配置页面进行配置 76 | 77 | 添加数据包加密的配置,暂时没办法将响应包还原为中间带换行的格式,还好客户端支持不带换行,所以请求包和响应包使用同一个加密配置即可 78 | 79 | ![image-20230725024907874](./assets/image-20230725024907874.png) 80 | 81 | 添加请求包解密配置 82 | 83 | ![image-20230725024938223](./assets/image-20230725024938223.png) 84 | 85 | 添加响应包解密配置,先将\n替换为空,再进行解密。 86 | 87 | ![image-20230725025008113](./assets/image-20230725025008113.png) 88 | 89 | 在自动解密配置中选择对应的加解密链,和配置对应的密文,点击save按钮,弹出提示即可。 90 | 91 | ![image-20230725025220142](./assets/image-20230725025220142.png) 92 | 93 | 回到重放模块,点击Crypto tools标签即可查看明文,并且可以直接对明文进行修改。 94 | 95 | ![image-20230725025125794](./assets/image-20230725025125794.png) 96 | 97 | ## 爆破 98 | 99 | 如果需要对上述数据包的passwd进行爆破,可以如下操作 100 | 101 | 1、将刚刚的数据包发送到Intruder,删除所有加密数据,添加 § 符号。 102 | 103 | ![image-20230725025954768](./assets/image-20230725025954768.png) 104 | 105 | 2、将不需要爆破的内容提取出来,添加prefix和suffix,再加插件生成的processor。 106 | 107 | ![image-20230725030215013](./assets/image-20230725030215013.png) 108 | 109 | 查看爆破的payload 110 | 111 | ![image-20230725030530263](./assets/image-20230725030530263.png) 112 | 113 | 同时可以在Extensions页面查看payload的变化过程。 114 | 115 | ![image-20230725030658414](./assets/image-20230725030658414.png) 116 | 117 | # 关于获取加密算法及参数 118 | 119 | 第一种方式:直接在源码中搜索参数名、"encrypt"、”AES"、"SM4"等关键字。 120 | 121 | 第二种方式(比较通用):在浏览器开发者工具->源代码,左边打下XHR断点,然后通过调用堆栈找到内容没加密之前的位置(过程中可以重复在堆栈下面的函数打断点,然后重新发送请求),再单步调试,这样比较容易找到加密方法 122 | 123 | ![image-20230618203042865](./assets/image-20230618203042865.png) 124 | 125 | # 关于加密的几种情况 126 | 127 | 1. 直接使用固定密钥的对称密码(直接找到密钥就行) 128 | 2. 客户端生成动态对称密码的密钥,通过公钥加密传输到服务端 129 | 130 | 这种情况一般将密钥固定即可,方式有事件断点、burp替换、本地文件替换(可能不太好使)等方式。 131 | 132 | 事件断点,右击断点选择最后一个。 133 | 134 | ![image-20230618203856329](./assets/image-20230618203856329.png) 135 | 136 | burp自动替换 137 | 138 | ![image-20230618204038455](./assets/image-20230618204038455.png) 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, "&#x", ";", 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 | --------------------------------------------------------------------------------