因为在处理反爬的过程中遇到了一些动态JS,但是由于服务端会返回一些参数参与本地加密,不能用固定的JS进行AST还原替换调试。所以才有了这个思路,本文只讲思路不涉及具体网站处理。

先记录下mitmproxy基本的api:

针对http,常用的API

http.HTTPFlow 实例 flow
flow.request.headers #获取所有头信息,包含Host、User-Agent、Content-type等字段
flow.request.url #完整的请求地址,包含域名及请求参数,但是不包含放在body里面的请求参数
flow.request.pretty_url #同flow.request.url目前没看出什么差别
flow.request.host #域名
flow.request.method #请求方式。POST、GET等
flow.request.scheme #什么请求 ,如https
flow.request.path # 请求的路径,url除域名之外的内容
flow.request.get_text() #请求中body内容,有一些http会把请求参数放在body里面,那么可通过此方法获取,返回字典类型
flow.request.query #返回MultiDictView类型的数据,url直接带的键值参数
flow.request.get_content()#bytes,结果如flow.request.get_text()
flow.request.raw_content #bytes,结果如flow.request.get_content()
flow.request.urlencoded_form #MultiDictView,content-type:application/x-www-form-urlencoded时的请求参数,不包含url直接带的键值参数
flow.request.multipart_form #MultiDictView,content-type:multipart/form-data
时的请求参数,不包含url直接带的键值参数

以上均为获取request信息的一些常用方法,对于response,同理
flow.response.status_code #状态码
flow.response.text#返回内容,已解码
flow.response.content #返回内容,二进制
flow.response.setText()#修改返回内容,不需要转码
  1. 先给需要反混淆的JS文件写个AST,通过express启动作为服务端,伪代码如下:

    const parser = require("@babel/parser");
    const { visitors } = require("@babel/traverse");
    const traverse = require("@babel/traverse").default;
    const t = require("@babel/types");
    const generator = require("@babel/generator").default;
    const express = require('express');
    var bodyParser = require('body-parser');
    const app = express();
    app.listen(9091,function(){
    console.log('Express server running at http://127.0.0.1')
    })
    
    app.use(bodyParser.json({limit: '50mb'}));
    app.post('/', (req, sendReq) => {
        visitor = {
            ...
        };
        let ast = parser.parse(req.body["content"]);
        traverse(ast, visitor);
        let {code} = generator(ast);
        sendReq.send(code);
    })
  2. 编写mitmproxy代码拦截response对象,然后把获取到的JS代码交给我们上面启动的服务端进行反混淆,随便我们可以在反混淆完了后可以添加Hook代码。伪代码如下:

    class intercept_:
        def response(self, flow):
            if flow.request.url == 'https://www.baidu.com/123.js' and flow.request.method == "GET":  #'https://www.baidu.com/123.js'为需要反混淆js的网址
                content = flow.response.text
                decrypt_response = requests.post("http://127.0.0.1:9091", json={"content": content}).text
                flow.response.text = """此处加上需要Hook的代码,没有可以不加""" + decrypt_response
    
    addons = [
        intercept_()
    ]
  3. 命令行启动mitmproxy脚本:

    mitmdump -s .\mimt.py u www.baidu.com    #www.baidu.com为js所在域名
  4. 命令行启动chrome浏览器:

    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=127.0.0.1:8080 --ignore-certificate-errors

    现在可以随便调试了。