0.分析目的
制作一款命令行QQ软件。可以在命令行下登录qq,以及处理一些简单的文本消息。
1.怎么通信
A->server
server->B
2.采用何种协议
QICQ:用于更新数据库中的状态(在线,离线,隐身…),
传递对称加密的密钥(sessionkey)。
UDP:data本身是经过加密的。用上一步得到的sessionkey进行加密。
3.攻击者的角度
- 唯密文攻击
- 已知明文攻击
- 选择明文攻击
- 选择密文攻击
- 选择文本攻击
4.猜测的登录流程
M=…+QQ密码+…
client A:
tea(M);
5.别人分析的流程,不知道真伪
https://blog.csdn.net/mingzznet/article/details/46910437
6.OICQ协议分析
命令字 解释
1 log out
2 hert message
4 跟新用户信息
5 搜索用户
6 获取用户信息
9 不需认证方式添加好友
10 删除好友
11 需要认证的方式添加好友
13 设置隐身、示忙等状态
18 确认收到系统消息
22 发送消息
23 receive message
29 request key
39 get friend online
60 group name operation
62 memo operation
88 download group operation
92 get level
101 request extra information
103 signature operation
7.wireshark分析
QQ发送消息用的是运输层的UDP协议。
而登录,初始化协商对称加密密钥,服务器端不断地验证客户端是否在线同时客户端不断地索要服务器端自己的好友数据这些则用OCIQ协议完成。
8.结构体
typedef _oicqhdr {
uint8_t flag;
uint16_t ver;
uint16_t command;
uint16_t sequence;
uint32_t qq;
} __attribute__((packed)) oicqhdr;
9.实战中获取到的信息
1>qq客户端如何获取QQ服务器端IP地址
qq客户端怎么知道腾讯的IP?
通过DNS协议。
目前检测到的tencent的域名有,(域名是腾讯写死在软件里的)
sz.tencent.com
sz2.tencent.com
sz3.tencent.com
sz4.tencent.com
sz5.tencent.com
sz6.tencent.com
sz7.tencent.com
sz8.tencent.com
sz9.tencent.com
rs.qq.com
rs7.qq.com
对应的几个IP地址池:(1类IP)
123.*
111..*
125.*
通过不让QQ登录成功来得到结果
2>想象一下登录流程
登录其实就是从tx
的服务器池里面选出了一台机器进行处理你的消息。
这些服务器应该是类似于docker
形式部署的实例
。
一个IP就只服务一个用户吗?
通过网上的数据,qq月活跃用户数达到了7.07亿
,
也就是7.07 * 10^8
。
而假设以111.*.*.*
为例服务用户,那么共有2^24=16,777,216
个机器。
即使使用1类IP地址,也还是无法解决如此大的用户量。
那么复用是必然的。
可能一个用户掉线后立马回收这个资源给另一个用户使用。
服务器端接受消息,那么服务器端必然不能只给一个用户使用。那样太浪费了。
综上所述,登录QQ就是从tx
的服务器中找一台为自己服务。这台服务器可能还同时为其他人服务。然后自己下线后,这个服务器就会将自己保存在服务器上的数据进行转存等等。情空你的信息后为其他人服务。
嗯,应该是这样。
3>联想一下怎么得到QQ好友的地理位置
A和B通信。需要经过tx
的服务器转发。
但是A,B都是在内网。那么他们上网会获得一个临时的公网IP。腾讯服务器就会记录这个IP。干什么呢?
假如A和B要直接通信,(为什么不中继转发
?这样会对服务器造成压力很大。)
那么就通过tx
的服务器告诉对方的IP地址。
这样就实现了判断好友在哪儿。
10.算法搜集
tea算法,md5加密算法。
11.参考资料
https://wenku.baidu.com/view/241747906bec0975f465e25e.html
12.大致思路
Login verify:客户端向server发送
Login verifyUDPpacket = key2 + Tea(key2,Tea(key1,PlainUDPPacket))
这个算法好像3des?
用了两个密钥,而且密钥2还是公开的。
密钥key1只有用户自己知道,就像私钥。
引入key2纯属为了防止穷举暴破。
穷举的时间复杂度为2^(key1和key2的有效位数求和)
已知key1=MD5(MD5(password)+QQ号))
现在key1,key2已知,可以得出PlainUDPPacket.
PlainUDPPacket中包含login_verify_key.
tx
为什么要对PlainUDPPacket加密?且和用户的密码绑定?一定有不可告人的秘密。
Login verify key:服务器返回的报文。
发送报文后服务器返回的报文。使用login_verify_key解密可以得到login_verify_reply_key.
Login session:服务器发回来的报文。
使用login_verify_key可以解密得到session_key.
13.软件怎么做
- gocui
-
go command line UI.做界面的。
https://github.com/jroimartin/gocui
可以先做一个命令行的UI界面。
然后将QQ的一些东西封装进函数。
按下按键就会激活相应的功能。
先建立一个仓库吧。
https://github.com/jroimartin/gocui
https://github.com/happysmile12321/lazyqq.git