文章来源:重生信息安全
前言
使用详情如下
下面就直接从其的源码入手,BurpExtender.java的代码分析如下所示,此代码主要是实现burpsuite当中要定义插件的要求
package burp;
import wooyun.GUI;
import wooyun.Menu;
import javax.swing.*;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
//所有的插件必须实现此接口。实现的类名必须为“BurpExtender”。在 burp包中,必须申明为 public ,并且必须提供一个默认的构造器。
//对于IContextMenuFactory接口提供了下面的方法
//#!java java.util.List<javax.swing.JMenuItem> createMenuItems(IContextMenuInvocation invocation)
public class BurpExtender implements IBurpExtender, IContextMenuFactory {
public PrintWriter stdout;
public PrintWriter stderr;
//这个接口包含许多帮助器方法,这些扩展可以用来帮助处理Burp扩展中出现的各种常见任务。扩展可以调用BurpExtenderCallbacks.getHelpers获取该接口的实例。
public IExtensionHelpers helpers;
//使用这个接口burpsuite通过扩展一组扩展使用的回调方法
public IBurpExtenderCallbacks cbs;
//当Burp调用扩展提供的带有上下文菜单调用细节的IContextMenuFactory时,将使用此接口。
//自定义上下文菜单工厂可以查询此接口来获取调用事件的详细信息,以便确定应该显示哪些菜单项。
public IContextMenuInvocation context;
@Override
//// 实现 IBurpExtender 接口的 registerExtenderCallbacks 方法
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
String pluginName = "From wooyun search";
//设置扩展插件名
callbacks.setExtensionName(pluginName);
//burp扩展的帮助类,有一些字符串转换的功能,例如helpers.base64Encode(parameter.getValue())
this.helpers = callbacks.getHelpers();
this.cbs = callbacks;
//输出流,在burp输出内容,可用来调试代码
this.stdout = new PrintWriter(callbacks.getStdout(), true);
//错误流,在burp输出内容,可用来调试代码
this.stderr = new PrintWriter(callbacks.getStderr(), true);
this.stdout.println("hello burp!");
//Burp 的作者在设计上下文菜单功能中采用了工厂模式的设计模式,扩展可以实现此接口,然后调用 IBurpExtenderCallbacks.registerContextMenuFactory() 注册自定义上下文菜单项的工厂。
callbacks.registerContextMenuFactory(this);// for menus
}
@Override
//当用户在 Burp 中的任何地方调用一个上下文菜单时,Burp 则会调用这个工厂方法。
//此方法会根据菜单调用的细节,提供应该被显示在上下文菜单中的任何自定义上下文菜单项。
//invocation - 一个实现 IMessageEditorTabFactory 接口的对象, 通过此对象可以获取上下文菜单调用的细节。
public List<JMenuItem> createMenuItems(IContextMenuInvocation invocation) {
ArrayList<JMenuItem> menu_list = new ArrayList<JMenuItem>();
this.context = invocation;
menu_list.add(new Menu(this));
//此工厂方法将会返回需要被显示的自定义菜单项的一个列表(包含子菜单,checkbox 菜单项等等),
//若无菜单项显示,此工厂方法会返回 null 。
return menu_list;
}
}
关于TableStruct.java的代码,其实就是要显示的一个table表的结构
package wooyun;
import java.util.HashMap;
import java.util.Map;
public class TableStruct {
private Map<String, Object[]> ColumnNames;
private Map<String, Object[][]> RowDatas;
private Map<String, String> ExtraInfo;
TableStruct() {
//列名
ColumnNames = new HashMap<String, Object[]>();
//行数据
RowDatas = new HashMap<String, Object[][]>();
//提取的信息
ExtraInfo = new HashMap<String, String>();
}
public void SetExtraInfo(String name, String info) {
this.ExtraInfo.put(name, info);
}
public String GetExtraInfo(String name) {
return this.ExtraInfo.get(name);
}
public String[] GetNameSets() {
//带参数的toArray方法,则是根据参数数组的类型,构造了一个对应类型的,长度跟ArrayList的size一致的空数组,
//虽然方法本身还是以 Object数组的形式返回结果,不过由于构造数组使用的ComponentType跟需要转型的ComponentType一致,就不会产生转型异常。
//java.lang.reflect.Array类提供静态方法来动态创建和访问Java数组
//在Java的反射机制中,通过 数组的 class 对象的getComponentType()方法可以取得一个数组的Class对象,
a = (Object[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
return RowDatas.keySet().toArray(new String[0]);
}
public void AddColumnNames(String name, Object[] obj) {
this.ColumnNames.put(name, obj);
}
public void AddRowDatas(String name, Object[][] obj) {
this.RowDatas.put(name, obj);
}
public Object[] GetColumnNamesFromTabName(String name) {
return this.ColumnNames.get(name);
}
public Object[][] GetRowDatasFromTabName(String name) {
return this.RowDatas.get(name);
}
}
关于GUI.java的代码
package wooyun;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import java.awt.*;
public class GUI {
public GUI(TableStruct t) {
TabbedPaneFrame jf = new TabbedPaneFrame(t); //创建一个JFrame对象
//设置Title
jf.setTitle("WooYun 搜索结果");
//设置大小
jf.setSize(650, 480);
//设置窗口相对于指定组件的位置。如果组件当前未显示或者 c 为 null,则此窗口将置于屏幕的中央。
jf.setLocationRelativeTo(null);
// jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true); //设置窗口可见
}
}
//java的GUI程序的基本思路是以JFrame为基础,它是屏幕上window的对象,能够最大化、最小化、关闭
class TabbedPaneFrame extends JFrame {
//JTabbedPane是一种可以放多个面板的并且可以方便切换的容器,选项卡面板。它允许用户通过点击给定标题或图标的选项卡,在一组组件之间进行切换显示
private JTabbedPane tabbedPane;
private int count = 0;
//定义结构体化的
private TableStruct struct;
public TabbedPaneFrame(TableStruct t) {
this.struct = t;
// 添加选项卡,进行初始化
tabbedPane = new JTabbedPane();
//获取key的集合
for (String s : struct.GetNameSets()) {
//例如可以以下面的方式进行创建
//创建第 1 个选项卡(选项卡只包含 标题)
//tabbedPane.addTab("Tab01", createTextPanel("TAB 01"));
// 创建第 2 个选项卡(选项卡包含 标题 和 图标)
//tabbedPane.addTab("Tab02", new ImageIcon("bb.jpg"), createTextPanel("TAB 02"));
// 创建第 3 个选项卡(选项卡包含 标题、图标 和 tip提示)
//tabbedPane.addTab("Tab03", new ImageIcon("bb.jpg"), createTextPanel("TAB 03"), "This is a tab.");
tabbedPane.addTab(s, null);
}
// 添加选项卡面板的控件
add(tabbedPane, "Center");
// 添加监听器,添加选项卡选中状态改变的监听器
tabbedPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
//获取当前被选中的选项卡
int n = tabbedPane.getSelectedIndex();
loadTab(n);
}
});
//设置默认进行加载的方式
loadTab(0);
}
private static String convertToMultiline(String orig) {
//replaceAll(String regex, String replacement),
//用replacement替换所有的regex匹配项,regex很明显是个正则表达式,replacement是字符串。
return "<html>" + orig.replaceAll("\n", "
");
}
private void loadTab(int n) {
//获取选定的title
String title = tabbedPane.getTitleAt(n);
//根据title获取行的数据
Object[][] tableDate = struct.GetRowDatasFromTabName(title);
//根据title获取列数据
Object[] name = struct.GetColumnNamesFromTabName(title);
//创建表格控件
//JTable table = new JTable(cellData, columnNames);
JTable table = new JTable(tableDate, name);
//JPanel:面板组件,非顶层容器
JPanel jp = new JPanel(); //创建一个JPanel对象
JTableHeader head = table.getTableHeader(); // 创建表格标题对象
//dimension是Java的一个类,封装了一个构件的高度和宽度
//setSize是设定的固定大小,而setPreferredSize仅仅是设置最好的大小,这个不一定与实际显示出来的控件大小一致(根据界面整体的变化而变化)
head.setPreferredSize(new Dimension(head.getWidth(), 20));// 设置表头大小
//设置自动调整的模式
//AUTO_RESIZE_SUBSEQUENT_COLUMNS 在 UI 调整中,更改后续列以保持总宽度不变,这是默认的行为
table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
//利用JTable中的getColumnModel()方法取得TableColumnModel对象;再利用TableColumnModel界面
//所定义的getColumn()方法取TableColumn对象,利用此对象的setPreferredWidth()方法就可以控制字段的宽度.
TableColumnModel tc = table.getColumnModel();
tc.getColumn(0).setPreferredWidth(10);
table.setRowHeight(22);
//获取额外的信息
String ret = struct.GetExtraInfo(title);
JLabel jl = new JLabel(convertToMultiline(ret)); //创建一个标签
//BorderLayout表示的就是边界布局
jp.setLayout(new BorderLayout());
//
jp.add(jl, "North");
//在JScrollPane里放入JPanel
jp.add(new JScrollPane(table), "Center");
//将组件设置为index至component,如果该索引中没有选项卡,则会引发内部异常
tabbedPane.setComponentAt(n, jp);
}
}
关于Menu.java
package wooyun;
import burp.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Menu extends JMenuItem {//JMenuItem vs. JMenu
//初始化方法
public Menu(BurpExtender burp) {
this.setText(" 从乌云搜索类似漏洞");
// 添加动作监听器
this.addActionListener(new SearchFromWooyun(burp, burp.context));
}
}
class SearchFromWooyun implements ActionListener {
public IContextMenuInvocation invocation;
public IExtensionHelpers helpers;
public PrintWriter stdout;
public PrintWriter stderr;
public IBurpExtenderCallbacks callbacks;
//下面就是其的初始化方法
public SearchFromWooyun(BurpExtender burp, IContextMenuInvocation context) {
//通过burpExtender当中的内容给context
this.invocation = context;
this.helpers = burp.helpers;
this.callbacks = burp.cbs;
this.stdout = burp.stdout;
this.stderr = burp.stderr;
}
@Override
//在ActionListener中的actionPerformed中定义相应方法处理事件
public void actionPerformed(ActionEvent e) {
//IContextMenuInvocation的getSelectedMessages方法
//此方法可用于检索用户在调用上下文菜单时显示或选择的HTTP请求响应的详细信息。注意:出于性能原因,
//从这个方法返回的对象被绑定到Burp UI中消息的原始上下文。例如,如果在代理拦截面板上调用了上下文菜单,
//那么由该方法返回的IHttpRequestResponse将反映拦截面板的当前内容,并且当当前消息已被转发或删除时,
//这将发生变化。如果您的扩展需要存储的细节信息的上下文菜单中被调用,那么你应该从IHttpRequestResponse查询这些细节的时候调用,
//或者你应该使用IBurpExtenderCallbacks.saveBuffersToTempFiles()来创建一个持久的只读副本
//IHttpRequestResponse @return IHttpRequestResponse对象数组代表显示的物品或由用户选择上下文菜单时调用。
//如果没有适用于调用的消息,此方法将返回null。
IHttpRequestResponse[] selectedItems = this.invocation.getSelectedMessages();
//此方法用于检索请求消息
//byte[] getRequest();
byte[] selectedRequest = selectedItems[0].getRequest();
//此方法用于接收此请求响应的HTTP服务。
IHttpService httpService = selectedItems[0].getHttpService();
//**************获取参数 通过IRequestInfo对象*************************//
//此方法可用于分析HTTP请求,并获取有关它的各种关键细节。
// IRequestInfo analyzeRequest(byte[] request);
IRequestInfo analyzedRequest = this.helpers.analyzeRequest(selectedRequest);//only get the first
// String url = analyzedRequest.getUrl().toString();
String pattern = "(GET|POST) ([^ ]*) HTTP/";
//List<String> getHeaders();此方法用于获取请求中包含的HTTP标头。
//获取请求当中的第一个行
String line0 = analyzedRequest.getHeaders().get(0);
//利用正则去匹配
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(line0);
String url = "";
if (m.find()) {
//获取协议和host,然后获取匹配到的url
url = httpService.getProtocol() + "://" + httpService.getHost() + m.group(2);
} else {
stderr.println("Host:" + httpService.getHost() + " url匹配失败");
return;
}
List<String> gets = new ArrayList<String>();
List<String> posts = new ArrayList<String>();
List<String> cookies = new ArrayList<String>();
//下面就是获取请求参数
List<IParameter> paraList = analyzedRequest.getParameters();
for (IParameter para : paraList) {
byte type = para.getType(); //获取参数的类型
String key = para.getName(); //获取参数的名称
String value = para.getValue(); //获取参数的值
//根据不同的type放到不同的list当中
switch (type) {
case 0:
gets.add(key);
break;
case 1:
posts.add(key);
break;
case 2:
cookies.add(key);
break;
}
}
//参数共有7种格式,0是URL参数,1是body参数,2是cookie参数,6是json格式参数
Wooyun w = null;
try {
w = new Wooyun();
} catch (Exception e1) {
for (StackTraceElement
elem : e1.getStackTrace()) {
this.stderr.println(elem);
}
//showMessageDialog():消息对话框
//JOptionPane.showMessageDialog有三种参数设置
// JOptionPane.showMessageDialog(parentComponent, message);
// JOptionPane.showMessageDialog(parentComponent, message, title, messageType);
// JOptionPane.showMessageDialog(parentComponent, message, title, messageType, icon);
//type为1表示messagetType值为1,含义为提示信息
JOptionPane.showMessageDialog(null, "初始化数据库失败", "提示", 1);
return;
}
try {
//初始化TableStruct结构,调用Search方法,然后将gets、posts、cookies进行转换为数组
TableStruct ret = w.Search(new URL(url), gets.toArray(new String[gets.size()]), cookies.toArray(new String[cookies.size()]), posts.toArray(new String[posts.size()]));
//获取RowDatas当中的所有keySet
if (ret.GetNameSets().length == 0) {
JOptionPane.showMessageDialog(null, "未发现可用参数", "提示", 1);
return;
}
new GUI(ret);
} catch (Exception e1) {
for (StackTraceElement
elem : e1.getStackTrace()) {
this.stderr.println(elem);
}
this.stderr.println(e1);
}
}
}
关于此项目的Wooyun.java其实就是搜索类,根据源码当中的wooyun.json进行搜索
package wooyun;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static java.lang.String.join;
import static java.lang.String.valueOf;
public class Wooyun {
public StringBuilder sb;
private String shuimugan;
private TableStruct struct;
public Wooyun() throws IOException {
//Class.getClassLoader.getResourceAsStream(String path) :默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源。
InputStream is = this.getClass().getClassLoader().getResourceAsStream("wooyun.json");
if (is==null) {
throw new NullPointerException();
}
// InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("wooyun.json");
sb = new StringBuilder();
//public InputStreamReader(InputStream in,Charset cs)
//创建使用给定字符集的 InputStreamReader,下面就是使用的是StandardCharsets.UTF_8字符集
//BufferedReader :提供通用的缓冲方式文本读取
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
int ch;
while ((ch = br.read()) != -1) {
sb.append((char) ch);
}
shuimugan = "https://shuimugan.com/bug/view?bug_no=";
struct = new TableStruct();
}
//自己定义了一个数组的连接函数
private static Object[] concat(Object[] a, Object[] b) {
Object[] c = new Object[a.length + b.length];
System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(b, 0, c, a.length, b.length);
return c;
}
/*
输入:一段url,host,get参数,cookie参数,post参数
返回: path统计,host统计,各种参数统计
漏洞类型占比(path,host)
*/
//相应的搜索函数
public TableStruct Search(URL url, String[] GetParams, String[] CookieParams, String[] PostParams) {
JSONArray jobj;
//参数是Stringbuffer的toString方法
//转换为jsonobject对象
jobj = JSONArray.parseArray(sb.toString());
//如果用“.”作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split(".");
//获取路径
String[] path_array = url.getPath().split("/");
String path = path_array[path_array.length - 1];
//从url当中获取host
String host = url.getHost();
Map<String, Integer> pathTJMap = new TreeMap<String, Integer>();
List<Object[]> pathList = new ArrayList<Object[]>();
Map<String, Integer> hostTJMap = new TreeMap<String, Integer>();
List<Object[]> hostList = new ArrayList<Object[]>();
Map<String, Integer> getMap = new TreeMap<String, Integer>();
Map<String, Integer> cookieMap = new TreeMap<String, Integer>();
Map<String, Integer> postMap = new TreeMap<String, Integer>();
for (Object object : jobj) {
JSONObject jsonObject = (JSONObject) object;
//获取漏洞的类型
String BugType = jsonObject.getString("type");
if (BugType.equals("")) {
BugType = "不知名的漏洞类型";
}
String BugID = jsonObject.getString("bugid");
String Title = jsonObject.getString("title");
JSONArray urls = jsonObject.getJSONArray("url");
JSONArray targets = jsonObject.getJSONArray("target");
JSONArray get_params = jsonObject.getJSONArray("params");
JSONArray cookie_params = jsonObject.getJSONArray("cookie_params");
JSONArray post_params = jsonObject.getJSONArray("post_params");
for (Object obj_url : urls)
try {
URL _url = new URL((String) obj_url);
String[] path_array2 = _url.getPath().split("/");
if (path_array2.length > 0) {
String _path = path_array2[path_array2.length - 1];
//此处就是判断url是否是一样的
if (!_path.equals("") && _path.equalsIgnoreCase(path)) {
int count = 1;
if (pathTJMap.containsKey(BugType)) {
count = pathTJMap.get(BugType) + 1;
}
pathTJMap.put(BugType, count);
pathList.add(new Object[]{BugType, Title, shuimugan + BugID, _url.toString()});
break;
}
}
} catch (MalformedURLException | ArrayIndexOutOfBoundsException ignored) {
}
for (Object _target : targets) {
String target = (String) _target;
//判断host是否是一样的
if (target.equalsIgnoreCase(host)) {
int count = 1;
if (hostTJMap.containsKey(BugType)) {
count = hostTJMap.get(BugType) + 1;
}
hostTJMap.put(BugType, count);
// hostList.add("[" + BugType + "] " + Title + " 漏洞链接:" + shuimugan + BugID);
hostList.add(new Object[]{BugType, Title, shuimugan + BugID});
}
}
String flag = "!!flag{aabbc}!!";
if (GetParams.length > 0) {
Set<String> param = new HashSet<String>();
//根据get的参数进行判断
for (Object _get : get_params) {
String target = (String) _get;
for (String get2 : GetParams) {
if (target.equalsIgnoreCase(get2)) {
param.add(get2);
}
}
}
if (param.size() > 0) {
String[] ret = {BugType, Title, join(",", param), shuimugan + BugID};
getMap.put(join(flag, ret), param.size());
}
}
//根据cookie参数进行判断
if (CookieParams.length > 0) {
Set<String> param = new HashSet<String>();
for (Object _get : cookie_params) {
String target = (String) _get;
for (String get2 : CookieParams) {
if (target.equalsIgnoreCase(get2)) {
param.add(get2);
}
}
}
if (param.size() > 0) {
String[] ret = {BugType, Title, join(",", param), shuimugan + BugID};
cookieMap.put(join(flag, ret), param.size());
}
}
//根据post参数进行判断
if (PostParams.length > 0) {
Set<String> param = new HashSet<String>();
for (Object _get : post_params) {
String target = (String) _get;
for (String get2 : PostParams) {
if (target.equalsIgnoreCase(get2)) {
param.add(get2);
}
}
}
if (param.size() > 0) {
String[] ret = {BugType, Title, join(",", param), shuimugan + BugID};
postMap.put(join(flag, ret), param.size());
}
}
}
List<Map.Entry<String, Integer>> patTJlist = new ArrayList<Map.Entry<String, Integer>>(pathTJMap.entrySet());
Collections.sort(patTJlist, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o2.getValue() - o1.getValue();
}
});
List<Map.Entry<String, Integer>> hostTJlist = new ArrayList<Map.Entry<String, Integer>>(hostTJMap.entrySet());
//调用函数进行排序
//Collections是一个工具类,sort是其中的静态方法,是用来对List类型进行排序的
Collections.sort(hostTJlist, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
//// 返回值为int类型,大于0表示正序,小于0表示逆序
return o2.getValue() - o1.getValue();
}
});
List<Map.Entry<String, Integer>> getList = new ArrayList<Map.Entry<String, Integer>>(getMap.entrySet());
getList.sort(new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o2.getValue() - o1.getValue();
}
});
List<Map.Entry<String, Integer>> cookieList = new ArrayList<Map.Entry<String, Integer>>(cookieMap.entrySet());
cookieList.sort(new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o2.getValue() - o1.getValue();
}
});
List<Map.Entry<String, Integer>> postList = new ArrayList<Map.Entry<String, Integer>>(postMap.entrySet());
postList.sort(new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o2.getValue() - o1.getValue();
}
});
// 输出 path 部分
if (pathList.size() > 0) {
StringBuilder ret = new StringBuilder(String.format("相同路径:%s 下历史漏洞及漏洞类型:\n", path));
int index = 0;
for (Map.Entry<String, Integer> entry : patTJlist) {
ret.append(entry.getKey()).append(":").append(entry.getValue()).append(" ");
index++;
if (index % 3 == 0) {
ret.append("\n");
}
if (index >= 6) {
break;
}
}
struct.SetExtraInfo("Path", ret.toString());
struct.AddColumnNames("Path", new Object[]{"ID", "漏洞类型", "漏洞标题", "乌云镜像地址", "漏洞页面"});
// struct.AddRowDatas();
Object[][] rows = new Object[pathList.size()][];
for (int i = 0; i < pathList.size(); i++) {
Object[] obj = concat(new Object[]{valueOf(i)}, pathList.get(i));
rows[i] = obj;
}
struct.AddRowDatas("Path", rows);
}
// 输出host部分
if (hostList.size() > 0) {
StringBuilder ret = new StringBuilder(String.format("相同Host:%s 下历史漏洞及漏洞类型:\n", host));
int index = 0;
for (Map.Entry<String, Integer> entry : hostTJlist) {
ret.append(entry.getKey()).append(":").append(entry.getValue()).append(" ");
index++;
if (index % 3 == 0) {
ret.append("\n");
}
if (index >= 6) {
break;
}
}
struct.SetExtraInfo("Host", ret.toString());
struct.AddColumnNames("Host", new Object[]{"ID", "漏洞类型", "漏洞标题", "乌云镜像地址"});
Object[][] rows = new Object[hostList.size()][];
for (int i = 0; i < hostList.size(); i++) {
Object[] obj = concat(new Object[]{valueOf(i)}, hostList.get(i));
rows[i] = obj;
}
struct.AddRowDatas("Host", rows);
}
// 输出Get参数部分
String flag_split = "!!flag\\{aabbc\\}!!";
if (getList.size() > 0) {
struct.SetExtraInfo("Get Params", "Get参数历史漏洞:");
struct.AddColumnNames("Get Params", new Object[]{"ID", "漏洞类型", "漏洞标题", "影响参数", "漏洞链接"});
Object[][] data = new Object[getList.size()][5];
for (int i = 0; i < getList.size(); i++) {
Map.Entry<String, Integer> entry = getList.get(i);
data[i] = concat(new Object[]{String.valueOf(i)}, (Object[]) entry.getKey().split(flag_split));
}
struct.AddRowDatas("Get Params", data);
}
if (cookieList.size() > 0) {
struct.SetExtraInfo("Cookie Params", "Cookie参数历史漏洞:");
struct.AddColumnNames("Cookie Params", new Object[]{"ID", "漏洞类型", "漏洞标题", "影响参数", "漏洞链接"});
Object[][] data = new Object[cookieList.size()][5];
for (int i = 0; i < cookieList.size(); i++) {
Map.Entry<String, Integer> entry = cookieList.get(i);
data[i] = concat(new Object[]{String.valueOf(i)}, (Object[]) entry.getKey().split(flag_split));
}
struct.AddRowDatas("Cookie Params", data);
}
if (postList.size() > 0) {
struct.SetExtraInfo("Post Params", "Post参数历史漏洞:");
struct.AddColumnNames("Post Params", new Object[]{"ID", "漏洞类型", "漏洞标题", "影响参数", "漏洞链接"});
Object[][] data = new Object[postList.size()][5];
for (int i = 0; i < postList.size(); i++) {
Map.Entry<String, Integer> entry = postList.get(i);
data[i] = concat(new Object[]{String.valueOf(i)}, (Object[]) entry.getKey().split(flag_split));
}
struct.AddRowDatas("Post Params", data);
}
return struct;
}
}
推荐文章++++