参考文档:https://www.wenjiangs.com/doc/2fgfiorb
一,什么是Mitmproxy?
是一款免费、开放的基于Python 开发的交互式HTTPS代理工具。
二,Mitmproxy的工作原理与特性
工作原理如下图:
image
特性:
1、支持Web
2、支持终端
3、支持Python脚本
4、可以记录和重放
三,Mitmproxy与Fiddler、Charles异同
1、相同点
- 都是用来捕获 HTTP,HTTPS 请求的(其他协议比如 TCP,UDP,IP,ICMP 等就用Wireshark)抓包、断点调试、请求替换、构造请求、模拟弱网等
2、不同点 - Fiddler只能运行在Windows系统;Mitmproxy、Charles是跨平台的,可运行在Windows、Mac或Linux系统等。
- Fiddler、Mitmproxy开源免费、Charles是收费的(可破解)。
- Mitmproxy支持命令行交互模式、GUI界面,Fiddler、Charles仅支持GUI界面(Fiddler底部有个命令行工具叫做 QuickExec)
四,安装Mitmproxy
pip install mitmproxy
五,使用
1,启动代理服务
mitmproxy 提供了三个命令,启动模式不同:
- mitmproxy -> 提供一个命令行界面(该命令不支持windows)
mitmproxy 快捷键操作如下:
按键 | 说明 |
---|---|
q | 退出(相当于返回键,可一级一级返回) |
d | 删除当前(黄色箭头)指向的链接 |
D | 恢复刚才删除的请求 |
G | 跳到最新一个请求 |
g | 跳到第一个请求 |
C | 清空控制台(C是大写) |
i | 可输入需要拦截的文件或者域名(逗号需要用\来做转译,栗子:feezu.cn) |
a | 放行请求 |
A | 放行所有请求 |
? | 查看界面帮助信息 |
^ v | 上下箭头移动光标 |
enter | 查看光标所在列的内容 |
tab | 分别查看 Request 和 Response 的详细信息 |
/ | 搜索body里的内容 |
esc | 退出编辑 |
e | 进入编辑模式 |
-
mitmdump -> 提供一个简单的终端输出
image.png mitmweb -> 提供一个浏览器界面,访问时端口为(8081),如果8081端口被占用就运行不了
#杀死windows进程
netstat -ano|findstr 8081
#找出进程程序
tasklist |findstr 1620
#杀死进程
taskkill /pid 1260 /F
image.png
ps:这三种方式启动都默认用8080端口,-p可指定其他端口
2,安装证书
1,设置代理(需要对哪个设备抓包就对哪个设备设置代理,要先设置代理才能抓包)
-
电脑端设置代理(wifi手动设置或对浏览器设置代理)
image.png
image.png -
手机端设置代理(wifi手动设置代理)
image.png
window:
image.png
2,下载并安装证书(不安装证书无法抓取https)
在(电脑/手机)浏览器中,手动设置代理后(不先设置代理无法下载证书),浏览器输入mitm.it,选择对应的系统证书,下载完成后,去设置-描述文件中安装,添加信任
image.png
六,-s参数可指定python脚本启动
-
启动
image.png - 脚本内容:
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)
if __name__ == '__main__':
addons = [
Counter()
]
- 在浏览器输入http://www.baidu.com
image.png
七,核心组件
1,Addons(插件)
文档:https://docs.mitmproxy.org/stable/addons-overview/
2,Events(事件)
文档:https://docs.mitmproxy.org/stable/api/events.html
常用事件:
"""HTTP-specific events."""
import mitmproxy.http
class Events:
def http_connect(self, flow: mitmproxy.http.HTTPFlow):
"""
收到了来自客户端的 HTTP CONNECT 请求。在 flow 上设置非 2xx 响应将返回该响应并断开连接。CONNECT 不
是常用的 HTTP 请求方法,目的是与服务器建立代理连接,仅是 client 与 proxy 的之间的交流,所以 CONNECT
请求不会触发request、response 等其他常规的 HTTP 事件
"""
def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
"""
来自客户端的 HTTP 请求的头部被成功读取。此时 flow 中的 request 的 body 是空的.
"""
def request(self, flow: mitmproxy.http.HTTPFlow):
"""
来自客户端的 HTTP 请求被成功完整读取
"""
def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
"""
来自服务端的 HTTP 响应的头部被成功读取。此时 flow 中的 response 的 body 是空的.
"""
def response(self, flow: mitmproxy.http.HTTPFlow):
"""
来自服务端端的 HTTP 响应被成功完整读取
"""
def error(self, flow: mitmproxy.http.HTTPFlow):
"""
发生了一个 HTTP 错误。比如无效的服务端响应、连接断开等。注意与“有效的 HTTP 错误返回”不是一回事,后者\
是一个正确的服务端响应,只是 HTTP code 表示错误而已
"""
八,示例
示例一:实现map local,更改雪球app行情看板从本地json文件取值
需要篡改客户端请求,所以实现一个 request 事件
def request(self, flow: mitmproxy.http.HTTPFlow):
"""
来自客户端的 HTTP 请求被成功完整读取
"""
pathurl = '/stock.xueqiu.com/v5/stock/batch/quote.json'
if pathurl in flow.request.pretty_url:
with open("./quote.json", 'r', encoding="utf-8") as f:
content = f.read()
flow.response = mitmproxy.http.Response.make(
200, # (optional) status code
content, # (optional) content
{"Content-Type": "application/json"} # (optional) headers
)
示例二:实现Rewrite,更改雪球app行情看板的第二个股票名称价格和涨幅
需要篡改服务端返回,所以实现一个 response事件
def response(self, flow: mitmproxy.http.HTTPFlow):
"""
来自服务端端的 HTTP 响应被成功完整读取
"""
pathurl = '/stock.xueqiu.com/v5/stock/batch/quote.json'
if pathurl in flow.request.pretty_url:
data = json.loads(flow.response.get_content())
data['data']['items'][1]['quote']['name'] = data['data']['items'][1]['quote']['name'] + "test"
data['data']['items'][1]['quote']['current'] = '50'
data['data']['items'][1]['quote']['percent'] = '0.00'
flow.response.text = json.dumps(data, ensure_ascii=True)
ctx.log.info(flow.response.get_content())
结果:
image.png