回到顶部

阅读目录

fiddler 二次转发实现动态改包(发送请求)

问题场景描述

如何更加精确有状态地实现动态修改请求返回包?对有状态这里理解可能有点问题,我描述一个场景会更直观一点。

一个应用软件向服务器请求时间戳,第一次请求返回为 A,通过修改返回包,使第二次返回 A+B,第三次返回 A+B+B.....这里面有一个递增的关系,这就是我所描述的状态。

常见的改包是无状态的,即我使用 burp,他的自动改包是一个正则表达式匹配的字符串替换;使用 fiddler,通过的他脚本进行返回包修改,但修改函数是无状态的,每请求一次,函数便重新运行一次,是无法计数的,也就是我所说的无状态。

解决问题思考

要解决这个问题,首先想到的是重写的一个代理,但这部分工作我觉得并不是那么简单,要做到像 burp 或者 fiddler 那样成熟的工具,并不是个简单的活。

偶然间的想法,让我想到可以在 fiddler 这一层代理上,进行一个请求的二次“转发”,这个转发有点歧义,我所说的转发是将请求的返回结果进行一次转发,再发送到一个第三方服务器,这个服务器返回我们要的结果。自然,这个第三方服务器是我们可以控制的,自然。

fiddler发送请求实现

查找资料发现fiddler的script可以通过以下三个函数进行请求发送:

  1. FiddlerApplication.oProxy.SendRequest
  2. FiddlerApplication.oProxy.SendRequestAndWait
  3. FiddlerObject.utilIssueRequest

SendRequest和SendRequestAndWait用法是一样的,区别在于一个只是发送了请求,并不能处理返回包,SendRequestAndWait 可以处理返回包,所以SendRequestAndWait 就是我们需要的函数。utilIssueRequest 也是发送请求无法处理返回包。

这里也简单提一下 utilIssueRequest 的使用方法,utilIssueRequest 的使用比另外两个函数要简单得多,只是处理字符串,然后拼接成一个请求头,而 SendRequest 和 SendRequestAndWait 得两个参数分别是 HTTPRequestHeaders 和 Byte[] 类型。utilIssueRequest 使用简单 demo 如下,即向http://localhost:9090/ 发送了一个 POST 请求:

var method:String = 'POST';
var url:String = 'http://localhost:9090/';
var protocol = "HTTP/1.1";
raw += method + " " + url + " " + protocol + "\r\n";
var body = 'test';
raw += "\r\n" + body;
FiddlerObject.utilIssueRequest(raw);

回到真正所需要得 SendRequestAndWait 函数,这个函数用法挺难找的,所幸还是找到了,我最后写的代码如下:

if (oSession.HostnameIs("www.humblegames.cn")&& oSession.uriContains('fightingx/utils/timeUtil2.php')){
			var responses = oSession.GetResponseBodyAsString();
            oSession.utilDecodeResponse(); //解码 
			var Content: byte[] = System.Text.Encoding.UTF8.GetBytes(responses);
			var oRQH: HTTPRequestHeaders = new HTTPRequestHeaders("/path", ['Host: 127.0.0.1:9090','Content-Length: '+Content.length.ToString(), 'Content-Type: application/x-www-url-encoded']);
			oRQH.HTTPMethod = "POST";
			var oSD = new System.Collections.Specialized.StringDictionary();
			var newSession = FiddlerApplication.oProxy.SendRequestAndWait(oRQH, Content, oSD, null);     	
			var second_res = newSession.GetResponseBodyAsString();			
			FiddlerApplication.Log.LogString(second_res);
			oSession.utilSetResponseBody(second_res);    
        }

代码实现的内容:首先获取当前请求的返回包,将返回包的 body 通过 POST 请求转发到 127.0.0.1:9090,再将 127.0.0.1:9090 返回的结果当作最后此次请求的返回 body。

在 9090 端口也是一个简单的 flask 服务器,这里通过一个计数器便可以解决上面的状态问题:

# -*- coding: utf-8 -*-
from flask import Flask,request
app = Flask(__name__)

count = 0

@app.route('/path', methods=['GET', 'POST'])
def index():
    global count
    count += 1
    time = str(1569076091 + count * 21700)
    return time


if __name__ == '__main__':
    app.run(host='0.0.0.0',port=9090,debug=True)

这上面两段代码也就解决了我一开始所描述的场景问题。

 

另外一个发送请求的方式:

//把内容通过ajax http发送其它地方
var _xhr = new ActiveXObject('Microsoft.XMLHTTP');
var url = 'http://huoshan.loc/';
//发送的数据参数
var param = {
    a: oSession.GetResponseBodyAsString(),
    b: 'bbbbbbbbb'
};
var par = '';
for (var i in param) {
    var _data = escape(param[i]);
    par += par ? ("&" + i + "=" + _data) : (i + "=" + _data);
}
//不需要返回值所以写啦个空回调
_xhr.onreadystatechange = function() {}
_xhr.open('POST', url, true);
_xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
_xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
_xhr.send(par);

又一个问题

这里我所实现的第三方服务器是一个 flask,但当请求返回的结果是一个复杂的 html 时,里面有各种换行各种符号等等,将这种数据作为 POST 请求的 data,在 flask 这边是很难处理的。是否有更优雅更加完备的第三方服务器实现方式,能够获取所有 POST 数据,处理这种问题?

转载于:


^_^
请喝咖啡 ×

文章部分资料可能来源于网络,如有侵权请告知删除。谢谢!

前一篇: Notarized HoRNDIS(Mac12 通过安卓手机连接 vpn)
下一篇: fiddler OnBeforeResponse oSession.utilSetResponseBody 未生效的解决办法
captcha