HTTP数据都是成对的,一个request对应一个response. 下面介绍怎么从数据流(回调方式)中处理这种数据。

我的目标是想对请求和响应体的内容进行搜索,如果搜索到指定内容,就报警提示。

但是Burp的插件开发,对接的接口是一个回调函数——processHttpMessage,它和HTTP的工作机制是一样的,发送一次请求,等待响应回来。一来一回。

如果以1作为request,2作为response. 那模拟数据传输的流程:
1212121212...
也可能是(考虑丢包或不稳定网络):
12121122...

代码思路:

  1. 在得到request的时候,先将request存储起来;
  2. 在得到response的时候,将上一次存储起来的request提取出来,一并将request和response一起存储,并传递出去;
  3. 将之前缓存的request删除掉,方便下次再次时候。

使用Burp插件开发code案例举例:

    // 定义两个Map,一个存储单独的请求,一个存储请求-响应对
    private Map<String, IHttpRequestResponse> requestCache = new HashMap<>();
    private Map<String, Pair<IHttpRequestResponse, IHttpRequestResponse>> fullRequestResponse = new HashMap<>();

    /**
     * 功能: 监听HTTP proxy模块的流量,根据配置去做匹配,并高亮显示
     *
     * @param i                    —— 区分什么是什么Burp模块过来的数据;
     * @param b                    —— boolean b(messageIsRequest)这个参数是用来判断当前传入的messageInfo对象是HTTP请求还是HTTP响应;
     * @param iHttpRequestResponse —— 一个结构体,存储了请求和响应属性;
     */
    @Override
    public void processHttpMessage(int i, boolean b, IHttpRequestResponse iHttpRequestResponse) {
        System.out.println(i);
        //不同的toolFlag代表了不同的burp组件模块 https://portswigger.net/burp/extender/api/constant-values.html#burp.IBurpExtenderCallbacks
        if (i == IBurpExtenderCallbacks.TOOL_PROXY) {

            if (b) {
                // 生成一个唯一的key,用于区分不同的请求
                String key = Integer.toString(Utils.generateUID());
                // 先缓存请求数据
                requestCache.put(key, iHttpRequestResponse);
            } else {
                // 获取历史Key
                // 获取所有 key-value 对的 Set 集合
                Set<Map.Entry<String, IHttpRequestResponse>> entries = requestCache.entrySet();

                // 非空判断
                if (entries.isEmpty())
                    return;

                String key = "";
                // 遍历 Set 集合
                for (Map.Entry<String, IHttpRequestResponse> entry : entries) {
                    key = entry.getKey();
                }

                // 获取对应的请求数据
                IHttpRequestResponse request = requestCache.get(key);
                if (request != null) {
                    // 构造请求-响应对,并存入fullRequestResponse
                    fullRequestResponse.put(key, new Pair<>(request, iHttpRequestResponse));

                    // 将成对的数据,传递到处理类进行数据处理
                    TODO

                    // 从请求缓存中移除,节省内存空间
                    requestCache.remove(key);
                    fullRequestResponse.remove(key);
                }
            }

        }
    }

缓存结构设计:
private Map<String, IHttpRequestResponse> requestCache = new HashMap<>();
private Map<String, Pair<IHttpRequestResponse, IHttpRequestResponse>> fullRequestResponse = new HashMap<>();

自定义一个Pair类:

public class Pair<F, S> {
    public final F first;
    public final S second;

    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }
}

如果使用的是Java 9+版本, 官方库中提供了一个Pair通用类供使用, 使用效果和上面自定义类一样。

posted on 2024-03-05 16:05  Mysticbinary  阅读(19)  评论(0编辑  收藏  举报