2016/09/29 :
理清了
rsa的步骤,所以自己写了一个。加密思路更清晰明了。
2016/09/24 :
闲着没事,又玩起了模拟登录。距离上一次写模拟登录QQ已经过去很久了。
抓包
是的,一切分析源自于抓包。

这是登录时,浏览器提交的请求参数。很明显,我们需要知道params和encSecKey是怎么来的。
分析JS源码
我们现在浏览器里搜索params,然后成功的找到了。为了方便操作,我们把它整个复制到本地文件中。

从上面的截图我可以知道,我们需要的参数来自于window.asrsea这个函数。
中间省略我漫长的查找、分析和验证的过程。我们来直奔主题吧。
先看传入的第一个参数JSON.stringify(bl)。
bl在不同的请求下会有不同的值。这里我只列出它在登录时的值。
const bl = {
username: '帐号',
password: crypto.createHash('md5').update('密码').digest('hex'),
rememberLogin: true,
csrf_token: ''
}
关于后面的三个参数其实都是定值。感兴趣,可以自行推演分析。
//bbZ(['流泪', '强'])
const x = '010001'
//bbZ(Ka.md)
const y = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
//bbZ(["爱心", "女孩", "惊恐", "大笑"])
const z = '0CoJUm6Qyw8W8jud'
好的,至此,我们所需要的参数都有了。那么这个window.asrsea到底对这个四个参数做了什么呢。
加密过程
其实并没有很复杂的加密流程。
/*
* 下面我用data替代JSON.stringify(bl)
* 简要介绍一下,加密流程
*/
window.asrsea(data, x, y, z) {
const str = randomString(16)
const params = AES.encrypt(AES.encrypt(data, z), str)
const encSecKey = rsa(str)
}
解释一下上面的代码:
randomString()是用于生成一个随机字符串str,长度为16。
然后以z为key加密原始数据。得到结果后再以str为key加密。将此结果作为params。
然后再通过RSA加密str。此结果为encSecKey。
这里RSA加密需要的PublicKey哪里来的呢。其实就是x, y。
x转成整数的值是:65537。
代码
移至:github
总结
也许你们会问,为什么RSA加密没有用Nodejs自带的。嗯,不是我不想,而是网易这个RSA填充方式似乎没按套路来,也许也是我没用对。所以我,就偷懒直接把他的RSA加密实现从源码里拿了出来放到了rsa.js。
如果你用Nodejs的crypto实现了,望告知。
还有目前这个没有考虑登录出现验证码的情况。
另外,试了一下Chrome的debugger。嗯,很棒。为什么以前不知道用呢。
附
网易实现的rsa应该是来自这个:RSA in JavaScript