├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── settings.gradle └── src └── main └── java └── burp ├── BurpExtender.java ├── Config.java ├── action ├── DoAction.java ├── ExtractContent.java ├── GetColorKey.java ├── MatchHTTP.java ├── ProcessMessage.java └── UpgradeColor.java ├── ui ├── Databoard.java ├── JTabbedPaneCloseButton.java ├── MainUI.java ├── RulePane.java └── RuleSetting.java └── yaml ├── LoadConfig.java ├── RulesConfig.java ├── SetConfig.java └── template ├── Rule.java └── Rules.java /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/**/workspace.xml 3 | .idea/**/tasks.xml 4 | .idea/**/usage.statistics.xml 5 | .idea/**/dictionaries 6 | .idea/**/shelf 7 | 8 | # AWS User-specific 9 | .idea/**/aws.xml 10 | 11 | # Generated files 12 | .idea/**/contentModel.xml 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | .idea/**/dbnavigator.xml 22 | 23 | # Gradle 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # Gradle and Maven with auto-import 28 | # When using Gradle or Maven with auto-import, you should exclude module files, 29 | # since they will be recreated, and may cause churn. Uncomment if using 30 | # auto-import. 31 | # .idea/artifacts 32 | # .idea/compiler.xml 33 | # .idea/jarRepositories.xml 34 | # .idea/modules.xml 35 | # .idea/*.iml 36 | # .idea/modules 37 | # *.iml 38 | # *.ipr 39 | 40 | # CMake 41 | cmake-build-*/ 42 | 43 | # Mongo Explorer plugin 44 | .idea/**/mongoSettings.xml 45 | 46 | # File-based project format 47 | *.iws 48 | 49 | # IntelliJ 50 | out/ 51 | 52 | # mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Cursive Clojure plugin 59 | .idea/replstate.xml 60 | 61 | # SonarLint plugin 62 | .idea/sonarlint/ 63 | 64 | # Crashlytics plugin (for Android Studio and IntelliJ) 65 | com_crashlytics_export_strings.xml 66 | crashlytics.properties 67 | crashlytics-build.properties 68 | fabric.properties 69 | 70 | # Editor-based Rest Client 71 | .idea/httpRequests 72 | 73 | # Android studio 3.1+ serialized cache file 74 | .idea/caches/build_file_checksums.ser 75 | 76 | ### JetBrains+all Patch ### 77 | # Ignore everything but code style settings and run configurations 78 | # that are supposed to be shared within teams. 79 | 80 | .idea/* 81 | 82 | !.idea/codeStyles 83 | !.idea/runConfigurations 84 | 85 | ### macOS ### 86 | # General 87 | .DS_Store 88 | .AppleDouble 89 | .LSOverride 90 | 91 | # Icon must end with two \r 92 | Icon 93 | 94 | 95 | # Thumbnails 96 | ._* 97 | 98 | # Files that might appear in the root of a volume 99 | .DocumentRevisions-V100 100 | .fseventsd 101 | .Spotlight-V100 102 | .TemporaryItems 103 | .Trashes 104 | .VolumeIcon.icns 105 | .com.apple.timemachine.donotpresent 106 | 107 | # Directories potentially created on remote AFP share 108 | .AppleDB 109 | .AppleDesktop 110 | Network Trash Folder 111 | Temporary Items 112 | .apdisk 113 | 114 | ### Gradle ### 115 | .gradle 116 | **/build/ 117 | !src/**/build/ 118 | 119 | # Ignore Gradle GUI config 120 | gradle-app.setting 121 | 122 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 123 | !gradle-wrapper.jar 124 | 125 | # Avoid ignore Gradle wrappper properties 126 | !gradle-wrapper.properties 127 | 128 | # Cache of project 129 | .gradletasknamecache 130 | 131 | # Eclipse Gradle plugin generated files 132 | # Eclipse Core 133 | .project 134 | # JDT-specific (Eclipse Java Development Tools) 135 | .classpath 136 | 137 | # End of https://www.toptal.com/developers/gitignore/api/macos,gradle,jetbrains+all -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Highlight and Extractor

Burp Extension

