1. 程式人生 > >snapchat閱後即焚實現分析

snapchat閱後即焚實現分析

    最近主打閱後即焚的snapchat似乎又火了起來,估值已經達到100億美元了。閱後即焚這個功能看上去挺神祕的樣子,我們來分析一下它到底是怎麼實現的吧。

    通過wireshark抓包,發現全部都是SSL包,無法解密,但是至少可以確定這個app全程使用https進行通訊。另外APP還對HTTPS程式碼做了某些處理,使得fiddler的證書劫持功能也無法正常使用,那就只有再次祭上netbeans了。

    通過apkIDE搜尋"https"字串,因為一般來說會註冊一個httpsScheme。在找到的位置下斷點,就可以跟蹤到https使用的URL了。不過這裡第二個https連結並不是直接走這裡的程式碼,需要單步跟過去才會找到。

    下面直接講下它的網路和儲存過程吧。

     .登入過程獲取auth_token

     通過如下URL來進行登入,並獲取auth_token

         https://feelinsonice-hrd.appspot.com/loq/login

     它會返回一個包含auth_tokenjson

     .接收照片過程

接收照片的過程比較多一點,會分下幾個步驟

     1.https://feelinsonice-hrd.appspot.com/loq/all_updates

     得到類似如下的未讀資訊

                        "snap": {

                            "sn":"teamsnapchat",

                            "t": 7,

                            "timer":7,

                            "id":"882091414483730340r",

                           "st":1,

                            "m": 1,

                            "ts":1414483730340,

                            "sts":1414483730340

                            "zipped":true

                        }

      zipped是可選項,表示檔案被壓縮過

      獲取到有未取訊息後,在對話方塊裡顯示“點選載入”,提示使用者有新閱後即焚訊息可讀

    2.使用者點選“點選載入”後,觸發的行為

    1)構造一個類似的如下URL,下載該點選對應的檔案到記憶體

https://feelinsonice-hrd.appspot.com/ph/blob?id=795436414647955780r&username=shsjsjsjshsxxxx&timestamp=1414650012732&req_token=630010c93a89ceb579c2bd79f659d518efc9b763521c4d0537b7dab777392277

id就是上面loq/all_updates獲取的未讀id,  username也是loq/all_updates返回的json中的內容,表示來自哪個好友,timestamp是本地時間戳,req_token是本地通過auth_tokentimestamp再加上本地固定key,進行SHA-256加密後的串,可用於服務端認證及防篡改校驗

生成演算法,如下函式

   public static String a(String authToken, String timestamp) {

       String v0 = "iEk21fuwZApXlz93750dmW22pw389dPwOk" + authToken;

       String v1 = timestamp + "iEk21fuwZApXlz93750dmW22pw389dPwOk";

       MessageDigest v2 = MessageDigest.getInstance("SHA-256");

       v2.update(v0.getBytes("UTF-8"));

       String v3 = new String(RequestAuthorization.a(v2.digest()));

       v2.update(v1.getBytes("UTF-8"));

       String v2_1 = new String(RequestAuthorization.a(v2.digest()));

       v1 = "";

       int v0_1 = 0;

   label_26:

       if(v0_1 <"0001110111101110001111010101111011010001001110011000110001000110".length()){

           int v4 ="0001110111101110001111010101111011010001001110011000110001000110".charAt(v0_1);

           StringBuilder v5 = new StringBuilder().append(v1);

           char v1_1 = v4 == 0x30 ? v3.charAt(v0_1) : v2_1.charAt(v0_1);

           v1 = v5.append(v1_1).toString();

           ++v0_1;

           goto label_26;

       }

       return v1;

    }

   2)對下載後的記憶體使用固定的key進行aes解密,這個key的值為:M02cnQ51Ji97vwT4,這一步進行解密後,記憶體中的內容是以明文存在的。

   3)本地生成一個隨機key,重新對解密後的檔案進行aes加密,並儲存為檔案,同時將key儲存起來:

   照片檔案儲存名字如下所示:       /data/data/com.snapchat.android/cache/received_image_snaps/h1a81hurcs00h-XXXXXXXXXXXXXXXXXXX.jpg.nomedia

   XXX為可變數字

   視訊檔案儲存名字如下所示:

/mnt/sdcard/Android/data/com.snapchat.android/cache/received_video_snaps/sesrh_dlw21-XXXXXXXXXXXX.mp4.nomedia

    載入完成後,閱後即焚的資料就以這樣的一個加密檔案形式存在,此時“點選載入"按鈕變成了“按住檢視”,一直到使用者看完照片,這裡的URL都是可以訪問的

    3.使用者點選“按住檢視”後,使用儲存的KEY對加密檔案進行解密,並顯示出來,然後刪除本地檔案,並向服務端傳送該照片或視訊對的id,通知該id已讀,服務端會使上一步使用的URL失效,同時通知此圖片或視訊的客戶端,此訊息已讀。

   通過上面的分析可知,閱後即焚的圖片在記憶體中被AES解密後,是明文存在的,只要在這一步將該記憶體儲存為檔案,就可以將閱後即焚圖片扣出來了。因此閱後即焚功能相對而言還是比較脆弱的。