成对的数据流处理经验

Mysticbinary / 2024-03-05 / 原文

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

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

    // 定义两个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通用类供使用, 使用效果和上面自定义类一样。