QQ"坦白說"簡單分析

2018-04-04

本文首發(fā)于簡書,作者initialize_Zero,轉(zhuǎn)載請注明作者以及本文鏈接


近期騰訊在手Q上線了新功能--坦白說,可以匿名對好友打上標簽,許多人玩的不亦樂乎,也引發(fā)了各個平臺上的大討論,趁著假期寫篇文章

坦白說

既然是剛剛上線的新功能,必然有不完善的地方,大神們各顯神通,只為了找到坦白說背后的發(fā)送者

經(jīng)過整理大致有以下幾種方法:

1.將對方所發(fā)圖片收藏,然后進入我的收藏,即可看到

2.iOS版手Q可以通過搜索消息記錄的方式搜索到發(fā)送方

3.API數(shù)據(jù)接口 https://ti.qq.com/cgi-node/honest-say/receive/mine ,在手Q中打開此鏈接,獲取并解碼相關(guān)json數(shù)據(jù)

截止4月3日,第1,2種方法已失效,下面我們重點分析第三種方法.

4月1日之前,對API接口請求可得到如下所示的json數(shù)據(jù):

{
  "code":0,
  "data":{
    "list":[
      {
        "fromNick":"一個認識y年的男生",
        "fromEncodeUin":"*S1*oKoezon5",
        "fromFaceUrl":"man.png",
        "fromGender":0,
        "toUin":1088668866,
        "toNick":"",
        "topicId":666,
        "topicName":"別人對你的匿名評價",
        "timestamp":1534435200
      },
      {
        "fromNick":"一個x歲的女生",
        "fromEncodeUin":"*S1*oKoezon5",
        "fromFaceUrl":"woman.png",
        "fromGender":1,
        "toUin":1088668866,
        "toNick":"",
        "topicId":666,
        "topicName":"別人對你的匿名評價",
        "timestamp":1534435200
      }
    ]
  }
}

不過tx也很快地封殺了第三種方法,4月1日后直接對API請求會返回如下結(jié)果:

{
    "code":2333333,
    "msg":"皮這一下你很開心么ヽ( ̄▽ ̄)?"
}

皮一下可以,皮幾萬就不行了,這更加激發(fā)了我的好奇心,身為程序猿的我,怎能因為這樣的一點小困難止步不前


下面祭出神器

Packet Capture (又名無root抓包)

Packet Capture

Packet Capture
Packet capture/Network traffic sniffer app with SSL decryption.
Not that feature rich yet, but it's a powerful debugging tool especially when developing an app.

Features:

  • Capture network packets and record them.
  • SSL decryption using man-in-the-middle technique.
  • No root required.
  • Easy to use.
  • Show packet in either hex or text.

簡單來說此軟件可以抓取并記錄各種APP的網(wǎng)絡請求數(shù)據(jù)包,安裝自帶的證書后還可以解密https內(nèi)容.
下面我們介紹使用方法

1.安裝

酷安APP中搜索并下載,安裝完成后打開

  • 點擊GetStarted
  • Continue
  • 這里一定要點擊 Install Certificate , 安裝配套證書,不然在稍后操作中無法看到https內(nèi)容
  • 會彈出Android 系統(tǒng)證書添加界面,點擊確定
  • 這樣就進入到主界面,左上角兩個綠色按鈕分別是抓取單一APP網(wǎng)絡請求與抓取全部請求

這樣就完成了抓取前的準備工作

2.抓取請求

抓取前盡可能關(guān)掉除QQ與Packet Capture以外的所有軟件,提高成功率,還可以避免抓到其他無關(guān)數(shù)據(jù)

下面是重點,請嚴格按照如圖所示操作

1.確保QQ列表中有"坦白說"這一會話

2.切換到Packet Capture,點擊右上角的綠色按鈕,開始抓取
第一次使用會提示,點擊"確定"即可

3.綠色按鈕變?yōu)榧t色表示正在抓取中,同時出現(xiàn)提示信息

4.切換回QQ,點擊坦白說會話進入

5.繼續(xù)點擊進入,如果有下圖提示,一定點擊繼續(xù)訪問,原因是我們抓取數(shù)據(jù)時用了Packet Capture自帶證書替換了原證書.

6.右上角點擊進入"收到的坦白說"

7.進入此列表,等待一會,一定保證列表加載完全

