Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99ed2cb2fd | ||
|
|
8a47f61caa | ||
|
|
ad323ba7a5 |
Binary file not shown.
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 176 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 328 KiB After Width: | Height: | Size: 362 KiB |
BIN
images/rules.png
BIN
images/rules.png
Binary file not shown.
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 162 KiB |
@@ -10,13 +10,13 @@ import hae.instances.editor.ResponseEditor;
|
|||||||
import hae.instances.editor.WebSocketEditor;
|
import hae.instances.editor.WebSocketEditor;
|
||||||
import hae.instances.http.HttpMessageHandler;
|
import hae.instances.http.HttpMessageHandler;
|
||||||
import hae.instances.websocket.WebSocketMessageHandler;
|
import hae.instances.websocket.WebSocketMessageHandler;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
|
|
||||||
public class HaE implements BurpExtension {
|
public class HaE implements BurpExtension {
|
||||||
@Override
|
@Override
|
||||||
public void initialize(MontoyaApi api) {
|
public void initialize(MontoyaApi api) {
|
||||||
// 设置扩展名称
|
// 设置扩展名称
|
||||||
String version = "3.1";
|
String version = "3.2";
|
||||||
api.extension().setName(String.format("HaE (%s) - Highlighter and Extractor", version));
|
api.extension().setName(String.format("HaE (%s) - Highlighter and Extractor", version));
|
||||||
|
|
||||||
// 加载扩展后输出的项目信息
|
// 加载扩展后输出的项目信息
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import hae.component.board.Databoard;
|
|||||||
import hae.component.board.message.MessageTableModel;
|
import hae.component.board.message.MessageTableModel;
|
||||||
import hae.component.config.Config;
|
import hae.component.config.Config;
|
||||||
import hae.component.rule.Rules;
|
import hae.component.rule.Rules;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|||||||
@@ -1,27 +1,39 @@
|
|||||||
package hae.component.board;
|
package hae.component.board;
|
||||||
|
|
||||||
import burp.api.montoya.MontoyaApi;
|
import burp.api.montoya.MontoyaApi;
|
||||||
|
import burp.api.montoya.http.HttpService;
|
||||||
|
import burp.api.montoya.http.message.HttpRequestResponse;
|
||||||
|
import burp.api.montoya.http.message.requests.HttpRequest;
|
||||||
|
import burp.api.montoya.http.message.responses.HttpResponse;
|
||||||
import hae.Config;
|
import hae.Config;
|
||||||
|
import hae.component.board.message.MessageEntry;
|
||||||
import hae.component.board.message.MessageTableModel;
|
import hae.component.board.message.MessageTableModel;
|
||||||
import hae.component.board.message.MessageTableModel.MessageTable;
|
import hae.component.board.message.MessageTableModel.MessageTable;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.instances.http.utils.RegularMatcher;
|
||||||
|
import hae.utils.ConfigLoader;
|
||||||
|
import hae.utils.project.ProjectProcessor;
|
||||||
|
import hae.utils.project.model.HaeFileContent;
|
||||||
import hae.utils.string.StringProcessor;
|
import hae.utils.string.StringProcessor;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
import javax.swing.table.TableColumnModel;
|
import javax.swing.table.TableColumnModel;
|
||||||
import javax.swing.table.TableModel;
|
import javax.swing.table.TableModel;
|
||||||
import javax.swing.table.TableRowSorter;
|
import javax.swing.table.TableRowSorter;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class Databoard extends JPanel {
|
public class Databoard extends JPanel {
|
||||||
private final MontoyaApi api;
|
private final MontoyaApi api;
|
||||||
private final ConfigLoader configLoader;
|
private final ConfigLoader configLoader;
|
||||||
|
private final ProjectProcessor projectProcessor;
|
||||||
private final MessageTableModel messageTableModel;
|
private final MessageTableModel messageTableModel;
|
||||||
private JTextField hostTextField;
|
private JTextField hostTextField;
|
||||||
private JTabbedPane dataTabbedPane;
|
private JTabbedPane dataTabbedPane;
|
||||||
@@ -35,6 +47,7 @@ public class Databoard extends JPanel {
|
|||||||
public Databoard(MontoyaApi api, ConfigLoader configLoader, MessageTableModel messageTableModel) {
|
public Databoard(MontoyaApi api, ConfigLoader configLoader, MessageTableModel messageTableModel) {
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.configLoader = configLoader;
|
this.configLoader = configLoader;
|
||||||
|
this.projectProcessor = new ProjectProcessor(api);
|
||||||
this.messageTableModel = messageTableModel;
|
this.messageTableModel = messageTableModel;
|
||||||
|
|
||||||
initComponents();
|
initComponents();
|
||||||
@@ -50,11 +63,15 @@ public class Databoard extends JPanel {
|
|||||||
JLabel hostLabel = new JLabel("Host:");
|
JLabel hostLabel = new JLabel("Host:");
|
||||||
|
|
||||||
JButton clearButton = new JButton("Clear");
|
JButton clearButton = new JButton("Clear");
|
||||||
|
JButton exportButton = new JButton("Export");
|
||||||
|
JButton importButton = new JButton("Import");
|
||||||
JButton actionButton = new JButton("Action");
|
JButton actionButton = new JButton("Action");
|
||||||
JPanel menuPanel = new JPanel(new GridLayout(1, 1));
|
JPanel menuPanel = new JPanel(new GridLayout(3, 1, 0, 5));
|
||||||
menuPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
|
menuPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
|
||||||
JPopupMenu menu = new JPopupMenu();
|
JPopupMenu menu = new JPopupMenu();
|
||||||
menuPanel.add(clearButton);
|
menuPanel.add(clearButton);
|
||||||
|
menuPanel.add(exportButton);
|
||||||
|
menuPanel.add(importButton);
|
||||||
menu.add(menuPanel);
|
menu.add(menuPanel);
|
||||||
|
|
||||||
hostTextField = new JTextField();
|
hostTextField = new JTextField();
|
||||||
@@ -68,6 +85,8 @@ public class Databoard extends JPanel {
|
|||||||
});
|
});
|
||||||
|
|
||||||
clearButton.addActionListener(this::clearActionPerformed);
|
clearButton.addActionListener(this::clearActionPerformed);
|
||||||
|
exportButton.addActionListener(this::exportActionPerformed);
|
||||||
|
importButton.addActionListener(this::importActionPerformed);
|
||||||
|
|
||||||
splitPane.addComponentListener(new ComponentAdapter() {
|
splitPane.addComponentListener(new ComponentAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@@ -204,9 +223,8 @@ public class Databoard extends JPanel {
|
|||||||
if (selectedHost.contains("*")) {
|
if (selectedHost.contains("*")) {
|
||||||
// 通配符数据
|
// 通配符数据
|
||||||
selectedDataMap = new HashMap<>();
|
selectedDataMap = new HashMap<>();
|
||||||
String hostPattern = StringProcessor.replaceFirstOccurrence(selectedHost, "*.", "");
|
|
||||||
for (String key : dataMap.keySet()) {
|
for (String key : dataMap.keySet()) {
|
||||||
if (key.contains(hostPattern) || selectedHost.equals("*")) {
|
if ((StringProcessor.matchesHostPattern(key, selectedHost) || selectedHost.equals("*")) && !key.contains("*")) {
|
||||||
Map<String, List<String>> ruleMap = dataMap.get(key);
|
Map<String, List<String>> ruleMap = dataMap.get(key);
|
||||||
for (String ruleKey : ruleMap.keySet()) {
|
for (String ruleKey : ruleMap.keySet()) {
|
||||||
List<String> dataList = ruleMap.get(ruleKey);
|
List<String> dataList = ruleMap.get(ruleKey);
|
||||||
@@ -256,7 +274,8 @@ public class Databoard extends JPanel {
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
String host = StringProcessor.getHostByUrl((String) entry.getValue(1));
|
String host = StringProcessor.getHostByUrl((String) entry.getValue(1));
|
||||||
return StringProcessor.matchFromEnd(host, cleanedText);
|
|
||||||
|
return StringProcessor.matchesHostPattern(host, filterText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -267,7 +286,155 @@ public class Databoard extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getHostByList() {
|
private List<String> getHostByList() {
|
||||||
return new ArrayList<>(Config.globalDataMap.keySet());
|
if (!(Config.globalDataMap.keySet().size() == 1 && Config.globalDataMap.keySet().stream().anyMatch(key -> key.contains("*")))) {
|
||||||
|
return new ArrayList<>(Config.globalDataMap.keySet());
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportActionPerformed(ActionEvent e) {
|
||||||
|
String selectedHost = hostTextField.getText().trim();
|
||||||
|
|
||||||
|
if (selectedHost.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String exportDir = selectDirectory(true);
|
||||||
|
|
||||||
|
if (exportDir.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConcurrentHashMap<String, Map<String, List<String>>> dataMap = Config.globalDataMap;
|
||||||
|
List<String> taskStatusList = exportData(selectedHost, exportDir, dataMap);
|
||||||
|
|
||||||
|
if (!taskStatusList.isEmpty()) {
|
||||||
|
String exportStatusMessage = String.format("Exported File List Status:\n%s", String.join("\n", taskStatusList));
|
||||||
|
JOptionPane.showConfirmDialog(null, exportStatusMessage, "Info", JOptionPane.YES_OPTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> exportData(String selectedHost, String exportDir, Map<String, Map<String, List<String>>> dataMap) {
|
||||||
|
return dataMap.entrySet().stream()
|
||||||
|
.filter(entry -> selectedHost.equals("*") || StringProcessor.matchesHostPattern(entry.getKey(), selectedHost))
|
||||||
|
.filter(entry -> !entry.getKey().contains("*"))
|
||||||
|
.map(entry -> exportEntry(entry, exportDir))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String exportEntry(Map.Entry<String, Map<String, List<String>>> entry, String exportDir) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
Map<String, List<String>> ruleMap = entry.getValue();
|
||||||
|
|
||||||
|
if (ruleMap == null || ruleMap.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MessageEntry> messageEntryList = messageTableModel.getLogs();
|
||||||
|
Map<String, Map<String, String>> httpMap = messageEntryList.stream()
|
||||||
|
.filter(messageEntry -> !StringProcessor.getHostByUrl(messageEntry.getUrl()).isEmpty())
|
||||||
|
.filter(messageEntry -> StringProcessor.getHostByUrl(messageEntry.getUrl()).equals(key))
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
MessageEntry::getUrl,
|
||||||
|
this::createHttpItemMap,
|
||||||
|
(existing, replacement) -> existing
|
||||||
|
));
|
||||||
|
|
||||||
|
String hostName = key.replace(":", "_");
|
||||||
|
String filename = String.format("%s/%s.hae", exportDir, hostName);
|
||||||
|
boolean createdStatus = projectProcessor.createHaeFile(filename, key, ruleMap, httpMap);
|
||||||
|
|
||||||
|
return String.format("Filename: %s, Status: %s", filename, createdStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> createHttpItemMap(MessageEntry entry) {
|
||||||
|
Map<String, String> httpItemMap = new HashMap<>();
|
||||||
|
httpItemMap.put("comment", entry.getComment());
|
||||||
|
httpItemMap.put("color", entry.getColor());
|
||||||
|
httpItemMap.put("request", entry.getRequestResponse().request().toString());
|
||||||
|
httpItemMap.put("response", entry.getRequestResponse().response().toString());
|
||||||
|
return httpItemMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importActionPerformed(ActionEvent e) {
|
||||||
|
String exportDir = selectDirectory(false);
|
||||||
|
if (exportDir.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> filesWithExtension = findFilesWithExtension(new File(exportDir), ".hae");
|
||||||
|
List<String> taskStatusList = filesWithExtension.stream()
|
||||||
|
.map(this::importData)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!taskStatusList.isEmpty()) {
|
||||||
|
String importStatusMessage = "Imported File List Status:\n" + String.join("\n", taskStatusList);
|
||||||
|
JOptionPane.showConfirmDialog(null, importStatusMessage, "Info", JOptionPane.YES_OPTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String importData(String filename) {
|
||||||
|
HaeFileContent haeFileContent = projectProcessor.readHaeFile(filename);
|
||||||
|
boolean readStatus = haeFileContent != null;
|
||||||
|
|
||||||
|
if (readStatus) {
|
||||||
|
String host = haeFileContent.getHost();
|
||||||
|
haeFileContent.getDataMap().forEach((key, value) -> RegularMatcher.putDataToGlobalMap(host, key, value));
|
||||||
|
|
||||||
|
haeFileContent.getHttpMap().forEach((key, httpItemMap) -> {
|
||||||
|
String comment = httpItemMap.get("comment");
|
||||||
|
String color = httpItemMap.get("color");
|
||||||
|
HttpRequestResponse httpRequestResponse = createHttpRequestResponse(key, httpItemMap);
|
||||||
|
messageTableModel.add(httpRequestResponse, comment, color);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format("Filename: %s, Status: %s", filename, readStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpRequestResponse createHttpRequestResponse(String key, Map<String, String> httpItemMap) {
|
||||||
|
HttpService httpService = HttpService.httpService(key);
|
||||||
|
HttpRequest httpRequest = HttpRequest.httpRequest(httpService, httpItemMap.get("request"));
|
||||||
|
HttpResponse httpResponse = HttpResponse.httpResponse(httpItemMap.get("response"));
|
||||||
|
return HttpRequestResponse.httpRequestResponse(httpRequest, httpResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> findFilesWithExtension(File directory, String extension) {
|
||||||
|
List<String> filePaths = new ArrayList<>();
|
||||||
|
if (directory.isDirectory()) {
|
||||||
|
File[] files = directory.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
filePaths.addAll(findFilesWithExtension(file, extension));
|
||||||
|
} else if (file.isFile() && file.getName().toLowerCase().endsWith(extension)) {
|
||||||
|
filePaths.add(file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filePaths.add(directory.getAbsolutePath());
|
||||||
|
return filePaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String selectDirectory(boolean forDirectories) {
|
||||||
|
JFileChooser chooser = new JFileChooser();
|
||||||
|
chooser.setCurrentDirectory(new java.io.File(configLoader.getRulesFilePath()));
|
||||||
|
chooser.setDialogTitle(String.format("Select a Directory%s", forDirectories ? "" : " or File"));
|
||||||
|
FileNameExtensionFilter filter = new FileNameExtensionFilter(".hae Files", "hae");
|
||||||
|
chooser.addChoosableFileFilter(filter);
|
||||||
|
chooser.setFileFilter(filter);
|
||||||
|
|
||||||
|
chooser.setFileSelectionMode(forDirectories ? JFileChooser.DIRECTORIES_ONLY : JFileChooser.FILES_AND_DIRECTORIES);
|
||||||
|
chooser.setAcceptAllFileFilterUsed(!forDirectories);
|
||||||
|
|
||||||
|
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||||||
|
File selectedDirectory = chooser.getSelectedFile();
|
||||||
|
return selectedDirectory.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearActionPerformed(ActionEvent e) {
|
private void clearActionPerformed(ActionEvent e) {
|
||||||
@@ -286,7 +453,7 @@ public class Databoard extends JPanel {
|
|||||||
Config.globalDataMap.remove(host);
|
Config.globalDataMap.remove(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
messageTableModel.deleteByHost(cleanedHost);
|
messageTableModel.deleteByHost(host);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package hae.component.board;
|
|||||||
|
|
||||||
import burp.api.montoya.MontoyaApi;
|
import burp.api.montoya.MontoyaApi;
|
||||||
import hae.component.board.message.MessageTableModel;
|
import hae.component.board.message.MessageTableModel;
|
||||||
import hae.utils.ui.UIEnhancer;
|
import hae.utils.UIEnhancer;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public class MessageTableModel extends AbstractTableModel {
|
|||||||
MessageEntry entry = log.get(i);
|
MessageEntry entry = log.get(i);
|
||||||
String host = StringProcessor.getHostByUrl(entry.getUrl());
|
String host = StringProcessor.getHostByUrl(entry.getUrl());
|
||||||
if (!host.isEmpty()) {
|
if (!host.isEmpty()) {
|
||||||
if (StringProcessor.matchFromEnd(host, filterText) || filterText.contains("*")) {
|
if (StringProcessor.matchesHostPattern(host, filterText) || filterText.contains("*")) {
|
||||||
rowsToRemove.add(i);
|
rowsToRemove.add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ public class MessageTableModel extends AbstractTableModel {
|
|||||||
for (MessageEntry entry : log) {
|
for (MessageEntry entry : log) {
|
||||||
String host = StringProcessor.getHostByUrl(entry.getUrl());
|
String host = StringProcessor.getHostByUrl(entry.getUrl());
|
||||||
if (!host.isEmpty()) {
|
if (!host.isEmpty()) {
|
||||||
if (filterText.contains("*.") && StringProcessor.matchFromEnd(host, cleanedText)) {
|
if (filterText.contains("*.") && StringProcessor.matchFromEnd(StringProcessor.extractHostname(host), cleanedText)) {
|
||||||
filteredLog.add(entry);
|
filteredLog.add(entry);
|
||||||
} else if (host.equals(filterText) || filterText.contains("*")) {
|
} else if (host.equals(filterText) || filterText.contains("*")) {
|
||||||
filteredLog.add(entry);
|
filteredLog.add(entry);
|
||||||
@@ -351,7 +351,6 @@ public class MessageTableModel extends AbstractTableModel {
|
|||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return filteredLog.size();
|
return filteredLog.size();
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package hae.component.config;
|
|||||||
|
|
||||||
import burp.api.montoya.MontoyaApi;
|
import burp.api.montoya.MontoyaApi;
|
||||||
import hae.component.rule.Rules;
|
import hae.component.rule.Rules;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
import hae.utils.ui.UIEnhancer;
|
import hae.utils.UIEnhancer;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
@@ -14,6 +14,8 @@ import java.awt.*;
|
|||||||
import java.awt.datatransfer.Clipboard;
|
import java.awt.datatransfer.Clipboard;
|
||||||
import java.awt.datatransfer.DataFlavor;
|
import java.awt.datatransfer.DataFlavor;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.KeyAdapter;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -23,6 +25,8 @@ public class Config extends JPanel {
|
|||||||
private final MontoyaApi api;
|
private final MontoyaApi api;
|
||||||
private final ConfigLoader configLoader;
|
private final ConfigLoader configLoader;
|
||||||
private final Rules rules;
|
private final Rules rules;
|
||||||
|
private JTextField addTextField;
|
||||||
|
private final String defaultText = "Enter a new item";
|
||||||
|
|
||||||
public Config(MontoyaApi api, ConfigLoader configLoader, Rules rules) {
|
public Config(MontoyaApi api, ConfigLoader configLoader, Rules rules) {
|
||||||
this.api = api;
|
this.api = api;
|
||||||
@@ -40,7 +44,7 @@ public class Config extends JPanel {
|
|||||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
|
||||||
JPanel ruleInfoPanel = new JPanel(new GridBagLayout());
|
JPanel ruleInfoPanel = new JPanel(new GridBagLayout());
|
||||||
ruleInfoPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
ruleInfoPanel.setBorder(new EmptyBorder(10, 15, 5, 15));
|
||||||
|
|
||||||
JLabel ruleLabel = new JLabel("Path:");
|
JLabel ruleLabel = new JLabel("Path:");
|
||||||
JTextField pathTextField = new JTextField();
|
JTextField pathTextField = new JTextField();
|
||||||
@@ -112,7 +116,7 @@ public class Config extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selected.equals("Block host")) {
|
if (selected.equals("Block host")) {
|
||||||
if (!values.equals(configLoader.getExcludeSuffix()) && !values.isEmpty()) {
|
if (!values.equals(configLoader.getBlockHost()) && !values.isEmpty()) {
|
||||||
configLoader.setBlockHost(values);
|
configLoader.setBlockHost(values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,8 +135,7 @@ public class Config extends JPanel {
|
|||||||
constraints.gridy = 4;
|
constraints.gridy = 4;
|
||||||
buttonPanel.add(clearButton, constraints);
|
buttonPanel.add(clearButton, constraints);
|
||||||
|
|
||||||
JTextField addTextField = new JTextField();
|
addTextField = new JTextField();
|
||||||
String defaultText = "Enter a new item";
|
|
||||||
UIEnhancer.setTextFieldPlaceholder(addTextField, defaultText);
|
UIEnhancer.setTextFieldPlaceholder(addTextField, defaultText);
|
||||||
|
|
||||||
inputPanelB.add(addTextField, BorderLayout.CENTER);
|
inputPanelB.add(addTextField, BorderLayout.CENTER);
|
||||||
@@ -142,13 +145,16 @@ public class Config extends JPanel {
|
|||||||
settingPanel.add(buttonPanel, BorderLayout.EAST);
|
settingPanel.add(buttonPanel, BorderLayout.EAST);
|
||||||
settingPanel.add(inputPanel, BorderLayout.CENTER);
|
settingPanel.add(inputPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
addButton.addActionListener(e -> {
|
|
||||||
String addTextFieldText = addTextField.getText();
|
addButton.addActionListener(e -> addActionPerformedAction(e, model));
|
||||||
if (!addTextFieldText.equals(defaultText)) {
|
|
||||||
addDataToTable(addTextFieldText, model);
|
addTextField.addKeyListener(new KeyAdapter() {
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
addActionPerformedAction(null, model);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addTextField.setText("");
|
|
||||||
addTextField.requestFocusInWindow();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
pasteButton.addActionListener(e -> {
|
pasteButton.addActionListener(e -> {
|
||||||
@@ -176,7 +182,7 @@ public class Config extends JPanel {
|
|||||||
JLabel settingLabel = new JLabel("Setting:");
|
JLabel settingLabel = new JLabel("Setting:");
|
||||||
JPanel settingLabelPanel = new JPanel(new BorderLayout());
|
JPanel settingLabelPanel = new JPanel(new BorderLayout());
|
||||||
settingLabelPanel.add(settingLabel, BorderLayout.WEST);
|
settingLabelPanel.add(settingLabel, BorderLayout.WEST);
|
||||||
settingMainPanel.setBorder(new EmptyBorder(0, 5, 10, 5));
|
settingMainPanel.setBorder(new EmptyBorder(0, 15, 10, 15));
|
||||||
settingMainPanel.add(settingLabelPanel, BorderLayout.NORTH);
|
settingMainPanel.add(settingLabelPanel, BorderLayout.NORTH);
|
||||||
settingMainPanel.add(settingPanel, BorderLayout.CENTER);
|
settingMainPanel.add(settingPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
@@ -184,6 +190,7 @@ public class Config extends JPanel {
|
|||||||
add(settingMainPanel, BorderLayout.CENTER);
|
add(settingMainPanel, BorderLayout.CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String getFirstColumnDataAsString(DefaultTableModel model) {
|
private String getFirstColumnDataAsString(DefaultTableModel model) {
|
||||||
StringBuilder firstColumnData = new StringBuilder();
|
StringBuilder firstColumnData = new StringBuilder();
|
||||||
int numRows = model.getRowCount();
|
int numRows = model.getRowCount();
|
||||||
@@ -232,6 +239,15 @@ public class Config extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addActionPerformedAction(ActionEvent e, DefaultTableModel model) {
|
||||||
|
String addTextFieldText = addTextField.getText();
|
||||||
|
if (!addTextFieldText.equals(defaultText)) {
|
||||||
|
addDataToTable(addTextFieldText, model);
|
||||||
|
}
|
||||||
|
addTextField.setText("");
|
||||||
|
addTextField.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
|
||||||
private void onlineUpdateActionPerformed(ActionEvent e) {
|
private void onlineUpdateActionPerformed(ActionEvent e) {
|
||||||
// 添加提示框防止用户误触导致配置更新
|
// 添加提示框防止用户误触导致配置更新
|
||||||
int retCode = JOptionPane.showConfirmDialog(null, "Do you want to update rules?", "Info", JOptionPane.YES_NO_OPTION);
|
int retCode = JOptionPane.showConfirmDialog(null, "Do you want to update rules?", "Info", JOptionPane.YES_NO_OPTION);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package hae.component.rule;
|
|||||||
|
|
||||||
import burp.api.montoya.MontoyaApi;
|
import burp.api.montoya.MontoyaApi;
|
||||||
import hae.Config;
|
import hae.Config;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
import hae.utils.rule.RuleProcessor;
|
import hae.utils.rule.RuleProcessor;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@@ -151,7 +151,7 @@ public class Rule extends JPanel {
|
|||||||
|
|
||||||
private void ruleRemoveActionPerformed(ActionEvent e, JTable ruleTable, JTabbedPane tabbedPane) {
|
private void ruleRemoveActionPerformed(ActionEvent e, JTable ruleTable, JTabbedPane tabbedPane) {
|
||||||
if (ruleTable.getSelectedRowCount() >= 1) {
|
if (ruleTable.getSelectedRowCount() >= 1) {
|
||||||
if (JOptionPane.showConfirmDialog(null, "Are you sure you want to delete this rule?", "Info", JOptionPane.OK_OPTION) == 0) {
|
if (JOptionPane.showConfirmDialog(null, "Are you sure you want to remove this rule?", "Info", JOptionPane.YES_NO_OPTION) == 0) {
|
||||||
DefaultTableModel model = (DefaultTableModel) ruleTable.getModel();
|
DefaultTableModel model = (DefaultTableModel) ruleTable.getModel();
|
||||||
int select = ruleTable.convertRowIndexToModel(ruleTable.getSelectedRow());
|
int select = ruleTable.convertRowIndexToModel(ruleTable.getSelectedRow());
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package hae.component.rule;
|
|||||||
|
|
||||||
import burp.api.montoya.MontoyaApi;
|
import burp.api.montoya.MontoyaApi;
|
||||||
import hae.Config;
|
import hae.Config;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
import hae.utils.rule.RuleProcessor;
|
import hae.utils.rule.RuleProcessor;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import burp.api.montoya.ui.editor.extension.ExtensionProvidedHttpRequestEditor;
|
|||||||
import burp.api.montoya.ui.editor.extension.HttpRequestEditorProvider;
|
import burp.api.montoya.ui.editor.extension.HttpRequestEditorProvider;
|
||||||
import hae.component.board.Datatable;
|
import hae.component.board.Datatable;
|
||||||
import hae.instances.http.utils.MessageProcessor;
|
import hae.instances.http.utils.MessageProcessor;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
import hae.utils.string.StringProcessor;
|
import hae.utils.string.StringProcessor;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import burp.api.montoya.ui.editor.extension.ExtensionProvidedHttpResponseEditor;
|
|||||||
import burp.api.montoya.ui.editor.extension.HttpResponseEditorProvider;
|
import burp.api.montoya.ui.editor.extension.HttpResponseEditorProvider;
|
||||||
import hae.component.board.Datatable;
|
import hae.component.board.Datatable;
|
||||||
import hae.instances.http.utils.MessageProcessor;
|
import hae.instances.http.utils.MessageProcessor;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
import hae.utils.string.StringProcessor;
|
import hae.utils.string.StringProcessor;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import burp.api.montoya.http.message.requests.HttpRequest;
|
|||||||
import hae.component.board.message.MessageTableModel;
|
import hae.component.board.message.MessageTableModel;
|
||||||
import hae.instances.editor.RequestEditor;
|
import hae.instances.editor.RequestEditor;
|
||||||
import hae.instances.http.utils.MessageProcessor;
|
import hae.instances.http.utils.MessageProcessor;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
import hae.utils.string.StringProcessor;
|
import hae.utils.string.StringProcessor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
@@ -90,43 +90,15 @@ public class RegularMatcher {
|
|||||||
result.clear();
|
result.clear();
|
||||||
result.addAll(tmpList);
|
result.addAll(tmpList);
|
||||||
|
|
||||||
String nameAndSize = String.format("%s (%s)", name, result.size());
|
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
tmpMap.put("color", color);
|
tmpMap.put("color", color);
|
||||||
String dataStr = String.join("\n", result);
|
String dataStr = String.join("\n", result);
|
||||||
tmpMap.put("data", dataStr);
|
tmpMap.put("data", dataStr);
|
||||||
|
|
||||||
|
String nameAndSize = String.format("%s (%s)", name, result.size());
|
||||||
finalMap.put(nameAndSize, tmpMap);
|
finalMap.put(nameAndSize, tmpMap);
|
||||||
// 添加到全局变量中,便于Databoard检索
|
|
||||||
if (!Objects.equals(host, "") && host != null) {
|
|
||||||
List<String> dataList = Arrays.asList(dataStr.split("\n"));
|
|
||||||
|
|
||||||
Config.globalDataMap.compute(host, (existingHost, existingMap) -> {
|
putDataToGlobalMap(host, name, result);
|
||||||
Map<String, List<String>> gRuleMap = Optional.ofNullable(existingMap).orElse(new ConcurrentHashMap<>());
|
|
||||||
|
|
||||||
gRuleMap.merge(name, new ArrayList<>(dataList), (existingList, newList) -> {
|
|
||||||
Set<String> combinedSet = new LinkedHashSet<>(existingList);
|
|
||||||
combinedSet.addAll(newList);
|
|
||||||
return new ArrayList<>(combinedSet);
|
|
||||||
});
|
|
||||||
|
|
||||||
return gRuleMap;
|
|
||||||
});
|
|
||||||
|
|
||||||
String[] splitHost = host.split("\\.");
|
|
||||||
String onlyHost = host.split(":")[0];
|
|
||||||
|
|
||||||
String anyHost = (splitHost.length > 2 && !onlyHost.matches("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b")) ? StringProcessor.replaceFirstOccurrence(onlyHost, splitHost[0], "*") : "";
|
|
||||||
|
|
||||||
if (!Config.globalDataMap.containsKey(anyHost) && anyHost.length() > 0) {
|
|
||||||
// 添加通配符Host,实际数据从查询哪里将所有数据提取
|
|
||||||
Config.globalDataMap.put(anyHost, new HashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Config.globalDataMap.containsKey("*")) {
|
|
||||||
// 添加通配符全匹配,同上
|
|
||||||
Config.globalDataMap.put("*", new HashMap<>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,6 +108,38 @@ public class RegularMatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void putDataToGlobalMap(String host, String name, List<String> dataList) {
|
||||||
|
// 添加到全局变量中,便于Databoard检索
|
||||||
|
if (!Objects.equals(host, "") && host != null) {
|
||||||
|
Config.globalDataMap.compute(host, (existingHost, existingMap) -> {
|
||||||
|
Map<String, List<String>> gRuleMap = Optional.ofNullable(existingMap).orElse(new ConcurrentHashMap<>());
|
||||||
|
|
||||||
|
gRuleMap.merge(name, new ArrayList<>(dataList), (existingList, newList) -> {
|
||||||
|
Set<String> combinedSet = new LinkedHashSet<>(existingList);
|
||||||
|
combinedSet.addAll(newList);
|
||||||
|
return new ArrayList<>(combinedSet);
|
||||||
|
});
|
||||||
|
|
||||||
|
return gRuleMap;
|
||||||
|
});
|
||||||
|
|
||||||
|
String[] splitHost = host.split("\\.");
|
||||||
|
String onlyHost = host.split(":")[0];
|
||||||
|
|
||||||
|
String anyHost = (splitHost.length > 2 && !onlyHost.matches("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b")) ? StringProcessor.replaceFirstOccurrence(onlyHost, splitHost[0], "*") : "";
|
||||||
|
|
||||||
|
if (!Config.globalDataMap.containsKey(anyHost) && anyHost.length() > 0) {
|
||||||
|
// 添加通配符Host,实际数据从查询哪里将所有数据提取
|
||||||
|
Config.globalDataMap.put(anyHost, new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Config.globalDataMap.containsKey("*")) {
|
||||||
|
// 添加通配符全匹配,同上
|
||||||
|
Config.globalDataMap.put("*", new HashMap<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> matchByRegex(String f_regex, String s_regex, String content, String format, String engine, boolean sensitive) {
|
private List<String> matchByRegex(String f_regex, String s_regex, String content, String format, String engine, boolean sensitive) {
|
||||||
List<String> retList = new ArrayList<>();
|
List<String> retList = new ArrayList<>();
|
||||||
if ("nfa".equals(engine)) {
|
if ("nfa".equals(engine)) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package hae.utils.config;
|
package hae.utils;
|
||||||
|
|
||||||
import burp.api.montoya.MontoyaApi;
|
import burp.api.montoya.MontoyaApi;
|
||||||
import burp.api.montoya.http.RequestOptions;
|
import burp.api.montoya.http.RequestOptions;
|
||||||
@@ -178,7 +178,7 @@ public class ConfigLoader {
|
|||||||
|
|
||||||
try (InputStream in = Files.newInputStream(path)) {
|
try (InputStream in = Files.newInputStream(path)) {
|
||||||
return yaml.load(in);
|
return yaml.load(in);
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
return new LinkedHashMap<>(); // 读取失败时也返回空的Map
|
return new LinkedHashMap<>(); // 读取失败时也返回空的Map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ public class ConfigLoader {
|
|||||||
|
|
||||||
try (Writer ws = new OutputStreamWriter(Files.newOutputStream(Paths.get(configFilePath)), StandardCharsets.UTF_8)) {
|
try (Writer ws = new OutputStreamWriter(Files.newOutputStream(Paths.get(configFilePath)), StandardCharsets.UTF_8)) {
|
||||||
yaml.dump(currentConfig, ws);
|
yaml.dump(currentConfig, ws);
|
||||||
} catch (IOException ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ public class ConfigLoader {
|
|||||||
|
|
||||||
try (Writer ws = new OutputStreamWriter(Files.newOutputStream(Paths.get(configFilePath)), StandardCharsets.UTF_8)) {
|
try (Writer ws = new OutputStreamWriter(Files.newOutputStream(Paths.get(configFilePath)), StandardCharsets.UTF_8)) {
|
||||||
yaml.dump(currentConfig, ws);
|
yaml.dump(currentConfig, ws);
|
||||||
} catch (IOException ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ public class ConfigLoader {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (IOException ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package hae.utils.ui;
|
package hae.utils;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
77
src/main/java/hae/utils/project/ProjectProcessor.java
Normal file
77
src/main/java/hae/utils/project/ProjectProcessor.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package hae.utils.project;
|
||||||
|
|
||||||
|
import burp.api.montoya.MontoyaApi;
|
||||||
|
import hae.utils.project.model.HaeFileContent;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
public class ProjectProcessor {
|
||||||
|
private final MontoyaApi api;
|
||||||
|
|
||||||
|
public ProjectProcessor(MontoyaApi api) {
|
||||||
|
this.api = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean createHaeFile(String haeFilePath, String host, Map<String, List<String>> dataMap, Map<String, Map<String, String>> httpMap) {
|
||||||
|
ByteArrayOutputStream dataYamlStream = new ByteArrayOutputStream();
|
||||||
|
ByteArrayOutputStream httpYamlStream = new ByteArrayOutputStream();
|
||||||
|
Yaml yaml = new Yaml();
|
||||||
|
|
||||||
|
yaml.dump(dataMap, new OutputStreamWriter(dataYamlStream, StandardCharsets.UTF_8));
|
||||||
|
yaml.dump(httpMap, new OutputStreamWriter(httpYamlStream, StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(haeFilePath))) {
|
||||||
|
zipOut.putNextEntry(new ZipEntry("info"));
|
||||||
|
zipOut.write(host.getBytes(StandardCharsets.UTF_8));
|
||||||
|
zipOut.closeEntry();
|
||||||
|
|
||||||
|
zipOut.putNextEntry(new ZipEntry("data.yml"));
|
||||||
|
zipOut.write(dataYamlStream.toByteArray());
|
||||||
|
zipOut.closeEntry();
|
||||||
|
|
||||||
|
zipOut.putNextEntry(new ZipEntry("http.yml"));
|
||||||
|
zipOut.write(httpYamlStream.toByteArray());
|
||||||
|
zipOut.closeEntry();
|
||||||
|
} catch (Exception e) {
|
||||||
|
api.logging().logToOutput(e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HaeFileContent readHaeFile(String haeFilePath) {
|
||||||
|
HaeFileContent haeFileContent = new HaeFileContent(api);
|
||||||
|
Yaml yaml = new Yaml();
|
||||||
|
|
||||||
|
try (ZipInputStream zipIn = new ZipInputStream(new FileInputStream(haeFilePath))) {
|
||||||
|
ZipEntry entry;
|
||||||
|
while ((entry = zipIn.getNextEntry()) != null) {
|
||||||
|
switch (entry.getName()) {
|
||||||
|
case "info":
|
||||||
|
haeFileContent.setHost(new String(zipIn.readAllBytes(), StandardCharsets.UTF_8));
|
||||||
|
break;
|
||||||
|
case "data.yml":
|
||||||
|
haeFileContent.setDataMap(yaml.load(new InputStreamReader(zipIn, StandardCharsets.UTF_8)));
|
||||||
|
break;
|
||||||
|
case "http.yml":
|
||||||
|
haeFileContent.setHttpMap(yaml.load(new InputStreamReader(zipIn, StandardCharsets.UTF_8)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
zipIn.closeEntry();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
api.logging().logToOutput(e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return haeFileContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
67
src/main/java/hae/utils/project/model/HaeFileContent.java
Normal file
67
src/main/java/hae/utils/project/model/HaeFileContent.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package hae.utils.project.model;
|
||||||
|
|
||||||
|
import burp.api.montoya.MontoyaApi;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class HaeFileContent {
|
||||||
|
private final MontoyaApi api;
|
||||||
|
private String host;
|
||||||
|
private final Map<String, List<String>> dataMap;
|
||||||
|
private final Map<String, Map<String, String>> httpMap;
|
||||||
|
|
||||||
|
public HaeFileContent(MontoyaApi api) {
|
||||||
|
this.api = api;
|
||||||
|
this.dataMap = new HashMap<>();
|
||||||
|
this.httpMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, List<String>> getDataMap() {
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Map<String, String>> getHttpMap() {
|
||||||
|
return httpMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHost(String host) {
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataMap(Map<String, List<Object>> dataMap) {
|
||||||
|
for (Map.Entry<String, List<Object>> entry : dataMap.entrySet()) {
|
||||||
|
List<String> values = new ArrayList<>();
|
||||||
|
for (Object value : entry.getValue()) {
|
||||||
|
try {
|
||||||
|
values.add(new String((byte[]) value, StandardCharsets.UTF_8));
|
||||||
|
} catch (Exception e) {
|
||||||
|
values.add(value.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.dataMap.put(entry.getKey(), values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHttpMap(Map<String, Map<String, Object>> httpMap) {
|
||||||
|
for (Map.Entry<String, Map<String, Object>> entry : httpMap.entrySet()) {
|
||||||
|
Map<String, String> newValues = new HashMap<>();
|
||||||
|
Map<String, Object> values = entry.getValue();
|
||||||
|
for (String key : values.keySet()) {
|
||||||
|
try {
|
||||||
|
newValues.put(key, new String((byte[]) values.get(key), StandardCharsets.UTF_8));
|
||||||
|
} catch (Exception e) {
|
||||||
|
newValues.put(key, values.get(key).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.httpMap.put(entry.getKey(), newValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package hae.utils.rule;
|
|||||||
|
|
||||||
import burp.api.montoya.MontoyaApi;
|
import burp.api.montoya.MontoyaApi;
|
||||||
import hae.Config;
|
import hae.Config;
|
||||||
import hae.utils.config.ConfigLoader;
|
import hae.utils.ConfigLoader;
|
||||||
import hae.utils.rule.model.Group;
|
import hae.utils.rule.model.Group;
|
||||||
import hae.utils.rule.model.Info;
|
import hae.utils.rule.model.Info;
|
||||||
import org.yaml.snakeyaml.DumperOptions;
|
import org.yaml.snakeyaml.DumperOptions;
|
||||||
|
|||||||
@@ -32,6 +32,29 @@ public class StringProcessor {
|
|||||||
return patternIndex == -1;
|
return patternIndex == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String extractHostname(String hostWithPort) {
|
||||||
|
if (hostWithPort == null || hostWithPort.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
int colonIndex = hostWithPort.indexOf(":");
|
||||||
|
if (colonIndex != -1) {
|
||||||
|
return hostWithPort.substring(0, colonIndex);
|
||||||
|
} else {
|
||||||
|
return hostWithPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean matchesHostPattern(String host, String selectedHost) {
|
||||||
|
String hostname = StringProcessor.extractHostname(host);
|
||||||
|
String hostPattern = selectedHost.replace("*.", "");
|
||||||
|
boolean matchesDirectly = selectedHost.equals("*") || host.equals(selectedHost);
|
||||||
|
boolean matchesPattern = !host.contains("*") &&
|
||||||
|
(hostPattern.equals(selectedHost) ?
|
||||||
|
StringProcessor.matchFromEnd(host, hostPattern) :
|
||||||
|
StringProcessor.matchFromEnd(hostname, hostPattern));
|
||||||
|
return matchesDirectly || matchesPattern;
|
||||||
|
}
|
||||||
|
|
||||||
public static String mergeComment(String comment) {
|
public static String mergeComment(String comment) {
|
||||||
if (!comment.contains(",")) {
|
if (!comment.contains(",")) {
|
||||||
return comment;
|
return comment;
|
||||||
|
|||||||
Reference in New Issue
Block a user