如何利用mitmproxy來批量修改Android中HTTP流量

jopen 9年前發布 | 17K 次閱讀 mitmproxy Android開發 移動開發

背景

有時候我們常常在調試Android程序時,常常需要對API返回的response進行修改,以達到測試特殊情況的目的。比如有時候我們需要某個字符串顯示超過某個限制來看看此時Android上面顯示是否正常,有時候我們需要特定高度的圖片來顯示頁面是否異常。

對于這些場景,其實通過調試工具mitmproxy就能完成。利用mitmproxy可以讓我們的APP開發調試事半功倍。對于從來沒有聽說過mitmproxy的朋友,推薦查看我之前的兩篇博客:如何調試 Android 上 HTTP(S) 流量 和 mitmproxy基礎實踐教程

之前所講的關于mitmproxy的使用教程都是比較基礎的。比如我們可以攔截某些特定的request,然后修改這個request的某些屬性,有必要還可以修改response的某些屬性,這樣就可以解決本文開頭所講的場景里面的問題。但是,這樣做的效率很低,我在手機上發起某個API請求,然后被電腦上的mitmproxy截獲了,然后我更改這個請求返回的response,然后這個response就會到了手機上了。

Mitmproxy的Inline Scripts 特性介紹

這樣聽起來好像有點麻煩。可以不可以自動的修改這些resquest和respones。當然可以!這就是我們今天要說的主題,mitmproxy還一個非常極客的特性,叫做 Inline Scripts。有了它,我們就不要在手機和電腦上來來回回地調試了。mitmproxy的Inline Scripts可以讓我們對通過mitmproxy的所有HTTP(S)流量進行可編程的定制,這里的script指的是python腳本。Inline Scripts是一種靠HTTP中的事件進行驅動的API,這有點類似于Android的Activity的生命周期。Inline Scripts提供了HTTP請求中各個時間點的hook函數,比如HTTP請求啟動的時候,request到達mitmproxy的時候,response到達mitmproxy的時候等等。下面我就簡單介紹一下Inline Scripts中的一些Event:

Inline Scripts 中常用的Event介紹

  1. start(context, argv)
    HTTP請求開始啟動的時候,這個event在所有event之前。
  2. clientconnect(context, root_layer)
    客戶端向代理(mitmproxy)建立一個connection的時候,一個connection可以對應多個request。
  3. request(context, flow)
    客戶端的HTTP請求被代理(mitmproxy)接收到的時候。flow里面包含了request對象,比如request的方法,request的url,參數等等。
  4. serverconnect(context, server_conn)
    代理(mitmproxy)向服務器端建立一個connection的時候,同理一個connection可以對應多個request。
  5. responseheaders(context, flow)
    當服務器的response header被代理(mitmproxy)接收的時候,這個event在接下來的response event之前。
  6. response(context, flow)
    當服務器的response被代理(mitmproxy)接收的時候,這個event在responseheaders事件之后。
  7. error(context, flow)
    當flow出現異常的時候會產生該事件。比如connection被中斷等。
  8. serverdisconnect(context, server_conn)
    當代理(mitmproxy)斷開到服務器的連接時
  9. clientdisconnect(context, root_layer)
    當客戶端斷開到代理(mitmproxy)的連接時
  10. done(context, argv)
    Inline Scripts被關閉的時候。
  11. </ol>

    Inline Scripts 使用示例

     

    下面的示例為了說明 mitmproxy 中的 Inline Scripts是如何使用的。具體思路:

    1. 首先我們將已有的相關API 流量通過mitmproxy截獲
    2. 將這些API中response中特性屬性的value全部改為我們想要的value
    3. </ol>

      假設我們要測試的某個請求返回的數據格式如下:

      {"data":[{"key":"value1"},{"key":"value2"},{"key":"value3"}]}

      因此接下來我們就可以寫相應的python腳本(change.py)了:
      from libmproxy.protocol.http import decoded  #來自mitmproxy中的庫
      from libmproxy.protocol.http import HTTPResponse
      import json

      mitmproxy中代理所有HTTP請求的response全部會經過這里

      def response(context, flow):

      #如果request的url里面包含了某個關鍵字(需要按照你的需要設置)
      if 'KEYWORD' in flow.request.pretty_url(hostheader=True):
          #解碼請求的response
          with decoded(flow.response):
             #使用json封裝response
             body = json.loads(flow.response.content)  
             if body['data']:  
                 list = body['data']
                 for item in list:
                     if item['key']:
                         #將符合條件的屬性進行更改
                         item['key']='value_special'  
             #將更改后的數據重新封裝為response 
             flow.response.content = json.dumps(body)</pre><br />
      

      然后咱們再結合之前兩篇教程,我們只需執行以下命令就可以完成我們的需求:

      ./mitmproxy -b YOUR_LOCAL_IP_ADDRESS -p PORT -s change.py

      1
      </div> </td>

      ./mitmproxy -b YOUR_LOCAL_IP_ADDRESS -p PORT -s change.py
      </div> </td> </tr> </tbody> </table> </div> </div>

      當這個命令行運行的時候,每次手機請求這個api,請求經過mitmproxy的時候,mitmproxy會把請求轉發給服務器端,接著服務器端講 response返回給mitmproxy。mitmproxy拿到數據之后,將response中的數據按照前面的python腳本進行了更改,最后這個被修改過的response回到手機上了。

      這一切都是自動的,你只需拿著手機發起請求就行了。

      來自:https://greenrobot.me/devpost/how-to-use-mitmproxy-custom-android-api-call/

       本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
       轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
       本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
    4. sesese色