8.切換到Packet Capture,點擊右上角的紅色停止按鈕,結(jié)束本次抓包,這樣我們就有了一次記錄,點擊進入

9.重點尋找QQ發(fā)出/接收的數(shù)據(jù)包,包含坦白說列表數(shù)據(jù)的數(shù)據(jù)包大小在10KB以上,且為SSL類型
(抓到的數(shù)據(jù)包大約在30~50個左右,耐心尋找)

10.點擊進入此記錄,如果找到了具有如下類型請求的數(shù)據(jù)包,恭喜你,離成功又近了一步!
(GET /honest-say/main.html , Host: ti.qq.com)

11.這個數(shù)據(jù)包很大,使勁往下翻,如果類似于發(fā)現(xiàn)下圖中的數(shù)據(jù),就是我們所需分析的重點內(nèi)容
(可以長按文本進行選擇,復制等操作)


接下來重點分析這些數(shù)據(jù)

{
  "code":0,
  "data":{
    "list":[
      {
        "fromNick":"一個認識y年的男生",
        "fromEncodeUin":"*S1*oKoezon5",
        "fromFaceUrl":"man.png",
        "fromGender":0,
        "toUin":1088668866,
        "toNick":"",
        "topicId":666,
        "topicName":"別人對你的匿名評價",
        "timestamp":1534435200
      },
      {
        "fromNick":"一個x歲的女生",
        "fromEncodeUin":"*S1*oKoezon5",
        "fromFaceUrl":"woman.png",
        "fromGender":1,
        "toUin":1088668866,
        "toNick":"",
        "topicId":666,
        "topicName":"別人對你的匿名評價",
        "timestamp":1534435200
      }
    ]
  }
}
參數(shù)名 含義 備注
fromNick 對方所顯示的匿名昵稱 e.g."一個認識3年的男生"
"一個南京的女生"
fromEncodeUin 編碼后的對方QQ 重點,從這里入手
fromFaceUrl 對方頭像圖片文件
fromGender 對方性別 0為男,1為女
toUin 你的QQ號
toNick 你的昵稱 似乎都是空
topicId 話題ID 話題索引
topicName 話題名稱 e.g. "我身邊的最強大腦"
"將來能干一番大事"
"擁有迷人的長發(fā)"
也是對方給你發(fā)送的第一條消息
timestamp 時間戳 1970年1月1日(UTC/GMT的午夜)開始所經(jīng)過的秒數(shù)

各參數(shù)說明如下:

參數(shù)名 含義 備注
fromNick 對方所顯示的匿名昵稱 e.g."一個認識3年的男生"
"一個南京的女生"
fromEncodeUin 編碼后的對方QQ 重點,從這里入手
fromFaceUrl 對方頭像圖片文件
fromGender 對方性別 0為男,1為女
toUin 你的QQ號
toNick 你的昵稱 似乎都是空
topicId 話題ID 話題索引
topicName 話題名稱 e.g. "我身邊的最強大腦"
"將來能干一番大事"
"擁有迷人的長發(fā)"
也是對方給你發(fā)送的第一條消息
timestamp 時間戳 1970年1月1日(UTC/GMT的午夜)開始所經(jīng)過的秒數(shù)

接下來就是如何解碼fromEncodeUin的問題,我們以*S1*oKoezon5為例,寫出具體解碼過程:

1.去除*S1*這四個字符

結(jié)果變?yōu)?oKoezon5

2.對照表格解碼

下圖是之前某大神總結(jié)出的部分規(guī)律(有點像AES加密中的S盒,不過對應關(guān)系簡單了許多)

經(jīng)過測試,發(fā)現(xiàn)部分對應關(guān)系存在問題(比如3同時對應了oi,o與i,很明顯這里有問題,個人猜測原因是分析樣本數(shù)據(jù)不足),重新測試十幾條數(shù)據(jù)后,增添以下六組對應關(guān)系


為了解碼方便,列出如下規(guī)則:

  • 規(guī)則1: 優(yōu)先使用2字符對應1數(shù)字的關(guān)系,其次使用1字符對應1數(shù)字的關(guān)系
    e.g. oion6 解碼為 301,而不是33301
    即'oi'對應3,'on'對應0,'6'對應1的方式
    不應按照'o'對應3,'i'對應3,'o'對應3,'n'對應0,'6'對應1的方式

  • 規(guī)則2: 遇到某一位無法解碼,跳過該位從下一位進行解碼

