• Python好酷|抓包神器 mitmproxy


    mitmproxy(Man-in-the-middle attack,中间人攻击代理)是一款提供交互能力的抓包工具,可以用来拦截、修改、保存 HTTP/HTTPS 请求,对于爬虫尤其是基于APP的爬虫来说,是必不可少的一款神器。mitmproxy 基于Python开发,可以通过Python代码对请求和响应进行自定义过滤和修改。

    image.png

    image.png

    1. 安装

    mitmproxy安装

    >> pip install mitmproxy
    
    >> mitmproxy --version
    Mitmproxy: 6.0.2
    Python:    3.8.6
    OpenSSL:   OpenSSL 1.1.1i  8 Dec 2020
    Platform:  macOS-10.16-x86_64-i386-64bit

    证书安装

    image.png

    Chrome输入mimt.it,则打开如下页面,根据操作系统选择对应的证书。

    image.png

    如果是Mac电脑,需要将证书添加为信任文件方可生效。

    IPhone的话要开启对证书信任的按钮。设置里面搜索信任。否则无法获取https请求。

    2. 启动

    mitmproxy 提供了三种启动模式:

    1. mitmproxy -> 提供一个可交互的命令行界面。

    image.png

    1. mitmdump -> 提供一个简单的终端输出。

    屏幕录制2021-05-14 23.59.51.mov

    1. mitmweb -> 提供一个浏览器界面。

    image.png

    3. 功能介绍

    1. HTTP 回放

    可以将拦截的http请求,进行request内容修改后重新回放。

    屏幕录制2021-05-15 00.06.07.mov

    1. 设置过滤。类似postman interceptor的filter功能。

    如果是mimtweb方式开启,则可以在GUI上配置过滤信息。

    image.png

    如果是通过mitmdump开启,则可以使用过滤表达式进行过滤。

    a

    Match asset in response: CSS, Javascript, Flash, images.

    b regex

    Body

    bq regex

    Request body

    bs regex

    Response body

    c int

    HTTP response code

    d regex

    Domain

    dst regex

    Match destination address

    e

    Match error

    h regex

    Header

    hq regex

    Request header

    hs regex

    Response header

    http

    Match HTTP flows

    m regex

    Method

    marked

    Match marked flows

    q

    Match request with no response

    s

    Match response

    src regex

    Match source address

    t regex

    Content-type header

    tcp

    Match TCP flows

    tq regex

    Request Content-Type header

    ts regex

    Response Content-Type header

    u regex

    URL

    websocket

    Match WebSocket flows (and HTTP-WebSocket handshake flows)

    !

    unary not

    &

    and

    |

    or

    举例:URL中仅包含 baidu.com;

    mitmproxy -p 8080 u baidu\.com

    terminal仅展示baidu.com的http请求。(ps:只是过滤展示而已)

    4. 进阶-插件开发

    4.1插件

    Mitmproxy的插件机制由一组API组成,插件通过响应事件与mitmproxy进行交互,从而使它们能够改变mitmproxy的行为。

    插件是mitmproxy的强大组成部分。实际上,许多mitmproxy自己的功能是在一组内置插件中定义的,实现了从反缓存和粘性Cookie之类的功能到我们的入门Webapp的所有功能。内置的插件有助于进行指导性阅读, 你很快就会发现,相当复杂的功能通常可以归结为非常小的,完全独立的模块。Mitmproxy为第三方脚本编写者和扩展程序提供了与内置功能完全相同的一组工具。

    创建一个python脚本 anatomy.py

    from mitmproxy import ctx
    
    class Counter:
        def __init__(self):
            self.num = 0
    
        def request(self, flow):
            self.num = self.num + 1
            ctx.log.info("We've seen %d flows" % self.num)
    
    addons = [
        Counter()
    ]

    上面是一个简单的插件,用于跟踪我们拦截HTTP请求的数量。每次看到新的HTTP请求时,它都会使用mitmproxy的内部日志记录机制来打印出来。可以在交互式工具的事件日志中或mitmdump的控制台中看到输出结果。

    在示例中使用mitmpdump指令:

    > mitmdump -s ./anatomy.py

    4.2配置

    mitmproxy的核心是全局选项存储,其中包含确定mitmproxy及其附加组件行为的设置。可以从配置文件中读取选项,在命令行上进行设置,并由用户即时进行交互更改。

    下面是在更改响应headers信息,增加计数的例子:

    from mitmproxy import ctx
    
    
    class AddHeader:
        def __init__(self):
            self.num = 0
    
        def load(self, loader):
            loader.add_option(
                name = "addheader",
                typespec = bool,
                default = False,
                help = "Add a count header to responses",
            )
    
        def response(self, flow):
            if ctx.options.addheader:
                self.num = self.num + 1
                flow.response.headers["count"] = str(self.num)
    
    addons = [
        AddHeader()
    ]
    >> env http_proxy=http://localhost:8080 curl -I http://baidu.com
              
    HTTP/1.1 200 OK
    Date: Sat, 15 May 2021 02:41:52 GMT
    Server: Apache
    Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
    ETag: "51-47cf7e6ee8400"
    Accept-Ranges: bytes
    Content-Length: 81
    Cache-Control: max-age=86400
    Expires: Sun, 16 May 2021 02:41:52 GMT
    Connection: Keep-Alive
    Content-Type: text/html
    count: 5

    4.3指令

    命令允许用户与插件进行积极的交互-查询其状态。像options一样,将键入命令,并在运行时检查命令的调用和返回的数据。命令是一个非常强大的结构-例如mitmproxy控制台中的所有用户交互都是通过将命令绑定到键来构建的。如下插件,开发一个指令 myaddon.addheader,在terminal输入即可向请求头增加一个key: myheader

    import typing
    
    from mitmproxy import command
    from mitmproxy import ctx
    from mitmproxy import flow
    
    
    class MyAddon:
        @command.command("myaddon.addheader")
        def addheader(self, flows: typing.Sequence[flow.Flow]) -> None:
            for f in flows:
                f.request.headers["myheader"] = "value"
            ctx.log.alert("done")
    
    
    addons = [
        MyAddon()
    ]
    >> mitmproxy -s ./examples/addons/commands-flows.py
    >> :myaddon.addheader @focus

    截屏2021-05-15 上午10.59.21.png

    4.4脚本

    addons机制具有一种非常便捷的方式,可以将模块作为一个整体视为一个addon对象。这使我们可以将事件处理程序函数放在模块作用域中。例如,下面是一个完整的脚本,它向每个请求头添加键值对

    def request(flow):
        flow.request.headers["myheader"] = "value"

    拦截特定URL的请求并发送任意响应的示例:

    from mitmproxy import http
    
    def request(flow: http.HTTPFlow) -> None:
        if flow.request.pretty_url == "http://example.com/path":
            flow.response = http.HTTPResponse.make(
                200,  # (optional) status code
                b"Hello World",  # (optional) content
                {"Content-Type": "text/html"}  # (optional) headers
            )

    可以基于mitmproxy支持的所有事件开发自己的脚本;附 /api/events.html

    5. 项目实践

    动态获取知乎视频专栏信息,不停刷知乎就会不停打印输出。

    #!/usr/bin/env python3
    # _*_ coding: utf-8 _*_
    
    import json
    import re
    from mitmproxy import ctx
    
    class zhihu:
    
        def response(self, flow):
            # 提取请求的 url 地址
            request_url = flow.request.url
            # 通过 zhihu 字符串,过滤出 知乎APP 的请求和返回数据
            if bool(re.search(r"zhihu", request_url)):
                print("request_url >>> ", request_url)
                response_body = flow.response.text
                response_url = flow.request.url
                print("response_url >>> ", response_url)
                ctx.log.info("打印输出:" + response_body)
                data = json.loads(response_body)
                try:
                    ware_infos = data.get("data")
                    av_info = {}
                    # 以下逻辑需要提前熟悉接口响应信息结构,再做出解析
                    if ware_infos is not None:
                        for ware_info in ware_infos:
                            av_info["标题"]    = ware_info['card']['title']['plain_text']
                            av_info["视频地址"]    = ware_info['card']['action']['intent_url']
                            av_info["UP主"]    = ware_info['card']['author']['name']
                            print(av_info)
                except:
                    ctx.log.info("跳过")
    
    addons = [
        zhihu()
    ]

    执行

     mitmdump -s jingdong.py u zhihu.com

    image.png

  • 相关阅读:
    新闻网站个人中心(头像修改)流程分析
    新闻网站个人中心(个人信息修改)流程分析
    新闻网站个人中心(用户信息页面展示)流程分析
    Flask上下文
    SQLALchemy
    日志
    flask_script扩展包的作用
    四个session
    汇编学习笔记(2) -- 寄存器(内存访问),数据段和栈
    汇编学习笔记(1) -- 计算机简单结构与寄存器
  • 原文地址:https://www.cnblogs.com/iloverain/p/16515150.html
Copyright © 2020-2023  润新知