MitmProxy使用:http/https劫持腳本開發


 

如何編寫一個插件

插件的作用主要是用於攔截請求,根據自身業務需求,在不同的事件函數中,添加業務邏輯處理代碼。插件的編寫格式相對比較簡單,如果不熟悉如何編寫,可參考官方樣例:https://github.com/mitmproxy/mitmproxy/blob/master/examples/addons進行模仿,這里摘取其中一個增加響應頭部信息的樣例,anatomy.py如下:

from mitmproxy import ctx

class
AddHeader: def __init__(self): self.num = 0 //這里選擇所需要處理的事件函數,e.g. 如對 response 進行處理 def response(self, flow): self.num = self.num + 1 flow.response.headers["count"] = str(self.num)
     ctx.log.info("We've seen %d flows"%self.num)
//這個是固定格式 addons = [ AddHeader() ]
在命令行輸入:mitmproxy -s anatomy.py。

事件

mitmproxy 插件編寫主要是基於事件可以在不同層面上分為 5 類:HTTP、TCP、WebSocket、Network、General。
 
其中最常用的就是 HTTP事件,包括:
def http_connect(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 收到了來自客戶端的 HTTP CONNECT 請求。在 flow 上設置非 2xx 響應將返回該響應並斷開連接。CONNECT 不是常用的 HTTP 請求方法,目的是與服務器建立代理連接,僅是 client 與 proxy 的之間的交流,所以 CONNECT 請求不會觸發 request、response 等其他常規的 HTTP 事件
    """

def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 來自客戶端的 HTTP 請求的頭部被成功讀取。此時 flow 中的 request 的 body 是空的。
    """

def request(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 來自客戶端的 HTTP 請求被成功完整讀取。
    """

def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 來自服務端的 HTTP 響應的頭部被成功讀取。此時 flow 中的 response 的 body 是空的。
    """

def response(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 來自服務端端的 HTTP 響應被成功完整讀取。
    """

def error(self, flow: mitmproxy.http.HTTPFlow):
    """
        (Called when) 發生了一個 HTTP 錯誤。比如無效的服務端響應、連接斷開等。注意與“有效的 HTTP 錯誤返回”不是一回事,后者是一個正確的服務端響應,只是 HTTP code 表示錯誤而已。
    """

核心 API 

mitmproxy.http.HTTPRequest

  • cookies

    返回一個MultiDictView對象

  • get_content(strict: bool = True) → bytes
    使用內容編碼標頭(例如gzip)解碼的HTTP消息正文
  • get_text(strict: bool = True) → typing.Union[str, NoneType]
    使用內容編碼標頭(例如gzip)和內容類型標頭字符集解碼的HTTP消息正文。
  • headers
    返回mitmproxy.net.http.Headers對象
  • multipart_form
    多部分表單數據作為MultiDictView對象。
    鍵和值都是bytes。
  • pretty_url:攔截的url路徑
  • urlencoded_form
    URL編碼的表單數據作為MultiDictView對象。
  • replace(pattern, repl, flags=0, count=0)
    將header,請求路徑和請求體中的repl替換為正則表達式模式。編碼后的內容將在替換前進行解碼,然后再進行編碼。

mitmproxy.http.HTTPResponse

  • make(status_code: int = 200, content: AnyStr = b'', headers: typing.Union[typing.Dict[AnyStr, AnyStr], typing.Iterable[typing.Tuple[bytes, bytes]]] = ())
    用於創建response對象的簡化API。
  • status_code
    狀態碼
  • 大部分和mitmproxy.http.HTTPRequest差不多

mitmproxy.http.HTTPFlow

HTTPFlow是代表單個HTTP事務的對象的集合

  • request
  • response

mitmproxy.log.Log

中央記錄器,在腳本中暴露為mitmproxy.ctx.log

  • debug
  • info
  • warn
  • error

 

HTTP腳本

攔截篡改 http 請求的工具類,包含的功能主要有:

  • 攔截請求並請求 header 信息
  • 攔截請求及修改 body 信息
  • 攔截請求方法及修改類型,e.g. get/post
  • 攔截請求及修改 query 參數
  • 攔截響應並修改響應狀態碼
  • 攔截響應並修改響應頭信息
  • 攔截響應並修改響應正文信息
  • 攔截響應並構造響應信息,e.g. 狀態碼、響應頭、響應體
class HTTPRecordModifier:

    def __init__(self, flow: http.HTTPFlow):
        self.flow = flow
    //設置請求頭信息
    def set_request_header(self, headers):
        for header_key, header_value in headers.items():
            self.flow.request.headers[header_key] = header_value

    //設置請求 body 參數
    def set_request_body(self, body):
        self.flow.request.content = bytes(body, "utf-8")

    //設置請求方法
    def set_request_method(self, method):
        self.flow.request.method = method

    //設置請求 query 參數
    def set_request_query(self, key, value):
        self.flow.request.query[key] = value

    //設置響應狀態碼
    def set_response_status_code(self, code):
        self.flow.response.status_code = code

    //設置響應頭信息
    def set_response_header(self, headers):
        for header_key, header_value in headers.items():
            self.flow.response.headers[header_key] = header_value

     //設置響應體內容
    def set_response_body(self, body):
        self.flow.response.content = bytes(body, "utf-8")

    //構造響應報文
    def create_mocked_response(self, code=200, header={}, body=""):
        self.flow.response = http.HTTPResponse.make(code, bytes(body, "utf-8"), header)

 

class Test:

    def response(self, flow: http.HTTPFlow):
        """
        Event for handling response before sending it back to the client
        """
        //這里編寫我們的 mock 邏輯代碼
        breakpoint_url = "https://frodo.douban.com/api/v2/user/91807076/following"
        if breakpoint_url in flow.request.pretty_url:
            response_content = json.loads(flow.response.content.decode("utf-8"))
            response_content['total'] = 20
            new_response = HTTPRecordModifier(flow)
            userinfo = {
                //這里放置上面抓包獲取的用戶信息格式
               }
            for i in range(response_content['total']):
                //添加 20 個用戶信息
                response_content['users'].append(userinfo)
            new_response.set_response_body(json.dumps(response_content))

addons = [
    Test()
]

啟動 mitmproxy 插件腳本,如下:

 mitmdump -s 插件的腳本名字

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM