实现效果
IMessageEditor
是burp提供的HTTP数据包展示和编辑的UI组件,简单来说就是每天用的抓包改包的组件,如下。
因此我们想要实现的效果如下:使用IDEA创建一个GUI界面,并展示在Burp中
- 创建一个新的Tab标签页
- 作用为记录所有Scanner的日志,点击对应的记录可以看到详细的数据包。
涉及接口:
- ITab
- IHttpListener
- IMessageEditorController (重要)
实现代码
创建项目过程省略,使用旧版API开发,平常的UI可以参考上一节《GUI开发》,此时已经默认画好了UI如下,上面是table组件,下面是2个展示内容的框(记得尽量给相关的组件都取一个字段名,尤其是TextArea上层组件和自己,后续会用到)。
测试UI展示是否正常(看着还行)
基础UI画好了,但还没有用到IMessageEditor
,这是因为IDEA默认没有这个组件,网上的教程都是手搓UI,但对于使用IDEA辅助画UI的来说就要命了,为了实现起来更加简单,我发现只需要画好UI,然后用创建好的MessageEditor
直接替换对应的组件即可。(比如我这里俩TextArea
是需要展示IMessageEditor
的地方,那我后面就直接用生成好的MessageEditor
替换或者覆盖这俩组件即可。)
先打开IDEA的设置,开启UI生成代码
再次编译,就可以看到相关的UI代码了。
此时我们创建2个IMessageEditor
然后分别替换 reqTextArea
和 respTextArea
注意:需要当前的UI类实现 IMessageEditorController
接口,代码如下:
package org.gm7.ui;
import burp.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
public class BurpGUI implements IMessageEditorController {
private JTabbedPane tabbedPane1;
private JTabbedPane tabbedPane2;
private JTextArea reqTextArea;
private JTextArea respTextArea;
private JTable table1;
private JPanel rootPanel;
private JPanel respPanel;
private JPanel reqPanel;
private IHttpRequestResponse currentlyDisplayedItem;
public BurpGUI(IBurpExtenderCallbacks callbacks) {
// 创建2个 MessageEditor
IMessageEditor req = callbacks.createMessageEditor(this, false);
IMessageEditor resp = callbacks.createMessageEditor(this, false);
// 隐藏原来的组件,再用生成的组件占用隐藏的组件的位置
reqTextArea.setVisible(false);
respTextArea.setVisible(false);
reqPanel.add(req.getComponent(), new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false));
respPanel.add(resp.getComponent(), new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false));
// 设置显示内容
req.setMessage("this is request".getBytes(), true);
resp.setMessage("this is response".getBytes(), false);
// 设置table的header,决定table格式
DefaultTableModel tableModel = new DefaultTableModel(new Object[][]{}, new Object[]{"URL", "Method", "request", "response"});
table1.setModel(tableModel);
// 隐藏3 4列
table1.getTableHeader().getColumnModel().getColumn(2).setMaxWidth(0);
table1.getTableHeader().getColumnModel().getColumn(2).setMinWidth(0);
table1.getTableHeader().getColumnModel().getColumn(2).setPreferredWidth(0);
table1.getTableHeader().getColumnModel().getColumn(3).setMaxWidth(0);
table1.getTableHeader().getColumnModel().getColumn(3).setMinWidth(0);
table1.getTableHeader().getColumnModel().getColumn(3).setPreferredWidth(0);
}
public JPanel getRootPanel() {
return rootPanel;
}
// 获取Table组件,方便扩展调用
public JTable getTable1() {
return table1;
}
@Override
public IHttpService getHttpService() {
return currentlyDisplayedItem.getHttpService();
}
@Override
public byte[] getRequest() {
return currentlyDisplayedItem.getRequest();
}
@Override
public byte[] getResponse() {
return currentlyDisplayedItem.getResponse();
}
再次打包,效果如下:
也就是说到现在,所有的UI就完成了,后面就是加数据和事件了。
实现IHttpListener
接口,监听所有的数据,如果是Scanner的请求,那么就加到我们创建的tab中。实现代码如下:
package burp;
import org.gm7.ui.BurpGUI;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
public class BurpExtender implements IBurpExtender, ITab, IHttpListener {
// 回调对象
private IBurpExtenderCallbacks callbacks;
// 辅助类,一般用于辅助分析数据包结构
private IExtensionHelpers helpers;
private BurpGUI burpGUI;
private JPanel rootPanel;
// 实现 IBurpExtender 接口函数
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
// 设置插件名字
callbacks.setExtensionName("Demo");
// callbacks到处都要用,搞成类变量
this.callbacks = callbacks;
// 辅助类,一般用于辅助分析数据包结构,类变量方便其他函数调用
helpers = callbacks.getHelpers();
// 注册UI
burpGUI = new BurpGUI(callbacks);
rootPanel = burpGUI.getRootPanel();
callbacks.customizeUiComponent(rootPanel);
callbacks.addSuiteTab(this);
// 注册监听
callbacks.registerHttpListener(this);
}
@Override
public String getTabCaption() {
return "My Tab";
}
@Override
public Component getUiComponent() {
return rootPanel;
}
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
// 如果是scanner 且 是响应
if (toolFlag == IBurpExtenderCallbacks.TOOL_SCANNER && !messageIsRequest) {
// 先拿到table
JTable table = burpGUI.getTable1();
// 解析出新的数据
String url = helpers.analyzeRequest(messageInfo).getUrl().toString();
String method = helpers.analyzeRequest(messageInfo).getMethod();
String request = helpers.bytesToString(messageInfo.getRequest());
String response = helpers.bytesToString(messageInfo.getResponse());
// 添加到table中
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
tableModel.addRow(new Object[]{url, method, request, response});
}
}
}
扫描后可见达到预期值,在Tab中成功有了相关的数据。
但现在还有一个问题,就是点击对应的数据后,下面的 MessageEditor
中的内容没有同步,在 BurpGUI
类中给table添加选择事件。
// table添加选中事件
ListSelectionModel selectionModel = table1.getSelectionModel();
selectionModel.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
// 选中行
int selectedRow = table1.getSelectedRow();
// 设置值
req.setMessage(table1.getValueAt(selectedRow, 2).toString().getBytes(), true);
resp.setMessage(table1.getValueAt(selectedRow, 3).toString().getBytes(), false);
}
});
至此一切都OK
扩展总结
- 最简单的办法,先画好UI界面,然后再用
MessageEditor
组件去覆盖到想要展示的地方即可 - 在IDEA设置中可配置生成相关UI代码,方便进行覆盖
- JTable中想要监听选中对象,可以给
ListSelectionModel
对象添加监听事件实现