Files
HaE/burp/BurpExtender.java
2020-11-27 03:48:28 +08:00

426 lines
13 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package burp;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.util.*;
import org.json.*;
import burp.action.DoAction;
import burp.action.ExtractContent;
import burp.action.MatchHTTP;
import burp.color.GetColorKey;
import burp.color.UpgradeColor;
import burp.file.FileExists;
import burp.file.ReadFile;
import burp.file.RemoveContent;
import burp.file.WriteFile;
import burp.ui.FillTable;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.DefaultCellEditor;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.File;
import java.awt.event.ActionEvent;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.JLabel;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEditorTabFactory, ITab {
private JFrame frame;
private JPanel panel;
private JTable table;
private JTextField textField;
private IBurpExtenderCallbacks callbacks;
private static IExtensionHelpers helpers;
private static String configFilePath = "config.json";
private static String initFilePath = "init.hae";
private static IMessageEditorTab HaETab;
private static PrintWriter stdout;
ReadFile rf = new ReadFile();
WriteFile wfc = new WriteFile();
FileExists fe = new FileExists();
RemoveContent rc = new RemoveContent();
GetColorKey gck = new GetColorKey();
UpgradeColor uc = new UpgradeColor();
ExtractContent ec = new ExtractContent();
MatchHTTP mh = new MatchHTTP();
FillTable ft = new FillTable();
DoAction da = new DoAction();
@Override
public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks)
{
this.callbacks = callbacks;
this.helpers = callbacks.getHelpers();
// 设置插件名字和版本
String version = "1.5";
callbacks.setExtensionName(String.format("HaE (%s) - Highlighter and Extractor", version));
// 定义输出
stdout = new PrintWriter(callbacks.getStdout(), true);
stdout.println("@Author: EvilChen");
stdout.println("@Blog: cn.gh0st.cn");
// UI
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// 判断"config.json"文件是否具备内容,如若不具备则进行初始化
if (configFilePath.equals("config.json")) {
if (rf.readFileContent(configFilePath).equals("")) {
wfc.writeFileContent(configFilePath, Config.initConfigContent);
wfc.writeFileContent(initFilePath, configFilePath);
}
}
// 判断配置文件是否存在
if (fe.fileExists(configFilePath)) {
configFilePath = rf.readFileContent(initFilePath);
} else {
JOptionPane.showMessageDialog(null, "Config File Not Found!", "Error", JOptionPane.ERROR_MESSAGE);
}
initialize();
ft.fillTable(configFilePath, table);
}
});
callbacks.registerHttpListener(BurpExtender.this);
callbacks.registerMessageEditorTabFactory(BurpExtender.this);
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 526, 403);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(new BorderLayout(0, 0));
JPanel panel_3 = new JPanel();
panel.add(panel_3, BorderLayout.NORTH);
JLabel lblNewLabel_1 = new JLabel("Config File:");
panel_3.add(lblNewLabel_1);
textField = new JTextField();
textField.setEditable(false);
panel_3.add(textField);
textField.setColumns(20);
textField.setText(configFilePath);
JButton btnNewButton = new JButton("Select File ...");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser jfc = new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
jfc.showDialog(new JLabel(), "Choose");
File file = jfc.getSelectedFile();
textField.setText(file.getAbsolutePath());
configFilePath = textField.getText();
wfc.writeFileContent(initFilePath, configFilePath);
ft.fillTable(configFilePath, table);
}
});
panel_3.add(btnNewButton);
JPanel panel_2 = new JPanel();
panel.add(panel_2, BorderLayout.CENTER);
panel_2.setLayout(new BorderLayout(0, 0));
JPanel panel_1 = new JPanel();
panel_2.add(panel_1, BorderLayout.NORTH);
panel_1.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "Actions", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
JButton btnReloadRule = new JButton("Reload");
btnReloadRule.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ft.fillTable(configFilePath, table);
}
});
panel_1.add(btnReloadRule);
JButton btnNewRule = new JButton("New");
btnNewRule.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
Vector rules = new Vector();
rules.add(true);
rules.add("New Rule");
rules.add("New Regex");
rules.add("red");
rules.add("response");
rules.add("any");
dtm.addRow(rules);
}
});
panel_1.add(btnNewRule);
JButton btnDeleteRule = new JButton("Delete");
btnDeleteRule.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int selectRows = table.getSelectedRows().length;
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
if (selectRows == 1) {
int selectedRowIndex = table.getSelectedRow();
// 在配置文件中删除数据
String cellValue = (String) dtm.getValueAt(selectedRowIndex, 1);
// System.out.println(cellValue);
rc.removeFileContent(cellValue, configFilePath);
// 在表格中删除数据
dtm.removeRow(selectedRowIndex);
}
}
});
panel_1.add(btnDeleteRule);
JScrollPane scrollPane = new JScrollPane();
panel_2.add(scrollPane, BorderLayout.CENTER);
table = new JTable();
table.setModel(new DefaultTableModel(
new Object[][] {
},
new String[] {
"Loaded", "Name", "Regex", "Color", "Scope", "Action"
}
));
scrollPane.setViewportView(table);
table.getColumnModel().getColumn(2).setPreferredWidth(172);
table.getColumnModel().getColumn(3).setCellEditor(new DefaultCellEditor(new JComboBox(Config.colorArray)));
table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(new JCheckBox()));
table.getColumnModel().getColumn(4).setCellEditor(new DefaultCellEditor(new JComboBox(Config.scopeArray)));
table.getColumnModel().getColumn(5).setCellEditor(new DefaultCellEditor(new JComboBox(Config.actionArray)));
JLabel lblNewLabel = new JLabel("@EvilChen Love YuChen.");
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(lblNewLabel, BorderLayout.SOUTH);
table.getModel().addTableModelListener(
new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.INSERT || e.getType() == TableModelEvent.UPDATE) {
DefaultTableModel dtm = (DefaultTableModel) table.getModel();
int rows = dtm.getRowCount();
JSONObject jsonObj = new JSONObject();
for (int i = 0; i < rows; i++) {
JSONObject jsonObj1 = new JSONObject();
jsonObj1.put("loaded", (boolean) dtm.getValueAt(i, 0));
jsonObj1.put("regex", (String) dtm.getValueAt(i, 2));
jsonObj1.put("color", (String) dtm.getValueAt(i, 3));
jsonObj1.put("scope", (String) dtm.getValueAt(i, 4));
jsonObj1.put("action", (String) dtm.getValueAt(i, 5));
// 添加数据
jsonObj.put((String) dtm.getValueAt(i, 1), jsonObj1);
}
wfc.writeFileContent(configFilePath, jsonObj.toString());
}
}
}
);
callbacks.customizeUiComponent(panel);
callbacks.customizeUiComponent(panel_1);
callbacks.customizeUiComponent(panel_2);
callbacks.customizeUiComponent(panel_3);
callbacks.customizeUiComponent(scrollPane);
callbacks.addSuiteTab(BurpExtender.this);
}
@Override
public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) {
HaETab = new MarkInfoTab(controller, editable);
return HaETab;
}
@Override
public String getTabCaption() {
return "HaE";
}
@Override
public Component getUiComponent() {
return panel;
}
/*
* 使用processHttpMessage用来做Highlighter
*/
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
// 判断是否是响应且该代码作用域为REPEATER、INTRUDER、PROXY分别对应toolFlag 64、32、4
if (toolFlag == 64 || toolFlag == 32 || toolFlag == 4) {
JSONObject jsonObj = new JSONObject();
byte[] content = messageInfo.getRequest();
// 流量清洗
String urlString = helpers.analyzeRequest(messageInfo.getHttpService(), content).getUrl().toString();
urlString = urlString.indexOf("?") > 0 ? urlString.substring(0, urlString.indexOf("?")) : urlString;
// 正则判断
if (mh.matchSuffix(urlString)) {
return;
}
if (messageIsRequest) {
try {
String c = new String(content, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
jsonObj = ec.matchRegex(content, "request", "highlight", configFilePath);
} else {
content = messageInfo.getResponse();
// 流量清洗
List<String> mimeList = helpers.analyzeResponse(content).getHeaders();
// 正则判断
if (mh.matchMIME(mimeList)) {
return;
}
try {
String c = new String(content, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
jsonObj = ec.matchRegex(content, "response", "highlight", configFilePath);
}
List<String> colorList = da.highlightList(jsonObj);
if (colorList.size() != 0) {
String color = uc.getEndColor(gck.getColorKeys(colorList, Config.colorArray), Config.colorArray);;
messageInfo.setHighlight(color);
}
}
}
class MarkInfoTab implements IMessageEditorTab {
private ITextEditor markInfoText;
private byte[] currentMessage;
private final IMessageEditorController controller;
private byte[] extractRequestContent;
private byte[] extractResponseContent;
public MarkInfoTab(IMessageEditorController controller, boolean editable) {
this.controller = controller;
markInfoText = callbacks.createTextEditor();
markInfoText.setEditable(editable);
}
@Override
public String getTabCaption() {
return "MarkInfo";
}
@Override
public Component getUiComponent() {
return markInfoText.getComponent();
}
@Override
public boolean isEnabled(byte[] content, boolean isRequest) {
try {
// 流量清洗
String urlString = helpers.analyzeRequest(controller.getHttpService(), controller.getRequest()).getUrl().toString();
urlString = urlString.indexOf("?") > 0 ? urlString.substring(0, urlString.indexOf("?")) : urlString;
// 正则判断
if (mh.matchSuffix(urlString)) {
return false;
}
} catch (Exception e) {
return false;
}
if (isRequest) {
JSONObject jsonObj = ec.matchRegex(content, "request", "extract", configFilePath);
if (jsonObj.length() != 0) {
String result = da.extractString(jsonObj);
extractRequestContent = result.getBytes();
return true;
}
} else {
// 流量清洗
List<String> mimeList = helpers.analyzeResponse(controller.getResponse()).getHeaders();
// 正则判断
if (mh.matchMIME(mimeList)) {
return false;
}
JSONObject jsonObj = ec.matchRegex(content, "response", "extract", configFilePath);
if (jsonObj.length() != 0) {
String result = da.extractString(jsonObj);
extractResponseContent = result.getBytes();
return true;
}
}
return false;
}
@Override
public byte[] getMessage() {
return currentMessage;
}
@Override
public boolean isModified() {
return markInfoText.isTextModified();
}
@Override
public byte[] getSelectedData() {
return markInfoText.getSelectedText();
}
/*
* 使用setMessage用来做Extractor
*/
@Override
public void setMessage(byte[] content, boolean isRequest) {
try {
String c = new String(content, "UTF-8").intern();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (content.length > 0) {
if (isRequest) {
markInfoText.setText(extractRequestContent);
} else {
markInfoText.setText(extractResponseContent);
}
}
currentMessage = content;
}
}
public static void main(String[] args) {
}
}