oKoezon5
'oK', 'oe', 'z', 'on', '5'
10001

這樣就成功得到了對方QQ號,剩下怎么做就不需要我說了吧(滑稽)


對于懶于動手的同學,我提供了C++代碼(附在最后),可復制到 VisualStudio / Dev Cpp / Code::blocks等IDE中運行
或者在以下網(wǎng)站在線編譯運行
運行前將main()函數(shù)中的str數(shù)組內(nèi)容修改為fromEncodeUin即可
http://www.dooccn.com/cpp/


嚴正聲明:
本文中所提到的技術(shù)/方法僅能用于個人學習與交流,請勿用于商業(yè)以及其他目的;請勿進行非法操作,請勿損害他人/社會/國家利益,請遵守相關(guān)法律法規(guī),否則由此帶來的一切后果均由操作者本人承擔,與本文作者無關(guān).


C++ Code

#include <memory.h>
#include <iostream>
static char* table[] = {
    "oe", "oK", "ow", "oi", "7e", "7K", "7w", "7i", "Ne", "NK",
     "n",  "6",  "-",  "o",  "v",  "4",  "C",  "S",  "c",  "E",
     "z",  "5",  "A",  "i",  "P",  "k",  "s",  "l",  "F",  "q"
};
int matchChar(char a, char b, char* mNum);
int decode(char* src, char * buf);
int main() {
    /*待解碼fromEncodeUin放在這里,注意不要包含*S1*這四個字符*/
    char str[30] = { "oKoezon5" };
    char buf[30];
    memset(buf, 0, 30);
    decode(str, buf);
    std::cout << "解碼結(jié)果:\n" << buf << std::endl;
    return 0;
}
int matchChar(char a, char b, char* mNum) {
    if (NULL == mNum)
        return -1;
    int i;
    if ('o' == a) {
        i = 0;
        while (i < 4) {
            if (table[i][1] == b) {
                *mNum = i % 10 + 48;
                return 2;
            }
            i++;
        }
        /*增加多條特殊情況,if語句太多了-_-*/
        if ('n' == b) {
            *mNum = 0 + 48;
            return 2;
        }
        if ('z' == b) {
            *mNum = 3 + 48;
            return 2;
        }
        *mNum = 3 + 48;
        return 1;
    }
    else if ('7' == a) {
        i = 4;
        while (i < 8) {
            if (table[i][1] == b) {
                *mNum = i % 10 + 48;
                return 2;
            }
            i++;
        }
        if ('v' == b) {
            *mNum = 5 + 48;
            return 2;
        }
        if ('z' == b) {
            *mNum = 7 + 48;
            return 2;
        }
        return -1;
    }
    else if ('N' == a) {
        i = 8;
        while (i < 10) {
            if (table[i][1] == b) {
                *mNum = i % 10 + 48;
                return 2;
            }
            i++;
        }
        if ('v' == b) {
            *mNum = 9 + 48;
            return 2;
        }
        if ('n' == b) {
            *mNum = 8 + 48;
            return 2;
        }
        return -1;
    }
    i = 10;
    while (i < 30) {
        if (table[i][0] == a) {
            *mNum = i % 10 + 48;
            return 1;
        }
        i++;
    }
    return -1;
}
int decode(char* src, char * buf) {
    if (NULL == src || NULL == buf) {
        return -1;
    }
    char* p = src;
    char* q = buf;
    int rc = 0;
    while ('\0' != *p && -1 != (rc = matchChar(*p, *(p + 1), q))) {
        p += rc;
        q++;
    }
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 簡介 用簡單的話來定義tcpdump,就是:dump the traffic on a network,根據(jù)使用者...
    保川閱讀 6,077評論 1 13
  • 3.1. 介紹 現(xiàn)在,您已經(jīng)安裝了Wireshark并有可能熱衷于開始捕捉您的第一個數(shù)據(jù)包。在接下來的章節(jié)中,我們...
    wwyyzz閱讀 1,489評論 0 1
  • 教程一:視頻截圖(Tutorial 01: Making Screencaps) 首先我們需要了解視頻文件的一些基...
    90后的思維閱讀 4,988評論 0 3
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,008評論 25 709
  • 過年了,在家休息也好好調(diào)理身體。那就選擇艾灸吧
    愜意永不放棄閱讀 298評論 0 0

友情鏈接更多精彩內(nèi)容