mitm命令和脚本

1、介绍

在命令窗口中,输入命令可以获得帮助。

常用的一些命令整理:

-h, --help 查看帮助信息
--version 查看版本新
-q, --quiet 退出
-v, --verbose 增加日志详情
--scripts script, -s script 这里的script是.py文件

mitmweb:
  --no-web-open-browser
  --web-open-browser    Start a browser.
  --web-port PORT       Web UI port.
  --web-host HOST       Web UI host.

  Proxy Options:
  --listen-host HOST  
  --listen-port PORT, -p PORT
                       

2、脚本

(1)命令

mitmweb -s a.py
  • 命令脚本的方式如上,基于-s指令,参数为py文件
  • 不一定是mitmweb,另外两个mitmproxy和mitmdump大致也可以
  • 并不建议在脚本中写子线程,虽然可以实现,但是无法通过ctrl+c关闭命令窗口,相对有些麻烦

使用时,有两类场景:直接系统命令窗口执行命令,python程序以调用系统命令的形式执行该命令。

由于python的路径机制,如果代码使用到相对路径,都是以启动的py文件作为参照。

所以,习惯将作为脚本的py文件和作为python程序启动的py文件,设置在同一目录下

这样,可以两种方式使用脚本。

(2)脚本编写

from mitmproxy import http
class Counter:
    def __init__(self):
        print('代理开始')
    def response(self, flow):
        # 请求处理
        flow.request: http.Request
        url = flow.request.url
        print(url)
addons = [
    Counter()
]
  • 注意尽量参照这里的范例进行引入和声明,以帮助pycharm中代码提示
  • 经测试,脚本中是支持引入开发者自定义的模块的
  • 以上范例讲解:
    • addons的名称是固定的,会被mitm使用。而Counter类名称并不固定,可以随意命名。
    • 一般,脚本执行过程中,Counter类会初始化一次,然后该对象被反复使用。(pycharm中测试时,发现如果中间过程脚本被编辑,那么可能会重新被动的重新初始化Counter类)。相应的,可以在初始化中声明count变量,记录次数。
    • 浏览器每次发生相应的动作,会调用Counter类中对应的方法,比如接收响应,对应response方法,这些方法名称是固定的。
    • 类中方法,开发者可以自定义内部代码,操作方法接收的数据。
  • addons的列表中,可以声明多个类的对象,不同类实现不同功能,比如请求过滤,相应过滤,计数等。按照方向进行传递。

3、示例

这是一个脚本代码,用于记录请求和响应数据,写入文件。(一些自定义的类和函数并未展出)

import json
import os
import time

from mitmproxy import http

from api import requestclass, responseclass, propertiesclass, httplog
from api.httplog import read_own


class Counter:
    def __init__(self):
        print('代理开始')

        # 请求id,最小为1
        self.id = 1
        # 在mitm目录下创建log目录存放产生的http日志和异常日志
        if not os.path.exists(os.path.abspath('').replace('\\', '/') + '/mitm/log'):
            os.mkdir(os.path.abspath('').replace('\\', '/') + '/mitm/log')
        # 读取配置文件log_set.json
        if not os.path.exists('mitm/log_set.json'):
            self.log_set = {'message_log': '', 'err_log': '', 'append_flag': False}
            # 创建文件并写入初始数据
            with open('mitm/log_set.json', mode='w', encoding='utf-8') as f:
                f.write(json.dumps(self.log_set))
        else:
            with open('mitm/log_set.json', mode='r', encoding='utf-8') as f:
                self.log_set = json.loads(f.read())
        # 如果配置文件append_flag为True,则mitm代理的日志写入之前的日志文件,否则新建日志文件
        if self.log_set.get('append_flag'):
            # 需要解析message_log日志文件,获取最大id+1
            req_list = read_own(self.log_set.get('message_log'))
            if len(req_list) > 0:
                self.id = req_list[-1].id + 1
        else:
            # 每次启动,都是http日志文件路径和异常日志文件路径
            t = time.strftime('%Y%m%d-%H%M%S')
            # 写入中间文件,方便日志窗口获取日志路径
            self.log_set.update({'message_log': os.path.abspath('').replace('\\', '/') + '/mitm/log/' + t + '.log',
                                 'err_log': os.path.abspath('').replace('\\', '/') + '/mitm/log/' + t + '_err.log'})
            with open(self.log_set.get('message_log'), mode='w', encoding='utf-8') as f:
                pass
            with open(self.log_set.get('err_log'), mode='w', encoding='utf-8') as f:
                pass
            with open('mitm/log_set.json', mode='w', encoding='utf-8') as f:
                f.write(json.dumps(self.log_set))

    def response(self, flow):
        # 请求处理
        flow.request: http.Request
        url = flow.request.url
        print(url)
        req = requestclass.Request(url=url)
        req.id = self.id
        req.send_time = time.strftime('%Y%m%d-%H:%M:%S')
        req.method = flow.request.method
        req.protocol_version = flow.request.http_version
        for name, value in flow.request.headers.items():
            # 注意这里应该是add直接添加,而不是自定义的update
            req.headers.add(str(name).replace('\r', ''), str(value).replace('\r', ''))
        try:
            req.body = flow.request.content.decode('utf-8')
        except Exception as e:
            req.body = flow.request.content.decode('iso-8859-1')
        # 响应处理
        flow.response: http.Response
        req.res = responseclass.Response()
        req.res.protocol_version = flow.response.http_version
        req.res.status_code = str(flow.response.status_code)
        req.res.reason = flow.response.reason
        req.res.headers = propertiesclass.Headers()
        for name, value in flow.response.headers.items():
            req.res.headers.add(str(name).replace('\r', ''), str(value).replace('\r', ''))
        try:
            print(flow.response.content, type(flow.response.content))
            req.res.body = flow.response.content.decode('utf-8')
        except Exception as e:
            req.res.body = flow.response.content.decode('iso-8859-1')

        httplog.write_own([req], self.log_set.get('message_log'), append_flag=True)
        self.id = self.id + 1


addons = [
    Counter()
]

 

posted @ 2023-04-18 18:31  挖洞404  阅读(286)  评论(0编辑  收藏  举报