2022-03-23 13:04:38 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# dump content to files based on a filter
|
|
|
|
# usage: mitmdump -s httpdump.py "~ts application/json"
|
|
|
|
#
|
|
|
|
# options:
|
|
|
|
# - dumper_folder: content dump destination folder (default: ./httpdump)
|
|
|
|
# - open_browser: open integrated browser with proxy configured at start (default: true)
|
|
|
|
#
|
2024-03-11 07:19:36 +00:00
|
|
|
# remember to add your own mitmproxy authoritative certs in your browser/os!
|
2022-03-23 13:04:38 +00:00
|
|
|
# certs docs: https://docs.mitmproxy.org/stable/concepts-certificates/
|
|
|
|
# filter expressions docs: https://docs.mitmproxy.org/stable/concepts-filters/
|
2022-09-17 13:41:54 +00:00
|
|
|
import logging
|
2022-03-23 13:04:38 +00:00
|
|
|
import mimetypes
|
2022-09-17 13:41:54 +00:00
|
|
|
import os
|
2022-03-23 13:04:38 +00:00
|
|
|
from pathlib import Path
|
|
|
|
|
2022-11-29 13:28:41 +00:00
|
|
|
from mitmproxy import ctx
|
2022-09-17 13:41:54 +00:00
|
|
|
from mitmproxy import flowfilter
|
2022-11-29 13:28:41 +00:00
|
|
|
from mitmproxy import http
|
2022-03-23 13:04:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
class HTTPDump:
|
|
|
|
def load(self, loader):
|
|
|
|
self.filter = ctx.options.dumper_filter
|
|
|
|
|
|
|
|
loader.add_option(
|
2022-09-17 13:41:54 +00:00
|
|
|
name="dumper_folder",
|
|
|
|
typespec=str,
|
|
|
|
default="httpdump",
|
|
|
|
help="content dump destination folder",
|
2022-03-23 13:04:38 +00:00
|
|
|
)
|
|
|
|
loader.add_option(
|
2022-09-17 13:41:54 +00:00
|
|
|
name="open_browser",
|
|
|
|
typespec=bool,
|
|
|
|
default=True,
|
2022-11-29 13:28:41 +00:00
|
|
|
help="open integrated browser at start",
|
2022-03-23 13:04:38 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
def running(self):
|
|
|
|
if ctx.options.open_browser:
|
|
|
|
ctx.master.commands.call("browser.start")
|
|
|
|
|
|
|
|
def configure(self, updated):
|
|
|
|
if "dumper_filter" in updated:
|
|
|
|
self.filter = ctx.options.dumper_filter
|
|
|
|
|
|
|
|
def response(self, flow: http.HTTPFlow) -> None:
|
|
|
|
if flowfilter.match(self.filter, flow):
|
|
|
|
self.dump(flow)
|
|
|
|
|
|
|
|
def dump(self, flow: http.HTTPFlow):
|
|
|
|
if not flow.response:
|
|
|
|
return
|
|
|
|
|
|
|
|
# create dir
|
|
|
|
folder = Path(ctx.options.dumper_folder) / flow.request.host
|
|
|
|
if not folder.exists():
|
|
|
|
os.makedirs(folder)
|
|
|
|
|
|
|
|
# calculate path
|
|
|
|
path = "-".join(flow.request.path_components)
|
|
|
|
filename = "-".join([path, flow.id])
|
|
|
|
content_type = flow.response.headers.get("content-type", "").split(";")[0]
|
|
|
|
ext = mimetypes.guess_extension(content_type) or ""
|
|
|
|
filepath = folder / f"{filename}{ext}"
|
|
|
|
|
|
|
|
# dump to file
|
|
|
|
if flow.response.content:
|
|
|
|
with open(filepath, "wb") as f:
|
|
|
|
f.write(flow.response.content)
|
2022-09-17 13:41:54 +00:00
|
|
|
logging.info(f"Saved! {filepath}")
|
2022-03-23 13:04:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
addons = [HTTPDump()]
|