上一章我们完成了mitmproxy代理流程,这一章主要讲解如何编写脚本,实现接口代理篡改返回值实现数据转发,处理等。
1.建立脚本
- mproxy.py
import json
import os
import sys
import logging
import functools
from mitmproxy import http
from web import douyin
# 日志配置
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename=os.path.join(sys.path[0], "log", "mproxy.log"),
filemode='a')
'''
异常捕捉
'''
def log_exception(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
try:
fn(*args, **kwargs)
except Exception as e:
logging.exception("[Error in {}] msg: {}".format(__name__, str(e)))
raise
return wrapper
'''
抓包监听
'''
class mproxy:
'''
监听response
'''
@log_exception
def response(self, flow):
host = flow.request.host
if "snssdk.com" in host or "amemv.com" in host:
if ('/user/profile/self/?' in flow.request.path or '/user/?' in flow.request.path) \
and 'user_id=' not in flow.request.path and 'sec_user_id=' not in flow.request.path:
# 处理抖音服务
logging.info(flow.request.path)
douyin.save_request_data(flow)
addons = [
mproxy()
]
- web/douyin.py
import json
import re
from urllib import parse
import pymysql
from config import mysql
is_legal_header_name = re.compile(rb'[^:\s][^:\r\n]*').fullmatch
'''
存储用户请求数据
'''
def save_request_data(flow):
url_data = parse.urlparse(flow.request.path)
query = url_data.query
# 删除不合法的header头信息
for header_key in flow.request.headers.keys():
if not is_legal_header_name(header_key.encode('ascii')):
del flow.request.headers[header_key]
headers_json = json.dumps(dict(flow.request.headers.items()))
user_data = json.loads(flow.response.text)
if user_data["status_code"] != 0:
return
if "user" in user_data:
user_data["user"]["signature"] = "(已成功接入抖音系统)"
flow.response.text = json.dumps(user_data)
user_data = user_data["user"]
short_id = user_data["unique_id"]
if short_id == "":
short_id = user_data["short_id"]
db = pymysql.connect(mysql["douyin"]["host"], mysql["douyin"]["user"], mysql["douyin"]["password"],
mysql["douyin"]["database"])
cursor = db.cursor()
sql = 'INSERT INTO user_request_data(user_id,short_id,nickname,avatar,query,headers) ' \
'values(%s,%s,%s,%s,%s,%s) ' \
'ON DUPLICATE KEY UPDATE short_id = VALUES(short_id),nickname = VALUES(nickname),' \
'avatar = VALUES(avatar),query = VALUES(query),headers = VALUES(headers),status = 0'
try:
cursor.execute(sql,
[user_data["uid"], short_id, user_data["nickname"], user_data["avatar_medium"]["url_list"][0], query,
headers_json])
db.commit()
except:
db.rollback()
db.close()
- config.py
mysql = {
"douyin":
{
"host": "127.0.0.1",
"user": "root",
"password": "123456",
"database": "douyin"
}
}
- 执行运行命令
mitmdump -s ./mproxy.py "~a"
2.完成数据接入,测试流程
- 连接手机WIFI,随后点击红圈处进行代理设置
代理选择手动输入以下信息
主机名: 这里输入运行mitmdump
服务的局域网IP|线上环境则为外网IP
端口:8080(默认端口)
然后点击右上角√保存
3. 打开抖音APP进入抖音后点击右下角的 我,账号签名处显示(已成功接入抖音系统)则已完成账号授权。
- 最后再次进入WIFI设置界面将代理设置为 无
5.最后查看数据表已经有了对应的用户态信息了。
3.对于其他接口请求的问题
熟悉抖音接口这块的朋友就会发现,这个请求体除了部分公共接口能够请求通以外,其他接口会出现请求白板或者请求错误等,这个是因为抖音校验了请求头中的x-khronos
和x-gorgon
x-khronos
请求当前时间戳。x-gorgon
通过Query请求体以及Cookie和x-khronos
进行加密,所以每一次请求这个参数都会不同。
gorgon算法是抖音接口核心参数,这里不再讲解,后续若有时间可以在讲解目前最新版抖音的gorgon算法的Hook方法,实现gorgon算法。