diff --git a/README.md b/README.md index 511674b..6190bab 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,11 @@
第一作者: EvilChen(中孚信息元亨实验室), 第二作者: 0chencc(米斯特安全团队)
- ## 项目介绍 -**HaE**是基于 `BurpSuite Java插件API` 开发的请求高亮标记与信息提取的辅助型框架式插件,该插件可以通过自定义正则的方式匹配响应报文或请求报文,并对满足正则匹配的报文进行信息高亮与提取。 +**HaE**是一个基于`BurpSuite Java插件API`开发的辅助型框架式插件,旨在实现对HTTP消息的高亮标记和信息提取。该插件通过自定义正则表达式匹配响应报文或请求报文,并对匹配成功的报文进行标记和提取。 -现代化Web应用走上前后端分离开发模式,这就导致在日常测试时候会有许多的流量,如果你想要尽可能全面的对一个Web应用进行测试评估,将花费大量精力浪费在无用的报文上;**HaE的出现正是为了解决这一类似场景**,借助HaE你可以**有效的减少**测试的时间,将更多的精力放在**有价值、有意义**的报文上,**提高漏洞挖掘效率**。 +随着现代化Web应用采用前后端分离的开发模式,日常漏洞挖掘的过程中,捕获的HTTP请求流量也相应增加。若想全面评估一个Web应用,会花费大量时间在无用的报文上。**HaE的出现旨在解决这类情况**,借助HaE,您能够**有效减少**测试时间,将更多精力集中在**有价值且有意义**的报文上,从而**提高漏洞挖掘效率**。 **注**: 要想灵活的使用`HaE`,你需要掌握正则表达式阅读、编写、修改能力;由于`Java`正则表达式的库并没有`Python`的优雅或方便,所以HaE要求使用者必须用`()`将所需提取的表达式内容包含;例如你要匹配一个**Shiro应用**的响应报文,正常匹配规则为`rememberMe=delete`,如果你要提取这段内容的话就需要变成`(rememberMe=delete)`。 @@ -22,35 +21,32 @@ 1. Linux/Mac用户的配置文件目录:`~/.config/HaE/` 2. Windows用户的配置文件目录:`%USERPROFILE%/.config/HaE/` - ## 优势特点 -1. **精细化配置项**:高自由度配置更适配精细化场景需求; -2. **简洁可视界面**:简洁的可视化界面让你更加清晰了解HaE的各项配置,操作更轻松,使用更简单; -3. **颜色升级算法**:内置颜色升级算法,避免“屠龙者终成恶龙”场景,突出最具价值的请求; -4. **标签化规则项**:标签化你的正则规则,让规则可分类,让管理更轻松; -5. **数据集合面板**:将所有匹配数据集合到Databoard中,使得测试、梳理更高效; -6. **高亮标记一体**:在Proxy - History页面你可以通过颜色高亮与Comment判断请求价值; -7. **实战化官方库**:基于实战化场景、案例进行输出的官方规则库,提升测试实战性; -8. **配置文件易读**:配置文件使用YAML格式存储,更加便于阅读与修改。 +1. 精细配置:高度自由的配置选项,以满足各类精细化场景需求。 +2. 分类标签:使用标签对规则进行分类,便于管理和组织规则。 +3. 高亮标记:在HTTP History页面,通过颜色高亮和注释判断请求的价值。 +4. 易读配置:使用易读的YAML格式存储配置文件,方便阅读和修改。 +5. 数据集合:将匹配到的数据、请求和响应集中在数据面板中,提高测试和梳理效率。 +6. 简洁可视:清晰可视的界面设计,更轻松地了解和配置HaE,操作简单、使用便捷。 +7. 颜色升级:内置颜色升级算法,避免“屠龙者终成恶龙”场景,突出最具价值的请求。 +8. 实战规则:官方规则库是基于实战化场景总结输出,提升数据发现的有效性、精准性。 | 界面名称 | 界面展示 | -| ------------------------- | ----------------------------------------------------- | +| ------------------------ | ---------------------------------------------------- | | Rules(规则信息管理) | | | Config(配置信息管理) | | | Databoard(数据集合面板) | | - - ## 实际使用 使用 RGPerson 生成测试数据,放入网站根目录文件中: -![-w467](images/16000719723284.jpg) +![-w467](images/rgperson.jpg) -访问该地址,在`Proxy - HTTP History`中可以看见高亮请求,响应标签页中含有`MarkINFO`标签,其中将匹配到的信息提取了出来。 +访问该地址,在`Proxy - HTTP History`中可以看见高亮请求,响应标签页中含有`MarkInfo`标签,其中将匹配到的信息提取了出来。 -![-w1047](images/16000720732854.png) +![-w1047](images/markinfo.png) ## 文末随笔 @@ -68,4 +64,4 @@ `HaE` 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-Galaxy) 中的一环,如果对 `HaE` 有任何疑问又或是想要找小伙伴交流,可以参考星链计划的加群方式。 -- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community) +- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community) \ No newline at end of file diff --git a/images/config.png b/images/config.png index f0106bd..451b0cf 100644 Binary files a/images/config.png and b/images/config.png differ diff --git a/images/databoard.png b/images/databoard.png index eaf47ba..728e852 100644 Binary files a/images/databoard.png and b/images/databoard.png differ diff --git a/images/16000720732854.png b/images/markinfo.png similarity index 100% rename from images/16000720732854.png rename to images/markinfo.png diff --git a/images/16000719723284.jpg b/images/rgperson.jpg similarity index 100% rename from images/16000719723284.jpg rename to images/rgperson.jpg diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java index 29da5ad..1f47093 100644 --- a/src/main/java/burp/BurpExtender.java +++ b/src/main/java/burp/BurpExtender.java @@ -1,8 +1,10 @@ package burp; -import burp.action.*; +import burp.core.processor.ColorProcessor; +import burp.core.processor.MessageProcessor; import burp.ui.MainUI; - +import burp.ui.board.MessagePanel; +import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.Objects; import javax.swing.*; @@ -19,14 +21,14 @@ import javax.swing.event.ChangeListener; */ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEditorTabFactory, ITab { - private final MainUI main = new MainUI(); + private MainUI main; // stdout变成公开属性,便于其他类调用输出调试信息 public static PrintWriter stdout; private IBurpExtenderCallbacks callbacks; private static IExtensionHelpers helpers; - GetColorKey gck = new GetColorKey(); - UpgradeColor uc = new UpgradeColor(); - ProcessMessage pm = new ProcessMessage(); + ColorProcessor colorProcessor = new ColorProcessor(); + MessageProcessor messageProcessor = new MessageProcessor(); + private MessagePanel messagePanel; @Override public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) @@ -34,21 +36,31 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito this.callbacks = callbacks; BurpExtender.helpers = callbacks.getHelpers(); - String version = "2.4.7"; + String version = "2.5"; callbacks.setExtensionName(String.format("HaE (%s) - Highlighter and Extractor", version)); + // 定义输出 stdout = new PrintWriter(callbacks.getStdout(), true); - stdout.println("@First Author: EvilChen"); - stdout.println("@Second Author: 0chencc"); - stdout.println("@Github: https://github.com/gh0stkey/HaE"); + stdout.println("[ HACK THE WORLD - TO DO IT ]"); + stdout.println("[#] Author: EvilChen & 0chencc"); + stdout.println("[#] Github: https://github.com/gh0stkey/HaE"); + // UI - SwingUtilities.invokeLater(this::initialize); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + initialize(); + } + }); callbacks.registerHttpListener(BurpExtender.this); callbacks.registerMessageEditorTabFactory(BurpExtender.this); + } private void initialize(){ + messagePanel = new MessagePanel(callbacks, helpers); + main = new MainUI(messagePanel); callbacks.customizeUiComponent(main); callbacks.addSuiteTab(BurpExtender.this); } @@ -71,6 +83,7 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito // 判断是否是响应,且该代码作用域为:REPEATER、INTRUDER、PROXY(分别对应toolFlag 64、32、4) if (toolFlag == 64 || toolFlag == 32 || toolFlag == 4) { byte[] content; + if (messageIsRequest) { content = messageInfo.getRequest(); } else { @@ -78,20 +91,29 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito } IHttpService iHttpService = null; + try { iHttpService = messageInfo.getHttpService(); } catch (Exception ignored) { } + // 获取请求主机信息 assert iHttpService != null; String host = iHttpService.getHost(); String c = new String(content, StandardCharsets.UTF_8).intern(); - List> result = pm.processMessageByContent(helpers, content, messageIsRequest, true, host); + List> result = null; + try { + result = messageProcessor.processMessage(helpers, content, messageIsRequest, true, host); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + String resComment = ""; + String resColor = ""; + String originalColor = messageInfo.getHighlight(); + String originalComment = messageInfo.getComment(); if (result != null && !result.isEmpty() && result.size() > 0) { - String originalColor = messageInfo.getHighlight(); - String originalComment = messageInfo.getComment(); List colorList = new ArrayList<>(); if (originalColor != null) { @@ -99,15 +121,20 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito } colorList.add(result.get(0).get("color")); - String color = uc.getEndColor(gck.getColorKeys(colorList)); - - messageInfo.setHighlight(color); + resColor = colorProcessor.retrieveFinalColor(colorProcessor.retrieveColorIndices(colorList)); + messageInfo.setHighlight(resColor); String addComment = String.join(", ", result.get(1).get("comment")); - String resComment = !Objects.equals(originalComment, "") ? String.format("%s, %s", originalComment, addComment) : addComment; - + resComment = !Objects.equals(originalComment, "") ? String.format("%s, %s", originalComment, addComment) : addComment; messageInfo.setComment(resComment); } + + String endComment = resComment.isEmpty() ? originalComment : resComment; + String endColor = resColor.isEmpty() ? originalColor : resColor; + + if (!messageIsRequest && !endComment.isEmpty() && !endColor.isEmpty()) { + messagePanel.add(messageInfo, endComment, String.valueOf(content.length), endColor); + } } } @@ -142,7 +169,12 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito @Override public boolean isEnabled(byte[] content, boolean isRequest) { String c = new String(content, StandardCharsets.UTF_8).intern(); - List> result = pm.processMessageByContent(helpers, content, isRequest, false, ""); + List> result = null; + try { + result = messageProcessor.processMessage(helpers, content, isRequest, false, ""); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } if (result != null && !result.isEmpty()) { Map dataMap = result.get(0); @@ -207,7 +239,6 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito Object[][] data = new Object[extractData.length][1]; for (int x = 0; x < extractData.length; x++) { data[x][0] = extractData[x]; - // stdout.println(extractData[x]); } JTable infoTable = new JTable(data, new Object[]{"Information"}); infoTable.setAutoCreateRowSorter(true); diff --git a/src/main/java/burp/action/DoAction.java b/src/main/java/burp/action/DoAction.java deleted file mode 100644 index 89d2f87..0000000 --- a/src/main/java/burp/action/DoAction.java +++ /dev/null @@ -1,38 +0,0 @@ -package burp.action; - -import burp.BurpExtender; -import java.util.HashMap; -import java.util.Map; -import java.util.ArrayList; -import java.util.List; - -/** - * @author EvilChen - */ - -public class DoAction { - public Map extractString(Map> obj) { - Map resultMap = new HashMap<>(); - obj.keySet().forEach(i->{ - Map tmpMap = obj.get(i); - String data = tmpMap.get("data").toString(); - resultMap.put(i, data); - }); - return resultMap; - } - - public List> highlightAndComment(Map> obj) { - List colorList = new ArrayList<>(); - List commentList = new ArrayList<>(); - List> result = new ArrayList<>(); - obj.keySet().forEach(i->{ - Map tmpMap = obj.get(i); - String color = tmpMap.get("color").toString(); - colorList.add(color); - commentList.add(i); - }); - result.add(colorList); - result.add(commentList); - return result; - } -} \ No newline at end of file diff --git a/src/main/java/burp/action/ExtractContent.java b/src/main/java/burp/action/ExtractContent.java deleted file mode 100644 index 6d3109b..0000000 --- a/src/main/java/burp/action/ExtractContent.java +++ /dev/null @@ -1,146 +0,0 @@ -package burp.action; - -import burp.BurpExtender; -import java.nio.charset.StandardCharsets; -import java.util.*; -import burp.Config; -import dk.brics.automaton.Automaton; -import dk.brics.automaton.AutomatonMatcher; -import dk.brics.automaton.RegExp; -import dk.brics.automaton.RunAutomaton; -import jregex.Matcher; -import jregex.Pattern; - -/** - * @author EvilChen - */ - -public class ExtractContent { - - public Map> matchRegex(byte[] content, String headers, byte[] body, String scopeString, String host) { - Map> map = new HashMap<>(); // 最终返回的结果 - Config.ruleConfig.keySet().forEach(i -> { - for (Object[] objects : Config.ruleConfig.get(i)) { - // 多线程执行,一定程度上减少阻塞现象 - Thread t = new Thread(() -> { - String matchContent = ""; - // 遍历获取规则 - List result = new ArrayList<>(); - Map tmpMap = new HashMap<>(); - - String name = objects[1].toString(); - boolean loaded = (Boolean) objects[0]; - String regex = objects[2].toString(); - String color = objects[3].toString(); - String scope = objects[4].toString(); - String engine = objects[5].toString(); - boolean sensitive = (Boolean) objects[6]; - // 判断规则是否开启与作用域 - if (loaded && (scope.contains(scopeString) || scope.contains("any"))) { - switch (scope) { - case "any": - case "request": - case "response": - matchContent = new String(content, StandardCharsets.UTF_8).intern(); - break; - case "any header": - case "request header": - case "response header": - matchContent = headers; - break; - case "any body": - case "request body": - case "response body": - matchContent = new String(body, StandardCharsets.UTF_8).intern(); - break; - default: - break; - } - - if ("nfa".equals(engine)) { - Pattern pattern; - // 判断规则是否大小写敏感 - if (sensitive) { - pattern = new Pattern(regex); - } else { - pattern = new Pattern(regex, Pattern.IGNORE_CASE); - } - - Matcher matcher = pattern.matcher(matchContent); - while (matcher.find()) { - // 添加匹配数据至list - // 强制用户使用()包裹正则 - result.add(matcher.group(1)); - } - } else { - RegExp regexp = new RegExp(regex); - Automaton auto = regexp.toAutomaton(); - RunAutomaton runAuto = new RunAutomaton(auto, true); - AutomatonMatcher autoMatcher = runAuto.newMatcher(matchContent); - while (autoMatcher.find()) { - // 添加匹配数据至list - // 强制用户使用()包裹正则 - result.add(autoMatcher.group()); - } - } - - // 去除重复内容 - HashSet tmpList = new HashSet(result); - result.clear(); - result.addAll(tmpList); - - String nameAndSize = String.format("%s (%s)", name, result.size()); - if (!result.isEmpty()) { - tmpMap.put("color", color); - String dataStr = String.join("\n", result); - tmpMap.put("data", dataStr); - map.put(nameAndSize, tmpMap); - - // 添加到全局变量中,便于Databoard检索 - if (!host.isEmpty()) { - String[] splitHost = host.split("\\."); - String anyHost = (splitHost.length > 2 && !host.matches("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b")) ? host.replace(splitHost[0], "*") : ""; - List dataList = Arrays.asList(dataStr.split("\n")); - if (Config.globalDataMap.containsKey(host)) { - Map> gRuleMap = new HashMap<>(Config.globalDataMap.get(host)); - if (gRuleMap.containsKey(name)) { - List gDataList = gRuleMap.get(name); - gDataList.addAll(dataList); - gDataList = new ArrayList<>(new HashSet<>(gDataList)); - gRuleMap.replace(name, gDataList); - } else { - gRuleMap.put(name, dataList); - } - Config.globalDataMap.remove(host); - Config.globalDataMap.put(host, gRuleMap); - } else { - Map> ruleMap = new HashMap<>(); - ruleMap.put(name, dataList); - // 添加单一Host - Config.globalDataMap.put(host, ruleMap); - } - - if (!Config.globalDataMap.containsKey(anyHost) && anyHost.length() > 0) { - // 添加通配符Host,实际数据从查询哪里将所有数据提取 - Config.globalDataMap.put(anyHost, new HashMap<>()); - } else if (!Config.globalDataMap.containsKey("*")) { - // 添加通配符全匹配,同上 - Config.globalDataMap.put("*", new HashMap<>()); - } - } - } - } - }); - t.start(); - try { - t.join(); - } catch (InterruptedException e) { - BurpExtender.stdout.println(e); - } - - - } - }); - return map; - } -} diff --git a/src/main/java/burp/action/GetColorKey.java b/src/main/java/burp/action/GetColorKey.java deleted file mode 100644 index e4754e9..0000000 --- a/src/main/java/burp/action/GetColorKey.java +++ /dev/null @@ -1,29 +0,0 @@ -package burp.action; - -import burp.Config; -import java.util.ArrayList; -import java.util.List; - -/** - * @author EvilChen - */ - -public class GetColorKey { - /** - * 颜色下标获取 - */ - public List getColorKeys(List keys){ - List result = new ArrayList<>(); - String[] colorArray = Config.colorArray; - int size = colorArray.length; - // 根据颜色获取下标 - for (String key : keys) { - for (int v = 0; v < size; v++) { - if (colorArray[v].equals(key)) { - result.add(v); - } - } - } - return result; - } -} diff --git a/src/main/java/burp/action/MatchHTTP.java b/src/main/java/burp/action/MatchHTTP.java deleted file mode 100644 index 60b0499..0000000 --- a/src/main/java/burp/action/MatchHTTP.java +++ /dev/null @@ -1,20 +0,0 @@ -package burp.action; - -import jregex.Matcher; -import jregex.Pattern; -import jregex.REFlags; -import burp.yaml.LoadConfig; - -/** - * @author EvilChen - */ - -public class MatchHTTP { - // 匹配后缀 - LoadConfig lc = new LoadConfig(); - public boolean matchSuffix(String str) { - Pattern pattern = new Pattern(String.format("[\\w]+[\\.](%s)", lc.getExcludeSuffix()), REFlags.IGNORE_CASE); - Matcher matcher = pattern.matcher(str); - return matcher.find(); - } -} diff --git a/src/main/java/burp/Config.java b/src/main/java/burp/config/ConfigEntry.java similarity index 91% rename from src/main/java/burp/Config.java rename to src/main/java/burp/config/ConfigEntry.java index 03b6545..29e1f4a 100644 --- a/src/main/java/burp/Config.java +++ b/src/main/java/burp/config/ConfigEntry.java @@ -1,14 +1,10 @@ -package burp; - -/** - * @author EvilChen - */ +package burp.config; import java.util.HashMap; import java.util.List; import java.util.Map; -public class Config { +public class ConfigEntry { public static String excludeSuffix = "3g2|3gp|7z|aac|abw|aif|aifc|aiff|apk|arc|au|avi|azw|bat|bin|bmp|bz|bz2|cmd|cmx|cod|com|csh|css|csv|dll|doc|docx|ear|eot|epub|exe|flac|flv|gif|gz|ico|ics|ief|jar|jfif|jpe|jpeg|jpg|less|m3u|mid|midi|mjs|mkv|mov|mp2|mp3|mp4|mpa|mpe|mpeg|mpg|mpkg|mpp|mpv2|odp|ods|odt|oga|ogg|ogv|ogx|otf|pbm|pdf|pgm|png|pnm|ppm|ppt|pptx|ra|ram|rar|ras|rgb|rmi|rtf|scss|sh|snd|svg|swf|tar|tif|tiff|ttf|vsd|war|wav|weba|webm|webp|wmv|woff|woff2|xbm|xls|xlsx|xpm|xul|xwd|zip"; public static String[] scopeArray = new String[] { @@ -40,7 +36,7 @@ public class Config { "gray" }; - public static Map ruleConfig = null; + public static Map globalRules = null; public static Map>> globalDataMap = new HashMap<>(); } \ No newline at end of file diff --git a/src/main/java/burp/config/ConfigLoader.java b/src/main/java/burp/config/ConfigLoader.java new file mode 100644 index 0000000..10000a8 --- /dev/null +++ b/src/main/java/burp/config/ConfigLoader.java @@ -0,0 +1,131 @@ +package burp.config; + +import burp.rule.utils.RuleTool; +import burp.rule.utils.YamlTool; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import org.yaml.snakeyaml.Yaml; + +/** + * @author EvilChen + */ + +public class ConfigLoader { + private static final Yaml yaml = YamlTool.newStandardYaml(); + private static final String HaEConfigPath = String.format("%s/.config/HaE", System.getProperty("user.home")); + private static final String RulesFilePath = String.format("%s/%s", HaEConfigPath, "Rules.yml"); + private static final String ConfigFilePath = String.format("%s/%s", HaEConfigPath, "Config.yml"); + + public ConfigLoader() { + // 构造函数,初始化配置 + File HaEConfigPathFile = new File(HaEConfigPath); + if (!(HaEConfigPathFile.exists() && HaEConfigPathFile.isDirectory())) { + HaEConfigPathFile.mkdirs(); + } + + File configFilePath = new File(ConfigFilePath); + + if (!(configFilePath.exists() && configFilePath.isFile())) { + initConfig(); + initRules(); + } + ConfigEntry.globalRules = ConfigLoader.getRules(); + } + + public void initConfig() { + Map r = new LinkedHashMap<>(); + r.put("rulesPath", RulesFilePath); + r.put("excludeSuffix", getExcludeSuffix()); + try { + Writer ws = new OutputStreamWriter(Files.newOutputStream(Paths.get(ConfigFilePath)), StandardCharsets.UTF_8); + yaml.dump(r, ws); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public void initRules() { + RuleTool rt = new RuleTool(RulesFilePath); + rt.getRulesFromSite(); + } + + public static String getRulesFilePath() { + try { + Map r = YamlTool.loadYaml(ConfigFilePath); + return r.get("rulesPath").toString(); + } catch (Exception e) { + e.printStackTrace(); + return RulesFilePath; + } + } + + public String getExcludeSuffix(){ + String excludeSuffix = ""; + File yamlSetting = new File(ConfigFilePath); + if (yamlSetting.exists() && yamlSetting.isFile()) { + try { + InputStream inorder = Files.newInputStream(Paths.get(ConfigFilePath)); + Map r = yaml.load(inorder); + excludeSuffix = r.get("excludeSuffix").toString(); + } catch (Exception e) { + // e.printStackTrace(); + excludeSuffix = ConfigEntry.excludeSuffix; + } + } else { + excludeSuffix = ConfigEntry.excludeSuffix; + } + return excludeSuffix; + } + + // 获取规则配置 + public static Map getRules() { + Map rulesMap = YamlTool.loadYaml(getRulesFilePath()); + Map resRule = new HashMap<>(); + String[] fieldKeys = {"loaded", "name", "regex", "color", "scope", "engine", "sensitive"}; + + Object rulesObj = rulesMap.get("rules"); + if (rulesObj instanceof List) { + List> groupData = (List>) rulesObj; + for (Map groupFields : groupData) { + ArrayList data = new ArrayList<>(); + + Object ruleObj = groupFields.get("rule"); + if (ruleObj instanceof List) { + List> ruleData = (List>) ruleObj; + for (Map ruleFields : ruleData) { + Object[] valuesArray = new Object[fieldKeys.length]; + for (int i = 0; i < fieldKeys.length; i++) { + valuesArray[i] = ruleFields.get(fieldKeys[i]); + } + data.add(valuesArray); + } + } + + Object[][] dataArray = data.toArray(new Object[data.size()][]); + resRule.put(groupFields.get("group").toString(), dataArray); + } + } + + return resRule; + } + + public void setExcludeSuffix(String excludeSuffix){ + Map r = new LinkedHashMap<>(); + r.put("rulesPath", getRulesFilePath()); + r.put("excludeSuffix", excludeSuffix); + try{ + Writer ws = new OutputStreamWriter(Files.newOutputStream(Paths.get(RulesFilePath)), StandardCharsets.UTF_8); + yaml.dump(r, ws); + }catch (Exception ex){ + ex.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/burp/core/GlobalCachePool.java b/src/main/java/burp/core/GlobalCachePool.java new file mode 100644 index 0000000..3844026 --- /dev/null +++ b/src/main/java/burp/core/GlobalCachePool.java @@ -0,0 +1,26 @@ +package burp.core; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author EvilChen + */ + +public class GlobalCachePool { + // 用于缓存匹配结果,以请求/响应的MD5 Hash作为索引 + private static final Map>> cache = new HashMap<>(); + + public static void addToCache(String key, Map> value) { + cache.put(key, value); + } + + public static Map> getFromCache(String key) { + return cache.get(key); + } + + public static void removeFromCache(String key) { + cache.remove(key); + } + +} \ No newline at end of file diff --git a/src/main/java/burp/action/UpgradeColor.java b/src/main/java/burp/core/processor/ColorProcessor.java similarity index 52% rename from src/main/java/burp/action/UpgradeColor.java rename to src/main/java/burp/core/processor/ColorProcessor.java index eca7b59..8ee6a14 100644 --- a/src/main/java/burp/action/UpgradeColor.java +++ b/src/main/java/burp/core/processor/ColorProcessor.java @@ -1,6 +1,6 @@ -package burp.action; +package burp.core.processor; -import burp.Config; +import burp.config.ConfigEntry; import java.util.*; @@ -8,14 +8,30 @@ import java.util.*; * @author EvilChen */ -public class UpgradeColor { - private String endColor = ""; +public class ColorProcessor { + private String finalColor = ""; + + public List retrieveColorIndices(List colors){ + List indices = new ArrayList<>(); + String[] colorArray = ConfigEntry.colorArray; + int size = colorArray.length; + + for (String color : colors) { + for (int i = 0; i < size; i++) { + if (colorArray[i].equals(color)) { + indices.add(i); + } + } + } + return indices; + } + /** * 颜色升级递归算法 */ - private void colorUpgrade(List colorList) { + private void upgradeColors(List colorList) { int colorSize = colorList.size(); - String[] colorArray = Config.colorArray; + String[] colorArray = ConfigEntry.colorArray; colorList.sort(Comparator.comparingInt(Integer::intValue)); int i = 0; List stack = new ArrayList<>(); @@ -36,17 +52,17 @@ public class UpgradeColor { if (stack.size() == tmpList.size()) { stack.sort(Comparator.comparingInt(Integer::intValue)); if(stack.get(0) < 0) { - this.endColor = colorArray[0]; + this.finalColor = colorArray[0]; } else { - this.endColor = colorArray[stack.get(0)]; + this.finalColor = colorArray[stack.get(0)]; } } else { - this.colorUpgrade(stack); + this.upgradeColors(stack); } } - public String getEndColor(List colorList) { - colorUpgrade(colorList); - return endColor; + public String retrieveFinalColor(List colorList) { + upgradeColors(colorList); + return finalColor; } } diff --git a/src/main/java/burp/core/processor/DataProcessingUnit.java b/src/main/java/burp/core/processor/DataProcessingUnit.java new file mode 100644 index 0000000..54732fb --- /dev/null +++ b/src/main/java/burp/core/processor/DataProcessingUnit.java @@ -0,0 +1,201 @@ +package burp.core.processor; + +import burp.core.GlobalCachePool; +import burp.core.utils.HashCalculator; +import burp.core.utils.MatchTool; +import burp.config.ConfigEntry; +import burp.core.utils.StringHelper; +import dk.brics.automaton.Automaton; +import dk.brics.automaton.AutomatonMatcher; +import dk.brics.automaton.RegExp; +import dk.brics.automaton.RunAutomaton; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.ArrayList; +import java.util.List; +import jregex.Matcher; +import jregex.Pattern; + +/** + * @author EvilChen + */ + +public class DataProcessingUnit { + public Map extractDataFromMap(Map> inputData) { + Map extractedData = new HashMap<>(); + inputData.keySet().forEach(key -> { + Map tempMap = inputData.get(key); + String data = tempMap.get("data").toString(); + extractedData.put(key, data); + }); + return extractedData; + } + + public List> extractColorsAndComments(Map> inputData) { + List colorList = new ArrayList<>(); + List commentList = new ArrayList<>(); + inputData.keySet().forEach(key -> { + Map tempMap = inputData.get(key); + String color = tempMap.get("color").toString(); + colorList.add(color); + commentList.add(key); + }); + List> result = new ArrayList<>(); + result.add(colorList); + result.add(commentList); + return result; + } + + public Map> matchContentByRegex(byte[] content, String headers, byte[] body, String scopeString, String host) + throws NoSuchAlgorithmException { + // 先从池子里判断是否有已经匹配好的结果 + String messageIndex = HashCalculator.calculateHash(content); + Map> map = GlobalCachePool.getFromCache(messageIndex); + if (map != null) { + return map; + } else { + // 最终返回的结果 + Map> finalMap = new HashMap<>(); + ConfigEntry.globalRules.keySet().forEach(i -> { + for (Object[] objects : ConfigEntry.globalRules.get(i)) { + // 多线程执行,一定程度上减少阻塞现象 + Thread t = new Thread(() -> { + String matchContent = ""; + // 遍历获取规则 + List result = new ArrayList<>(); + Map tmpMap = new HashMap<>(); + + String name = objects[1].toString(); + boolean loaded = (Boolean) objects[0]; + String regex = objects[2].toString(); + String color = objects[3].toString(); + String scope = objects[4].toString(); + String engine = objects[5].toString(); + boolean sensitive = (Boolean) objects[6]; + // 判断规则是否开启与作用域 + if (loaded && (scope.contains(scopeString) || scope.contains("any"))) { + switch (scope) { + case "any": + case "request": + case "response": + matchContent = new String(content, StandardCharsets.UTF_8).intern(); + break; + case "any header": + case "request header": + case "response header": + matchContent = headers; + break; + case "any body": + case "request body": + case "response body": + matchContent = new String(body, StandardCharsets.UTF_8).intern(); + break; + default: + break; + } + + if ("nfa".equals(engine)) { + Pattern pattern; + // 判断规则是否大小写敏感 + if (sensitive) { + pattern = new Pattern(regex); + } else { + pattern = new Pattern(regex, Pattern.IGNORE_CASE); + } + + Matcher matcher = pattern.matcher(matchContent); + while (matcher.find()) { + // 添加匹配数据至list + // 强制用户使用()包裹正则 + result.add(matcher.group(1)); + } + } else { + RegExp regexp = new RegExp(regex); + Automaton auto = regexp.toAutomaton(); + RunAutomaton runAuto = new RunAutomaton(auto, true); + AutomatonMatcher autoMatcher = runAuto.newMatcher(matchContent); + while (autoMatcher.find()) { + // 添加匹配数据至list + // 强制用户使用()包裹正则 + result.add(autoMatcher.group()); + } + } + + // 去除重复内容 + HashSet tmpList = new HashSet(result); + result.clear(); + result.addAll(tmpList); + + String nameAndSize = String.format("%s (%s)", name, result.size()); + if (!result.isEmpty()) { + tmpMap.put("color", color); + String dataStr = String.join("\n", result); + tmpMap.put("data", dataStr); + finalMap.put(nameAndSize, tmpMap); + + // 添加到全局变量中,便于Databoard检索 + if (!host.isEmpty()) { + List dataList = Arrays.asList(dataStr.split("\n")); + if (ConfigEntry.globalDataMap.containsKey(host)) { + Map> gRuleMap = new HashMap<>(ConfigEntry.globalDataMap.get(host)); + if (gRuleMap.containsKey(name)) { + // gDataList为不可变列表,因此需要重新创建一个列表以便于使用addAll方法 + List gDataList = gRuleMap.get(name); + List newDataList = new ArrayList<>(gDataList); + newDataList.addAll(dataList); + newDataList = new ArrayList<>(new HashSet<>(newDataList)); + gRuleMap.remove(name); + gRuleMap.put(name, newDataList); + } else { + gRuleMap.put(name, dataList); + } + ConfigEntry.globalDataMap.remove(host); + ConfigEntry.globalDataMap.put(host, gRuleMap); + } else { + Map> ruleMap = new HashMap<>(); + ruleMap.put(name, dataList); + // 添加单一Host + ConfigEntry.globalDataMap.put(host, ruleMap); + } + + String[] splitHost = host.split("\\."); + + String anyHost = (splitHost.length > 2 && !MatchTool.matchIP(host)) ? StringHelper.replaceFirstOccurrence(host, splitHost[0], "*") : ""; + + if (!ConfigEntry.globalDataMap.containsKey(anyHost) && anyHost.length() > 0) { + // 添加通配符Host,实际数据从查询哪里将所有数据提取 + ConfigEntry.globalDataMap.put(anyHost, new HashMap<>()); + } + + if (!ConfigEntry.globalDataMap.containsKey("*")) { + // 添加通配符全匹配,同上 + ConfigEntry.globalDataMap.put("*", new HashMap<>()); + } + + if (!ConfigEntry.globalDataMap.containsKey("**")) { + // 添加通配符全匹配,同上 + ConfigEntry.globalDataMap.put("**", new HashMap<>()); + } + } + } + } + }); + t.start(); + try { + t.join(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + }); + GlobalCachePool.addToCache(messageIndex, finalMap); + return finalMap; + } + + } +} \ No newline at end of file diff --git a/src/main/java/burp/action/ProcessMessage.java b/src/main/java/burp/core/processor/MessageProcessor.java similarity index 62% rename from src/main/java/burp/action/ProcessMessage.java rename to src/main/java/burp/core/processor/MessageProcessor.java index b9f6b57..6da2b37 100644 --- a/src/main/java/burp/action/ProcessMessage.java +++ b/src/main/java/burp/core/processor/MessageProcessor.java @@ -1,92 +1,78 @@ -package burp.action; +package burp.core.processor; -import burp.BurpExtender; import burp.IExtensionHelpers; +import burp.core.utils.MatchTool; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -public class ProcessMessage { - MatchHTTP mh = new MatchHTTP(); - ExtractContent ec = new ExtractContent(); - DoAction da = new DoAction(); - GetColorKey gck = new GetColorKey(); - UpgradeColor uc = new UpgradeColor(); +public class MessageProcessor { + MatchTool matcher = new MatchTool(); + DataProcessingUnit dataProcessingUnit = new DataProcessingUnit(); + ColorProcessor colorProcessor = new ColorProcessor(); - public List> processMessageByContent(IExtensionHelpers helpers, byte[] content, boolean isRequest, boolean messageInfo, String host) { - List> result = new ArrayList<>();; + public List> processMessage(IExtensionHelpers helpers, byte[] content, boolean isRequest, boolean messageInfo, String host) + throws NoSuchAlgorithmException { + List> result = new ArrayList<>(); Map> obj; if (isRequest) { - - // 获取报文头 List requestTmpHeaders = helpers.analyzeRequest(content).getHeaders(); String requestHeaders = String.join("\n", requestTmpHeaders); try { - // 流量清洗 String urlString = requestTmpHeaders.get(0).split(" ")[1]; urlString = urlString.indexOf("?") > 0 ? urlString.substring(0, urlString.indexOf("?")) : urlString; - - // 正则判断 - if (mh.matchSuffix(urlString)) { + if (matcher.matchUrlSuffix(urlString)) { return result; } } catch (Exception e) { return result; } - // 获取报文主体 int requestBodyOffset = helpers.analyzeRequest(content).getBodyOffset(); byte[] requestBody = Arrays.copyOfRange(content, requestBodyOffset, content.length); - - obj = ec.matchRegex(content, requestHeaders, requestBody, "request", host); + obj = dataProcessingUnit.matchContentByRegex(content, requestHeaders, requestBody, "request", host); } else { try { - // 流量清洗 String inferredMimeType = String.format("hae.%s", helpers.analyzeResponse(content).getInferredMimeType().toLowerCase()); String statedMimeType = String.format("hae.%s", helpers.analyzeResponse(content).getStatedMimeType().toLowerCase()); - // 正则判断 - if (mh.matchSuffix(statedMimeType) || mh.matchSuffix(inferredMimeType)) { + if (matcher.matchUrlSuffix(statedMimeType) || matcher.matchUrlSuffix(inferredMimeType)) { return result; } } catch (Exception e) { return result; } - // 获取报文头 List responseTmpHeaders = helpers.analyzeResponse(content).getHeaders(); String responseHeaders = String.join("\n", responseTmpHeaders); - - // 获取报文主体 int responseBodyOffset = helpers.analyzeResponse(content).getBodyOffset(); byte[] responseBody = Arrays.copyOfRange(content, responseBodyOffset, content.length); - obj = ec.matchRegex(content, responseHeaders, responseBody, "response", host); + obj = dataProcessingUnit.matchContentByRegex(content, responseHeaders, responseBody, "response", host); } if (obj.size() > 0) { if (messageInfo) { - List> resultList = da.highlightAndComment(obj); + List> resultList = dataProcessingUnit.extractColorsAndComments(obj); List colorList = resultList.get(0); List commentList = resultList.get(1); - if (colorList.size() != 0 && commentList.size() != 0) { - String color = uc.getEndColor(gck.getColorKeys(colorList)); - Map colorMap = new HashMap(){{ + if (!colorList.isEmpty() && !commentList.isEmpty()) { + String color = colorProcessor.retrieveFinalColor(colorProcessor.retrieveColorIndices(colorList)); + Map colorMap = new HashMap() {{ put("color", color); }}; - Map commentMap = new HashMap(){{ + Map commentMap = new HashMap() {{ put("comment", String.join(", ", commentList)); }}; result.add(colorMap); result.add(commentMap); } } else { - result.add(da.extractString(obj)); + result.add(dataProcessingUnit.extractDataFromMap(obj)); } } - return result; - } -} \ No newline at end of file +} diff --git a/src/main/java/burp/core/utils/HashCalculator.java b/src/main/java/burp/core/utils/HashCalculator.java new file mode 100644 index 0000000..a61f35f --- /dev/null +++ b/src/main/java/burp/core/utils/HashCalculator.java @@ -0,0 +1,28 @@ +package burp.core.utils; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * @author EvilChen + */ + +public class HashCalculator { + public static String calculateHash(byte[] bytes) throws NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance("MD5"); + byte[] hashBytes = digest.digest(bytes); + return bytesToHex(hashBytes); + } + + private static String bytesToHex(byte[] bytes) { + StringBuilder hexString = new StringBuilder(); + for (byte b : bytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} diff --git a/src/main/java/burp/core/utils/MatchTool.java b/src/main/java/burp/core/utils/MatchTool.java new file mode 100644 index 0000000..3b1a39e --- /dev/null +++ b/src/main/java/burp/core/utils/MatchTool.java @@ -0,0 +1,24 @@ +package burp.core.utils; + +import jregex.Pattern; +import jregex.REFlags; +import burp.config.ConfigLoader; + +/** + * @author EvilChen + */ + +public class MatchTool { + // 匹配后缀 + ConfigLoader configLoader = new ConfigLoader(); + + public boolean matchUrlSuffix(String str) { + Pattern pattern = new Pattern(String.format("[\\w]+[\\.](%s)", configLoader.getExcludeSuffix()), REFlags.IGNORE_CASE); + jregex.Matcher matcher = pattern.matcher(str); + return matcher.find(); + } + + public static boolean matchIP(String str) { + return str.matches("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b"); + } +} diff --git a/src/main/java/burp/core/utils/StringHelper.java b/src/main/java/burp/core/utils/StringHelper.java new file mode 100644 index 0000000..0e640be --- /dev/null +++ b/src/main/java/burp/core/utils/StringHelper.java @@ -0,0 +1,30 @@ +package burp.core.utils; + +public class StringHelper { + public static String replaceFirstOccurrence(String original, String find, String replace) { + int index = original.indexOf(find); + if (index != -1) { + return original.substring(0, index) + replace + original.substring(index + find.length()); + } + return original; + } + + public static boolean matchFromEnd(String input, String pattern) { + int inputLength = input.length(); + int patternLength = pattern.length(); + + int inputIndex = inputLength - 1; + int patternIndex = patternLength - 1; + + while (inputIndex >= 0 && patternIndex >= 0) { + if (input.charAt(inputIndex) != pattern.charAt(patternIndex)) { + return false; + } + inputIndex--; + patternIndex--; + } + + // 如果patternIndex为-1,表示pattern字符串已经完全匹配 + return patternIndex == -1; + } +} diff --git a/src/main/java/burp/rule/RuleProcessor.java b/src/main/java/burp/rule/RuleProcessor.java new file mode 100644 index 0000000..5f655ed --- /dev/null +++ b/src/main/java/burp/rule/RuleProcessor.java @@ -0,0 +1,98 @@ +package burp.rule; + +import burp.config.ConfigEntry; +import burp.config.ConfigLoader; +import burp.rule.model.Rule; +import burp.rule.model.RuleGroup; +import burp.rule.utils.YamlTool; +import java.io.IOException; +import java.nio.file.Files; +import java.util.stream.Collectors; +import org.yaml.snakeyaml.Yaml; +import java.io.File; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * @author EvilChen + */ + +public class RuleProcessor { + public void rulesFormatAndSave() { + Yaml yaml = YamlTool.newStandardYaml(); + List ruleGroupList = new ArrayList<>(); + + ConfigEntry.globalRules.forEach((k, v) -> { + List ruleList = Arrays.stream(v) + .map(objects -> new Rule( + (boolean) objects[0], + (String) objects[1], + (String) objects[2], + (String) objects[3], + (String) objects[4], + (String) objects[5], + (boolean) objects[6])) + .collect(Collectors.toList()); + ruleGroupList.add(new RuleGroup(k, ruleList)); + }); + + List> outputGroupsMap = ruleGroupList.stream() + .map(RuleGroup::getFields) + .collect(Collectors.toList()); + + Map outputMap = new LinkedHashMap<>(); + outputMap.put("rules", outputGroupsMap); + + File f = new File(ConfigLoader.getRulesFilePath()); + try (Writer ws = new OutputStreamWriter(Files.newOutputStream(f.toPath()), StandardCharsets.UTF_8)) { + yaml.dump(outputMap, ws); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + public void changeRule(Vector data, int select, String type) { + ConfigEntry.globalRules.get(type)[select] = data.toArray(); + this.rulesFormatAndSave(); + } + + public void addRule(Vector data, String type) { + ArrayList x = new ArrayList<>(Arrays.asList(ConfigEntry.globalRules.get(type))); + x.add(data.toArray()); + ConfigEntry.globalRules.put(type,x.toArray(new Object[x.size()][])); + this.rulesFormatAndSave(); + } + public void removeRule(int select,String type) { + ArrayList x = new ArrayList<>(Arrays.asList(ConfigEntry.globalRules.get(type))); + x.remove(select); + ConfigEntry.globalRules.put(type,x.toArray(new Object[x.size()][])); + this.rulesFormatAndSave(); + } + + public void renameRuleGroup(String oldName, String newName) { + ConfigEntry.globalRules.put(newName, ConfigEntry.globalRules.remove(oldName)); + this.rulesFormatAndSave(); + } + + public void deleteRuleGroup(String Rules) { + ConfigEntry.globalRules.remove(Rules); + this.rulesFormatAndSave(); + } + public String newRule() { + int i = 0; + String name = "New "; + Object[][] data = new Object[][] { + { + false, "New Name", "(New Regex)", "gray", "any", "nfa", false + } + }; + while (ConfigEntry.globalRules.containsKey(name + i)) { + i++; + } + ConfigEntry.globalRules.put(name + i, data); + this.rulesFormatAndSave(); + return name + i; + } +} diff --git a/src/main/java/burp/rule/model/Rule.java b/src/main/java/burp/rule/model/Rule.java new file mode 100644 index 0000000..fcc5191 --- /dev/null +++ b/src/main/java/burp/rule/model/Rule.java @@ -0,0 +1,35 @@ +package burp.rule.model; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @author EvilChen + */ + +public class Rule { + private Map fields; + + public Rule(boolean loaded, String name, String regex, String color, String scope, String engine, boolean sensitive) { + fields = new LinkedHashMap<>(); + fields.put("name", name); + fields.put("loaded", loaded); + fields.put("regex", regex); + fields.put("color", color); + fields.put("scope", scope); + fields.put("engine", engine); + fields.put("sensitive", sensitive); + } + + public Rule() { + + } + + public Map getFields() { + return fields; + } + + public void loadFields(Map fields) { + this.fields = fields; + } +} \ No newline at end of file diff --git a/src/main/java/burp/rule/model/RuleGroup.java b/src/main/java/burp/rule/model/RuleGroup.java new file mode 100644 index 0000000..1c9e9a1 --- /dev/null +++ b/src/main/java/burp/rule/model/RuleGroup.java @@ -0,0 +1,37 @@ +package burp.rule.model; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * @author EvilChen + */ + +public class RuleGroup { + private Map fields; + + public RuleGroup(String groupName, List rules) { + List> ruleList = new ArrayList<>(); + for (Rule rule : rules) { + ruleList.add(rule.getFields()); + } + + fields = new LinkedHashMap<>(); + fields.put("group", groupName); + fields.put("rule", ruleList); + } + + public RuleGroup() { + + } + + public Map getFields() { + return fields; + } + + public void loadFields(Map fields) { + this.fields = fields; + } +} \ No newline at end of file diff --git a/src/main/java/burp/rule/utils/RuleTool.java b/src/main/java/burp/rule/utils/RuleTool.java new file mode 100644 index 0000000..d65ff87 --- /dev/null +++ b/src/main/java/burp/rule/utils/RuleTool.java @@ -0,0 +1,35 @@ +package burp.rule.utils; + +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; +import java.io.FileOutputStream; +import javax.swing.JOptionPane; + +/** + * @author EvilChen + */ +public class RuleTool { + private String rulesFilePath; + + public RuleTool(String rulesFilePath) { + this.rulesFilePath = rulesFilePath; + } + + public void getRulesFromSite() { + String url = "https://cdn.jsdelivr.net/gh/gh0stkey/HaE@gh-pages/Rules.yml"; + OkHttpClient httpClient = new OkHttpClient(); + Request httpRequest = new Request.Builder().url(url).get().build(); + try { + Response httpResponse = httpClient.newCall(httpRequest).execute(); + // 获取官方规则文件,在线更新写入 + FileOutputStream fileOutputStream = new FileOutputStream(this.rulesFilePath); + fileOutputStream.write(httpResponse.body().bytes()); + JOptionPane.showMessageDialog(null, "Config file updated successfully!", "Error", + JOptionPane.INFORMATION_MESSAGE); + } catch (Exception ignored) { + JOptionPane.showMessageDialog(null, "Please check your network!", "Error", + JOptionPane.ERROR_MESSAGE); + } + } +} diff --git a/src/main/java/burp/rule/utils/YamlTool.java b/src/main/java/burp/rule/utils/YamlTool.java new file mode 100644 index 0000000..ff8c7be --- /dev/null +++ b/src/main/java/burp/rule/utils/YamlTool.java @@ -0,0 +1,35 @@ +package burp.rule.utils; + +import java.util.Map; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import org.yaml.snakeyaml.representer.Representer; + +/** + * @author EvilChen + */ + +public class YamlTool { + + public static Yaml newStandardYaml() { + DumperOptions dop = new DumperOptions(); + dop.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + Representer representer = new Representer(); + return new Yaml(representer, dop); + } + + public static Map loadYaml(String filePath) { + try { + InputStream inputStream = new FileInputStream(filePath); + Yaml yaml = newStandardYaml(); + return yaml.load(inputStream); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } + } +} + diff --git a/src/main/java/burp/ui/Databoard.java b/src/main/java/burp/ui/Databoard.java deleted file mode 100644 index 3562b53..0000000 --- a/src/main/java/burp/ui/Databoard.java +++ /dev/null @@ -1,248 +0,0 @@ -package burp.ui; - -import burp.Config; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import javax.swing.table.DefaultTableModel; -import org.jetbrains.annotations.NotNull; - -import java.awt.*; -import java.awt.event.*; -import java.util.ArrayList; -import java.util.Map; -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -/** - * @author LinChen && EvilChen - */ - -public class Databoard extends JPanel { - public Databoard() { - initComponents(); - } - - /** - * 清空数据 - */ - private void clearActionPerformed(ActionEvent e) { - // 清空页面 - dataTabbedPane.removeAll(); - String host = hostTextField.getText(); - if (host.contains("*")) { - Map>> ruleMap = Config.globalDataMap; - ruleMap.keySet().forEach(i -> { - if (i.contains(host.replace("*.", "")) || host.equals("*")) { - Config.globalDataMap.remove(i); - } - }); - } else { - Config.globalDataMap.remove(host); - } - } - - private void initComponents() { - // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents - hostLabel = new JLabel(); - hostTextField = new JTextField(); - dataTabbedPane = new JTabbedPane(); - clearButton = new JButton(); - - //======== this ======== - setLayout(new GridBagLayout()); - ((GridBagLayout)getLayout()).columnWidths = new int[] {25, 0, 0, 0, 20, 0}; - ((GridBagLayout)getLayout()).rowHeights = new int[] {0, 65, 20, 0}; - ((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 0.0, 1.0, 0.0, 0.0, 1.0E-4}; - ((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 1.0, 0.0, 1.0E-4}; - - //---- hostLabel ---- - hostLabel.setText("Host:"); - add(hostLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(8, 0, 5, 5), 0, 0)); - add(hostTextField, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(8, 0, 5, 5), 0, 0)); - clearButton.setText("Clear"); - clearButton.addActionListener(this::clearActionPerformed); - add(clearButton, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(8, 0, 5, 5), 0, 0)); - add(dataTabbedPane, new GridBagConstraints(1, 1, 3, 2, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(8, 0, 0, 5), 0, 0)); - - setAutoMatch(hostTextField, dataTabbedPane); - } - - /** - * 获取Host列表 - */ - private static List getHostByList(){ - List hostList = new ArrayList<>(); - hostList.addAll(Config.globalDataMap.keySet()); - return hostList; - } - - /** - * 设置输入自动匹配 - */ - public static void setAutoMatch(JTextField textField, JTabbedPane tabbedPane) { - final DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel(); - - final JComboBox hostComboBox = new JComboBox(comboBoxModel) { - @Override - public Dimension getPreferredSize() { - return new Dimension(super.getPreferredSize().width, 0); - } - }; - - isMatchHost = false; - - for (String host : getHostByList()) { - comboBoxModel.addElement(host); - } - - hostComboBox.setSelectedItem(null); - - hostComboBox.addActionListener(e -> { - if (!isMatchHost) { - if (hostComboBox.getSelectedItem() != null) { - textField.setText(hostComboBox.getSelectedItem().toString()); - getInfoByHost(hostComboBox, tabbedPane, textField); - } - } - }); - - // 事件监听 - textField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - isMatchHost = true; - if (e.getKeyCode() == KeyEvent.VK_SPACE) { - if (hostComboBox.isPopupVisible()) { - e.setKeyCode(KeyEvent.VK_ENTER); - } - } - if (e.getKeyCode() == KeyEvent.VK_ENTER - || e.getKeyCode() == KeyEvent.VK_UP - || e.getKeyCode() == KeyEvent.VK_DOWN) { - e.setSource(hostComboBox); - hostComboBox.dispatchEvent(e); - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - textField.setText(hostComboBox.getSelectedItem().toString()); - getInfoByHost(hostComboBox, tabbedPane, textField); - hostComboBox.setPopupVisible(false); - } - } - if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - hostComboBox.setPopupVisible(false); - } - isMatchHost = false; - } - }); - - textField.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - updateList(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - updateList(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - updateList(); - } - - private void updateList() { - isMatchHost = true; - comboBoxModel.removeAllElements(); - String input = textField.getText(); - if (!input.isEmpty()){ - for (String host : getHostByList()) { - if (host.toLowerCase().contains(input.toLowerCase())) { - if (host.length() == input.length()){ - comboBoxModel.insertElementAt(host,0); - comboBoxModel.setSelectedItem(host); - }else{ - comboBoxModel.addElement(host); - } - } - } - } - hostComboBox.setPopupVisible(comboBoxModel.getSize() > 0); - isMatchHost = false; - } - }); - - textField.setLayout(new BorderLayout()); - textField.add(hostComboBox, BorderLayout.SOUTH); - } - - private static void getInfoByHost(@NotNull JComboBox hostComboBox, JTabbedPane tabbedPane, JTextField textField) { - if (hostComboBox.getSelectedItem() != null) { - Map>> ruleMap = Config.globalDataMap; - Map> selectHost = new HashMap<>(); - String host = hostComboBox.getSelectedItem().toString(); - if (host.contains("*")) { - // 通配符数据 - Map> finalSelectHost = selectHost; - ruleMap.keySet().forEach(i -> { - if (i.contains(host.replace("*.", "")) || host.equals("*")) { - ruleMap.get(i).keySet().forEach(e -> { - if (finalSelectHost.containsKey(e)) { - // 合并操作 - List newList = new ArrayList<>(finalSelectHost.get(e)); - newList.addAll(ruleMap.get(i).get(e)); - // 去重操作 - HashSet tmpList = new HashSet(newList); - newList.clear(); - newList.addAll(tmpList); - // 添加操作 - finalSelectHost.put(e, newList); - } else { - finalSelectHost.put(e, ruleMap.get(i).get(e)); - } - }); - } - }); - } else { - selectHost = ruleMap.get(host); - } - - tabbedPane.removeAll(); - for(Map.Entry> entry: selectHost.entrySet()){ - tabbedPane.addTab(String.format("%s (%s)", entry.getKey(), entry.getValue().size()), new JScrollPane(new HitRuleDataList(entry.getValue()))); - } - textField.setText(hostComboBox.getSelectedItem().toString()); - } - } - - // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables - private JLabel hostLabel; - private JTextField hostTextField; - private JTabbedPane dataTabbedPane; - private JButton clearButton; - // JFormDesigner - End of variables declaration //GEN-END:variables - - // 是否自动匹配Host - private static Boolean isMatchHost = false; -} -class HitRuleDataList extends JTable { - public HitRuleDataList(List list){ - DefaultTableModel model = new DefaultTableModel(); - Object[][] data = new Object[list.size()][1]; - for (int x = 0; x < list.size(); x++) { - data[x][0] = list.get(x); - } - model.setDataVector(data, new Object[]{"Information"}); - this.setAutoCreateRowSorter(true); - this.setModel(model); - } -} diff --git a/src/main/java/burp/ui/JTabbedPaneCloseButton.java b/src/main/java/burp/ui/JTabbedPaneCloseButton.java deleted file mode 100644 index 4bd8ccb..0000000 --- a/src/main/java/burp/ui/JTabbedPaneCloseButton.java +++ /dev/null @@ -1,114 +0,0 @@ -package burp.ui; - -import javax.swing.*; -import javax.swing.plaf.metal.MetalIconFactory; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -/** - * @author 6dc - * - * A class which creates a JTabbedPane and auto sets a close button when you add a tab - */ - -public class JTabbedPaneCloseButton extends JTabbedPane { - - public JTabbedPaneCloseButton() { - super(); - } - - /** Override Addtab in order to add the close Button everytime */ - @Override - public void addTab(String title, Icon icon, Component component, String tip) { - super.addTab(title, icon, component, tip); - int count = this.getTabCount() - 1; - setTabComponentAt(count, new CloseButtonTab(component, title, icon)); - } - - @Override - public void addTab(String title, Icon icon, Component component) { - addTab(title, icon, component, null); - } - - @Override - public void addTab(String title, Component component) { - addTab(title, null, component); - } - - - public void addTab(String title,Component component,Boolean closewith){ - if (closewith){ - addTab(title,component); - }else{ - super.addTab(title,null,component,null); - } - } - - /** addTabNoExit */ - public void addTabNoExit(String title, Icon icon, Component component, String tip) { - super.addTab(title, icon, component, tip); - } - - public void addTabNoExit(String title, Icon icon, Component component) { - addTabNoExit(title, icon, component, null); - } - - public void addTabNoExit(String title, Component component) { - addTabNoExit(title, null, component); - } - - /** Button */ - public class CloseButtonTab extends JPanel { - public CloseButtonTab(final Component tab, String title, Icon icon) { - setOpaque(false); - FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 3, 3); - setLayout(flowLayout); - JLabel jLabel = new JLabel(title); - jLabel.setIcon(icon); - add(jLabel); - JButton button = new JButton(MetalIconFactory.getInternalFrameCloseIcon(2)); - button.setMargin(new Insets(0, 0, 0, 0)); - button.addMouseListener(new CloseListener(tab)); - add(button); - } - } - /** ClickListener */ - public class CloseListener implements MouseListener - { - private final Component tab; - - public CloseListener(Component tab){ - this.tab=tab; - } - - @Override - public void mouseClicked(MouseEvent e) { - if(e.getSource() instanceof JButton){ - JButton clickedButton = (JButton) e.getSource(); - JTabbedPane tabbedPane = (JTabbedPane) clickedButton.getParent().getParent().getParent(); - tabbedPane.remove(tab); - } - } - - @Override - public void mousePressed(MouseEvent e) {} - - @Override - public void mouseReleased(MouseEvent e) {} - - @Override - public void mouseEntered(MouseEvent e) { - if(e.getSource() instanceof JButton){ - JButton clickedButton = (JButton) e.getSource(); - } - } - - @Override - public void mouseExited(MouseEvent e) { - if(e.getSource() instanceof JButton){ - JButton clickedButton = (JButton) e.getSource(); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/burp/ui/MainUI.java b/src/main/java/burp/ui/MainUI.java index bca2d83..b6e46bd 100644 --- a/src/main/java/burp/ui/MainUI.java +++ b/src/main/java/burp/ui/MainUI.java @@ -1,13 +1,12 @@ package burp.ui; -import burp.Config; -import burp.yaml.LoadConfig; -import burp.yaml.SetConfig; - -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import java.io.FileOutputStream; +import burp.config.ConfigEntry; +import burp.config.ConfigLoader; +import burp.rule.RuleProcessor; +import burp.rule.utils.RuleTool; +import burp.ui.board.Databoard; +import burp.ui.board.MessagePanel; +import burp.ui.rule.RulePane; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -21,26 +20,22 @@ import java.util.Map; * @author LinChen && EvilChen */ -public class MainUI extends JPanel{ - private final LoadConfig loadConn = new LoadConfig(); +public class MainUI extends JPanel { + private final ConfigLoader loadConn = new ConfigLoader(); + private MessagePanel messagePanel; - public MainUI() { + public MainUI(MessagePanel messagePanel) { + this.messagePanel = messagePanel; + databoardPanel = new Databoard(this.messagePanel); initComponents(); } - public void closeTabActionPerformed(ActionEvent e){ - if (ruleTabbedPane.getTabCount()>2){ - if (ruleTabbedPane.getSelectedIndex()!=0){ - SetConfig setConn = new SetConfig(); - setConn.deleteRules(ruleTabbedPane.getTitleAt(ruleTabbedPane.getSelectedIndex())); - ruleTabbedPane.remove(ruleTabbedPane.getSelectedIndex()); - ruleTabbedPane.setSelectedIndex(ruleTabbedPane.getSelectedIndex()-1); - } else { - SetConfig setConn = new SetConfig(); - setConn.deleteRules(ruleTabbedPane.getTitleAt(ruleTabbedPane.getSelectedIndex())); - ruleTabbedPane.remove(ruleTabbedPane.getSelectedIndex()); - ruleTabbedPane.setSelectedIndex(ruleTabbedPane.getSelectedIndex()); - } + public void closeTabActionPerformed(ActionEvent e) { + if (ruleTabbedPane.getTabCount() > 2 && ruleTabbedPane.getSelectedIndex() != 0) { + String title = ruleTabbedPane.getTitleAt(ruleTabbedPane.getSelectedIndex()); + new RuleProcessor().deleteRuleGroup(title); + ruleTabbedPane.remove(ruleTabbedPane.getSelectedIndex()); + ruleTabbedPane.setSelectedIndex(ruleTabbedPane.getSelectedIndex() - 1); } } @@ -49,23 +44,10 @@ public class MainUI extends JPanel{ int retCode = JOptionPane.showConfirmDialog(null, "Do you want to update config?", "Info", JOptionPane.YES_NO_CANCEL_OPTION); if (retCode == JOptionPane.YES_OPTION) { - String url = "https://cdn.jsdelivr.net/gh/gh0stkey/HaE@gh-pages/Config.yml"; - OkHttpClient httpClient = new OkHttpClient(); - Request httpRequest = new Request.Builder().url(url).get().build(); - try { - Response httpResponse = httpClient.newCall(httpRequest).execute(); - // 获取官方规则文件,在线更新写入 - String configFile = configTextField.getText(); - FileOutputStream fileOutputStream = new FileOutputStream(configFile); - fileOutputStream.write(httpResponse.body().bytes()); - JOptionPane.showMessageDialog(null, "Config file updated successfully!", "Error", - JOptionPane.INFORMATION_MESSAGE); - } catch (Exception ignored) { - JOptionPane.showMessageDialog(null, "Please check your network!", "Error", - JOptionPane.ERROR_MESSAGE); - } - - new LoadConfig(); + String rulesFilePath = rulesPathTextField.getText(); + RuleTool rt = new RuleTool(rulesFilePath); + rt.getRulesFromSite(); + new ConfigLoader(); reloadRule(); } } @@ -73,12 +55,13 @@ public class MainUI extends JPanel{ private void reloadRule(){ ruleTabbedPane.removeAll(); ruleSwitch.setListen(false); - Map rules = LoadConfig.getRules(); + Map rules = ConfigLoader.getRules(); rules.keySet().forEach( - i-> ruleTabbedPane.addTab( + i -> ruleTabbedPane.addTab( i, new RulePane(rules.get(i), ruleTabbedPane) ) + ); ruleTabbedPane.addTab("...", new JLabel()); ruleSwitch.setListen(true); @@ -89,20 +72,20 @@ public class MainUI extends JPanel{ } private void excludeSuffixSaveActionPerformed(ActionEvent e) { - LoadConfig loadCon = new LoadConfig(); + ConfigLoader loadCon = new ConfigLoader(); loadCon.setExcludeSuffix(excludeSuffixTextField.getText()); } private void initComponents() { - mainTabbedPane = new JTabbedPane(); + JTabbedPane mainTabbedPane = new JTabbedPane(); ruleTabbedPane = new JTabbedPane(); - rulePanel = new JPanel(); - configTextField = new JTextField(); - configLabel = new JLabel(); - onlineUpdateButton = new JButton(); - reloadButton = new JButton(); - excludeSuffixLabel = new JLabel(); + JPanel rulePanel = new JPanel(); + rulesPathTextField = new JTextField(); + JLabel rulesPathLabel = new JLabel(); + JButton onlineUpdateButton = new JButton(); + JButton reloadButton = new JButton(); + JLabel excludeSuffixLabel = new JLabel(); excludeSuffixTextField = new JTextField(); - excludeSuffixSaveButton = new JButton(); + JButton excludeSuffixSaveButton = new JButton(); setLayout(new GridBagLayout()); ((GridBagLayout)getLayout()).columnWidths = new int[] {0, 0}; @@ -120,13 +103,13 @@ public class MainUI extends JPanel{ ((GridBagLayout) rulePanel.getLayout()).columnWeights = new double[] {0.0, 1.0, 0.0, 0.0, 1.0E-4}; ((GridBagLayout) rulePanel.getLayout()).rowWeights = new double[] {0.0, 0.0, 1.0E-4}; - configTextField.setEditable(false); - rulePanel.add(configTextField, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, + rulesPathTextField.setEditable(false); + rulePanel.add(rulesPathTextField, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 0, 5, 5), 0, 0)); - configLabel.setText("Config Path:"); - rulePanel.add(configLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, + rulesPathLabel.setText("Rules Path:"); + rulePanel.add(rulesPathLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(5, 5, 5, 5), 0, 0)); @@ -158,39 +141,33 @@ public class MainUI extends JPanel{ new Insets(0, 0, 0, 5), 0, 0)); } mainTabbedPane.addTab("Config", rulePanel); - mainTabbedPane.addTab("Databoard", databoardPanel); + mainTabbedPane.addTab("Databoard", this.databoardPanel); } add(mainTabbedPane, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); - Config.ruleConfig.keySet().forEach(i-> ruleTabbedPane.addTab(i,new RulePane(Config.ruleConfig.get(i), + ConfigEntry.globalRules.keySet().forEach(i-> ruleTabbedPane.addTab(i, new RulePane( + ConfigEntry.globalRules.get(i), ruleTabbedPane))); ruleTabbedPane.addTab("...",new JLabel()); - configTextField.setText(LoadConfig.getConfigPath()); + rulesPathTextField.setText(ConfigLoader.getRulesFilePath()); excludeSuffixTextField.setText(loadConn.getExcludeSuffix()); ruleSwitch = new TabTitleEditListener(ruleTabbedPane); ruleTabbedPane.addChangeListener(ruleSwitch); ruleTabbedPane.addMouseListener(ruleSwitch); - closeTabMenuItem.addActionListener(this::closeTabActionPerformed); - tabMenu.add(closeTabMenuItem); + deleteMenuItem.addActionListener(this::closeTabActionPerformed); + tabMenu.add(deleteMenuItem); } - private JTabbedPane mainTabbedPane; private JTabbedPane ruleTabbedPane; - private JPanel rulePanel; - private JTextField configTextField; - private JLabel configLabel; - private JButton onlineUpdateButton; - private JButton reloadButton; - private JLabel excludeSuffixLabel; + private JTextField rulesPathTextField; private JTextField excludeSuffixTextField; - private JButton excludeSuffixSaveButton; - private Databoard databoardPanel = new Databoard(); + private Databoard databoardPanel; protected static JPopupMenu tabMenu = new JPopupMenu(); - private JMenuItem closeTabMenuItem = new JMenuItem("Delete"); + private final JMenuItem deleteMenuItem = new JMenuItem("Delete"); private TabTitleEditListener ruleSwitch; } @@ -203,7 +180,7 @@ class TabTitleEditListener extends MouseAdapter implements ChangeListener, Docum protected Dimension dim; protected Component tabComponent; protected Boolean isRenameOk = false; - protected SetConfig setConfig = new SetConfig(); + protected RuleProcessor ruleProcessor = new RuleProcessor(); protected final Action startEditing = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { @@ -227,7 +204,7 @@ class TabTitleEditListener extends MouseAdapter implements ChangeListener, Docum if (editingIndex >= 0 && !title.isEmpty()) { String oldName = ruleEditTabbedPane.getTitleAt(editingIndex); ruleEditTabbedPane.setTitleAt(editingIndex, title); - setConfig.rename(oldName,title); + ruleProcessor.renameRuleGroup(oldName,title); } cancelEditing.actionPerformed(null); } @@ -285,7 +262,7 @@ class TabTitleEditListener extends MouseAdapter implements ChangeListener, Docum public void newTab(){ Object[][] data = new Object[][]{{false, "New Name", "(New Regex)", "gray", "any", "nfa", false}}; - insertTab(ruleEditTabbedPane, setConfig.newRules(),data); + insertTab(ruleEditTabbedPane, ruleProcessor.newRule(),data); } public void insertTab(JTabbedPane pane,String title,Object[][] data){ diff --git a/src/main/java/burp/ui/RuleSetting.java b/src/main/java/burp/ui/RuleSetting.java deleted file mode 100644 index 20aff1c..0000000 --- a/src/main/java/burp/ui/RuleSetting.java +++ /dev/null @@ -1,118 +0,0 @@ -package burp.ui; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import javax.swing.*; -import java.awt.*; -import burp.Config; - -/** - * @author LinChen - */ - -public class RuleSetting extends JPanel { - public RuleSetting() { - initComponents(); - } - - public void initComponents() { - sensitiveLabel = new JLabel(); - engineLabel = new JLabel(); - scopeLabel = new JLabel(); - regexTextField = new JTextField(); - regexLabel = new JLabel(); - nameLabel = new JLabel(); - ruleNameTextField = new JTextField(); - scopeComboBox = new JComboBox<>(); - engineComboBox = new JComboBox<>(); - colorLabel = new JLabel(); - colorComboBox = new JComboBox<>(); - sensitiveComboBox = new JComboBox<>(); - - setLayout(null); - - engineLabel.setText("Engine:"); - add(engineLabel); - engineLabel.setBounds(new Rectangle(new Point(10, 175), engineLabel.getPreferredSize())); - - sensitiveLabel.setText("Sensitive:"); - add(sensitiveLabel); - sensitiveLabel.setBounds(new Rectangle(new Point(10,215), sensitiveLabel.getPreferredSize())); - - scopeLabel.setText("Scope:"); - add(scopeLabel); - scopeLabel.setBounds(new Rectangle(new Point(10, 135), scopeLabel.getPreferredSize())); - add(regexTextField); - regexTextField.setBounds(70, 50, 265, 30); - - regexLabel.setText("Regex:"); - add(regexLabel); - regexLabel.setBounds(new Rectangle(new Point(10, 55), regexLabel.getPreferredSize())); - - nameLabel.setText("Name:"); - add(nameLabel); - nameLabel.setBounds(new Rectangle(new Point(10, 15), nameLabel.getPreferredSize())); - add(ruleNameTextField); - ruleNameTextField.setBounds(70, 10, 265, 30); - - scopeComboBox.setModel(new DefaultComboBoxModel<>(Config.scopeArray)); - add(scopeComboBox); - scopeComboBox.setBounds(70, 130, 265, scopeComboBox.getPreferredSize().height); - - engineComboBox.setModel(new DefaultComboBoxModel<>(Config.engineArray)); - engineComboBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - String engineValue = engineComboBox.getSelectedItem().toString(); - if (engineValue.equals("nfa")) { - sensitiveComboBox.setEnabled(true); - } else { - sensitiveComboBox.setEnabled(false); - } - } - }); - add(engineComboBox); - engineComboBox.setBounds(70, 170, 265, engineComboBox.getPreferredSize().height); - - colorLabel.setText("Color:"); - add(colorLabel); - colorLabel.setBounds(new Rectangle(new Point(10, 95), colorLabel.getPreferredSize())); - - colorComboBox.setModel(new DefaultComboBoxModel<>(Config.colorArray)); - add(colorComboBox); - colorComboBox.setBounds(70, 90, 265, colorComboBox.getPreferredSize().height); - - sensitiveComboBox.setModel(new DefaultComboBoxModel<>(new Boolean[]{true, false})); - add(sensitiveComboBox); - sensitiveComboBox.setBounds(70,210,265,sensitiveComboBox.getPreferredSize().height); - - { - Dimension preferredSize = new Dimension(); - for(int i = 0; i < getComponentCount(); i++) { - Rectangle bounds = getComponent(i).getBounds(); - preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width); - preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height); - } - Insets insets = getInsets(); - preferredSize.width += insets.right; - preferredSize.height += insets.bottom; - setMinimumSize(preferredSize); - setPreferredSize(preferredSize); - } - } - - private JLabel engineLabel; - private JLabel sensitiveLabel; - private JLabel scopeLabel; - public JTextField regexTextField; - private JLabel regexLabel; - private JLabel nameLabel; - public JTextField ruleNameTextField; - public JComboBox scopeComboBox; - public JComboBox engineComboBox; - private JLabel colorLabel; - public JComboBox colorComboBox; - public JComboBox sensitiveComboBox; -} diff --git a/src/main/java/burp/ui/board/CustomTableCellRenderer.java b/src/main/java/burp/ui/board/CustomTableCellRenderer.java new file mode 100644 index 0000000..6b22c15 --- /dev/null +++ b/src/main/java/burp/ui/board/CustomTableCellRenderer.java @@ -0,0 +1,64 @@ +package burp.ui.board; + +import java.awt.Color; +import java.awt.Component; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; + +public class CustomTableCellRenderer extends DefaultTableCellRenderer { + + private List log; + private Map colorMap = new HashMap<>(); + private JTable table; // 保存对表格的引用 + + public CustomTableCellRenderer(List log, JTable table) { + this.log = log; + this.colorMap.put("red", Color.RED); + this.colorMap.put("orange", Color.ORANGE); + this.colorMap.put("yellow", Color.YELLOW); + this.colorMap.put("green", Color.GREEN); + this.colorMap.put("cyan", Color.CYAN); + this.colorMap.put("blue", Color.BLUE); + this.colorMap.put("pink", Color.PINK); + this.colorMap.put("magenta", Color.MAGENTA); + this.colorMap.put("gray", Color.GRAY); + this.table = table; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) { + Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + LogEntry logEntry = log.get(table.convertRowIndexToModel(row)); // 使用convertRowIndexToModel方法转换行索引 + + // 设置颜色 + String colorByLog = logEntry.getColor(); + Color color = colorMap.get(colorByLog); + + if (isSelected) { + // 如果行被选中,设置阴影颜色 + component.setBackground(new Color(173, 216, 230)); // Light Blue + } else { + // 否则使用原始颜色 + component.setBackground(color); + } + + return component; + } + + @Override + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + super.firePropertyChange(propertyName, oldValue, newValue); + // 监听表格排序的属性变化 + if ("tableCellRenderer".equals(propertyName)) { + // 更新每一行数据的颜色 + for (int i = 0; i < table.getRowCount(); i++) { + table.repaint(table.getCellRect(i, 0, true)); + } + } + } +} diff --git a/src/main/java/burp/ui/board/Databoard.java b/src/main/java/burp/ui/board/Databoard.java new file mode 100644 index 0000000..88fc39f --- /dev/null +++ b/src/main/java/burp/ui/board/Databoard.java @@ -0,0 +1,358 @@ +package burp.ui.board; + +import burp.config.ConfigEntry; +import burp.core.utils.StringHelper; +import burp.ui.board.MessagePanel.Table; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; +import java.util.Map; +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +/** + * @author LinChen && EvilChen + */ + +public class Databoard extends JPanel { + private static Boolean isMatchHost = false; + private JLabel hostLabel; + private JTextField hostTextField; + private JTabbedPane dataTabbedPaneA; + private JTabbedPane dataTabbedPaneB; + private JButton clearButton; + private JSplitPane splitPane; + private MessagePanel messagePanel; + private Table table; + + public Databoard(MessagePanel messagePanel) { + this.messagePanel = messagePanel; + initComponents(); + } + + private void cleanUI() { + dataTabbedPaneA.removeAll(); + dataTabbedPaneB.removeAll(); + splitPane.setVisible(false); + } + + private void clearActionPerformed(ActionEvent e) { + cleanUI(); + + String host = hostTextField.getText(); + String cleanedHost = StringHelper.replaceFirstOccurrence(host, "*.", ""); + + if (host.contains("*")) { + ConfigEntry.globalDataMap.keySet().removeIf(i -> i.contains(cleanedHost) || cleanedHost.equals("**")); + } else { + ConfigEntry.globalDataMap.remove(host); + } + + messagePanel.deleteByHost(cleanedHost); + } + + + private void initComponents() { + // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents + hostLabel = new JLabel(); + hostTextField = new JTextField(); + dataTabbedPaneA = new JTabbedPane(JTabbedPane.TOP); + dataTabbedPaneB = new JTabbedPane(JTabbedPane.TOP); + clearButton = new JButton(); + + //======== this ======== + setLayout(new GridBagLayout()); + ((GridBagLayout)getLayout()).columnWidths = new int[] {25, 0, 0, 0, 20, 0}; + ((GridBagLayout)getLayout()).rowHeights = new int[] {0, 65, 20, 0}; + ((GridBagLayout)getLayout()).columnWeights = new double[] {0.0, 0.0, 1.0, 0.0, 0.0, 1.0E-4}; + ((GridBagLayout)getLayout()).rowWeights = new double[] {0.0, 1.0, 0.0, 1.0E-4}; + + //---- hostLabel ---- + hostLabel.setText("Host:"); + add(hostLabel, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(8, 0, 5, 5), 0, 0)); + add(hostTextField, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(8, 0, 5, 5), 0, 0)); + clearButton.setText("Clear"); + clearButton.addActionListener(this::clearActionPerformed); + add(clearButton, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(8, 0, 5, 5), 0, 0)); + + splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + splitPane.setVisible(false); + + add(splitPane, new GridBagConstraints(1, 1, 3, 2, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(8, 0, 5, 5), 0, 0)); + + setAutoMatch(); + } + + private static List getHostByList() { + return new ArrayList<>(ConfigEntry.globalDataMap.keySet()); + } + + /** + * 设置输入自动匹配 + */ + private void setAutoMatch() { + final DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel(); + + final JComboBox hostComboBox = new JComboBox(comboBoxModel) { + @Override + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, 0); + } + }; + + isMatchHost = false; + + for (String host : getHostByList()) { + comboBoxModel.addElement(host); + } + + hostComboBox.setSelectedItem(null); + + hostComboBox.addActionListener(e -> { + if (!isMatchHost) { + if (hostComboBox.getSelectedItem() != null) { + hostTextField.setText(hostComboBox.getSelectedItem().toString()); + populateTabbedPaneByHost(hostComboBox); + } + } + }); + + // 事件监听 + hostTextField.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + isMatchHost = true; + int keyCode = e.getKeyCode(); + + if (keyCode == KeyEvent.VK_SPACE && hostComboBox.isPopupVisible()) { + e.setKeyCode(KeyEvent.VK_ENTER); + } + + if (keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN) { + e.setSource(hostComboBox); + hostComboBox.dispatchEvent(e); + + if (keyCode == KeyEvent.VK_ENTER) { + String selectedItem = hostComboBox.getSelectedItem().toString(); + hostTextField.setText(selectedItem); + populateTabbedPaneByHost(hostComboBox); + hostComboBox.setPopupVisible(false); + return; + } + } + + if (keyCode == KeyEvent.VK_ESCAPE) { + hostComboBox.setPopupVisible(false); + } + + isMatchHost = false; + } + }); + + hostTextField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + updateList(); + + } + + @Override + public void removeUpdate(DocumentEvent e) { + updateList(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + updateList(); + } + + private void updateList() { + isMatchHost = true; + comboBoxModel.removeAllElements(); + String input = hostTextField.getText().toLowerCase(); + if (!input.isEmpty()){ + for (String host : getHostByList()) { + String lowerCaseHost = host.toLowerCase(); + if (lowerCaseHost.contains(input)) { + if (host.length() == input.length()){ + comboBoxModel.insertElementAt(host,0); + comboBoxModel.setSelectedItem(host); + } else { + comboBoxModel.addElement(host); + } + } + } + } + hostComboBox.setPopupVisible(comboBoxModel.getSize() > 0); + isMatchHost = false; + } + }); + + hostTextField.setLayout(new BorderLayout()); + hostTextField.add(hostComboBox, BorderLayout.SOUTH); + } + + private void applyHostFilter(String filterText) { + TableRowSorter sorter = (TableRowSorter) table.getRowSorter(); + if (filterText.contains("*.")) { + filterText = StringHelper.replaceFirstOccurrence(filterText, "*.", ""); + } else if (filterText.contains("*")) { + filterText = ""; + } + RowFilter filter = RowFilter.regexFilter(filterText, 1); + sorter.setRowFilter(filter); + filterText = filterText.isEmpty() ? "*" : filterText; + + messagePanel.applyHostFilter(filterText); + } + + private void populateTabbedPaneByHost(JComboBox hostComboBox) { + if (hostComboBox.getSelectedItem() != null) { + String selectedHost = hostComboBox.getSelectedItem().toString(); + Map>> dataMap = ConfigEntry.globalDataMap; + Map> selectedDataMap; + + if (selectedHost.contains("*")) { + // 通配符数据 + selectedDataMap = new HashMap<>(); + String hostPattern = StringHelper.replaceFirstOccurrence(selectedHost, "*.", ""); + for (String key : dataMap.keySet()) { + if (key.contains(hostPattern) || selectedHost.equals("*")) { + Map> ruleMap = dataMap.get(key); + for (String ruleKey : ruleMap.keySet()) { + List dataList = ruleMap.get(ruleKey); + if (selectedDataMap.containsKey(ruleKey)) { + List mergedList = new ArrayList<>(selectedDataMap.get(ruleKey)); + mergedList.addAll(dataList); + HashSet uniqueSet = new HashSet<>(mergedList); + selectedDataMap.put(ruleKey, new ArrayList<>(uniqueSet)); + } else { + selectedDataMap.put(ruleKey, dataList); + } + } + } + } + } else { + selectedDataMap = dataMap.get(selectedHost); + } + + // 由于removeChangeListener不知什么原因不生效,因此建立两个tabbedPane + dataTabbedPaneA.removeAll(); + dataTabbedPaneB.removeAll(); + + ChangeListener changeListenerInstance = new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + int selectedIndex = dataTabbedPaneA.getSelectedIndex(); + String selectedTitle = ""; + if (selectedIndex != -1) { + selectedTitle = dataTabbedPaneA.getTitleAt(selectedIndex); + } + applyHostFilter(selectedTitle); + } + }; + + if (selectedHost.equals("**")) { + dataTabbedPaneA.setPreferredSize(new Dimension(500,0)); + dataTabbedPaneA.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + splitPane.setLeftComponent(dataTabbedPaneA); + for (Map.Entry>> entry : dataMap.entrySet()) { + JTabbedPane newTabbedPane = new JTabbedPane(); + newTabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + for (Map.Entry> entrySet : entry.getValue().entrySet()) { + Thread t = new Thread(() -> { + String tabTitle = String.format("%s (%s)", entrySet.getKey(), entrySet.getValue().size()); + newTabbedPane.addTab(tabTitle, new JScrollPane(new DataTable(entrySet.getKey(), entrySet.getValue()))); + dataTabbedPaneA.addTab(entry.getKey(), newTabbedPane); + }); + t.start(); + try { + t.join(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + dataTabbedPaneA.addChangeListener(changeListenerInstance); + } else { + dataTabbedPaneB.setPreferredSize(new Dimension(500,0)); + dataTabbedPaneB.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + splitPane.setLeftComponent(dataTabbedPaneB); + for (Map.Entry> entry : selectedDataMap.entrySet()) { + String tabTitle = String.format("%s (%s)", entry.getKey(), entry.getValue().size()); + dataTabbedPaneB.addTab(tabTitle, new JScrollPane(new DataTable(entry.getKey(), entry.getValue()))); + } + } + + // 展示请求消息表单 + JSplitPane messageSplitPane = this.messagePanel.getPanel(); + this.splitPane.setRightComponent(messageSplitPane); + // 获取字段 + table = this.messagePanel.getTable(); + + // 设置对应字段宽度 + TableColumnModel columnModel = table.getColumnModel(); + TableColumn column = columnModel.getColumn(1); + column.setPreferredWidth(300); + column = columnModel.getColumn(2); + column.setPreferredWidth(300); + + splitPane.setVisible(true); + applyHostFilter(selectedHost); + + // 主动调用一次stateChanged,使得dataTabbedPane可以精准展示内容 + if (selectedHost.equals("**")) { + changeListenerInstance.stateChanged(null); + } + + hostTextField.setText(selectedHost); + } + } + + + class DataTable extends JTable { + public DataTable(String tableName, List list){ + DefaultTableModel model = new DefaultTableModel(); + Object[][] data = new Object[list.size()][1]; + for (int x = 0; x < list.size(); x++) { + data[x][0] = list.get(x); + } + model.setDataVector(data, new Object[]{"Information"}); + setAutoCreateRowSorter(true); + setModel(model); + setDefaultEditor(Object.class, null); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + int selectedRow = getSelectedRow(); + if (selectedRow != -1) { + String rowData = getValueAt(selectedRow, 0).toString(); + messagePanel.applyMessageFilter(tableName, rowData); + } + } + } + }); + } + } +} diff --git a/src/main/java/burp/ui/board/LogEntry.java b/src/main/java/burp/ui/board/LogEntry.java new file mode 100644 index 0000000..6b0f39a --- /dev/null +++ b/src/main/java/burp/ui/board/LogEntry.java @@ -0,0 +1,47 @@ +package burp.ui.board; + +import burp.IHttpRequestResponsePersisted; +import java.net.URL; + +public class LogEntry { + + private final String comment; + private final IHttpRequestResponsePersisted requestResponse; + private final URL url; + private final String length; + private final String color; + private final String method; + + LogEntry(IHttpRequestResponsePersisted requestResponse, String method, URL url, String comment, String length, String color) { + this.requestResponse = requestResponse; + this.method = method; + this.url = url; + this.comment = comment; + this.length = length; + this.color = color; + } + + public String getColor() { + return this.color; + } + + public URL getUrl() { + return this.url; + } + + public String getLength() { + return this.length; + } + + public String getComment() { + return this.comment; + } + + public String getMethod() { + return this.method; + } + + public IHttpRequestResponsePersisted getRequestResponse() { + return this.requestResponse; + } +} diff --git a/src/main/java/burp/ui/board/MessagePanel.java b/src/main/java/burp/ui/board/MessagePanel.java new file mode 100644 index 0000000..9031881 --- /dev/null +++ b/src/main/java/burp/ui/board/MessagePanel.java @@ -0,0 +1,345 @@ +package burp.ui.board; + +import burp.IBurpExtenderCallbacks; +import burp.IExtensionHelpers; +import burp.IHttpRequestResponse; +import burp.IHttpRequestResponsePersisted; +import burp.IHttpService; +import burp.IMessageEditor; +import burp.IMessageEditorController; +import burp.config.ConfigEntry; +import burp.core.utils.StringHelper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; + +/** + * @author EvilChen + */ + +public class MessagePanel extends AbstractTableModel implements IMessageEditorController { + private JSplitPane splitPane; + private IMessageEditor requestViewer; + private IMessageEditor responseViewer; + private final IBurpExtenderCallbacks callbacks; + private final List log = new ArrayList(); + private final List filteredLog = new ArrayList(); + private IHttpRequestResponse currentlyDisplayedItem; + private final IExtensionHelpers helpers; + private Table logTable; + + public MessagePanel(IBurpExtenderCallbacks callbacks, IExtensionHelpers helpers) { + this.callbacks = callbacks; + this.helpers = helpers; + + splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + + logTable = new Table(MessagePanel.this); + logTable.setDefaultRenderer(Object.class, new CustomTableCellRenderer(filteredLog, logTable)); + logTable.setAutoCreateRowSorter(true); + + // Length字段根据大小进行排序 + TableRowSorter sorter = (TableRowSorter) logTable.getRowSorter(); + sorter.setComparator(3, new Comparator() { + @Override + public int compare(String s1, String s2) { + Integer age1 = Integer.parseInt(s1); + Integer age2 = Integer.parseInt(s2); + return age1.compareTo(age2); + } + }); + // Color字段根据颜色顺序进行排序 + sorter.setComparator(4, new Comparator() { + @Override + public int compare(String s1, String s2) { + int index1 = getIndex(s1); + int index2 = getIndex(s2); + return Integer.compare(index1, index2); + } + private int getIndex(String color) { + for (int i = 0; i < ConfigEntry.colorArray.length; i++) { + if (ConfigEntry.colorArray[i].equals(color)) { + return i; + } + } + return -1; + } + }); + + logTable.setRowSorter(sorter); + logTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + JScrollPane scrollPane = new JScrollPane(logTable); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + splitPane.setLeftComponent(scrollPane); + + JTabbedPane tabs = new JTabbedPane(); + requestViewer = callbacks.createMessageEditor(MessagePanel.this, false); + + responseViewer = callbacks.createMessageEditor(MessagePanel.this, false); + tabs.addTab("Request", requestViewer.getComponent()); + tabs.addTab("Response", responseViewer.getComponent()); + splitPane.setRightComponent(tabs); + } + + public JSplitPane getPanel() { + return splitPane; + } + + public Table getTable() { + return logTable; + } + + public List getLogs() { + return log; + } + + @Override + public int getRowCount() + { + return filteredLog.size(); + } + + @Override + public int getColumnCount() + { + return 5; + } + + @Override + public String getColumnName(int columnIndex) + { + switch (columnIndex) + { + case 0: + return "Method"; + case 1: + return "URL"; + case 2: + return "Comment"; + case 3: + return "Length"; + case 4: + return "Color"; + default: + return ""; + } + } + + @Override + public Class getColumnClass(int columnIndex) + { + return String.class; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) + { + LogEntry logEntry = filteredLog.get(rowIndex); + switch (columnIndex) + { + case 0: + return logEntry.getMethod(); + case 1: + return logEntry.getUrl().toString(); + case 2: + return logEntry.getComment(); + case 3: + return logEntry.getLength(); + case 4: + return logEntry.getColor(); + default: + return ""; + } + } + + public void applyHostFilter(String filterText) { + filteredLog.clear(); + fireTableDataChanged(); + for (LogEntry entry : log) { + String host = entry.getUrl().getHost(); + if (StringHelper.matchFromEnd(host, filterText) || filterText.contains("*")) { + filteredLog.add(entry); + } + } + fireTableDataChanged(); + } + + public void applyMessageFilter(String tableName, String filterText) { + filteredLog.clear(); + for (LogEntry entry : log) { + IHttpRequestResponsePersisted requestResponse = entry.getRequestResponse(); + byte[] requestByte = requestResponse.getRequest(); + byte[] responseByte = requestResponse.getResponse(); + + List requestTmpHeaders = helpers.analyzeRequest(requestByte).getHeaders(); + byte[] requestHeaders = helpers.stringToBytes(String.join("\n", requestTmpHeaders)); + int requestBodyOffset = helpers.analyzeRequest(requestByte).getBodyOffset(); + byte[] requestBody = Arrays.copyOfRange(requestByte, requestBodyOffset, requestByte.length); + + List responseTmpHeaders = helpers.analyzeResponse(responseByte).getHeaders(); + byte[] responseHeaders = helpers.stringToBytes(String.join("\n", responseTmpHeaders)); + int responseBodyOffset = helpers.analyzeResponse(responseByte).getBodyOffset(); + byte[] responseBody = Arrays.copyOfRange(responseByte, responseBodyOffset, responseByte.length); + + final boolean[] isMatched = {false}; // 标志变量,表示是否满足过滤条件 + + ConfigEntry.globalRules.keySet().forEach(i -> { + for (Object[] objects : ConfigEntry.globalRules.get(i)) { + String name = objects[1].toString(); + String scope = objects[4].toString(); + if (name.contains(tableName)) { + boolean match = false; // 标志变量,表示当前规则是否匹配 + + switch (scope) { + case "any": + match = helpers.indexOf(requestByte, helpers.stringToBytes(filterText), true, 0, requestByte.length) != -1 || helpers.indexOf(responseByte, helpers.stringToBytes(filterText), true, 0, responseByte.length) != -1; + break; + case "request": + match = helpers.indexOf(requestByte, helpers.stringToBytes(filterText), true, 0, requestByte.length) != -1; + break; + case "response": + match = helpers.indexOf(responseByte, helpers.stringToBytes(filterText), true, 0, responseByte.length) != -1; + break; + case "any header": + match = helpers.indexOf(requestHeaders, helpers.stringToBytes(filterText), true, 0, requestHeaders.length) != -1 || helpers.indexOf(responseHeaders, helpers.stringToBytes(filterText), true, 0, responseHeaders.length) != -1; + break; + case "request header": + match = helpers.indexOf(requestHeaders, helpers.stringToBytes(filterText), true, 0, requestHeaders.length) != -1; + break; + case "response header": + match = helpers.indexOf(responseHeaders, helpers.stringToBytes(filterText), true, 0, responseHeaders.length) != -1; + break; + case "any body": + match = helpers.indexOf(requestBody, helpers.stringToBytes(filterText), true, 0, requestBody.length) != -1 || helpers.indexOf(responseBody, helpers.stringToBytes(filterText), true, 0, responseBody.length) != -1; + break; + case "request body": + match = helpers.indexOf(requestBody, helpers.stringToBytes(filterText), true, 0, requestBody.length) != -1; + break; + case "response body": + match = helpers.indexOf(responseBody, helpers.stringToBytes(filterText), true, 0, responseBody.length) != -1; + break; + default: + break; + } + + if (match) { + isMatched[0] = true; + break; + } + } + } + }); + + if (isMatched[0]) { + filteredLog.add(entry); + } + } + fireTableDataChanged(); + } + + public void deleteByHost(String filterText) { + filteredLog.clear(); + List rowsToRemove = new ArrayList<>(); + for (int i = 0; i < log.size(); i++) { + LogEntry entry = log.get(i); + String host = entry.getUrl().getHost(); + if (StringHelper.matchFromEnd(host, filterText) || filterText.contains("*")) { + rowsToRemove.add(i); + } + } + + for (int i = rowsToRemove.size() - 1; i >= 0; i--) { + int row = rowsToRemove.get(i); + log.remove(row); + } + + if (!rowsToRemove.isEmpty()) { + int[] rows = rowsToRemove.stream().mapToInt(Integer::intValue).toArray(); + fireTableRowsDeleted(rows[0], rows[rows.length - 1]); + } + } + + @Override + public byte[] getRequest() + { + return currentlyDisplayedItem.getRequest(); + } + + @Override + public byte[] getResponse() + { + return currentlyDisplayedItem.getResponse(); + } + + @Override + public IHttpService getHttpService() + { + return currentlyDisplayedItem.getHttpService(); + } + + public void add(IHttpRequestResponse messageInfo, String comment, String length, String color) { + synchronized(log) + { + LogEntry logEntry = new LogEntry(callbacks.saveBuffersToTempFiles(messageInfo), helpers.analyzeRequest(messageInfo).getMethod(), + helpers.analyzeRequest(messageInfo).getUrl(), comment, length, color); + log.add(logEntry); + } + } + + public class Table extends JTable { + LogEntry logEntry; + private SwingWorker currentWorker; + + public Table(TableModel tableModel) { + super(tableModel); + } + + @Override + public void changeSelection(int row, int col, boolean toggle, boolean extend) { + logEntry = filteredLog.get(convertRowIndexToModel(row)); + requestViewer.setMessage("Loading...".getBytes(), true); + responseViewer.setMessage("Loading...".getBytes(), false); + currentlyDisplayedItem = logEntry.getRequestResponse(); + + // 取消之前的后台任务 + if (currentWorker != null && !currentWorker.isDone()) { + currentWorker.cancel(true); + } + // 在后台线程中执行耗时操作 + SwingWorker worker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + refreshMessage(); + return null; + } + }; + // 设置当前后台任务 + currentWorker = worker; + // 启动后台线程 + worker.execute(); + super.changeSelection(row, col, toggle, extend); + } + + private void refreshMessage() { + SwingUtilities.invokeLater(() -> { + requestViewer.setMessage(logEntry.getRequestResponse().getRequest(), true); + responseViewer.setMessage(logEntry.getRequestResponse().getResponse(), false); + }); + } + } + +} + diff --git a/src/main/java/burp/ui/RulePane.java b/src/main/java/burp/ui/rule/RulePane.java similarity index 79% rename from src/main/java/burp/ui/RulePane.java rename to src/main/java/burp/ui/rule/RulePane.java index 15cfaa5..4b66be2 100644 --- a/src/main/java/burp/ui/RulePane.java +++ b/src/main/java/burp/ui/rule/RulePane.java @@ -1,33 +1,54 @@ -package burp.ui; - -import burp.yaml.SetConfig; +package burp.ui.rule; +import burp.rule.RuleProcessor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableRowSorter; import java.awt.*; import java.util.Vector; /** - * @author LinChen + * @author LinChen & EvilChen */ public class RulePane extends JPanel { + private RuleProcessor ruleProcessor = new RuleProcessor(); + private Boolean isEdit = false; + private DefaultTableModel model = createModel(); + private static final int YES_OPTION = JOptionPane.YES_OPTION; + private static final String[] TITLE = { + "Loaded", "Name", "Regex", "Color", "Scope", "Engine", "Sensitive" + }; + public RulePane(Object[][] data, JTabbedPane pane) { initComponents(data, pane); } - private SetConfig setConfig = new SetConfig(); - private Boolean isEdit = false; + private DefaultTableModel createModel() { + return new DefaultTableModel() { + @Override + public Class getColumnClass(int column) { + return (column == 0) ? Boolean.class : String.class; + } + + @Override + public boolean isCellEditable(int row, int column) { + return column == 0; + } + }; + } + + private void updateModel() { + model = (DefaultTableModel) ruleTable.getModel(); + } private void ruleAddActionPerformed(ActionEvent e, JTabbedPane pane) { RuleSetting ruleSettingPanel = new RuleSetting(); - int showState = JOptionPane.showConfirmDialog(null, ruleSettingPanel, "RuleSetting - Add Rule", JOptionPane.OK_OPTION); - if(showState == 0){ - Vector ruleData = new Vector(); + int showState = JOptionPane.showConfirmDialog(null, ruleSettingPanel, "Add Rule", JOptionPane.OK_OPTION); + if (showState == YES_OPTION) { + Vector ruleData = new Vector<>(); ruleData.add(false); ruleData.add(ruleSettingPanel.ruleNameTextField.getText()); ruleData.add(ruleSettingPanel.regexTextField.getText()); @@ -36,8 +57,8 @@ public class RulePane extends JPanel { ruleData.add(ruleSettingPanel.engineComboBox.getSelectedItem().toString()); ruleData.add(ruleSettingPanel.sensitiveComboBox.getSelectedItem()); model.insertRow(model.getRowCount(), ruleData); - model = (DefaultTableModel) ruleTable.getModel(); - setConfig.add(ruleData, pane.getTitleAt(pane.getSelectedIndex())); + updateModel(); + ruleProcessor.addRule(ruleData, pane.getTitleAt(pane.getSelectedIndex())); } } @@ -55,7 +76,7 @@ public class RulePane extends JPanel { ruleSettingPanel.engineComboBox.getSelectedItem().toString().equals("nfa") ); - int showState = JOptionPane.showConfirmDialog(null, ruleSettingPanel, "RuleSetting - Edit Rule", JOptionPane.OK_OPTION); + int showState = JOptionPane.showConfirmDialog(null, ruleSettingPanel, "Edit Rule", JOptionPane.OK_OPTION); if (showState == 0){ int select = ruleTable.convertRowIndexToModel(ruleTable.getSelectedRow()); model.setValueAt(ruleSettingPanel.ruleNameTextField.getText(), select, 1); @@ -65,19 +86,19 @@ public class RulePane extends JPanel { model.setValueAt(ruleSettingPanel.engineComboBox.getSelectedItem().toString(), select, 5); model.setValueAt(ruleSettingPanel.sensitiveComboBox.getSelectedItem(), select, 6); model = (DefaultTableModel) ruleTable.getModel(); - setConfig.edit((Vector) model.getDataVector().get(select), select, pane.getTitleAt(pane.getSelectedIndex())); + ruleProcessor.changeRule((Vector) model.getDataVector().get(select), select, pane.getTitleAt(pane.getSelectedIndex())); } } } private void ruleRemoveActionPerformed(ActionEvent e, JTabbedPane pane){ if (ruleTable.getSelectedRowCount() >= 1){ - int isOk = JOptionPane.showConfirmDialog(null, "Are your sure?", "RuleSetting - Delete Rule", JOptionPane.OK_OPTION); + int isOk = JOptionPane.showConfirmDialog(null, "Are your sure?", "Delete Rule", JOptionPane.OK_OPTION); if (isOk == 0){ int select = ruleTable.convertRowIndexToModel(ruleTable.getSelectedRow()); model.removeRow(select); model = (DefaultTableModel) ruleTable.getModel(); - setConfig.remove(select, pane.getTitleAt(pane.getSelectedIndex())); + ruleProcessor.removeRule(select, pane.getTitleAt(pane.getSelectedIndex())); } } } @@ -86,7 +107,7 @@ public class RulePane extends JPanel { if (e.getColumn() == 0 && ruleTable.getSelectedRow() != -1 && !isEdit){ model = (DefaultTableModel) ruleTable.getModel(); int select = ruleTable.convertRowIndexToModel(ruleTable.getSelectedRow()); - setConfig.edit((Vector) model.getDataVector().get(select), select, pane.getTitleAt(pane.getSelectedIndex())); + ruleProcessor.changeRule((Vector) model.getDataVector().get(select), select, pane.getTitleAt(pane.getSelectedIndex())); } } @@ -171,17 +192,10 @@ public class RulePane extends JPanel { GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 3, 2), 0, 0)); - // JFormDesigner - End of component initialization //GEN-END:initComponents ruleTable.setModel(model); - model.setDataVector(data, title); - model.addTableModelListener(new TableModelListener() { - @Override - public void tableChanged(TableModelEvent e) { - ruleTableChange(e, pane); - } - }); - - ruleTable.setRowSorter(new TableRowSorter(model)); + model.setDataVector(data, TITLE); + model.addTableModelListener(e -> ruleTableChange(e, pane)); + ruleTable.setRowSorter(new TableRowSorter<>(model)); } // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables @@ -191,21 +205,5 @@ public class RulePane extends JPanel { public JTable ruleTable; public JButton removeButton; // JFormDesigner - End of variables declaration //GEN-END:variables - private final String[] title = new String[]{"Loaded", "Name", "Regex", "Color", "Scope", "Engine", "Sensitive"}; - private DefaultTableModel model = new DefaultTableModel() { - @Override - public Class getColumnClass (int column){ - if (column == 0) { - return Boolean.class; - }else{ - return String.class; - } - } - - @Override - public boolean isCellEditable(int row, int column){ - return column == 0; - } - }; } diff --git a/src/main/java/burp/ui/rule/RuleSetting.java b/src/main/java/burp/ui/rule/RuleSetting.java new file mode 100644 index 0000000..ca52ec3 --- /dev/null +++ b/src/main/java/burp/ui/rule/RuleSetting.java @@ -0,0 +1,71 @@ +package burp.ui.rule; + +import java.awt.*; +import javax.swing.*; +import burp.config.ConfigEntry; + +/** + * @author LinChen & EvilChen + */ + +public class RuleSetting extends JPanel { + + public JTextField regexTextField; + public JTextField ruleNameTextField; + public JComboBox scopeComboBox; + public JComboBox engineComboBox; + public JComboBox colorComboBox; + public JComboBox sensitiveComboBox; + + public RuleSetting() { + initComponents(); + } + + private void initComponents() { + setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + + addLabel("Name:", 0, c); + ruleNameTextField = addTextField(0, c); + + addLabel("Regex:", 1, c); + regexTextField = addTextField(1, c); + + addLabel("Scope:", 2, c); + scopeComboBox = addComboBox(ConfigEntry.scopeArray, 2, c); + + addLabel("Engine:", 3, c); + engineComboBox = addComboBox(ConfigEntry.engineArray, 3, c); + engineComboBox.addActionListener(e -> sensitiveComboBox.setEnabled("nfa".equals(engineComboBox.getSelectedItem().toString()))); + + addLabel("Color:", 4, c); + colorComboBox = addComboBox(ConfigEntry.colorArray, 4, c); + + addLabel("Sensitive:", 5, c); + sensitiveComboBox = addComboBox(new Boolean[]{true, false}, 5, c); + } + + private void addLabel(String text, int y, GridBagConstraints c) { + JLabel label = new JLabel(text); + c.gridx = 0; + c.gridy = y; + add(label, c); + } + + private JTextField addTextField(int y, GridBagConstraints c) { + JTextField textField = new JTextField(35); + c.gridx = 1; + c.gridy = y; + add(textField, c); + return textField; + } + + private JComboBox addComboBox(T[] items, int y, GridBagConstraints c) { + JComboBox comboBox = new JComboBox<>(items); + c.gridx = 1; + c.gridy = y; + add(comboBox, c); + return comboBox; + } +} diff --git a/src/main/java/burp/yaml/LoadConfig.java b/src/main/java/burp/yaml/LoadConfig.java deleted file mode 100644 index 3bd68c1..0000000 --- a/src/main/java/burp/yaml/LoadConfig.java +++ /dev/null @@ -1,162 +0,0 @@ -package burp.yaml; - -import burp.Config; -import burp.yaml.template.*; - -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.ArrayList; - -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.representer.Representer; -import org.yaml.snakeyaml.nodes.Tag; - -public class LoadConfig { - private static final Yaml yaml = new Yaml(); - private static String HaEConfigPath = String.format("%s/.config/HaE", System.getProperty("user.home")); - private static String SettingPath = String.format("%s/%s", HaEConfigPath, "Setting.yml"); - private static String ConfigPath = String.format("%s/%s", HaEConfigPath, "Config.yml"); - - public LoadConfig() { - // 构造函数,初始化配置 - File HaEConfigPathFile = new File(HaEConfigPath); - if (!(HaEConfigPathFile.exists() && HaEConfigPathFile.isDirectory())) { - HaEConfigPathFile.mkdirs(); - } - - File settingPathFile = new File(SettingPath); - if (!(settingPathFile.exists() && settingPathFile.isFile())) { - initSetting(); - initRules(); - } - Config.ruleConfig = LoadConfig.getRules(); - } - - - // 初始化设置信息 - public void initSetting() { - Map r = new HashMap<>(); - r.put("configPath", ConfigPath); - r.put("excludeSuffix", getExcludeSuffix()); - try { - Writer ws = new OutputStreamWriter(new FileOutputStream(SettingPath), StandardCharsets.UTF_8); - yaml.dump(r, ws); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - // 初始化规则配置 - public void initRules() { - Rule rule = new Rule(); - rule.setLoaded(true); - rule.setName("Email"); - rule.setColor("yellow"); - rule.setEngine("nfa"); - rule.setScope("response"); - rule.setRegex("(([a-zA-Z0-9][_|\\.])*[a-zA-Z0-9]+@([a-zA-Z0-9][-|_|\\.])*[a-zA-Z0-9]+\\.((?!js|css|jpg|jpeg|png|ico)[a-zA-Z]{2,}))"); - rule.setSensitive(false); - - Rules rules = new Rules(); - rules.setType("Basic Information"); - ArrayList rl = new ArrayList<>(); - rl.add(rule); - rules.setRule(rl); - ArrayList rls = new ArrayList<>(); - rls.add(rules); - RulesConfig config = new RulesConfig(); - config.setRules(rls); - - DumperOptions dop = new DumperOptions(); - dop.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - Representer representer = new Representer(); - representer.addClassTag(Config.class, Tag.MAP); - - Yaml yaml = new Yaml(new Constructor(),representer,dop); - File f = new File(ConfigPath); - try{ - Writer ws = new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8); - yaml.dump(config,ws); - }catch (Exception ex){ - ex.printStackTrace(); - } - } - - // 获取配置路径 - public static String getConfigPath(){ - try { - InputStream inorder = new FileInputStream(SettingPath); - Map r = yaml.load(inorder); - return r.get("configPath").toString(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - return ConfigPath; - } - - } - - // 获取不包含的后缀名 - public String getExcludeSuffix(){ - String excludeSuffix = ""; - File yamlSetting = new File(SettingPath); - if (yamlSetting.exists() && yamlSetting.isFile()) { - try { - InputStream inorder = new FileInputStream(SettingPath); - Map r = yaml.load(inorder); - excludeSuffix = r.get("excludeSuffix").toString(); - } catch (Exception e) { - // e.printStackTrace(); - excludeSuffix = ""; - } - } else { - excludeSuffix = Config.excludeSuffix; - } - return excludeSuffix; - } - - // 获取规则配置 - public static Map getRules(){ - InputStream inorder = null; - { - try { - inorder = new FileInputStream(getConfigPath()); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - } - Yaml yaml = new Yaml(new Constructor(RulesConfig.class)); - RulesConfig rulesConfig = yaml.loadAs(inorder, RulesConfig.class); - Map resRule = new HashMap<>(); - rulesConfig.rules.forEach(i->{ - ArrayList data = new ArrayList<>(); - i.rule.forEach(j->{ - try { - data.add(j.getRuleObject()); - }catch (Exception e){ - e.printStackTrace(); - } - }); - resRule.put(i.getType(), data.toArray(new Object[data.size()][])); - }); - return resRule; - } - - - // 设置不包含的后缀名 - public void setExcludeSuffix(String excludeSuffix){ - Map r = new HashMap<>(); - r.put("configPath", getConfigPath()); - r.put("excludeSuffix", excludeSuffix); - try{ - Writer ws = new OutputStreamWriter(new FileOutputStream(SettingPath), StandardCharsets.UTF_8); - yaml.dump(r, ws); - }catch (Exception ex){ - ex.printStackTrace(); - } - } - -} \ No newline at end of file diff --git a/src/main/java/burp/yaml/RulesConfig.java b/src/main/java/burp/yaml/RulesConfig.java deleted file mode 100644 index 9f29549..0000000 --- a/src/main/java/burp/yaml/RulesConfig.java +++ /dev/null @@ -1,12 +0,0 @@ -package burp.yaml; - -import java.util.List; -import burp.yaml.template.Rules; - -public class RulesConfig { - public List rules; - - public void setRules(List rules) { - this.rules = rules; - } -} diff --git a/src/main/java/burp/yaml/SetConfig.java b/src/main/java/burp/yaml/SetConfig.java deleted file mode 100644 index ceacd0b..0000000 --- a/src/main/java/burp/yaml/SetConfig.java +++ /dev/null @@ -1,101 +0,0 @@ -package burp.yaml; - -import burp.Config; -import burp.yaml.template.Rule; -import burp.yaml.template.Rules; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.Constructor; -import org.yaml.snakeyaml.nodes.Tag; -import org.yaml.snakeyaml.representer.Representer; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.util.*; - -public class SetConfig { - - public void format() { - DumperOptions dop = new DumperOptions(); - dop.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - Representer representer = new Representer(); - representer.addClassTag(RulesConfig.class, Tag.MAP); - Yaml yaml = new Yaml(new Constructor(), representer, dop); - RulesConfig con = new RulesConfig(); - List rls = new ArrayList<>(); - - Config.ruleConfig.keySet().forEach(i-> - { - Rules rlsTmp = new Rules(); - rlsTmp.setType(i); - List rl = new ArrayList<>(); - for (Object[] objects : Config.ruleConfig.get(i)) { - Rule rlTmp = new Rule(); - rlTmp.setName((String) objects[1]); - rlTmp.setLoaded((Boolean) objects[0]); - rlTmp.setRegex((String) objects[2]); - rlTmp.setColor((String) objects[3]); - rlTmp.setScope((String) objects[4]); - rlTmp.setEngine((String) objects[5]); - rlTmp.setSensitive((Boolean) objects[6]); - rl.add(rlTmp); - } - rlsTmp.setRule(rl); - rls.add(rlsTmp); - }); - con.setRules(rls); - File f = new File(LoadConfig.getConfigPath()); - try{ - Writer ws = new OutputStreamWriter(new FileOutputStream(f), StandardCharsets.UTF_8); - yaml.dump(con,ws); - }catch (Exception ex){ - ex.printStackTrace(); - } - } - - public void edit(Vector data, int select, String type) { - Config.ruleConfig.get(type)[select] = data.toArray(); - this.format(); - } - - public void add(Vector data, String type) { - ArrayList x = new ArrayList<>(Arrays.asList(Config.ruleConfig.get(type))); - x.add(data.toArray()); - Config.ruleConfig.put(type,x.toArray(new Object[x.size()][])); - this.format(); - } - public void remove(int select,String type) { - ArrayList x = new ArrayList<>(Arrays.asList(Config.ruleConfig.get(type))); - x.remove(select); - Config.ruleConfig.put(type,x.toArray(new Object[x.size()][])); - this.format(); - } - - public void rename(String oldName, String newName) { - Config.ruleConfig.put(newName, Config.ruleConfig.remove(oldName)); - this.format(); - } - - public void deleteRules(String Rules) { - Config.ruleConfig.remove(Rules); - this.format(); - } - public String newRules() { - int i = 0; - String name = "New "; - Object[][] data = new Object[][]{ - { - false, "New Name", "(New Regex)", "gray", "any", "nfa", false - } - }; - while (Config.ruleConfig.containsKey(name + i)) { - i++; - } - Config.ruleConfig.put(name + i, data); - this.format(); - return name + i; - } -} diff --git a/src/main/java/burp/yaml/template/Rule.java b/src/main/java/burp/yaml/template/Rule.java deleted file mode 100644 index 7ec546b..0000000 --- a/src/main/java/burp/yaml/template/Rule.java +++ /dev/null @@ -1,93 +0,0 @@ -package burp.yaml.template; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author LinChen - */ - -public class Rule { - private String Name; - private Boolean Loaded; - private String Regex; - private String Color; - private String Engine; - private String Scope; - private Boolean Sensitive; - - public Boolean getLoaded() { - return Loaded; - } - public String getColor() { - return Color; - } - - public String getEngine() { - return Engine; - } - - public String getName() { - return Name; - } - - public String getRegex() { - return Regex; - } - - public String getScope() { - return Scope; - } - - public Boolean getSensitive(){ - return Sensitive = Sensitive; - } - public void setLoaded(Boolean loaded) { - this.Loaded = loaded; - } - - - public void setColor(String color) { - this.Color = color; - } - - public void setEngine(String engine) { - this.Engine = engine; - } - - public void setName(String name) { - this.Name = name; - } - - public void setRegex(String regex) { - this.Regex = regex; - } - - public void setScope(String scope) { - this.Scope = scope; - } - public void setSensitive(Boolean sensitive){ - this.Sensitive = sensitive; - } - - public Object[] getRuleObject() { - return new Object[] { Loaded, Name, Regex, Color, Scope, Engine,Sensitive }; - } - - public Map getRuleObjMap(){ - Map r = new HashMap<>(); - r.put("Loaded", Loaded); - r.put("Name", Name); - r.put("Regex", Regex); - r.put("Color", Color); - r.put("Scope", Scope); - r.put("Engine", Engine); - r.put("Sensitive", Sensitive); - return r; - } - - @Override - public String toString() { - return "{ \nLoaded: " + Loaded + "\nName: " + Name + "\nRegex: " + Regex + "\nColor: " + Color + "\nScope: " + Scope + "\nEngine: " + Engine + "\nSensitive: " + Sensitive + "\n }"; - } -} \ No newline at end of file diff --git a/src/main/java/burp/yaml/template/Rules.java b/src/main/java/burp/yaml/template/Rules.java deleted file mode 100644 index 4c9fb96..0000000 --- a/src/main/java/burp/yaml/template/Rules.java +++ /dev/null @@ -1,37 +0,0 @@ -package burp.yaml.template; - -import burp.yaml.template.Rule; - -import java.util.List; - -/** - * @author LinChen - */ - -public class Rules { - private String type; - public List rule; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public List getRule() { - return rule; - } - - public void setRule(List rule) { - this.rule = rule; - } - - public void setRuleObj(){} - - @Override - public String toString(){ - return "{ type: "+type+"\n config: "+ rule +"}\n"; - } -} \ No newline at end of file