Version: 3.3.1 Update
This commit is contained in:
@@ -10,6 +10,8 @@ public class Config {
|
||||
|
||||
public static String host = "gh0st.cn";
|
||||
|
||||
public static String status = "404";
|
||||
|
||||
public static String[] scope = new String[]{
|
||||
"any",
|
||||
"any header",
|
||||
|
||||
@@ -18,7 +18,7 @@ public class HaE implements BurpExtension {
|
||||
@Override
|
||||
public void initialize(MontoyaApi api) {
|
||||
// 设置扩展名称
|
||||
String version = "3.3";
|
||||
String version = "3.3.1";
|
||||
api.extension().setName(String.format("HaE (%s) - Highlighter and Extractor", version));
|
||||
|
||||
// 加载扩展后输出的项目信息
|
||||
|
||||
@@ -13,9 +13,11 @@ import hae.utils.project.model.HaeFileContent;
|
||||
import hae.utils.string.StringProcessor;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import javax.swing.table.TableModel;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
@@ -49,8 +51,8 @@ public class Databoard extends JPanel {
|
||||
|
||||
private SwingWorker<Map<String, List<String>>, Void> handleComboBoxWorker;
|
||||
private SwingWorker<Void, Void> applyHostFilterWorker;
|
||||
private SwingWorker<List<String>, Void> exportActionWorker;
|
||||
private SwingWorker<List<String>, Void> importActionWorker;
|
||||
private SwingWorker<List<Object[]>, Void> exportActionWorker;
|
||||
private SwingWorker<List<Object[]>, Void> importActionWorker;
|
||||
|
||||
public Databoard(MontoyaApi api, ConfigLoader configLoader, MessageTableModel messageTableModel) {
|
||||
this.api = api;
|
||||
@@ -193,11 +195,11 @@ public class Databoard extends JPanel {
|
||||
|
||||
private void handleComboBoxAction(ActionEvent e) {
|
||||
if (!isMatchHost && hostComboBox.getSelectedItem() != null) {
|
||||
progressBar.setVisible(true);
|
||||
setProgressBar(true);
|
||||
String selectedHost = hostComboBox.getSelectedItem().toString();
|
||||
|
||||
if (getHostByList().contains(selectedHost)) {
|
||||
progressBar.setVisible(true);
|
||||
setProgressBar(true);
|
||||
hostTextField.setText(selectedHost);
|
||||
|
||||
if (handleComboBoxWorker != null && !handleComboBoxWorker.isDone()) {
|
||||
@@ -385,9 +387,9 @@ public class Databoard extends JPanel {
|
||||
exportActionWorker.cancel(true);
|
||||
}
|
||||
|
||||
exportActionWorker = new SwingWorker<List<String>, Void>() {
|
||||
exportActionWorker = new SwingWorker<List<Object[]>, Void>() {
|
||||
@Override
|
||||
protected List<String> doInBackground() {
|
||||
protected List<Object[]> doInBackground() {
|
||||
ConcurrentHashMap<String, Map<String, List<String>>> dataMap = Config.globalDataMap;
|
||||
return exportData(selectedHost, exportDir, dataMap);
|
||||
}
|
||||
@@ -395,11 +397,9 @@ public class Databoard extends JPanel {
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
List<String> taskStatusList = get();
|
||||
List<Object[]> taskStatusList = get();
|
||||
if (!taskStatusList.isEmpty()) {
|
||||
String exportStatusMessage = String.format("Exported File List Status:\n%s", String.join("\n", taskStatusList));
|
||||
|
||||
JOptionPane.showMessageDialog(Databoard.this, generateTaskStatusPane(exportStatusMessage), "Info", JOptionPane.INFORMATION_MESSAGE);
|
||||
JOptionPane.showMessageDialog(Databoard.this, generateTaskStatusPane(taskStatusList), "Info", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
@@ -409,17 +409,36 @@ public class Databoard extends JPanel {
|
||||
exportActionWorker.execute();
|
||||
}
|
||||
|
||||
private JScrollPane generateTaskStatusPane(String message) {
|
||||
JTextArea textArea = new JTextArea(message);
|
||||
textArea.setEditable(false);
|
||||
textArea.setLineWrap(true);
|
||||
JScrollPane scrollPane = new JScrollPane(textArea);
|
||||
scrollPane.setPreferredSize(new Dimension(400, 200));
|
||||
private JScrollPane generateTaskStatusPane(List<Object[]> dataList) {
|
||||
String[] columnNames = {"#", "Filename", "Status"};
|
||||
DefaultTableModel taskStatusTableModel = new DefaultTableModel(columnNames, 0);
|
||||
JTable taskStatusTable = new JTable(taskStatusTableModel);
|
||||
|
||||
for (Object[] data : dataList) {
|
||||
int rowCount = taskStatusTable.getRowCount();
|
||||
int id = rowCount > 0 ? (Integer) taskStatusTable.getValueAt(rowCount - 1, 0) + 1 : 1;
|
||||
Object[] rowData = new Object[data.length + 1];
|
||||
rowData[0] = id;
|
||||
System.arraycopy(data, 0, rowData, 1, data.length);
|
||||
taskStatusTableModel.addRow(rowData);
|
||||
}
|
||||
|
||||
TableRowSorter<DefaultTableModel> sorter = new TableRowSorter<>(taskStatusTableModel);
|
||||
taskStatusTable.setRowSorter(sorter);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(taskStatusTable);
|
||||
scrollPane.setBorder(new TitledBorder("Task status"));
|
||||
scrollPane.setPreferredSize(new Dimension(500, 300));
|
||||
|
||||
int paneWidth = scrollPane.getPreferredSize().width;
|
||||
taskStatusTable.getColumnModel().getColumn(0).setPreferredWidth((int) (paneWidth * 0.1));
|
||||
taskStatusTable.getColumnModel().getColumn(1).setPreferredWidth((int) (paneWidth * 0.7));
|
||||
taskStatusTable.getColumnModel().getColumn(2).setPreferredWidth((int) (paneWidth * 0.2));
|
||||
|
||||
return scrollPane;
|
||||
}
|
||||
|
||||
private List<String> exportData(String selectedHost, String exportDir, Map<String, Map<String, List<String>>> dataMap) {
|
||||
private List<Object[]> 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("*"))
|
||||
@@ -428,7 +447,7 @@ public class Databoard extends JPanel {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private String exportEntry(Map.Entry<String, Map<String, List<String>>> entry, String exportDir) {
|
||||
private Object[] exportEntry(Map.Entry<String, Map<String, List<String>>> entry, String exportDir) {
|
||||
String key = entry.getKey();
|
||||
Map<String, List<String>> ruleMap = entry.getValue();
|
||||
|
||||
@@ -442,7 +461,7 @@ public class Databoard extends JPanel {
|
||||
.collect(Collectors.toMap(
|
||||
messageEntry -> messageEntry,
|
||||
messageEntry -> StringProcessor.getRandomUUID(),
|
||||
(existing, replacement) -> existing // 在冲突时保留现有的映射
|
||||
(existing, replacement) -> existing
|
||||
));
|
||||
|
||||
Map<String, Map<String, Object>> httpMap = processEntries(
|
||||
@@ -463,7 +482,7 @@ public class Databoard extends JPanel {
|
||||
String filename = String.format("%s/%s-%s.hae", exportDir, StringProcessor.getCurrentTime(), hostName);
|
||||
boolean createdStatus = projectProcessor.createHaeFile(filename, key, ruleMap, urlMap, httpMap);
|
||||
|
||||
return String.format("Filename: %s, Status: %s", filename, createdStatus);
|
||||
return new Object[]{filename, createdStatus};
|
||||
}
|
||||
|
||||
|
||||
@@ -507,9 +526,9 @@ public class Databoard extends JPanel {
|
||||
importActionWorker.cancel(true);
|
||||
}
|
||||
|
||||
importActionWorker = new SwingWorker<List<String>, Void>() {
|
||||
importActionWorker = new SwingWorker<List<Object[]>, Void>() {
|
||||
@Override
|
||||
protected List<String> doInBackground() {
|
||||
protected List<Object[]> doInBackground() {
|
||||
List<String> filesWithExtension = findFilesWithExtension(new File(exportDir), ".hae");
|
||||
return filesWithExtension.stream()
|
||||
.map(Databoard.this::importData)
|
||||
@@ -519,10 +538,9 @@ public class Databoard extends JPanel {
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
List<String> taskStatusList = get();
|
||||
List<Object[]> taskStatusList = get();
|
||||
if (!taskStatusList.isEmpty()) {
|
||||
String importStatusMessage = "Imported File List Status:\n" + String.join("\n", taskStatusList);
|
||||
JOptionPane.showMessageDialog(Databoard.this, generateTaskStatusPane(importStatusMessage), "Info", JOptionPane.INFORMATION_MESSAGE);
|
||||
JOptionPane.showMessageDialog(Databoard.this, generateTaskStatusPane(taskStatusList), "Info", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
@@ -532,7 +550,7 @@ public class Databoard extends JPanel {
|
||||
importActionWorker.execute();
|
||||
}
|
||||
|
||||
private String importData(String filename) {
|
||||
private Object[] importData(String filename) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
|
||||
|
||||
HaeFileContent haeFileContent = projectProcessor.readHaeFile(filename);
|
||||
@@ -568,7 +586,7 @@ public class Databoard extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
return String.format("Filename: %s, Status: %s", filename, readStatus);
|
||||
return new Object[]{filename, readStatus};
|
||||
}
|
||||
|
||||
private List<String> findFilesWithExtension(File directory, String extension) {
|
||||
@@ -648,6 +666,8 @@ public class Databoard extends JPanel {
|
||||
}
|
||||
|
||||
messageTableModel.deleteByHost(host);
|
||||
|
||||
hostTextField.setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
|
||||
public class MessageTable extends JTable {
|
||||
private MessageEntry messageEntry;
|
||||
private SwingWorker<Object, Void> currentWorker;
|
||||
private SwingWorker<ByteArray[], Void> currentWorker;
|
||||
private int lastSelectedIndex = -1;
|
||||
private final HttpRequestEditor requestEditor;
|
||||
private final HttpResponseEditor responseEditor;
|
||||
@@ -450,16 +450,13 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
public void changeSelection(int row, int col, boolean toggle, boolean extend) {
|
||||
super.changeSelection(row, col, toggle, extend);
|
||||
|
||||
requestEditor.setRequest(HttpRequest.httpRequest("Loading..."));
|
||||
responseEditor.setResponse(HttpResponse.httpResponse("Loading..."));
|
||||
|
||||
if (currentWorker != null && !currentWorker.isDone()) {
|
||||
currentWorker.cancel(true);
|
||||
}
|
||||
|
||||
currentWorker = new SwingWorker<>() {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
protected ByteArray[] doInBackground() {
|
||||
int selectedIndex = convertRowIndexToModel(row);
|
||||
if (lastSelectedIndex != selectedIndex) {
|
||||
lastSelectedIndex = selectedIndex;
|
||||
@@ -470,14 +467,28 @@ public class MessageTableModel extends AbstractTableModel {
|
||||
ByteArray requestByte = httpRequestResponse.request().toByteArray();
|
||||
ByteArray responseByte = httpRequestResponse.response().toByteArray();
|
||||
|
||||
requestEditor.setRequest(HttpRequest.httpRequest(messageEntry.getRequestResponse().httpService(), requestByte));
|
||||
responseEditor.setResponse(HttpResponse.httpResponse(responseByte));
|
||||
|
||||
ByteArray[] httpByteArray = new ByteArray[2];
|
||||
httpByteArray[0] = requestByte;
|
||||
httpByteArray[1] = responseByte;
|
||||
return httpByteArray;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
ByteArray[] retByteArray = get();
|
||||
if (retByteArray != null) {
|
||||
requestEditor.setRequest(HttpRequest.httpRequest(messageEntry.getRequestResponse().httpService(), retByteArray[0]));
|
||||
responseEditor.setResponse(HttpResponse.httpResponse(retByteArray[1]));
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
currentWorker.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class AIPower {
|
||||
public AIPower(MontoyaApi api, ConfigLoader configLoader, String aiModel, String aiBaseUrl, String[] apiKey) {
|
||||
this.api = api;
|
||||
this.configLoader = configLoader;
|
||||
this.httpUtils = new HttpUtils(api);
|
||||
this.httpUtils = new HttpUtils(api, configLoader);
|
||||
this.aiModel = aiModel;
|
||||
this.aiBaseUrl = aiBaseUrl;
|
||||
|
||||
|
||||
@@ -27,24 +27,23 @@ public class Config extends JPanel {
|
||||
private final MontoyaApi api;
|
||||
private final ConfigLoader configLoader;
|
||||
private final Rules rules;
|
||||
private JTextField addTextField;
|
||||
private final String defaultText = "Enter a new item";
|
||||
private final GridBagConstraints constraints = new GridBagConstraints();
|
||||
|
||||
public Config(MontoyaApi api, ConfigLoader configLoader, Rules rules) {
|
||||
this.api = api;
|
||||
this.configLoader = configLoader;
|
||||
this.rules = rules;
|
||||
|
||||
constraints.weightx = 1.0;
|
||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
initComponents();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.weightx = 1.0;
|
||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
JPanel ruleInfoPanel = new JPanel(new GridBagLayout());
|
||||
ruleInfoPanel.setBorder(new EmptyBorder(10, 15, 5, 15));
|
||||
|
||||
@@ -67,7 +66,7 @@ public class Config extends JPanel {
|
||||
constraints.gridx = 1;
|
||||
JTabbedPane configTabbedPanel = new JTabbedPane();
|
||||
|
||||
String[] settingMode = new String[]{"Exclude suffix", "Block host"};
|
||||
String[] settingMode = new String[]{"Exclude suffix", "Block host", "Exclude status"};
|
||||
JPanel settingPanel = createConfigTablePanel(settingMode, "Setting");
|
||||
JPanel scopePanel = getScopePanel();
|
||||
JScrollPane scopeScrollPane = new JScrollPane(scopePanel);
|
||||
@@ -148,6 +147,12 @@ public class Config extends JPanel {
|
||||
configLoader.setBlockHost(values);
|
||||
}
|
||||
}
|
||||
|
||||
if (selected.equals("Exclude status")) {
|
||||
if (!values.equals(configLoader.getExcludeStatus()) && !values.isEmpty()) {
|
||||
configLoader.setExcludeStatus(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -166,6 +171,10 @@ public class Config extends JPanel {
|
||||
if (selected.equals("Block host")) {
|
||||
addDataToTable(configLoader.getBlockHost().replaceAll("\\|", "\r\n"), model);
|
||||
}
|
||||
|
||||
if (selected.equals("Exclude status")) {
|
||||
addDataToTable(configLoader.getExcludeStatus().replaceAll("\\|", "\r\n"), model);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -211,6 +220,10 @@ public class Config extends JPanel {
|
||||
}
|
||||
|
||||
private JPanel createConfigTablePanel(String[] mode, String type) {
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.weightx = 1.0;
|
||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
JPanel settingPanel = new JPanel(new BorderLayout());
|
||||
DefaultTableModel model = new DefaultTableModel();
|
||||
|
||||
@@ -255,7 +268,7 @@ public class Config extends JPanel {
|
||||
constraints.gridy = 4;
|
||||
buttonPanel.add(clearButton, constraints);
|
||||
|
||||
addTextField = new JTextField();
|
||||
JTextField addTextField = new JTextField();
|
||||
UIEnhancer.setTextFieldPlaceholder(addTextField, defaultText);
|
||||
|
||||
inputPanelB.add(addTextField, BorderLayout.CENTER);
|
||||
@@ -266,13 +279,13 @@ public class Config extends JPanel {
|
||||
settingPanel.add(inputPanel, BorderLayout.CENTER);
|
||||
|
||||
|
||||
addButton.addActionListener(e -> addActionPerformed(e, model));
|
||||
addButton.addActionListener(e -> addActionPerformed(e, model, addTextField));
|
||||
|
||||
addTextField.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
addActionPerformed(null, model);
|
||||
addActionPerformed(null, model, addTextField);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -372,8 +385,9 @@ public class Config extends JPanel {
|
||||
configLoader.setScope(String.join("|", HaEScope));
|
||||
}
|
||||
|
||||
private void addActionPerformed(ActionEvent e, DefaultTableModel model) {
|
||||
private void addActionPerformed(ActionEvent e, DefaultTableModel model, JTextField addTextField) {
|
||||
String addTextFieldText = addTextField.getText();
|
||||
api.logging().logToOutput(addTextFieldText);
|
||||
if (!addTextFieldText.equals(defaultText)) {
|
||||
addDataToTable(addTextFieldText, model);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import burp.api.montoya.ui.editor.extension.HttpRequestEditorProvider;
|
||||
import hae.component.board.table.Datatable;
|
||||
import hae.instances.http.utils.MessageProcessor;
|
||||
import hae.utils.ConfigLoader;
|
||||
import hae.utils.http.HttpUtils;
|
||||
import hae.utils.string.StringProcessor;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -37,6 +38,7 @@ public class RequestEditor implements HttpRequestEditorProvider {
|
||||
private static class Editor implements ExtensionProvidedHttpRequestEditor {
|
||||
private final MontoyaApi api;
|
||||
private final ConfigLoader configLoader;
|
||||
private final HttpUtils httpUtils;
|
||||
private final EditorCreationContext creationContext;
|
||||
private final MessageProcessor messageProcessor;
|
||||
private HttpRequestResponse requestResponse;
|
||||
@@ -47,6 +49,7 @@ public class RequestEditor implements HttpRequestEditorProvider {
|
||||
public Editor(MontoyaApi api, ConfigLoader configLoader, EditorCreationContext creationContext) {
|
||||
this.api = api;
|
||||
this.configLoader = configLoader;
|
||||
this.httpUtils = new HttpUtils(api, configLoader);
|
||||
this.creationContext = creationContext;
|
||||
this.messageProcessor = new MessageProcessor(api);
|
||||
}
|
||||
@@ -69,16 +72,10 @@ public class RequestEditor implements HttpRequestEditorProvider {
|
||||
try {
|
||||
String host = StringProcessor.getHostByUrl(request.url());
|
||||
if (!host.isEmpty()) {
|
||||
String[] hostList = configLoader.getBlockHost().split("\\|");
|
||||
boolean isBlockHost = isBlockHost(hostList, host);
|
||||
|
||||
List<String> suffixList = Arrays.asList(configLoader.getExcludeSuffix().split("\\|"));
|
||||
String toolType = creationContext.toolSource().toolType().toolName();
|
||||
boolean isToolScope = configLoader.getScope().contains(toolType);
|
||||
boolean matches = httpUtils.verifyHttpRequestResponse(requestResponse, toolType);
|
||||
|
||||
boolean matches = suffixList.contains(request.fileExtension().toLowerCase()) || isBlockHost || !isToolScope;
|
||||
|
||||
if (!matches && !request.bodyToString().equals("Loading...")) {
|
||||
if (!matches) {
|
||||
this.dataList = messageProcessor.processRequest("", request, false);
|
||||
return isListHasData(this.dataList);
|
||||
}
|
||||
@@ -121,19 +118,6 @@ public class RequestEditor implements HttpRequestEditorProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBlockHost(String[] hostList, String host) {
|
||||
boolean isBlockHost = false;
|
||||
for (String hostName : hostList) {
|
||||
String cleanedHost = StringProcessor.replaceFirstOccurrence(hostName, "*.", "");
|
||||
if (hostName.contains("*.") && StringProcessor.matchFromEnd(host, cleanedHost)) {
|
||||
isBlockHost = true;
|
||||
} else if (host.equals(hostName) || hostName.equals("*")) {
|
||||
isBlockHost = true;
|
||||
}
|
||||
}
|
||||
return isBlockHost;
|
||||
}
|
||||
|
||||
public static boolean isListHasData(List<Map<String, String>> dataList) {
|
||||
if (dataList != null && !dataList.isEmpty()) {
|
||||
Map<String, String> dataMap = dataList.get(0);
|
||||
|
||||
@@ -13,11 +13,11 @@ import burp.api.montoya.ui.editor.extension.HttpResponseEditorProvider;
|
||||
import hae.component.board.table.Datatable;
|
||||
import hae.instances.http.utils.MessageProcessor;
|
||||
import hae.utils.ConfigLoader;
|
||||
import hae.utils.http.HttpUtils;
|
||||
import hae.utils.string.StringProcessor;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -38,6 +38,7 @@ public class ResponseEditor implements HttpResponseEditorProvider {
|
||||
private static class Editor implements ExtensionProvidedHttpResponseEditor {
|
||||
private final MontoyaApi api;
|
||||
private final ConfigLoader configLoader;
|
||||
private final HttpUtils httpUtils;
|
||||
private final EditorCreationContext creationContext;
|
||||
private final MessageProcessor messageProcessor;
|
||||
private HttpRequestResponse requestResponse;
|
||||
@@ -48,6 +49,7 @@ public class ResponseEditor implements HttpResponseEditorProvider {
|
||||
public Editor(MontoyaApi api, ConfigLoader configLoader, EditorCreationContext creationContext) {
|
||||
this.api = api;
|
||||
this.configLoader = configLoader;
|
||||
this.httpUtils = new HttpUtils(api, configLoader);
|
||||
this.creationContext = creationContext;
|
||||
this.messageProcessor = new MessageProcessor(api);
|
||||
}
|
||||
@@ -75,20 +77,14 @@ public class ResponseEditor implements HttpResponseEditorProvider {
|
||||
try {
|
||||
String host = StringProcessor.getHostByUrl(request.url());
|
||||
if (!host.isEmpty()) {
|
||||
String[] hostList = configLoader.getBlockHost().split("\\|");
|
||||
boolean isBlockHost = RequestEditor.isBlockHost(hostList, host);
|
||||
|
||||
List<String> suffixList = Arrays.asList(configLoader.getExcludeSuffix().split("\\|"));
|
||||
String toolType = creationContext.toolSource().toolType().toolName();
|
||||
boolean isToolScope = configLoader.getScope().contains(toolType);
|
||||
|
||||
matches = suffixList.contains(request.fileExtension().toLowerCase()) || isBlockHost || !isToolScope;
|
||||
matches = httpUtils.verifyHttpRequestResponse(requestResponse, toolType);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!matches && !response.bodyToString().equals("Loading...")) {
|
||||
if (!matches) {
|
||||
this.dataList = messageProcessor.processResponse("", response, false);
|
||||
return RequestEditor.isListHasData(this.dataList);
|
||||
}
|
||||
|
||||
@@ -7,20 +7,20 @@ import burp.api.montoya.http.handler.*;
|
||||
import burp.api.montoya.http.message.HttpRequestResponse;
|
||||
import burp.api.montoya.http.message.requests.HttpRequest;
|
||||
import hae.component.board.message.MessageTableModel;
|
||||
import hae.instances.editor.RequestEditor;
|
||||
import hae.instances.http.utils.MessageProcessor;
|
||||
import hae.utils.ConfigLoader;
|
||||
import hae.utils.http.HttpUtils;
|
||||
import hae.utils.string.StringProcessor;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class HttpMessageHandler implements HttpHandler {
|
||||
private final MontoyaApi api;
|
||||
private final ConfigLoader configLoader;
|
||||
private final HttpUtils httpUtils;
|
||||
private final MessageTableModel messageTableModel;
|
||||
private final MessageProcessor messageProcessor;
|
||||
|
||||
@@ -29,12 +29,12 @@ public class HttpMessageHandler implements HttpHandler {
|
||||
private final ThreadLocal<String> host = ThreadLocal.withInitial(() -> "");
|
||||
private final ThreadLocal<List<String>> colorList = ThreadLocal.withInitial(ArrayList::new);
|
||||
private final ThreadLocal<List<String>> commentList = ThreadLocal.withInitial(ArrayList::new);
|
||||
private final ThreadLocal<Boolean> matches = ThreadLocal.withInitial(() -> false);
|
||||
private final ThreadLocal<HttpRequest> httpRequest = new ThreadLocal<>();
|
||||
|
||||
public HttpMessageHandler(MontoyaApi api, ConfigLoader configLoader, MessageTableModel messageTableModel) {
|
||||
this.api = api;
|
||||
this.configLoader = configLoader;
|
||||
this.httpUtils = new HttpUtils(api, configLoader);
|
||||
this.messageTableModel = messageTableModel;
|
||||
this.messageProcessor = new MessageProcessor(api);
|
||||
}
|
||||
@@ -49,20 +49,6 @@ public class HttpMessageHandler implements HttpHandler {
|
||||
try {
|
||||
httpRequest.set(httpRequestToBeSent);
|
||||
host.set(StringProcessor.getHostByUrl(httpRequestToBeSent.url()));
|
||||
|
||||
String[] hostList = configLoader.getBlockHost().split("\\|");
|
||||
boolean isBlockHost = RequestEditor.isBlockHost(hostList, host.get());
|
||||
|
||||
String toolType = httpRequestToBeSent.toolSource().toolType().toolName();
|
||||
boolean isToolScope = configLoader.getScope().contains(toolType);
|
||||
|
||||
List<String> suffixList = Arrays.asList(configLoader.getExcludeSuffix().split("\\|"));
|
||||
matches.set(suffixList.contains(httpRequestToBeSent.fileExtension().toLowerCase()) || isBlockHost || !isToolScope);
|
||||
|
||||
if (!matches.get()) {
|
||||
List<Map<String, String>> result = messageProcessor.processRequest(host.get(), httpRequestToBeSent, true);
|
||||
setColorAndCommentList(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
api.logging().logToError("handleHttpRequestToBeSent: " + e.getMessage());
|
||||
}
|
||||
@@ -73,33 +59,43 @@ public class HttpMessageHandler implements HttpHandler {
|
||||
@Override
|
||||
public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived httpResponseReceived) {
|
||||
Annotations annotations = httpResponseReceived.annotations();
|
||||
HttpRequest request = httpResponseReceived.initiatingRequest();
|
||||
HttpRequestResponse requestResponse = HttpRequestResponse.httpRequestResponse(request, httpResponseReceived);
|
||||
String toolType = httpResponseReceived.toolSource().toolType().toolName();
|
||||
|
||||
if (!matches.get()) {
|
||||
List<Map<String, String>> result = messageProcessor.processResponse(host.get(), httpResponseReceived, true);
|
||||
setColorAndCommentList(result);
|
||||
// 设置高亮颜色和注释
|
||||
if (!colorList.get().isEmpty() && !commentList.get().isEmpty()) {
|
||||
String color = messageProcessor.retrieveFinalColor(messageProcessor.retrieveColorIndices(colorList.get()));
|
||||
annotations.setHighlightColor(HighlightColor.highlightColor(color));
|
||||
String comment = StringProcessor.mergeComment(String.join(", ", commentList.get()));
|
||||
annotations.setNotes(comment);
|
||||
boolean matches = httpUtils.verifyHttpRequestResponse(requestResponse, toolType);
|
||||
|
||||
HttpRequestResponse httpRequestResponse = HttpRequestResponse.httpRequestResponse(httpRequest.get(), httpResponseReceived);
|
||||
if (!matches) {
|
||||
try {
|
||||
setColorAndCommentList(messageProcessor.processRequest(host.get(), request, true));
|
||||
setColorAndCommentList(messageProcessor.processResponse(host.get(), httpResponseReceived, true));
|
||||
|
||||
// 添加到Databoard
|
||||
String method = httpRequest.get().method();
|
||||
String url = httpRequest.get().url();
|
||||
String status = String.valueOf(httpResponseReceived.statusCode());
|
||||
String length = String.valueOf(httpResponseReceived.toByteArray().length());
|
||||
// 设置高亮颜色和注释
|
||||
if (!colorList.get().isEmpty() && !commentList.get().isEmpty()) {
|
||||
String color = messageProcessor.retrieveFinalColor(messageProcessor.retrieveColorIndices(colorList.get()));
|
||||
annotations.setHighlightColor(HighlightColor.highlightColor(color));
|
||||
String comment = StringProcessor.mergeComment(String.join(", ", commentList.get()));
|
||||
annotations.setNotes(comment);
|
||||
|
||||
// 后台提交,防止线程阻塞
|
||||
new SwingWorker<Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
messageTableModel.add(httpRequestResponse, url, method, status, length, comment, color, "", "");
|
||||
return null;
|
||||
}
|
||||
}.run();
|
||||
HttpRequestResponse httpRequestResponse = HttpRequestResponse.httpRequestResponse(httpRequest.get(), httpResponseReceived);
|
||||
|
||||
// 添加到Databoard
|
||||
String method = httpRequest.get().method();
|
||||
String url = httpRequest.get().url();
|
||||
String status = String.valueOf(httpResponseReceived.statusCode());
|
||||
String length = String.valueOf(httpResponseReceived.toByteArray().length());
|
||||
|
||||
// 后台提交,防止线程阻塞
|
||||
new SwingWorker<Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground() {
|
||||
messageTableModel.add(httpRequestResponse, url, method, status, length, comment, color, "", "");
|
||||
return null;
|
||||
}
|
||||
}.run();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
api.logging().logToError("handleHttpResponseReceived: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,11 +147,15 @@ public class ConfigLoader {
|
||||
}
|
||||
|
||||
public String getBlockHost() {
|
||||
return getValueFromConfig("blockHost", Config.host);
|
||||
return getValueFromConfig("BlockHost", Config.host);
|
||||
}
|
||||
|
||||
public String getExcludeSuffix() {
|
||||
return getValueFromConfig("excludeSuffix", Config.suffix);
|
||||
return getValueFromConfig("ExcludeSuffix", Config.suffix);
|
||||
}
|
||||
|
||||
public String getExcludeStatus() {
|
||||
return getValueFromConfig("ExcludeStatus", Config.status);
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
@@ -189,11 +193,15 @@ public class ConfigLoader {
|
||||
}
|
||||
|
||||
public void setExcludeSuffix(String excludeSuffix) {
|
||||
setValueToConfig("excludeSuffix", excludeSuffix);
|
||||
setValueToConfig("ExcludeSuffix", excludeSuffix);
|
||||
}
|
||||
|
||||
public void setBlockHost(String blockHost) {
|
||||
setValueToConfig("blockHost", blockHost);
|
||||
setValueToConfig("BlockHost", blockHost);
|
||||
}
|
||||
|
||||
public void setExcludeStatus(String status) {
|
||||
setValueToConfig("ExcludeStatus", status);
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
package hae.utils.http;
|
||||
|
||||
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.requests.HttpTransformation;
|
||||
import burp.api.montoya.http.message.responses.HttpResponse;
|
||||
import burp.api.montoya.utilities.RandomUtils;
|
||||
import hae.utils.ConfigLoader;
|
||||
import hae.utils.string.StringProcessor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class HttpUtils {
|
||||
private final MontoyaApi api;
|
||||
private final ConfigLoader configLoader;
|
||||
|
||||
public HttpUtils(MontoyaApi api) {
|
||||
public HttpUtils(MontoyaApi api, ConfigLoader configLoader) {
|
||||
this.api = api;
|
||||
this.configLoader = configLoader;
|
||||
}
|
||||
|
||||
public HttpRequest generateRequestByMultipartUploadMethod(String url, String name, String filename, String content) {
|
||||
@@ -28,15 +36,40 @@ public class HttpUtils {
|
||||
return baseRequest;
|
||||
}
|
||||
|
||||
public HttpRequest generateRequestByJsonMethod(String url, String data) {
|
||||
HttpRequest baseRequest = HttpRequest.httpRequestFromUrl(url).withTransformationApplied(HttpTransformation.TOGGLE_METHOD);
|
||||
HttpService baseService = baseRequest.httpService();
|
||||
String requestString = baseRequest.toString().replace("application/x-www-form-urlencoded", "application/json");
|
||||
baseRequest = HttpRequest.httpRequest(baseService, requestString).withBody(data);
|
||||
return baseRequest;
|
||||
}
|
||||
|
||||
public HttpRequest generateRequestByDeleteMethod(String url) {
|
||||
return HttpRequest.httpRequestFromUrl(url).withMethod("DELETE");
|
||||
}
|
||||
|
||||
public boolean verifyHttpRequestResponse(HttpRequestResponse requestResponse, String toolType) {
|
||||
HttpRequest request = requestResponse.request();
|
||||
HttpResponse response = requestResponse.response();
|
||||
|
||||
String host = StringProcessor.getHostByUrl(request.url());
|
||||
String[] hostList = configLoader.getBlockHost().split("\\|");
|
||||
boolean isBlockHost = isBlockHost(hostList, host);
|
||||
|
||||
List<String> suffixList = Arrays.asList(configLoader.getExcludeSuffix().split("\\|"));
|
||||
boolean isExcludeSuffix = suffixList.contains(request.fileExtension().toLowerCase());
|
||||
|
||||
boolean isToolScope = !configLoader.getScope().contains(toolType);
|
||||
|
||||
List<String> statusList = Arrays.asList(configLoader.getExcludeStatus().split("\\|"));
|
||||
boolean isExcludeStatus = statusList.contains(String.valueOf(response.statusCode()));
|
||||
|
||||
return isExcludeSuffix || isBlockHost || isToolScope || isExcludeStatus;
|
||||
}
|
||||
|
||||
private boolean isBlockHost(String[] hostList, String host) {
|
||||
boolean isBlockHost = false;
|
||||
for (String hostName : hostList) {
|
||||
String cleanedHost = StringProcessor.replaceFirstOccurrence(hostName, "*.", "");
|
||||
if (hostName.contains("*.") && StringProcessor.matchFromEnd(host, cleanedHost)) {
|
||||
isBlockHost = true;
|
||||
} else if (host.equals(hostName) || hostName.equals("*")) {
|
||||
isBlockHost = true;
|
||||
}
|
||||
}
|
||||
return isBlockHost;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user