2 | 3 | ## About 4 | 5 | This an altered version of the great **HaE Burp Extension** based on version 2.4.6. 6 | 7 | Thanks to EvilChen and 0chencc for the original version https://github.com/gh0stkey/HaE 8 | 9 | The Portswigger version can be found on https://github.com/portswigger/highlighter-and-extractor 10 | 11 | ## What's Different 12 | 13 | This is a great Burp extensions, but there were a few things I wanted to change, so I forked the original. Here's what's different: 14 | 15 | - Add `none` option for highlight 16 | - Default a new rule to `none` 17 | - Show comments split with `|` instead of `,` to make it easier to read 18 | - Only search and highlight `In Scope` requests and responses 19 | - Add more file extension exclusions 20 | - Add a config option for **Hghlight Method**. The original does colour upscaling, which means that if a number of matches are found for one request/response, the colour can end up being upscaled and shown as colour of increased severity. I personally preferred to have a highlight of the most severe finding only (this allows a request/response not to be highlighted at all, even if there ar 5 `none` rules fired). 21 | 22 | ## Excuses 23 | 24 | I'm not a Java programmer and I don't understand creating a proper UI, so the new Highlight Method option on the config tab is not aligned properly... but who cares?! 25 | 26 | ## Notes 27 | 28 | - If you want to use regex with special characters like `\n`, `\s`, etc. then you need to use engine `nfa` 29 | - Case sensitive only works for engine `nfa`, therefore if you use `dfa` you need to make sure you deal with different cases. 30 | - Apparently `dfa` is faster than `nfa` 31 | - You can search `Databoard` with `*.` (I;m not sure this change was in the Portswigger version). 32 | - You need to wrap the regex of rules in `()` to work correctly. 33 | - Apparently `dfa` is faster than `nfa` 34 | - Disable any rules that you don't need or want as they can slow thing down. 35 | 36 | Feel free to use this version too! 37 | 38 | Good luck and good hunting! 39 | If you really love the tool (or any others), or they helped you find an awesome bounty, consider [BUYING ME A COFFEE!](https://ko-fi.com/xnlh4ck3r) ☕ (I could use the caffeine!) 40 | 41 | 🤘 /XNL-h4ck3r 42 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | repositories { 6 | mavenCentral() 7 | } 8 | 9 | compileJava { 10 | options.encoding = "UTF-8" 11 | } 12 | 13 | sourceSets { 14 | main { 15 | java { 16 | srcDir './src/main/java' 17 | } 18 | } 19 | } 20 | 21 | task fatJar(type: Jar) { 22 | baseName = project.name + '-all' 23 | from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } 24 | with jar 25 | } 26 | 27 | dependencies { 28 | compile 'net.portswigger.burp.extender:burp-extender-api:1.7.13' 29 | compile 'org.jetbrains:annotations:16.0.2' 30 | compile group: 'org.yaml', name: 'snakeyaml', version: '1.28' 31 | compile 'net.sourceforge.jregex:jregex:1.2_01' 32 | compile 'dk.brics.automaton:automaton:1.11-8' 33 | compile 'com.squareup.okhttp:okhttp:2.7.5' 34 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'H&E' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/burp/BurpExtender.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | import burp.action.*; 4 | import burp.ui.MainUI; 5 | 6 | import java.util.Map; 7 | import java.util.Objects; 8 | import javax.swing.*; 9 | import java.awt.*; 10 | import java.nio.charset.StandardCharsets; 11 | import java.io.PrintWriter; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import javax.swing.event.ChangeEvent; 15 | import javax.swing.event.ChangeListener; 16 | 17 | /** 18 | * @author EvilChen & 0chencc 19 | */ 20 | 21 | public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEditorTabFactory, ITab { 22 | private final MainUI main = new MainUI(); 23 | // Make stdout a public property. It is convenient for other class calls to 24 | // output debugging information 25 | public static PrintWriter stdout; 26 | private IBurpExtenderCallbacks callbacks; 27 | private static IExtensionHelpers helpers; 28 | GetColorKey gck = new GetColorKey(); 29 | UpgradeColor uc = new UpgradeColor(); 30 | ProcessMessage pm = new ProcessMessage(); 31 | 32 | @Override 33 | public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) { 34 | this.callbacks = callbacks; 35 | BurpExtender.helpers = callbacks.getHelpers(); 36 | 37 | String version = "2.4.6"; 38 | callbacks.setExtensionName(String.format("Highlighter and Extractor - modified version of HaE (%s)", version)); 39 | // Define output 40 | stdout = new PrintWriter(callbacks.getStdout(), true); 41 | stdout.println("Highlight And Extractor - modified by @xnl_h4ck3r"); 42 | stdout.println("Original version:"); 43 | stdout.println("@First Author: EvilChen"); 44 | stdout.println("@Second Author: 0chencc"); 45 | stdout.println("@Github: https://github.com/gh0stkey/HaE"); 46 | 47 | // UI 48 | SwingUtilities.invokeLater(this::initialize); 49 | 50 | callbacks.registerHttpListener(BurpExtender.this); 51 | callbacks.registerMessageEditorTabFactory(BurpExtender.this); 52 | } 53 | 54 | private void initialize() { 55 | callbacks.customizeUiComponent(main); 56 | callbacks.addSuiteTab(BurpExtender.this); 57 | } 58 | 59 | @Override 60 | public String getTabCaption() { 61 | return "H&E"; 62 | } 63 | 64 | @Override 65 | public Component getUiComponent() { 66 | return main; 67 | } 68 | 69 | /** 70 | * Use processHttpMessage to do Highlighter 71 | */ 72 | @Override 73 | public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) { 74 | // Only process if the request is in scope 75 | IRequestInfo reqinfo = BurpExtender.helpers.analyzeRequest(messageInfo.getHttpService(), 76 | messageInfo.getRequest()); 77 | String requestUrl = reqinfo.getUrl().toString(); 78 | 79 | // Determine whether it is a response,and the code is scoped 80 | // to:REPEATER、INTRUDER、PROXY (Respectively: toolFlag 64, 32, 4) 81 | if (callbacks.isInScope(reqinfo.getUrl()) && (toolFlag == 64 || toolFlag == 32 || toolFlag == 4)) { 82 | byte[] content; 83 | if (messageIsRequest) { 84 | content = messageInfo.getRequest(); 85 | } else { 86 | content = messageInfo.getResponse(); 87 | } 88 | 89 | IHttpService iHttpService = null; 90 | try { 91 | iHttpService = messageInfo.getHttpService(); 92 | } catch (Exception ignored) { 93 | } 94 | // Get request host information 95 | assert iHttpService != null; 96 | String host = iHttpService.getHost(); 97 | 98 | String c = new String(content, StandardCharsets.UTF_8).intern(); 99 | List> result = pm.processMessageByContent(helpers, content, messageIsRequest, true, 100 | host); 101 | if (result != null && !result.isEmpty() && result.size() > 0) { 102 | String originalColor = messageInfo.getHighlight(); 103 | String originalComment = messageInfo.getComment(); 104 | List colorList = new ArrayList<>(); 105 | 106 | if (originalColor != null) { 107 | colorList.add(originalColor); 108 | } 109 | 110 | colorList.add(result.get(0).get("color")); 111 | String color = uc.getEndColor(gck.getColorKeys(colorList)); 112 | messageInfo.setHighlight(color); 113 | 114 | String addComment = String.join(" | ", result.get(1).get("comment")); 115 | String resComment = !Objects.equals(originalComment, "") 116 | ? String.format("%s | %s", originalComment, addComment) 117 | : addComment; 118 | 119 | messageInfo.setComment(resComment); 120 | } 121 | } 122 | } 123 | 124 | class MarkInfoTab implements IMessageEditorTab { 125 | private final JTabbedPane jTabbedPane = new JTabbedPane(); 126 | private JTable jTable = new JTable(); 127 | private final IMessageEditorController controller; 128 | private Map extractRequestMap; 129 | private Map extractResponseMap; 130 | private ArrayList titleList = new ArrayList<>(); 131 | 132 | public MarkInfoTab(IMessageEditorController controller, boolean editable) { 133 | this.controller = controller; 134 | } 135 | 136 | @Override 137 | public String getTabCaption() { 138 | return "MarkInfo"; 139 | } 140 | 141 | @Override 142 | public Component getUiComponent() { 143 | jTabbedPane.addChangeListener(new ChangeListener() { 144 | @Override 145 | public void stateChanged(ChangeEvent arg0) { 146 | jTable = (JTable) ((JScrollPane) jTabbedPane.getSelectedComponent()).getViewport().getView(); 147 | } 148 | }); 149 | return this.jTabbedPane; 150 | } 151 | 152 | @Override 153 | public boolean isEnabled(byte[] content, boolean isRequest) { 154 | String c = new String(content, StandardCharsets.UTF_8).intern(); 155 | List> result = pm.processMessageByContent(helpers, content, isRequest, false, ""); 156 | 157 | if (result != null && !result.isEmpty()) { 158 | Map dataMap = result.get(0); 159 | if (isRequest) { 160 | extractRequestMap = dataMap; 161 | } else { 162 | extractResponseMap = dataMap; 163 | } 164 | return true; 165 | } 166 | return false; 167 | } 168 | 169 | @Override 170 | public byte[] getMessage() { 171 | return null; 172 | } 173 | 174 | @Override 175 | public boolean isModified() { 176 | return false; 177 | } 178 | 179 | /** 180 | * Shortcut key copy function 181 | */ 182 | @Override 183 | public byte[] getSelectedData() { 184 | int[] selectRows = jTable.getSelectedRows(); 185 | StringBuilder selectData = new StringBuilder(); 186 | for (int row : selectRows) { 187 | selectData.append(jTable.getValueAt(row, 0).toString()).append("\n"); 188 | } 189 | // For easy one-line copying, strip the last newline 190 | String revData = selectData.reverse().toString().replaceFirst("\n", ""); 191 | StringBuilder retData = new StringBuilder(revData).reverse(); 192 | return helpers.stringToBytes(retData.toString()); 193 | } 194 | 195 | /** 196 | * Use setMessage used to do Extractor 197 | */ 198 | @Override 199 | public void setMessage(byte[] content, boolean isRequest) { 200 | String c = new String(content, StandardCharsets.UTF_8).intern(); 201 | if (content.length > 0) { 202 | if (isRequest) { 203 | makeTable(extractRequestMap); 204 | } else { 205 | makeTable(extractResponseMap); 206 | } 207 | } 208 | } 209 | 210 | /** 211 | * Create MarkInfo form 212 | */ 213 | public void makeTable(Map dataMap) { 214 | ArrayList lTitleList = new ArrayList<>(); 215 | dataMap.keySet().forEach(i -> { 216 | String[] extractData = dataMap.get(i).split("\n"); 217 | Object[][] data = new Object[extractData.length][1]; 218 | for (int x = 0; x < extractData.length; x++) { 219 | data[x][0] = extractData[x]; 220 | // stdout.println(extractData[x]); 221 | } 222 | JScrollPane jScrollPane = new JScrollPane(new JTable(data, new Object[] { "Information" })); 223 | lTitleList.add(i); 224 | this.jTabbedPane.addTab(i, jScrollPane); 225 | }); 226 | 227 | /* 228 | * Using removeAll will cause the MarkInfo UI to appear blank. In order to 229 | * improve the user experience, the remove method is used to delete; 230 | * Use the global ArrayList to traverse and delete Tabs to deal with the wrong 231 | * display of MarkInfo UI caused by the BurpSuite caching mechanism. 232 | */ 233 | titleList.forEach(t -> { 234 | int indexOfTab = this.jTabbedPane.indexOfTab(t); 235 | if (indexOfTab != -1) { 236 | this.jTabbedPane.removeTabAt(indexOfTab); 237 | } 238 | }); 239 | 240 | titleList = lTitleList; 241 | } 242 | } 243 | 244 | @Override 245 | public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) { 246 | return new MarkInfoTab(controller, editable); 247 | } 248 | } -------------------------------------------------------------------------------- /src/main/java/burp/Config.java: -------------------------------------------------------------------------------- 1 | package burp; 2 | 3 | /** 4 | * @author EvilChen 5 | */ 6 | 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public class Config { 12 | public static String excludeSuffix = "3g2|3gp|7z|aac|abw|aif|aifc|aiff|arc|au|avi|azw|bin|bmp|bz|bz2|cmx|cod|csh|css|csv|deb|dmg|doc|docx|eot|eps|epub|flv|gif|gltf|gz|htc|ico|ics|ief|image|img|jar|jfif|jpe|jpeg|jpg|m3u|m4a|m4p|mid|midi|mjs|mov|mp2|mp3|mp4|mpa|mpe|mpeg|mpg|mpkg|mpp|mpv2|odp|ods|odt|oga|ogv|ogx|otf|pbm|pdf|pict|pgm|png|pnm|ppm|ppt|pptx|ra|ram|rar|ras|rgb|rmi|rtf|rpm|scss|snd|svg|svgz|swf|tar|tif|tiff|ttf|vsd|wav|weba|webm|webp|woff|woff2|xbm|xls|xlsx|xpm|xul|xwd|zip"; 13 | 14 | public static String[] highlightMethod = new String[] { 15 | "top color only", 16 | "color upscaling" 17 | }; 18 | 19 | public static String[] scopeArray = new String[] { 20 | "any", 21 | "any header", 22 | "any body", 23 | "response", 24 | "response header", 25 | "response body", 26 | "request", 27 | "request header", 28 | "request body" 29 | }; 30 | 31 | public static String[] engineArray = new String[] { 32 | "nfa", 33 | "dfa" 34 | }; 35 | 36 | public static String[] colorArray = new String[] { 37 | "red", 38 | "orange", 39 | "yellow", 40 | "green", 41 | "cyan", 42 | "blue", 43 | "pink", 44 | "magenta", 45 | "gray", 46 | "none" 47 | }; 48 | 49 | public static Map ruleConfig = null; 50 | 51 | public static Map>> globalDataMap = new HashMap<>(); 52 | } -------------------------------------------------------------------------------- /src/main/java/burp/action/DoAction.java: -------------------------------------------------------------------------------- 1 | package burp.action; 2 | 3 | import burp.BurpExtender; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author EvilChen 11 | */ 12 | 13 | public class DoAction { 14 | public Map extractString(Map> obj) { 15 | Map resultMap = new HashMap<>(); 16 | obj.keySet().forEach(i->{ 17 | Map tmpMap = obj.get(i); 18 | String data = tmpMap.get("data").toString(); 19 | resultMap.put(i, data); 20 | }); 21 | return resultMap; 22 | } 23 | 24 | public List> highlightAndComment(Map> obj) { 25 | List colorList = new ArrayList<>(); 26 | List commentList = new ArrayList<>(); 27 | List> result = new ArrayList<>(); 28 | obj.keySet().forEach(i->{ 29 | Map tmpMap = obj.get(i); 30 | String color = tmpMap.get("color").toString(); 31 | colorList.add(color); 32 | commentList.add(i); 33 | }); 34 | result.add(colorList); 35 | result.add(commentList); 36 | return result; 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/burp/action/ExtractContent.java: -------------------------------------------------------------------------------- 1 | package burp.action; 2 | 3 | import burp.BurpExtender; 4 | import java.nio.charset.StandardCharsets; 5 | import java.util.*; 6 | import burp.Config; 7 | import dk.brics.automaton.Automaton; 8 | import dk.brics.automaton.AutomatonMatcher; 9 | import dk.brics.automaton.RegExp; 10 | import dk.brics.automaton.RunAutomaton; 11 | import jregex.Matcher; 12 | import jregex.Pattern; 13 | 14 | /** 15 | * @author EvilChen 16 | */ 17 | 18 | public class ExtractContent { 19 | 20 | public Map> matchRegex(byte[] content, String headers, byte[] body, String scopeString, String host) { 21 | Map> map = new HashMap<>(); // The final result returned 22 | Config.ruleConfig.keySet().forEach(i -> { 23 | for (Object[] objects : Config.ruleConfig.get(i)) { 24 | // Multi-threaded execution reduces blocking to a certain extent 25 | Thread t = new Thread(() -> { 26 | String matchContent = ""; 27 | // Traversal to get the rules 28 | List result = new ArrayList<>(); 29 | Map tmpMap = new HashMap<>(); 30 | 31 | String name = objects[1].toString(); 32 | boolean loaded = (Boolean) objects[0]; 33 | String regex = objects[2].toString(); 34 | String color = objects[3].toString(); 35 | String scope = objects[4].toString(); 36 | String engine = objects[5].toString(); 37 | boolean sensitive = (Boolean) objects[6]; 38 | // Determine whether the rule is enabled and its scope 39 | if (loaded && (scope.contains(scopeString) || scope.contains("any"))) { 40 | switch (scope) { 41 | case "any": 42 | case "request": 43 | case "response": 44 | matchContent = new String(content, StandardCharsets.UTF_8).intern(); 45 | break; 46 | case "any header": 47 | case "request header": 48 | case "response header": 49 | matchContent = headers; 50 | break; 51 | case "any body": 52 | case "request body": 53 | case "response body": 54 | matchContent = new String(body, StandardCharsets.UTF_8).intern(); 55 | break; 56 | default: 57 | break; 58 | } 59 | 60 | if ("nfa".equals(engine)) { 61 | Pattern pattern; 62 | // Determine whether the rule is case-sensitive 63 | if (sensitive) { 64 | pattern = new Pattern(regex); 65 | } else { 66 | pattern = new Pattern(regex, Pattern.IGNORE_CASE); 67 | } 68 | 69 | Matcher matcher = pattern.matcher(matchContent); 70 | while (matcher.find()) { 71 | // Add matching data to list 72 | // Force users to use () wrapped regular 73 | result.add(matcher.group(1)); 74 | } 75 | } else { 76 | RegExp regexp = new RegExp(regex); 77 | Automaton auto = regexp.toAutomaton(); 78 | RunAutomaton runAuto = new RunAutomaton(auto, true); 79 | AutomatonMatcher autoMatcher = runAuto.newMatcher(matchContent); 80 | while (autoMatcher.find()) { 81 | // Add matching data to list 82 | // Force users to use () wrapped regular 83 | result.add(autoMatcher.group()); 84 | } 85 | } 86 | 87 | // De-dupe 88 | HashSet tmpList = new HashSet(result); 89 | result.clear(); 90 | result.addAll(tmpList); 91 | 92 | if (!result.isEmpty()) { 93 | tmpMap.put("color", color); 94 | String dataStr = String.join("\n", result); 95 | tmpMap.put("data", dataStr); 96 | 97 | // Added to global variables for easy Databoard retrieval 98 | if (!host.isEmpty()) { 99 | String anyHost = host.replace(host.split("\\.")[0], "*"); 100 | List dataList = Arrays.asList(dataStr.split("\n")); 101 | if (Config.globalDataMap.containsKey(host)) { 102 | Map> gRuleMap = Config.globalDataMap.get(host); 103 | // Determine whether the matching rule exists (the logic is the same as that of Host) 104 | if (gRuleMap.containsKey(name)) { 105 | List gDataList = gRuleMap.get(name); 106 | List mergeDataList = new ArrayList<>(gDataList); 107 | // Merge two lists 108 | mergeDataList.addAll(dataList); 109 | // De-dupe 110 | tmpList = new HashSet(mergeDataList); 111 | mergeDataList.clear(); 112 | mergeDataList.addAll(tmpList); 113 | // Replace 114 | gRuleMap.replace(name, gDataList, mergeDataList); 115 | } else { 116 | gRuleMap.put(name, dataList); 117 | } 118 | } else if (!Config.globalDataMap.containsKey(anyHost)) { 119 | // Add wildcard Host 120 | Config.globalDataMap.put(anyHost, new HashMap<>()); 121 | } else { 122 | Map> ruleMap = new HashMap<>(); 123 | ruleMap.put(name, dataList); 124 | // Add a single host 125 | Config.globalDataMap.put(host, ruleMap); 126 | } 127 | } 128 | 129 | map.put(name, tmpMap); 130 | 131 | } 132 | } 133 | }); 134 | t.start(); 135 | try { 136 | t.join(); 137 | } catch (InterruptedException e) { 138 | e.printStackTrace(); 139 | } 140 | 141 | 142 | } 143 | }); 144 | return map; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/burp/action/GetColorKey.java: -------------------------------------------------------------------------------- 1 | package burp.action; 2 | 3 | import burp.Config; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | /** 8 | * @author EvilChen 9 | */ 10 | 11 | public class GetColorKey { 12 | /** 13 | * Color subscript acquisition 14 | */ 15 | public List getColorKeys(List keys){ 16 | List result = new ArrayList<>(); 17 | String[] colorArray = Config.colorArray; 18 | int size = colorArray.length; 19 | // Get subscript by color 20 | for (String key : keys) { 21 | for (int v = 0; v < size; v++) { 22 | if (colorArray[v].equals(key)) { 23 | result.add(v); 24 | } 25 | } 26 | } 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/burp/action/MatchHTTP.java: -------------------------------------------------------------------------------- 1 | package burp.action; 2 | 3 | import jregex.Matcher; 4 | import jregex.Pattern; 5 | import jregex.REFlags; 6 | import burp.yaml.LoadConfig; 7 | 8 | /** 9 | * @author EvilChen 10 | */ 11 | 12 | public class MatchHTTP { 13 | // Match suffix 14 | LoadConfig lc = new LoadConfig(); 15 | public boolean matchSuffix(String str) { 16 | Pattern pattern = new Pattern(String.format("[\\w]+[\\.](%s)", lc.getExcludeSuffix()), REFlags.IGNORE_CASE); 17 | Matcher matcher = pattern.matcher(str); 18 | return matcher.find(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/burp/action/ProcessMessage.java: -------------------------------------------------------------------------------- 1 | package burp.action; 2 | 3 | import burp.BurpExtender; 4 | import burp.IExtensionHelpers; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public class ProcessMessage { 12 | MatchHTTP mh = new MatchHTTP(); 13 | ExtractContent ec = new ExtractContent(); 14 | DoAction da = new DoAction(); 15 | GetColorKey gck = new GetColorKey(); 16 | UpgradeColor uc = new UpgradeColor(); 17 | 18 | public List> processMessageByContent(IExtensionHelpers helpers, byte[] content, boolean isRequest, boolean messageInfo, String host) { 19 | List> result = new ArrayList<>();; 20 | Map> obj; 21 | 22 | if (isRequest) { 23 | 24 | // Get header 25 | List requestTmpHeaders = helpers.analyzeRequest(content).getHeaders(); 26 | String requestHeaders = String.join("\n", requestTmpHeaders); 27 | 28 | try { 29 | String urlString = requestTmpHeaders.get(0).split(" ")[1]; 30 | urlString = urlString.indexOf("?") > 0 ? urlString.substring(0, urlString.indexOf("?")) : urlString; 31 | if (mh.matchSuffix(urlString)) { 32 | return result; 33 | } 34 | } catch (Exception e) { 35 | return result; 36 | } 37 | 38 | // Get message body 39 | int requestBodyOffset = helpers.analyzeRequest(content).getBodyOffset(); 40 | byte[] requestBody = Arrays.copyOfRange(content, requestBodyOffset, content.length); 41 | 42 | obj = ec.matchRegex(content, requestHeaders, requestBody, "request", host); 43 | } else { 44 | try { 45 | String inferredMimeType = String.format("hae.%s", helpers.analyzeResponse(content).getInferredMimeType().toLowerCase()); 46 | String statedMimeType = String.format("hae.%s", helpers.analyzeResponse(content).getStatedMimeType().toLowerCase()); 47 | 48 | if (mh.matchSuffix(statedMimeType) || mh.matchSuffix(inferredMimeType)) { 49 | return result; 50 | } 51 | } catch (Exception e) { 52 | return result; 53 | } 54 | // Get header 55 | List responseTmpHeaders = helpers.analyzeResponse(content).getHeaders(); 56 | String responseHeaders = String.join("\n", responseTmpHeaders); 57 | 58 | // Get message body 59 | int responseBodyOffset = helpers.analyzeResponse(content).getBodyOffset(); 60 | byte[] responseBody = Arrays.copyOfRange(content, responseBodyOffset, content.length); 61 | 62 | obj = ec.matchRegex(content, responseHeaders, responseBody, "response", host); 63 | } 64 | 65 | if (obj.size() > 0) { 66 | if (messageInfo) { 67 | List> resultList = da.highlightAndComment(obj); 68 | List colorList = resultList.get(0); 69 | List commentList = resultList.get(1); 70 | if (colorList.size() != 0 && commentList.size() != 0) { 71 | String color = uc.getEndColor(gck.getColorKeys(colorList)); 72 | Map colorMap = new HashMap(){{ 73 | put("color", color); 74 | }}; 75 | Map commentMap = new HashMap(){{ 76 | put("comment", String.join(" | ", commentList)); 77 | }}; 78 | result.add(colorMap); 79 | result.add(commentMap); 80 | } 81 | } else { 82 | result.add(da.extractString(obj)); 83 | //BurpExtender.stdout.println("result: " + result); 84 | } 85 | } 86 | 87 | return result; 88 | 89 | } 90 | } -------------------------------------------------------------------------------- /src/main/java/burp/action/UpgradeColor.java: -------------------------------------------------------------------------------- 1 | package burp.action; 2 | import burp.Config; 3 | import java.util.*; 4 | import burp.yaml.LoadConfig; 5 | 6 | /** 7 | * @author EvilChen 8 | */ 9 | 10 | public class UpgradeColor { 11 | private String endColor = ""; 12 | /** 13 | * Color Upscaling Recursive Algorithm 14 | */ 15 | private void colorUpgrade(List colorList) { 16 | int colorSize = colorList.size(); 17 | String[] colorArray = Config.colorArray; 18 | colorList.sort(Comparator.comparingInt(Integer::intValue)); 19 | LoadConfig lc = new LoadConfig(); 20 | 21 | if (lc.getHighlightMethod().equals(Config.highlightMethod[0])) { 22 | this.endColor = colorArray[colorList.get(0)]; 23 | } else { 24 | int i = 0; 25 | List stack = new ArrayList<>(); 26 | while (i < colorSize) { 27 | if (stack.isEmpty()) { 28 | stack.add(colorList.get(i)); 29 | } else { 30 | if (!Objects.equals(colorList.get(i), stack.stream().reduce((first, second) -> second).orElse(99999999))) { 31 | stack.add(colorList.get(i)); 32 | } else { 33 | stack.set(stack.size() - 1, stack.get(stack.size() - 1) - 1); 34 | } 35 | } 36 | i++; 37 | } 38 | 39 | // Use HashSet to delete duplicate elements 40 | HashSet tmpList = new HashSet(stack); 41 | if (stack.size() == tmpList.size()) { 42 | stack.sort(Comparator.comparingInt(Integer::intValue)); 43 | // If the first element of the stack array list is less than 0, then set it to Red (0) 44 | if(stack.get(0) < 0) { 45 | this.endColor = colorArray[0]; 46 | } else { 47 | // Else set the color of the first element in the stack array 48 | this.endColor = colorArray[stack.get(0)]; 49 | } 50 | } else { 51 | this.colorUpgrade(stack); 52 | } 53 | } 54 | } 55 | 56 | public String getEndColor(List colorList) { 57 | colorUpgrade(colorList); 58 | return endColor; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/burp/ui/Databoard.java: -------------------------------------------------------------------------------- 1 | package burp.ui; 2 | 3 | import burp.Config; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import javax.swing.table.DefaultTableModel; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | import java.awt.*; 11 | import java.awt.event.*; 12 | import java.util.ArrayList; 13 | import java.util.Map; 14 | import javax.swing.*; 15 | import javax.swing.event.DocumentEvent; 16 | import javax.swing.event.DocumentListener; 17 | 18 | /** 19 | * @author LinChen && EvilChen 20 | */ 21 | 22 | public class Databoard extends JPanel { 23 | public Databoard() { 24 | initComponents(); 25 | } 26 | 27 | /** 28 | * Clear data 29 | */ 30 | private void clearActionPerformed(ActionEvent e) { 31 | // Clear page 32 | dataTabbedPane.removeAll(); 33 | // Determine wildcard or single host 34 | String host = hostTextField.getText(); 35 | if(host.contains("*")){ 36 | Map>> ruleMap = Config.globalDataMap; 37 | Map> selectHost = new HashMap<>(); 38 | ruleMap.keySet().forEach(i -> { 39 | if (i.contains(host.replace("*.", ""))) { 40 | Config.globalDataMap.remove(i); 41 | } 42 | }); 43 | } else { 44 | Config.globalDataMap.remove(host); 45 | } 46 | } 47 | 48 | private void initComponents() { 49 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 50 | hostLabel = new JLabel(); 51 | hostTextField = new JTextField(); 52 | dataTabbedPane = new JTabbedPane(); 53 | clearButton = new JButton(); 54 | 55 | //======== this ======== 56 | setLayout(new GridBagLayout()); 57 | ((GridBagLayout)getLayout()).columnWidths = new int[] {25, 0, 0, 0, 20, 0}; 58 | ((GridBagLayout)getLayout()).rowHeights = new int[] {0, 65, 20, 0}; 59 | ((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 0.0, 1.0, 0.0, 0.0, 1.0E-4}; 60 | ((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 1.0, 0.0, 1.0E-4}; 61 | 62 | //---- hostLabel ---- 63 | hostLabel.setText("Host:"); 64 | add(hostLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, 65 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 66 | new Insets(8, 0, 5, 5), 0, 0)); 67 | add(hostTextField, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, 68 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 69 | new Insets(8, 0, 5, 5), 0, 0)); 70 | clearButton.setText("Clear"); 71 | clearButton.addActionListener(this::clearActionPerformed); 72 | add(clearButton, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, 73 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 74 | new Insets(8, 0, 5, 5), 0, 0)); 75 | add(dataTabbedPane, new GridBagConstraints(1, 1, 3, 2, 0.0, 0.0, 76 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 77 | new Insets(8, 0, 0, 5), 0, 0)); 78 | 79 | setAutoMatch(hostTextField, dataTabbedPane); 80 | } 81 | 82 | /** 83 | * Get the host list 84 | */ 85 | private static List getHostByList(){ 86 | List hostList = new ArrayList<>(); 87 | hostList.addAll(Config.globalDataMap.keySet()); 88 | return hostList; 89 | } 90 | 91 | /** 92 | * Set input auto-matching 93 | */ 94 | public static void setAutoMatch(JTextField textField, JTabbedPane tabbedPane) { 95 | final DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel(); 96 | 97 | final JComboBox hostComboBox = new JComboBox(comboBoxModel) { 98 | @Override 99 | public Dimension getPreferredSize() { 100 | return new Dimension(super.getPreferredSize().width, 0); 101 | } 102 | }; 103 | 104 | isMatchHost = false; 105 | 106 | for (String host : getHostByList()) { 107 | comboBoxModel.addElement(host); 108 | } 109 | 110 | hostComboBox.setSelectedItem(null); 111 | 112 | hostComboBox.addActionListener(e -> { 113 | if (!isMatchHost) { 114 | if (hostComboBox.getSelectedItem() != null) { 115 | textField.setText(hostComboBox.getSelectedItem().toString()); 116 | getInfoByHost(hostComboBox, tabbedPane, textField); 117 | } 118 | } 119 | }); 120 | 121 | // Event listener 122 | textField.addKeyListener(new KeyAdapter() { 123 | @Override 124 | public void keyPressed(KeyEvent e) { 125 | isMatchHost = true; 126 | if (e.getKeyCode() == KeyEvent.VK_SPACE) { 127 | if (hostComboBox.isPopupVisible()) { 128 | e.setKeyCode(KeyEvent.VK_ENTER); 129 | } 130 | } 131 | if (e.getKeyCode() == KeyEvent.VK_ENTER 132 | || e.getKeyCode() == KeyEvent.VK_UP 133 | || e.getKeyCode() == KeyEvent.VK_DOWN) { 134 | e.setSource(hostComboBox); 135 | hostComboBox.dispatchEvent(e); 136 | if (e.getKeyCode() == KeyEvent.VK_ENTER) { 137 | textField.setText(hostComboBox.getSelectedItem().toString()); 138 | getInfoByHost(hostComboBox, tabbedPane, textField); 139 | hostComboBox.setPopupVisible(false); 140 | } 141 | } 142 | if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { 143 | hostComboBox.setPopupVisible(false); 144 | } 145 | isMatchHost = false; 146 | } 147 | }); 148 | 149 | textField.getDocument().addDocumentListener(new DocumentListener() { 150 | @Override 151 | public void insertUpdate(DocumentEvent e) { 152 | updateList(); 153 | } 154 | 155 | @Override 156 | public void removeUpdate(DocumentEvent e) { 157 | updateList(); 158 | } 159 | 160 | @Override 161 | public void changedUpdate(DocumentEvent e) { 162 | updateList(); 163 | } 164 | 165 | private void updateList() { 166 | isMatchHost = true; 167 | comboBoxModel.removeAllElements(); 168 | String input = textField.getText(); 169 | if (!input.isEmpty()){ 170 | for (String host : getHostByList()) { 171 | if (host.toLowerCase().contains(input.toLowerCase())) { 172 | if (host.length() == input.length()){ 173 | comboBoxModel.insertElementAt(host,0); 174 | comboBoxModel.setSelectedItem(host); 175 | }else{ 176 | comboBoxModel.addElement(host); 177 | } 178 | } 179 | } 180 | } 181 | hostComboBox.setPopupVisible(comboBoxModel.getSize() > 0); 182 | isMatchHost = false; 183 | } 184 | }); 185 | 186 | textField.setLayout(new BorderLayout()); 187 | textField.add(hostComboBox, BorderLayout.SOUTH); 188 | } 189 | 190 | private static void getInfoByHost(@NotNull JComboBox hostComboBox, JTabbedPane tabbedPane, JTextField textField) { 191 | if (hostComboBox.getSelectedItem() != null) { 192 | Map>> ruleMap = Config.globalDataMap; 193 | Map> selectHost = new HashMap<>(); 194 | String host = hostComboBox.getSelectedItem().toString(); 195 | if (host.contains("*")) { 196 | // Wildcard data 197 | Map> finalSelectHost = selectHost; 198 | ruleMap.keySet().forEach(i -> { 199 | if (i.contains(host.replace("*.", ""))) { 200 | ruleMap.get(i).keySet().forEach(e -> { 201 | if (finalSelectHost.containsKey(e)) { 202 | // Merge operation 203 | List newList = new ArrayList<>(finalSelectHost.get(e)); 204 | newList.addAll(ruleMap.get(i).get(e)); 205 | // De-dupe 206 | HashSet tmpList = new HashSet(newList); 207 | newList.clear(); 208 | newList.addAll(tmpList); 209 | // Add operation 210 | finalSelectHost.put(e, newList); 211 | } else { 212 | finalSelectHost.put(e, ruleMap.get(i).get(e)); 213 | } 214 | }); 215 | } 216 | }); 217 | } else { 218 | selectHost = ruleMap.get(host); 219 | } 220 | 221 | tabbedPane.removeAll(); 222 | for(Map.Entry> entry: selectHost.entrySet()){ 223 | tabbedPane.addTab(entry.getKey(), new JScrollPane(new HitRuleDataList(entry.getValue()))); 224 | } 225 | textField.setText(hostComboBox.getSelectedItem().toString()); 226 | } 227 | } 228 | 229 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 230 | private JLabel hostLabel; 231 | private JTextField hostTextField; 232 | private JTabbedPane dataTabbedPane; 233 | private JButton clearButton; 234 | // JFormDesigner - End of variables declaration //GEN-END:variables 235 | 236 | // Whether to automatically match Host 237 | private static Boolean isMatchHost = false; 238 | } 239 | class HitRuleDataList extends JTable { 240 | public HitRuleDataList(List list){ 241 | DefaultTableModel model = new DefaultTableModel(); 242 | Object[][] data = new Object[list.size()][1]; 243 | for (int x = 0; x < list.size(); x++) { 244 | data[x][0] = list.get(x); 245 | } 246 | model.setDataVector(data, new Object[]{"Information"}); 247 | this.setModel(model); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /src/main/java/burp/ui/JTabbedPaneCloseButton.java: -------------------------------------------------------------------------------- 1 | package burp.ui; 2 | 3 | import javax.swing.*; 4 | import javax.swing.plaf.metal.MetalIconFactory; 5 | import java.awt.*; 6 | import java.awt.event.MouseEvent; 7 | import java.awt.event.MouseListener; 8 | 9 | /** 10 | * @author 6dc 11 | * 12 | * A class which creates a JTabbedPane and auto sets a close button when you add a tab 13 | */ 14 | 15 | public class JTabbedPaneCloseButton extends JTabbedPane { 16 | 17 | public JTabbedPaneCloseButton() { 18 | super(); 19 | } 20 | 21 | /** Override Addtab in order to add the close Button everytime */ 22 | @Override 23 | public void addTab(String title, Icon icon, Component component, String tip) { 24 | super.addTab(title, icon, component, tip); 25 | int count = this.getTabCount() - 1; 26 | setTabComponentAt(count, new CloseButtonTab(component, title, icon)); 27 | } 28 | 29 | @Override 30 | public void addTab(String title, Icon icon, Component component) { 31 | addTab(title, icon, component, null); 32 | } 33 | 34 | @Override 35 | public void addTab(String title, Component component) { 36 | addTab(title, null, component); 37 | } 38 | 39 | 40 | public void addTab(String title,Component component,Boolean closewith){ 41 | if (closewith){ 42 | addTab(title,component); 43 | }else{ 44 | super.addTab(title,null,component,null); 45 | } 46 | } 47 | 48 | /** addTabNoExit */ 49 | public void addTabNoExit(String title, Icon icon, Component component, String tip) { 50 | super.addTab(title, icon, component, tip); 51 | } 52 | 53 | public void addTabNoExit(String title, Icon icon, Component component) { 54 | addTabNoExit(title, icon, component, null); 55 | } 56 | 57 | public void addTabNoExit(String title, Component component) { 58 | addTabNoExit(title, null, component); 59 | } 60 | 61 | /** Button */ 62 | public class CloseButtonTab extends JPanel { 63 | public CloseButtonTab(final Component tab, String title, Icon icon) { 64 | setOpaque(false); 65 | FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 3, 3); 66 | setLayout(flowLayout); 67 | JLabel jLabel = new JLabel(title); 68 | jLabel.setIcon(icon); 69 | add(jLabel); 70 | JButton button = new JButton(MetalIconFactory.getInternalFrameCloseIcon(2)); 71 | button.setMargin(new Insets(0, 0, 0, 0)); 72 | button.addMouseListener(new CloseListener(tab)); 73 | add(button); 74 | } 75 | } 76 | /** ClickListener */ 77 | public class CloseListener implements MouseListener 78 | { 79 | private final Component tab; 80 | 81 | public CloseListener(Component tab){ 82 | this.tab=tab; 83 | } 84 | 85 | @Override 86 | public void mouseClicked(MouseEvent e) { 87 | if(e.getSource() instanceof JButton){ 88 | JButton clickedButton = (JButton) e.getSource(); 89 | JTabbedPane tabbedPane = (JTabbedPane) clickedButton.getParent().getParent().getParent(); 90 | tabbedPane.remove(tab); 91 | } 92 | } 93 | 94 | @Override 95 | public void mousePressed(MouseEvent e) {} 96 | 97 | @Override 98 | public void mouseReleased(MouseEvent e) {} 99 | 100 | @Override 101 | public void mouseEntered(MouseEvent e) { 102 | if(e.getSource() instanceof JButton){ 103 | JButton clickedButton = (JButton) e.getSource(); 104 | } 105 | } 106 | 107 | @Override 108 | public void mouseExited(MouseEvent e) { 109 | if(e.getSource() instanceof JButton){ 110 | JButton clickedButton = (JButton) e.getSource(); 111 | } 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /src/main/java/burp/ui/MainUI.java: -------------------------------------------------------------------------------- 1 | package burp.ui; 2 | 3 | import burp.Config; 4 | import burp.yaml.LoadConfig; 5 | import burp.yaml.SetConfig; 6 | 7 | import com.squareup.okhttp.OkHttpClient; 8 | import com.squareup.okhttp.Request; 9 | import com.squareup.okhttp.Response; 10 | import java.io.FileOutputStream; 11 | import javax.swing.*; 12 | import javax.swing.event.ChangeEvent; 13 | import javax.swing.event.ChangeListener; 14 | import javax.swing.event.DocumentEvent; 15 | import javax.swing.event.DocumentListener; 16 | import java.awt.*; 17 | import java.awt.event.*; 18 | import java.util.Map; 19 | 20 | /** 21 | * @author LinChen && EvilChen 22 | */ 23 | 24 | public class MainUI extends JPanel{ 25 | private final LoadConfig loadConn = new LoadConfig(); 26 | 27 | public MainUI() { 28 | initComponents(); 29 | } 30 | 31 | public void closeTabActionPerformed(ActionEvent e){ 32 | if (ruleTabbedPane.getTabCount()>2){ 33 | if (ruleTabbedPane.getSelectedIndex()!=0){ 34 | SetConfig setConn = new SetConfig(); 35 | setConn.deleteRules(ruleTabbedPane.getTitleAt(ruleTabbedPane.getSelectedIndex())); 36 | ruleTabbedPane.remove(ruleTabbedPane.getSelectedIndex()); 37 | ruleTabbedPane.setSelectedIndex(ruleTabbedPane.getSelectedIndex()-1); 38 | } else { 39 | SetConfig setConn = new SetConfig(); 40 | setConn.deleteRules(ruleTabbedPane.getTitleAt(ruleTabbedPane.getSelectedIndex())); 41 | ruleTabbedPane.remove(ruleTabbedPane.getSelectedIndex()); 42 | ruleTabbedPane.setSelectedIndex(ruleTabbedPane.getSelectedIndex()); 43 | } 44 | } 45 | } 46 | 47 | private void onlineUpdateActionPerformed(ActionEvent e) { 48 | // Add a prompt box to prevent users from accidentally touching the configuration update 49 | int retCode = JOptionPane.showConfirmDialog(null, "Do you want to update config?", "Info", 50 | JOptionPane.YES_NO_CANCEL_OPTION); 51 | if (retCode == JOptionPane.YES_OPTION) { 52 | String url = "https://cdn.jsdelivr.net/gh/gh0stkey/HaE@gh-pages/Config.yml"; 53 | OkHttpClient httpClient = new OkHttpClient(); 54 | Request httpRequest = new Request.Builder().url(url).get().build(); 55 | try { 56 | Response httpResponse = httpClient.newCall(httpRequest).execute(); 57 | // Obtain the official rule file, update and write online 58 | String configFile = configTextField.getText(); 59 | FileOutputStream fileOutputStream = new FileOutputStream(configFile); 60 | fileOutputStream.write(httpResponse.body().bytes()); 61 | JOptionPane.showMessageDialog(null, "Config file updated successfully!", "Error", 62 | JOptionPane.INFORMATION_MESSAGE); 63 | } catch (Exception ignored) { 64 | JOptionPane.showMessageDialog(null, "Please check your network!", "Error", 65 | JOptionPane.ERROR_MESSAGE); 66 | } 67 | 68 | new LoadConfig(); 69 | reloadRule(); 70 | } 71 | } 72 | 73 | private void reloadRule(){ 74 | ruleTabbedPane.removeAll(); 75 | ruleSwitch.setListen(false); 76 | Map rules = LoadConfig.getRules(); 77 | rules.keySet().forEach( 78 | i-> ruleTabbedPane.addTab( 79 | i, 80 | new RulePane(rules.get(i), ruleTabbedPane) 81 | ) 82 | ); 83 | ruleTabbedPane.addTab("...", new JLabel()); 84 | ruleSwitch.setListen(true); 85 | } 86 | 87 | private void reloadActionPerformed(ActionEvent e) { 88 | reloadRule(); 89 | } 90 | 91 | private void excludeSuffixSaveActionPerformed(ActionEvent e) { 92 | LoadConfig loadCon = new LoadConfig(); 93 | loadCon.setExcludeSuffix(excludeSuffixTextField.getText(), highlightMethodComboBox.getSelectedItem().toString()); 94 | } 95 | private void initComponents() { 96 | mainTabbedPane = new JTabbedPane(); 97 | ruleTabbedPane = new JTabbedPane(); 98 | rulePanel = new JPanel(); 99 | configTextField = new JTextField(); 100 | configLabel = new JLabel(); 101 | onlineUpdateButton = new JButton(); 102 | reloadButton = new JButton(); 103 | excludeSuffixLabel = new JLabel(); 104 | excludeSuffixTextField = new JTextField(); 105 | excludeSuffixSaveButton = new JButton(); 106 | highlightMethodLabel = new JLabel(); 107 | highlightMethodComboBox = new JComboBox<>(); 108 | 109 | setLayout(new GridBagLayout()); 110 | ((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0}; 111 | ((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0}; 112 | ((GridBagLayout)getLayout()).columnWeights = new double[] {1.0, 1.0E-4}; 113 | ((GridBagLayout)getLayout()).rowWeights = new double[] {1.0, 1.0E-4}; 114 | 115 | { 116 | mainTabbedPane.addTab("Rules", ruleTabbedPane); 117 | 118 | { 119 | rulePanel.setLayout(new GridBagLayout()); 120 | ((GridBagLayout) rulePanel.getLayout()).columnWidths = new int[] {0, 0, 0, 0, 0}; 121 | ((GridBagLayout) rulePanel.getLayout()).rowHeights = new int[] {0, 0, 0}; 122 | ((GridBagLayout) rulePanel.getLayout()).columnWeights = new double[] {0.0, 1.0, 0.0, 0.0, 1.0E-4}; 123 | ((GridBagLayout) rulePanel.getLayout()).rowWeights = new double[] {0.0, 0.0, 1.0E-4}; 124 | 125 | configTextField.setEditable(false); 126 | rulePanel.add(configTextField, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, 127 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 128 | new Insets(5, 0, 5, 5), 0, 0)); 129 | 130 | configLabel.setText("Config Path:"); 131 | rulePanel.add(configLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, 132 | GridBagConstraints.WEST, GridBagConstraints.VERTICAL, 133 | new Insets(5, 5, 5, 5), 0, 0)); 134 | 135 | onlineUpdateButton.setText("Online Update"); 136 | onlineUpdateButton.addActionListener(this::onlineUpdateActionPerformed); 137 | rulePanel.add(onlineUpdateButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, 138 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 139 | new Insets(5, 0, 5, 5), 0, 0)); 140 | 141 | reloadButton.setText("Reload"); 142 | reloadButton.addActionListener(this::reloadActionPerformed); 143 | rulePanel.add(reloadButton, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, 144 | 145 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 146 | new Insets(5, 0, 5, 5), 0, 0)); 147 | 148 | excludeSuffixLabel.setText("Exclude Suffix:"); 149 | rulePanel.add(excludeSuffixLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, 150 | GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, 151 | new Insets(5, 5, 5, 5), 0, 0)); 152 | rulePanel.add(excludeSuffixTextField, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, 153 | GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, 154 | new Insets(5, 0, 0, 5), 0, 0)); 155 | 156 | excludeSuffixSaveButton.setText("Save"); 157 | excludeSuffixSaveButton.addActionListener(this::excludeSuffixSaveActionPerformed); 158 | rulePanel.add(excludeSuffixSaveButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, 159 | GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, 160 | new Insets(5, 0, 0, 5), 0, 0)); 161 | 162 | highlightMethodLabel.setText("Highlight Method:"); 163 | rulePanel.add(highlightMethodLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, 164 | GridBagConstraints.WEST, GridBagConstraints.NONE, 165 | new Insets(5, 5, 5, 5), 0, 0)); 166 | 167 | highlightMethodComboBox.setModel(new DefaultComboBoxModel<>(Config.highlightMethod));; 168 | rulePanel.add(highlightMethodComboBox, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, 169 | GridBagConstraints.WEST, GridBagConstraints.NONE, 170 | new Insets(5, 0, 0, 5), 0, 0)); 171 | } 172 | mainTabbedPane.addTab("Config", rulePanel); 173 | mainTabbedPane.addTab("Databoard", databoardPanel); 174 | } 175 | add(mainTabbedPane, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, 176 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 177 | new Insets(0, 0, 0, 0), 0, 0)); 178 | 179 | Config.ruleConfig.keySet().forEach(i-> ruleTabbedPane.addTab(i,new RulePane(Config.ruleConfig.get(i), 180 | ruleTabbedPane))); 181 | 182 | ruleTabbedPane.addTab("...",new JLabel()); 183 | 184 | configTextField.setText(LoadConfig.getConfigPath()); 185 | excludeSuffixTextField.setText(loadConn.getExcludeSuffix()); 186 | highlightMethodComboBox.setSelectedItem(loadConn.getHighlightMethod()); 187 | ruleSwitch = new TabTitleEditListener(ruleTabbedPane); 188 | ruleTabbedPane.addChangeListener(ruleSwitch); 189 | ruleTabbedPane.addMouseListener(ruleSwitch); 190 | closeTabMenuItem.addActionListener(this::closeTabActionPerformed); 191 | tabMenu.add(closeTabMenuItem); 192 | } 193 | 194 | private JTabbedPane mainTabbedPane; 195 | private JTabbedPane ruleTabbedPane; 196 | private JPanel rulePanel; 197 | private JTextField configTextField; 198 | private JLabel configLabel; 199 | private JButton onlineUpdateButton; 200 | private JButton reloadButton; 201 | private JLabel excludeSuffixLabel; 202 | private JTextField excludeSuffixTextField; 203 | private JButton excludeSuffixSaveButton; 204 | private JLabel highlightMethodLabel; 205 | private JComboBox highlightMethodComboBox; 206 | private Databoard databoardPanel = new Databoard(); 207 | protected static JPopupMenu tabMenu = new JPopupMenu(); 208 | private JMenuItem closeTabMenuItem = new JMenuItem("Delete"); 209 | private TabTitleEditListener ruleSwitch; 210 | } 211 | 212 | class TabTitleEditListener extends MouseAdapter implements ChangeListener, DocumentListener { 213 | protected final JTextField ruleEditTextField = new JTextField(); 214 | protected final JTabbedPane ruleEditTabbedPane; 215 | protected int editingIndex = -1; 216 | protected int len = -1; 217 | protected Boolean listen = true; 218 | protected Dimension dim; 219 | protected Component tabComponent; 220 | protected Boolean isRenameOk = false; 221 | protected SetConfig setConfig = new SetConfig(); 222 | 223 | protected final Action startEditing = new AbstractAction() { 224 | @Override public void actionPerformed(ActionEvent e) { 225 | editingIndex = ruleEditTabbedPane.getSelectedIndex(); 226 | tabComponent = ruleEditTabbedPane.getTabComponentAt(editingIndex); 227 | ruleEditTabbedPane.setTabComponentAt(editingIndex, ruleEditTextField); 228 | isRenameOk = true; 229 | ruleEditTextField.setVisible(true); 230 | ruleEditTextField.setText(ruleEditTabbedPane.getTitleAt(editingIndex)); 231 | ruleEditTextField.selectAll(); 232 | ruleEditTextField.requestFocusInWindow(); 233 | len = ruleEditTextField.getText().length(); 234 | dim = ruleEditTextField.getPreferredSize(); 235 | ruleEditTextField.setMinimumSize(dim); 236 | } 237 | }; 238 | 239 | protected final Action renameTabTitle = new AbstractAction() { 240 | @Override public void actionPerformed(ActionEvent e) { 241 | String title = ruleEditTextField.getText().trim(); 242 | if (editingIndex >= 0 && !title.isEmpty()) { 243 | String oldName = ruleEditTabbedPane.getTitleAt(editingIndex); 244 | ruleEditTabbedPane.setTitleAt(editingIndex, title); 245 | setConfig.rename(oldName,title); 246 | } 247 | cancelEditing.actionPerformed(null); 248 | } 249 | }; 250 | 251 | protected final Action cancelEditing = new AbstractAction() { 252 | @Override public void actionPerformed(ActionEvent e) { 253 | if (editingIndex >= 0) { 254 | ruleEditTabbedPane.setTabComponentAt(editingIndex, tabComponent); 255 | ruleEditTextField.setVisible(false); 256 | editingIndex = -1; 257 | len = -1; 258 | tabComponent = null; 259 | ruleEditTextField.setPreferredSize(null); 260 | ruleEditTabbedPane.requestFocusInWindow(); 261 | } 262 | } 263 | }; 264 | 265 | protected TabTitleEditListener(JTabbedPane tabbedPane) { 266 | super(); 267 | this.ruleEditTabbedPane = tabbedPane; 268 | ruleEditTextField.setBorder(BorderFactory.createEmptyBorder()); 269 | ruleEditTextField.addFocusListener(new FocusAdapter() { 270 | @Override public void focusLost(FocusEvent e) { 271 | renameTabTitle.actionPerformed(null); 272 | } 273 | }); 274 | InputMap im = ruleEditTextField.getInputMap(JComponent.WHEN_FOCUSED); 275 | ActionMap am = ruleEditTextField.getActionMap(); 276 | im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel-editing"); 277 | am.put("cancel-editing", cancelEditing); 278 | im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "rename-tab-title"); 279 | am.put("rename-tab-title", renameTabTitle); 280 | ruleEditTextField.getDocument().addDocumentListener(this); 281 | tabbedPane.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "start-editing"); 282 | tabbedPane.getActionMap().put("start-editing", startEditing); 283 | } 284 | 285 | @Override public void stateChanged(ChangeEvent e) { 286 | if (e.getSource() instanceof JTabbedPane && listen) { 287 | JTabbedPane pane = (JTabbedPane) e.getSource(); 288 | if (!isRenameOk){ 289 | if (pane.getSelectedIndex() == pane.getComponentCount()-1){ 290 | newTab(); 291 | } 292 | }else{ 293 | if (pane.getSelectedIndex() == pane.getComponentCount()-2){ 294 | newTab(); 295 | } 296 | } 297 | } 298 | renameTabTitle.actionPerformed(null); 299 | } 300 | 301 | public void newTab(){ 302 | Object[][] data = new Object[][]{{false, "New Name", "(New Regex)", "none", "any", "nfa", false}}; 303 | insertTab(ruleEditTabbedPane, setConfig.newRules(),data); 304 | } 305 | 306 | public void insertTab(JTabbedPane pane,String title,Object[][] data){ 307 | pane.addTab(title,new RulePane(data,pane)); 308 | pane.remove(pane.getSelectedIndex()); 309 | pane.addTab("...",new JLabel()); 310 | } 311 | 312 | public void setListen(Boolean listen){ 313 | this.listen = listen; 314 | } 315 | 316 | @Override public void insertUpdate(DocumentEvent e) { 317 | updateTabSize(); 318 | } 319 | 320 | @Override public void removeUpdate(DocumentEvent e) { 321 | updateTabSize(); 322 | } 323 | 324 | @Override public void changedUpdate(DocumentEvent e) {} 325 | 326 | @Override public void mouseClicked(MouseEvent e) { 327 | switch (e.getButton()){ 328 | case 1: 329 | { 330 | Rectangle r = ruleEditTabbedPane.getBoundsAt(ruleEditTabbedPane.getSelectedIndex()); 331 | boolean isDoubleClick = e.getClickCount() >= 2; 332 | if (isDoubleClick && r.contains(e.getPoint())) { 333 | startEditing.actionPerformed(null); 334 | } else { 335 | renameTabTitle.actionPerformed(null); 336 | } 337 | break; 338 | } 339 | case 3:{ 340 | MainUI.tabMenu.show(e.getComponent(),e.getX(),e.getY()); 341 | break; 342 | } 343 | default: 344 | break; 345 | } 346 | } 347 | 348 | protected void updateTabSize() { 349 | ruleEditTextField.setPreferredSize(ruleEditTextField.getText().length() > len ? null : dim); 350 | ruleEditTabbedPane.revalidate(); 351 | } 352 | } -------------------------------------------------------------------------------- /src/main/java/burp/ui/RulePane.java: -------------------------------------------------------------------------------- 1 | package burp.ui; 2 | 3 | import burp.yaml.SetConfig; 4 | 5 | import java.awt.event.ActionEvent; 6 | import java.awt.event.ActionListener; 7 | import javax.swing.*; 8 | import javax.swing.event.TableModelEvent; 9 | import javax.swing.event.TableModelListener; 10 | import javax.swing.table.DefaultTableModel; 11 | import javax.swing.table.TableRowSorter; 12 | import java.awt.*; 13 | import java.util.Vector; 14 | 15 | /** 16 | * @author LinChen 17 | */ 18 | 19 | public class RulePane extends JPanel { 20 | public RulePane(Object[][] data, JTabbedPane pane) { 21 | initComponents(data, pane); 22 | } 23 | private SetConfig setConfig = new SetConfig(); 24 | private Boolean isEdit = false; 25 | 26 | private void ruleAddActionPerformed(ActionEvent e, JTabbedPane pane) { 27 | RuleSetting ruleSettingPanel = new RuleSetting(); 28 | ruleSettingPanel.ruleNameTextField.setText("New Rule"); 29 | ruleSettingPanel.regexTextField.setText("(REMEMBER TO PUT BRACKETS AROUND IT!)"); 30 | ruleSettingPanel.colorComboBox.setSelectedItem("none"); 31 | int showState = JOptionPane.showConfirmDialog(null, ruleSettingPanel, "RuleSetting - Add Rule", JOptionPane.OK_OPTION); 32 | if(showState == 0){ 33 | Vector ruleData = new Vector(); 34 | ruleData.add(false); 35 | ruleData.add(ruleSettingPanel.ruleNameTextField.getText()); 36 | ruleData.add(ruleSettingPanel.regexTextField.getText()); 37 | ruleData.add(ruleSettingPanel.colorComboBox.getSelectedItem().toString()); 38 | ruleData.add(ruleSettingPanel.scopeComboBox.getSelectedItem().toString()); 39 | ruleData.add(ruleSettingPanel.engineComboBox.getSelectedItem().toString()); 40 | ruleData.add(ruleSettingPanel.sensitiveComboBox.getSelectedItem()); 41 | model.insertRow(model.getRowCount(), ruleData); 42 | model = (DefaultTableModel) ruleTable.getModel(); 43 | setConfig.add(ruleData, pane.getTitleAt(pane.getSelectedIndex())); 44 | } 45 | } 46 | 47 | private void ruleEditActionPerformed(ActionEvent e, JTabbedPane pane){ 48 | if (ruleTable.getSelectedRowCount() >= 1){ 49 | RuleSetting ruleSettingPanel = new RuleSetting(); 50 | ruleSettingPanel.ruleNameTextField.setText(ruleTable.getValueAt(ruleTable.getSelectedRow(), 1).toString()); 51 | ruleSettingPanel.regexTextField.setText(ruleTable.getValueAt(ruleTable.getSelectedRow(), 2).toString()); 52 | ruleSettingPanel.colorComboBox.setSelectedItem(ruleTable.getValueAt(ruleTable.getSelectedRow(), 3).toString()); 53 | ruleSettingPanel.scopeComboBox.setSelectedItem(ruleTable.getValueAt(ruleTable.getSelectedRow(), 4).toString()); 54 | ruleSettingPanel.engineComboBox.setSelectedItem(ruleTable.getValueAt(ruleTable.getSelectedRow(), 5).toString()); 55 | ruleSettingPanel.sensitiveComboBox.setSelectedItem(ruleTable.getValueAt(ruleTable.getSelectedRow(),6)); 56 | 57 | if (ruleSettingPanel.engineComboBox.getSelectedItem().toString().equals("nfa")) { 58 | ruleSettingPanel.sensitiveComboBox.setEnabled(true); 59 | } else { 60 | ruleSettingPanel.sensitiveComboBox.setEnabled(false); 61 | ruleSettingPanel.sensitiveComboBox.setSelectedItem(true); 62 | } 63 | 64 | int showState = JOptionPane.showConfirmDialog(null, ruleSettingPanel, "RuleSetting - Edit Rule", JOptionPane.OK_OPTION); 65 | if (showState == 0){ 66 | int select = ruleTable.convertRowIndexToModel(ruleTable.getSelectedRow()); 67 | model.setValueAt(ruleSettingPanel.ruleNameTextField.getText(), select, 1); 68 | model.setValueAt(ruleSettingPanel.regexTextField.getText(), select, 2); 69 | model.setValueAt(ruleSettingPanel.colorComboBox.getSelectedItem().toString(), select, 3); 70 | model.setValueAt(ruleSettingPanel.scopeComboBox.getSelectedItem().toString(), select, 4); 71 | model.setValueAt(ruleSettingPanel.sensitiveComboBox.getSelectedItem(), select, 6); 72 | model.setValueAt(ruleSettingPanel.engineComboBox.getSelectedItem().toString(), select, 5); 73 | model = (DefaultTableModel) ruleTable.getModel(); 74 | setConfig.edit((Vector) model.getDataVector().get(select), select, pane.getTitleAt(pane.getSelectedIndex())); 75 | } 76 | } 77 | } 78 | 79 | private void ruleRemoveActionPerformed(ActionEvent e, JTabbedPane pane){ 80 | if (ruleTable.getSelectedRowCount() >= 1){ 81 | int isOk = JOptionPane.showConfirmDialog(null, "Are your sure?", "RuleSetting - Delete Rule", JOptionPane.OK_OPTION); 82 | if (isOk == 0){ 83 | int select = ruleTable.convertRowIndexToModel(ruleTable.getSelectedRow()); 84 | model.removeRow(select); 85 | model = (DefaultTableModel) ruleTable.getModel(); 86 | setConfig.remove(select, pane.getTitleAt(pane.getSelectedIndex())); 87 | } 88 | } 89 | } 90 | 91 | private void ruleTableChange(TableModelEvent e, JTabbedPane pane) { 92 | if (e.getColumn() == 0 && ruleTable.getSelectedRow() != -1 && !isEdit){ 93 | model = (DefaultTableModel) ruleTable.getModel(); 94 | int select = ruleTable.convertRowIndexToModel(ruleTable.getSelectedRow()); 95 | setConfig.edit((Vector) model.getDataVector().get(select), select, pane.getTitleAt(pane.getSelectedIndex())); 96 | } 97 | } 98 | 99 | private void initComponents(Object[][] data, JTabbedPane pane) { 100 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 101 | addButton = new JButton(); 102 | editButton = new JButton(); 103 | scrollPane = new JScrollPane(); 104 | ruleTable = new JTable(); 105 | removeButton = new JButton(); 106 | 107 | //======== this ======== 108 | setLayout(new GridBagLayout()); 109 | ((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0, 0}; 110 | ((GridBagLayout)getLayout()).rowHeights = new int[] {0, 0, 0, 0, 0}; 111 | ((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 1.0, 1.0E-4}; 112 | ((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 0.0, 0.0, 1.0, 1.0E-4}; 113 | 114 | //---- addButton ---- 115 | addButton.setText("Add"); 116 | 117 | addButton.addActionListener(new ActionListener() { 118 | @Override 119 | public void actionPerformed(ActionEvent e) { 120 | isEdit = true; 121 | ruleAddActionPerformed(e, pane); 122 | model = (DefaultTableModel) ruleTable.getModel(); 123 | isEdit = false; 124 | } 125 | }); 126 | 127 | add(addButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, 128 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 129 | new Insets(15, 5, 3, 2), 0, 0)); 130 | 131 | //---- editButton ---- 132 | editButton.setText("Edit"); 133 | editButton.addActionListener(new ActionListener() { 134 | @Override 135 | public void actionPerformed(ActionEvent e) { 136 | isEdit = true; 137 | ruleEditActionPerformed(e, pane); 138 | model = (DefaultTableModel) ruleTable.getModel(); 139 | isEdit = false; 140 | } 141 | }); 142 | 143 | add(editButton, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, 144 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 145 | new Insets(0, 5, 3, 2), 0, 0)); 146 | 147 | //======== scrollPane ======== 148 | { 149 | //---- table ---- 150 | ruleTable.setShowVerticalLines(false); 151 | ruleTable.setVerifyInputWhenFocusTarget(false); 152 | ruleTable.setUpdateSelectionOnSort(false); 153 | ruleTable.setShowHorizontalLines(false); 154 | ruleTable.setModel(new DefaultTableModel()); 155 | ruleTable.setSurrendersFocusOnKeystroke(true); 156 | scrollPane.setViewportView(ruleTable); 157 | } 158 | 159 | add(scrollPane, new GridBagConstraints(1, 0, 1, 4, 0.0, 0.0, 160 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 161 | new Insets(15, 5, 5, 5), 0, 0)); 162 | 163 | //---- removeButton ---- 164 | removeButton.setText("Remove"); 165 | 166 | removeButton.addActionListener(new ActionListener() { 167 | @Override 168 | public void actionPerformed(ActionEvent e) { 169 | isEdit = true; 170 | ruleRemoveActionPerformed(e, pane); 171 | model = (DefaultTableModel) ruleTable.getModel(); 172 | isEdit = false; 173 | } 174 | }); 175 | 176 | add(removeButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, 177 | GridBagConstraints.CENTER, GridBagConstraints.BOTH, 178 | new Insets(0, 5, 3, 2), 0, 0)); 179 | 180 | // JFormDesigner - End of component initialization //GEN-END:initComponents 181 | ruleTable.setModel(model); 182 | model.setDataVector(data, title); 183 | model.addTableModelListener(new TableModelListener() { 184 | @Override 185 | public void tableChanged(TableModelEvent e) { 186 | ruleTableChange(e, pane); 187 | } 188 | }); 189 | 190 | ruleTable.setRowSorter(new TableRowSorter(model)); 191 | } 192 | 193 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 194 | public JButton addButton; 195 | public JButton editButton; 196 | public JScrollPane scrollPane; 197 | public JTable ruleTable; 198 | public JButton removeButton; 199 | // JFormDesigner - End of variables declaration //GEN-END:variables 200 | private final String[] title = new String[]{"Loaded", "Name", "Regex", "Color", "Scope", "Engine", "Case Sensitive"}; 201 | private DefaultTableModel model = new DefaultTableModel() { 202 | @Override 203 | public Class getColumnClass (int column){ 204 | if (column == 0) { 205 | return Boolean.class; 206 | }else{ 207 | return String.class; 208 | } 209 | } 210 | 211 | @Override 212 | public boolean isCellEditable(int row, int column){ 213 | return column == 0; 214 | } 215 | }; 216 | } 217 | 218 | -------------------------------------------------------------------------------- /src/main/java/burp/ui/RuleSetting.java: -------------------------------------------------------------------------------- 1 | package burp.ui; 2 | 3 | import java.awt.event.ActionEvent; 4 | import java.awt.event.ActionListener; 5 | import java.awt.event.ItemEvent; 6 | import java.awt.event.ItemListener; 7 | import javax.swing.*; 8 | import java.awt.*; 9 | import burp.Config; 10 | 11 | /** 12 | * @author LinChen 13 | */ 14 | 15 | public class RuleSetting extends JPanel { 16 | public RuleSetting() { 17 | initComponents(); 18 | } 19 | 20 | public void initComponents() { 21 | sensitiveLabel = new JLabel(); 22 | engineLabel = new JLabel(); 23 | scopeLabel = new JLabel(); 24 | regexTextField = new JTextField(); 25 | regexLabel = new JLabel(); 26 | nameLabel = new JLabel(); 27 | ruleNameTextField = new JTextField(); 28 | scopeComboBox = new JComboBox<>(); 29 | engineComboBox = new JComboBox<>(); 30 | colorLabel = new JLabel(); 31 | colorComboBox = new JComboBox<>(); 32 | sensitiveComboBox = new JComboBox<>(); 33 | 34 | setLayout(null); 35 | 36 | engineLabel.setText("Engine:"); 37 | add(engineLabel); 38 | engineLabel.setBounds(new Rectangle(new Point(2, 175), engineLabel.getPreferredSize())); 39 | 40 | sensitiveLabel.setText("Case Sens.:"); 41 | add(sensitiveLabel); 42 | sensitiveLabel.setBounds(new Rectangle(new Point(2,215), sensitiveLabel.getPreferredSize())); 43 | 44 | scopeLabel.setText("Scope:"); 45 | add(scopeLabel); 46 | scopeLabel.setBounds(new Rectangle(new Point(2, 135), scopeLabel.getPreferredSize())); 47 | add(regexTextField); 48 | regexTextField.setBounds(90, 50, 350, 30); 49 | 50 | regexLabel.setText("Regex:"); 51 | add(regexLabel); 52 | regexLabel.setBounds(new Rectangle(new Point(2, 55), regexLabel.getPreferredSize())); 53 | 54 | nameLabel.setText("Name:"); 55 | add(nameLabel); 56 | nameLabel.setBounds(new Rectangle(new Point(2, 15), nameLabel.getPreferredSize())); 57 | add(ruleNameTextField); 58 | ruleNameTextField.setBounds(90, 10, 350, 30); 59 | 60 | scopeComboBox.setModel(new DefaultComboBoxModel<>(Config.scopeArray)); 61 | add(scopeComboBox); 62 | scopeComboBox.setBounds(90, 130, 350, scopeComboBox.getPreferredSize().height); 63 | 64 | engineComboBox.setModel(new DefaultComboBoxModel<>(Config.engineArray)); 65 | engineComboBox.addActionListener(new ActionListener() { 66 | @Override 67 | public void actionPerformed(ActionEvent e) { 68 | String engineValue = engineComboBox.getSelectedItem().toString(); 69 | if (engineValue.equals("nfa")) { 70 | sensitiveComboBox.setEnabled(true); 71 | } else { 72 | sensitiveComboBox.setEnabled(false); 73 | sensitiveComboBox.setSelectedItem(true); 74 | } 75 | } 76 | }); 77 | add(engineComboBox); 78 | engineComboBox.setBounds(90, 170, 350, engineComboBox.getPreferredSize().height); 79 | 80 | colorLabel.setText("Color:"); 81 | add(colorLabel); 82 | colorLabel.setBounds(new Rectangle(new Point(2, 95), colorLabel.getPreferredSize())); 83 | 84 | colorComboBox.setModel(new DefaultComboBoxModel<>(Config.colorArray)); 85 | add(colorComboBox); 86 | colorComboBox.setBounds(90, 90, 350, colorComboBox.getPreferredSize().height); 87 | 88 | sensitiveComboBox.setModel(new DefaultComboBoxModel<>(new Boolean[]{true, false})); 89 | add(sensitiveComboBox); 90 | sensitiveComboBox.setBounds(90,210,350,sensitiveComboBox.getPreferredSize().height); 91 | 92 | { 93 | Dimension preferredSize = new Dimension(); 94 | for(int i = 0; i < getComponentCount(); i++) { 95 | Rectangle bounds = getComponent(i).getBounds(); 96 | preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width); 97 | preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height); 98 | } 99 | Insets insets = getInsets(); 100 | preferredSize.width += insets.right; 101 | preferredSize.height += insets.bottom; 102 | setMinimumSize(preferredSize); 103 | setPreferredSize(preferredSize); 104 | } 105 | } 106 | 107 | private JLabel engineLabel; 108 | private JLabel sensitiveLabel; 109 | private JLabel scopeLabel; 110 | public JTextField regexTextField; 111 | private JLabel regexLabel; 112 | private JLabel nameLabel; 113 | public JTextField ruleNameTextField; 114 | public JComboBox scopeComboBox; 115 | public JComboBox engineComboBox; 116 | private JLabel colorLabel; 117 | public JComboBox colorComboBox; 118 | public JComboBox sensitiveComboBox; 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/burp/yaml/LoadConfig.java: -------------------------------------------------------------------------------- 1 | package burp.yaml; 2 | 3 | import burp.Config; 4 | import burp.yaml.template.*; 5 | 6 | import java.io.*; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.ArrayList; 11 | 12 | import org.yaml.snakeyaml.Yaml; 13 | import org.yaml.snakeyaml.constructor.Constructor; 14 | import org.yaml.snakeyaml.DumperOptions; 15 | import org.yaml.snakeyaml.representer.Representer; 16 | import org.yaml.snakeyaml.nodes.Tag; 17 | 18 | public class LoadConfig { 19 | private static final Yaml yaml = new Yaml(); 20 | private static String HaEConfigPath = String.format("%s/.config/H&E", System.getProperty("user.home")); 21 | private static String SettingPath = String.format("%s/%s", HaEConfigPath, "Setting.yml"); 22 | private static String ConfigPath = String.format("%s/%s", HaEConfigPath, "Config.yml"); 23 | 24 | public LoadConfig() { 25 | // Constructor, initialize configuration 26 | File HaEConfigPathFile = new File(HaEConfigPath); 27 | if (!(HaEConfigPathFile.exists() && HaEConfigPathFile.isDirectory())) { 28 | HaEConfigPathFile.mkdirs(); 29 | } 30 | 31 | File settingPathFile = new File(SettingPath); 32 | if (!(settingPathFile.exists() && settingPathFile.isFile())) { 33 | initSetting(); 34 | initRules(); 35 | } 36 | Config.ruleConfig = LoadConfig.getRules(); 37 | } 38 | 39 | 40 | // Initialize setting information 41 | public void initSetting() { 42 | Map r = new HashMap<>(); 43 | r.put("configPath", ConfigPath); 44 | r.put("excludeSuffix", getExcludeSuffix()); 45 | r.put("highlightMethod", getHighlightMethod()); 46 | try { 47 | Writer ws = new OutputStreamWriter(new FileOutputStream(SettingPath), StandardCharsets.UTF_8); 48 | yaml.dump(r, ws); 49 | } catch (Exception ex) { 50 | ex.printStackTrace(); 51 | } 52 | } 53 | 54 | // Initialize rule configuration 55 | public void initRules() { 56 | Rule rule = new Rule(); 57 | rule.setLoaded(true); 58 | rule.setName("Email"); 59 | rule.setColor("yellow"); 60 | rule.setEngine("nfa"); 61 | rule.setScope("response"); 62 | rule.setRegex("(([a-zA-Z0-9][_|\\.])*[a-zA-Z0-9]+@([a-zA-Z0-9][-|_|\\.])*[a-zA-Z0-9]+\\.((?!js|css|jpg|jpeg|png|ico)[a-zA-Z]{2,}))"); 63 | rule.setSensitive(false); 64 | 65 | Rules rules = new Rules(); 66 | rules.setType("Basic Information"); 67 | ArrayList rl = new ArrayList<>(); 68 | rl.add(rule); 69 | rules.setRule(rl); 70 | ArrayList rls = new ArrayList<>(); 71 | rls.add(rules); 72 | RulesConfig config = new RulesConfig(); 73 | config.setRules(rls); 74 | 75 | DumperOptions dop = new DumperOptions(); 76 | dop.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); 77 | Representer representer = new Representer(); 78 | representer.addClassTag(Config.class, Tag.MAP); 79 | 80 | Yaml yaml = new Yaml(new Constructor(),representer,dop); 81 | File f = new File(ConfigPath); 82 | try{ 83 | Writer ws = new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8); 84 | yaml.dump(config,ws); 85 | }catch (Exception ex){ 86 | ex.printStackTrace(); 87 | } 88 | } 89 | 90 | // Get configuration path 91 | public static String getConfigPath(){ 92 | try { 93 | InputStream inorder = new FileInputStream(SettingPath); 94 | Map r = yaml.load(inorder); 95 | return r.get("configPath").toString(); 96 | } catch (FileNotFoundException e) { 97 | e.printStackTrace(); 98 | return ConfigPath; 99 | } 100 | 101 | } 102 | 103 | // Ge the color highlighting setting 104 | public String getHighlightMethod(){ 105 | String highlightMethod = Config.highlightMethod[0]; 106 | File yamlSetting = new File(SettingPath); 107 | if (yamlSetting.exists() && yamlSetting.isFile()) { 108 | try { 109 | InputStream inorder = new FileInputStream(SettingPath); 110 | Map r = yaml.load(inorder); 111 | highlightMethod = r.get("highlightMethod").toString(); 112 | } catch (Exception e) { 113 | e.printStackTrace(); 114 | highlightMethod = Config.highlightMethod[0]; 115 | } 116 | } else { 117 | highlightMethod = Config.highlightMethod[0]; 118 | } 119 | return highlightMethod; 120 | } 121 | 122 | // Get the suffix to exclude 123 | public String getExcludeSuffix(){ 124 | String excludeSuffix = ""; 125 | File yamlSetting = new File(SettingPath); 126 | if (yamlSetting.exists() && yamlSetting.isFile()) { 127 | try { 128 | InputStream inorder = new FileInputStream(SettingPath); 129 | Map r = yaml.load(inorder); 130 | excludeSuffix = r.get("excludeSuffix").toString(); 131 | } catch (Exception e) { 132 | e.printStackTrace(); 133 | excludeSuffix = ""; 134 | } 135 | } else { 136 | excludeSuffix = Config.excludeSuffix; 137 | } 138 | return excludeSuffix; 139 | } 140 | 141 | // Get rule configuration 142 | public static Map getRules(){ 143 | InputStream inorder = null; 144 | { 145 | try { 146 | inorder = new FileInputStream(getConfigPath()); 147 | } catch (FileNotFoundException e) { 148 | e.printStackTrace(); 149 | } 150 | } 151 | Yaml yaml = new Yaml(new Constructor(RulesConfig.class)); 152 | RulesConfig rulesConfig = yaml.loadAs(inorder, RulesConfig.class); 153 | Map resRule = new HashMap<>(); 154 | rulesConfig.rules.forEach(i->{ 155 | ArrayList data = new ArrayList<>(); 156 | i.rule.forEach(j->{ 157 | try { 158 | data.add(j.getRuleObject()); 159 | }catch (Exception e){ 160 | e.printStackTrace(); 161 | } 162 | }); 163 | resRule.put(i.getType(), data.toArray(new Object[data.size()][])); 164 | }); 165 | return resRule; 166 | } 167 | 168 | 169 | // Set the file exclusion list 170 | public void setExcludeSuffix(String excludeSuffix, String highlightMethod){ 171 | Map r = new HashMap<>(); 172 | r.put("configPath", getConfigPath()); 173 | r.put("excludeSuffix", excludeSuffix); 174 | r.put("highlightMethod", highlightMethod); 175 | try{ 176 | Writer ws = new OutputStreamWriter(new FileOutputStream(SettingPath), StandardCharsets.UTF_8); 177 | yaml.dump(r, ws); 178 | }catch (Exception ex){ 179 | ex.printStackTrace(); 180 | } 181 | } 182 | 183 | } -------------------------------------------------------------------------------- /src/main/java/burp/yaml/RulesConfig.java: -------------------------------------------------------------------------------- 1 | package burp.yaml; 2 | 3 | import java.util.List; 4 | import burp.yaml.template.Rules; 5 | 6 | public class RulesConfig { 7 | public List rules; 8 | 9 | public void setRules(List rules) { 10 | this.rules = rules; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/burp/yaml/SetConfig.java: -------------------------------------------------------------------------------- 1 | package burp.yaml; 2 | 3 | import burp.Config; 4 | import burp.yaml.template.Rule; 5 | import burp.yaml.template.Rules; 6 | import org.yaml.snakeyaml.DumperOptions; 7 | import org.yaml.snakeyaml.Yaml; 8 | import org.yaml.snakeyaml.constructor.Constructor; 9 | import org.yaml.snakeyaml.nodes.Tag; 10 | import org.yaml.snakeyaml.representer.Representer; 11 | 12 | import java.io.File; 13 | import java.io.FileOutputStream; 14 | import java.io.OutputStreamWriter; 15 | import java.io.Writer; 16 | import java.nio.charset.StandardCharsets; 17 | import java.util.*; 18 | 19 | public class SetConfig { 20 | 21 | public void format() { 22 | DumperOptions dop = new DumperOptions(); 23 | dop.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); 24 | Representer representer = new Representer(); 25 | representer.addClassTag(RulesConfig.class, Tag.MAP); 26 | Yaml yaml = new Yaml(new Constructor(), representer, dop); 27 | RulesConfig con = new RulesConfig(); 28 | List rls = new ArrayList<>(); 29 | 30 | Config.ruleConfig.keySet().forEach(i-> 31 | { 32 | Rules rlsTmp = new Rules(); 33 | rlsTmp.setType(i); 34 | List rl = new ArrayList<>(); 35 | for (Object[] objects : Config.ruleConfig.get(i)) { 36 | Rule rlTmp = new Rule(); 37 | rlTmp.setName((String) objects[1]); 38 | rlTmp.setLoaded((Boolean) objects[0]); 39 | rlTmp.setRegex((String) objects[2]); 40 | rlTmp.setColor((String) objects[3]); 41 | rlTmp.setScope((String) objects[4]); 42 | rlTmp.setEngine((String) objects[5]); 43 | rlTmp.setSensitive((Boolean) objects[6]); 44 | rl.add(rlTmp); 45 | } 46 | rlsTmp.setRule(rl); 47 | rls.add(rlsTmp); 48 | }); 49 | con.setRules(rls); 50 | File f = new File(LoadConfig.getConfigPath()); 51 | try{ 52 | Writer ws = new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8); 53 | yaml.dump(con,ws); 54 | }catch (Exception ex){ 55 | ex.printStackTrace(); 56 | } 57 | } 58 | 59 | public void edit(Vector data, int select, String type) { 60 | Config.ruleConfig.get(type)[select] = data.toArray(); 61 | this.format(); 62 | } 63 | 64 | public void add(Vector data, String type) { 65 | ArrayList x = new ArrayList<>(Arrays.asList(Config.ruleConfig.get(type))); 66 | x.add(data.toArray()); 67 | Config.ruleConfig.put(type,x.toArray(new Object[x.size()][])); 68 | this.format(); 69 | } 70 | public void remove(int select,String type) { 71 | ArrayList x = new ArrayList<>(Arrays.asList(Config.ruleConfig.get(type))); 72 | x.remove(select); 73 | Config.ruleConfig.put(type,x.toArray(new Object[x.size()][])); 74 | this.format(); 75 | } 76 | 77 | public void rename(String oldName, String newName) { 78 | Config.ruleConfig.put(newName, Config.ruleConfig.remove(oldName)); 79 | this.format(); 80 | } 81 | 82 | public void deleteRules(String Rules) { 83 | Config.ruleConfig.remove(Rules); 84 | this.format(); 85 | } 86 | public String newRules() { 87 | int i = 0; 88 | String name = "New "; 89 | Object[][] data = new Object[][]{ 90 | { 91 | false, "New Name", "(New Regex)", "none", "any", "nfa", false 92 | } 93 | }; 94 | while (Config.ruleConfig.containsKey(name + i)) { 95 | i++; 96 | } 97 | Config.ruleConfig.put(name + i, data); 98 | this.format(); 99 | return name + i; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/burp/yaml/template/Rule.java: -------------------------------------------------------------------------------- 1 | package burp.yaml.template; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author LinChen 8 | */ 9 | 10 | public class Rule { 11 | private String Name; 12 | private Boolean Loaded; 13 | private String Regex; 14 | private String Color; 15 | private String Engine; 16 | private String Scope; 17 | private Boolean Sensitive; 18 | 19 | public Boolean getLoaded() { 20 | return Loaded; 21 | } 22 | public String getColor() { 23 | return Color; 24 | } 25 | 26 | public String getEngine() { 27 | return Engine; 28 | } 29 | 30 | public String getName() { 31 | return Name; 32 | } 33 | 34 | public String getRegex() { 35 | return Regex; 36 | } 37 | 38 | public String getScope() { 39 | return Scope; 40 | } 41 | 42 | public Boolean getSensitive(){ 43 | return Sensitive = Sensitive; 44 | } 45 | public void setLoaded(Boolean loaded) { 46 | this.Loaded = loaded; 47 | } 48 | 49 | 50 | public void setColor(String color) { 51 | this.Color = color; 52 | } 53 | 54 | public void setEngine(String engine) { 55 | this.Engine = engine; 56 | } 57 | 58 | public void setName(String name) { 59 | this.Name = name; 60 | } 61 | 62 | public void setRegex(String regex) { 63 | this.Regex = regex; 64 | } 65 | 66 | public void setScope(String scope) { 67 | this.Scope = scope; 68 | } 69 | public void setSensitive(Boolean sensitive){ 70 | this.Sensitive = sensitive; 71 | } 72 | 73 | public Object[] getRuleObject() { 74 | return new Object[] { Loaded, Name, Regex, Color, Scope, Engine,Sensitive }; 75 | } 76 | 77 | public Map getRuleObjMap(){ 78 | Map r = new HashMap<>(); 79 | r.put("Loaded", Loaded); 80 | r.put("Name", Name); 81 | r.put("Regex", Regex); 82 | r.put("Color", Color); 83 | r.put("Scope", Scope); 84 | r.put("Engine", Engine); 85 | r.put("Case Sensitive", Sensitive); 86 | return r; 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return "{ \nLoaded: " + Loaded + "\nName: " + Name + "\nRegex: " + Regex + "\nColor: " + Color + "\nScope: " + Scope + "\nEngine: " + Engine + "\nCase Sensitive: " + Sensitive + "\n }"; 92 | } 93 | } -------------------------------------------------------------------------------- /src/main/java/burp/yaml/template/Rules.java: -------------------------------------------------------------------------------- 1 | package burp.yaml.template; 2 | 3 | import burp.yaml.template.Rule; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author LinChen 9 | */ 10 | 11 | public class Rules { 12 | private String type; 13 | public List rule; 14 | 15 | public String getType() { 16 | return type; 17 | } 18 | 19 | public void setType(String type) { 20 | this.type = type; 21 | } 22 | 23 | public List getRule() { 24 | return rule; 25 | } 26 | 27 | public void setRule(List rule) { 28 | this.rule = rule; 29 | } 30 | 31 | public void setRuleObj(){} 32 | 33 | @Override 34 | public String toString(){ 35 | return "{ type: "+type+"\n config: "+ rule +"}\n"; 36 | } 37 | } --------------------------------------------------------------------------------