QQ"坦白说"简单分析

2018-04-04

本文首发于简书,作者initialize_Zero,转载请注明作者以及本文链接


近期腾讯在手Q上线了新功能--坦白说,可以匿名对好友打上标签,许多人玩的不亦乐乎,也引发了各个平台上的大讨论,趁着假期写篇文章

坦白说

既然是刚刚上线的新功能,必然有不完善的地方,大神们各显神通,只为了找到坦白说背后的发送者

经过整理大致有以下几种方法:

1.将对方所发图片收藏,然后进入我的收藏,即可看到

2.iOS版手Q可以通过搜索消息记录的方式搜索到发送方

3.API数据接口 https://ti.qq.com/cgi-node/honest-say/receive/mine ,在手Q中打开此链接,获取并解码相关json数据

截止4月3日,第1,2种方法已失效,下面我们重点分析第三种方法.

4月1日之前,对API接口请求可得到如下所示的json数据:

{
  "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请求会返回如下结果:

{
    "code":2333333,
    "msg":"皮这一下你很开心么ヽ( ̄▽ ̄)ノ"
}

皮一下可以,皮几万就不行了,这更加激发了我的好奇心,身为程序猿的我,怎能因为这样的一点小困难止步不前


下面祭出神器

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的网络请求数据包,安装自带的证书后还可以解密https内容.
下面我们介绍使用方法

1.安装

酷安APP中搜索并下载,安装完成后打开

  • 点击GetStarted
  • Continue
  • 这里一定要点击 Install Certificate , 安装配套证书,不然在稍后操作中无法看到https内容
  • 会弹出Android 系统证书添加界面,点击确定
  • 这样就进入到主界面,左上角两个绿色按钮分别是抓取单一APP网络请求与抓取全部请求

这样就完成了抓取前的准备工作

2.抓取请求

抓取前尽可能关掉除QQ与Packet Capture以外的所有软件,提高成功率,还可以避免抓到其他无关数据

下面是重点,请严格按照如图所示操作

1.确保QQ列表中有"坦白说"这一会话

2.切换到Packet Capture,点击右上角的绿色按钮,开始抓取
第一次使用会提示,点击"确定"即可

3.绿色按钮变为红色表示正在抓取中,同时出现提示信息

4.切换回QQ,点击坦白说会话进入

5.继续点击进入,如果有下图提示,一定点击继续访问,原因是我们抓取数据时用了Packet Capture自带证书替换了原证书.

6.右上角点击进入"收到的坦白说"

7.进入此列表,等待一会,一定保证列表加载完全

8.切换到Packet Capture,点击右上角的红色停止按钮,结束本次抓包,这样我们就有了一次记录,点击进入

9.重点寻找QQ发出/接收的数据包,包含坦白说列表数据的数据包大小在10KB以上,且为SSL类型
(抓到的数据包大约在30~50个左右,耐心寻找)

10.点击进入此记录,如果找到了具有如下类型请求的数据包,恭喜你,离成功又近了一步!
(GET /honest-say/main.html , Host: ti.qq.com)

11.这个数据包很大,使劲往下翻,如果类似于发现下图中的数据,就是我们所需分析的重点内容
(可以长按文本进行选择,复制等操作)


接下来重点分析这些数据

{
  "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
      }
    ]
  }
}
参数名 含义 备注
fromNick 对方所显示的匿名昵称 e.g."一个认识3年的男生"
"一个南京的女生"
fromEncodeUin 编码后的对方QQ 重点,从这里入手
fromFaceUrl 对方头像图片文件
fromGender 对方性别 0为男,1为女
toUin 你的QQ号
toNick 你的昵称 似乎都是空
topicId 话题ID 话题索引
topicName 话题名称 e.g. "我身边的最强大脑"
"将来能干一番大事"
"拥有迷人的长发"
也是对方给你发送的第一条消息
timestamp 时间戳 1970年1月1日(UTC/GMT的午夜)开始所经过的秒数

各参数说明如下:

参数名 含义 备注
fromNick 对方所显示的匿名昵称 e.g."一个认识3年的男生"
"一个南京的女生"
fromEncodeUin 编码后的对方QQ 重点,从这里入手
fromFaceUrl 对方头像图片文件
fromGender 对方性别 0为男,1为女
toUin 你的QQ号
toNick 你的昵称 似乎都是空
topicId 话题ID 话题索引
topicName 话题名称 e.g. "我身边的最强大脑"
"将来能干一番大事"
"拥有迷人的长发"
也是对方给你发送的第一条消息
timestamp 时间戳 1970年1月1日(UTC/GMT的午夜)开始所经过的秒数

接下来就是如何解码fromEncodeUin的问题,我们以*S1*oKoezon5为例,写出具体解码过程:

1.去除*S1*这四个字符

结果变为 oKoezon5

2.对照表格解码

下图是之前某大神总结出的部分规律(有点像AES加密中的S盒,不过对应关系简单了许多)

经过测试,发现部分对应关系存在问题(比如3同时对应了oi,o与i,很明显这里有问题,个人猜测原因是分析样本数据不足),重新测试十几条数据后,增添以下六组对应关系


为了解码方便,列出如下规则:

  • 规则1: 优先使用2字符对应1数字的关系,其次使用1字符对应1数字的关系
    e.g. oion6 解码为 301,而不是33301
    即'oi'对应3,'on'对应0,'6'对应1的方式
    不应按照'o'对应3,'i'对应3,'o'对应3,'n'对应0,'6'对应1的方式

  • 规则2: 遇到某一位无法解码,跳过该位从下一位进行解码

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

这样就成功得到了对方QQ号,剩下怎么做就不需要我说了吧(滑稽)


对于懒于动手的同学,我提供了C++代码(附在最后),可复制到 VisualStudio / Dev Cpp / Code::blocks等IDE中运行
或者在以下网站在线编译运行
运行前将main()函数中的str数组内容修改为fromEncodeUin即可
http://www.dooccn.com/cpp/


严正声明:
本文中所提到的技术/方法仅能用于个人学习与交流,请勿用于商业以及其他目的;请勿进行非法操作,请勿损害他人/社会/国家利益,请遵守相关法律法规,否则由此带来的一切后果均由操作者本人承担,与本文作者无关.


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 << "解码结果:\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;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者...
    保川阅读 5,940评论 1 13
  • 3.1. 介绍 现在,您已经安装了Wireshark并有可能热衷于开始捕捉您的第一个数据包。在接下来的章节中,我们...
    wwyyzz阅读 1,373评论 0 1
  • 教程一:视频截图(Tutorial 01: Making Screencaps) 首先我们需要了解视频文件的一些基...
    90后的思维阅读 4,648评论 0 3
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,389评论 25 707
  • 过年了,在家休息也好好调理身体。那就选择艾灸吧
    惬意永不放弃阅读 265评论 0 0