0x01 关于MitmProxy
An interactive HTTP agent that intercepts HTTPs for interceptors and software developers
官网: https://mitmproxy.org
文档:http://docs.mitmproxy.org/en/v0.18.2/introduction.html
版本支持:python2.7 支持到 0.18.2 直接pip install "mitmproxy==0.18.2"
即可安装成功
建议使用virtualenv或者docker来学习mitmproxy,
docker推荐镜象:
- docker pull mitmproxy/mitmproxy
- docker pull mitmproxy/mitmproxy:0.18.2
0x02 简单使用
先启动** mitmproxy**
-mitmproxy
-docker run --rm -it -p 8080:8080 mitmproxy/mitmproxy:0.18.2 mitmproxy
配置浏览器或手机WIFI,设置代理为127.0.0.1(或服务器IP),端口为8080
访问http://mitm.it 来安装证书
做完这三步,现在浏览器的所有请求都经过mitmproxy了.mitmproxy提供的shell界面操作,输入?
显示帮助,如需返回到请求列表界面则按 q。
在请求列表界面,黄色的箭头 >>
指示当前选择的请求,可以使用 vi 的快捷键k
,j
来移动箭头,PgUp
、PgDown
为上下翻页,此外空格键也可用来向下翻页。
- 过滤显示的链接
输入
f
,进入编辑模式,可在最下面编辑条件,ESC
或Enter
退出编辑
下面举几个例子
!(~c 200)
#显示所有返回不是200的请求!(~c 200) & ~d safecode
#显示域名包含safecode,返回不是200的请求~m post & ~u safe
#显示请求的链接里面包含safe的post请求
能过过滤,能够使得窗口只显示,我们需要的请求
- 下断点
输入
i
,进入编辑模式,可在最下面编辑条件,ESC
或Enter
退出编辑
断点的条件和过滤是一样的,符合条件的链接会被拦截
比如这个 :~d safecode & ~m post & ~u \.php
域名包含safecode,链接包含.php的post请求会被拦截
通过j
,l
或上下键选取当前拦截的请求,按Enter
进入详情页,在详情页输入e
进入模式,可以修改各项数据,如下所示:
输入对应字符,进入编辑,编辑界面为vim编辑器,完成后,回到请求显示列表,输入a
,将请求放行.
请求重放
选中需要重放的请求,输入r
可以重放请求,也可以先编辑后再重放输入
Q
可退出程序
0x03 MitmProxy脚本开发
[文档]http://docs.mitmproxy.org/en/v0.18.2/index.html
[事件]http://docs.mitmproxy.org/en/v0.18.2/scripting/events.html
[API]http://docs.mitmproxy.org/en/v0.18.2/scripting/api.html
编写脚本的话,主要用到的有两个东西
- Event
- API
1. Event 事件
事件里面有3个事件是比较重要的
- start 启动的时候被调用,会替换当前的插件, 可以用此事件注册过滤器.
- request(flow) 当发送请求时,被调用.
- response(flow) 当接收到回复时被调用.
2. API
三个比较重要的数据结构
- mitmproxy.models.http.HTTPRequest
- mitmproxy.models.http.HTTPResponse
- mitmproxy.models.http.HTTPFlow
在编写脚本的时候如果,不知道该怎么写,传过来的参数里面有什么,查看 这些就对了.
3. 脚本实例
先上代码:
头脑王者即时显示答案脚本
#!/usr/bin/env python
#coding=utf-8
import sys
import json
from mitmproxy import flowfilter
from pymongo import MongoClient
reload(sys)
sys.setdefaultencoding('utf-8')
'''
头脑王者即时显示答案脚本
'''
class TNWZ:
'''
从抓包可以看到 问题包的链接最后是 findQuiz
'''
def __init__(self):
#添加一个过滤器,只处理问题包
self.filter = flowfilter.parse('~u findQuiz')
#连接答案数据库
self.conn = MongoClient('localhost', 27017)
self.db = self.conn.tnwz
self.answer_set = self.db.quizzes
def request(self, flow):
'''
演示request事件效果, 请求的时候输出提示
:param flow:
:return:
'''
if flowfilter.match(self.filter,flow):
print(u'准备请求答案')
def responseheaders(self, flow):
'''
演示responseheaders事件效果, 添加头信息
:param flow:
:return:
'''
if flowfilter.match(self.filter, flow):
flow.response.headers['Cache-Control'] = 'no-cache'
flow.response.headers['Pragma'] = 'no-cache'
def response(self, flow):
'''
HTTPEvent 下面所有事件参数都是 flow 类型 HTTPFlow
可以在API下面查到 HTTPFlow, 下面有一个属性response 类型 TTPResponse
HTTPResponse 有个属性为 content 就是response在内容,更多属性可以查看 文档
:param flow:
:return:
'''
if flowfilter.match(self.filter, flow):
#匹配上后证明抓到的是问题了, 查答案
data = flow.response.content
quiz = json.loads(data)
#获取问题
question = quiz['quiz']
print(question)
#获取答案
answer = self.answer_set.find_one({"quiz":question})
if answer is None:
print('no answer')
else:
answerIndex = int(answer['answer'])-1
options = answer['options']
print(options[answerIndex])
#这里简单演示下start事件
def start():
return TNWZ()
使用方法:
mitmdump -s quiz.py
启动后也可以编辑脚本文件,mitmdump会自动重新加载不需要重新运行命令,本来是写了一个头脑王者自动抓问题找答案,结果游戏被封了,只在本地模拟下
是不是很简单, 如果还不够,可以考虑,在发送答案的时候, 拦截请求,然后替换为标准答案再发送到服务器,是不是很给力。工具都是死的,就看怎么用了。
0x04 结束语
希望能够给学习mitmproxy开发入门童鞋带来一点帮助,最后附上代码地址
[GitHub]https://github.com/ctwj/mitm_exam