前言

  1. 请勿用于商业用途,仅供学习
  2. 该登录方式为账号-密码登录,只能登录经常登录的账号,登录他人账号,只能进行扫码
  3. 感谢这个博客的帮助 https://blog.csdn.net/illbehere/article/details/53262033
  4. qq邮箱登录地址

正文

1 找到js文件,打断点


输入账号和错误的密码,可以看到有两个请求,一个check,一个login。check会根据账号返回一些参数,这些参数会使用在login里。

采用xhr的方式寻找js文件,你会发现然并卵,不会有断点停住的。
正确的寻找js文件,是监听登录按钮的点击事件。

一步一步往下执行的结果



这个i.p就是login登录里面的参数p,也就是加密后的密码,是重点要破解获取的。

2 寻找pt.plogin.salt

分析这个函数的参数

i.p = $.Encryption.getEncryption(n, pt.plogin.salt, i.verifycode, pt.plogin.armSafeEdit.isSafe)

n:是密码明文
pt.plogin.salt:暂时不明是个啥
i.verifycode:是check返回的参数之一
pt.plogin.armSafeEdit.isSafe:无意义,undefined

pt.plogin.salt全局搜索一下,可以看到调用了uin2hex的函数,参数是不带@qq.com的账号。跟进去,可以看到该函数的具体实现。


可以试验一下,这个函数是否正确,使用Snippets,查看控制台输入是否跟断点显示的一样。

3 分析h函数

所需参数分析完了,进入getEncryption函数,可以看到h函数,h函数是加密密码的主函数

主函数里面有各种函数的调用栈,非常复杂繁琐,一层跟进又一层,我原本尝试着一层一层跟进去,取出里面所涉及到的方法,后来分析到rsa_encrypt这个函数,彻底放弃了,方法太多,我取函数名都取得晕晕的,担心函数撞名,毕竟人家混淆后用abcd来命名,我们跟着这么命名会重复的,而且万一哪里出错了,你还得一个一个去核对函数是否正确。最后我发现所有涉及的函数都在c_login_2.js里面,所以我全部复制黏贴了,放到了sublime里面去查看

放到sublime里面一看,有4653行,还好不算很多。里面有很多方式是用不到的,所以接下来我们要取出主要涉及登录的函数部分。
首先 根据 function h(e, i, n, o),判断包含这个函数的函数是需要的,往上翻,可以看到h函数是存在$.Encryption = $pt.Encryption = function() 这里的,然后把这个函数全部复制黏贴下来。

然后看看h函数里面有涉及到哪些函数。仔细分析下h函数,看红色框框,凡是这种t,g,r这样的,都是跟h函数是同一个函数体下面的,刚刚已经复制黏贴了,不用管了。看看蓝色框框,有个TEA,不知道是哪个啥,全局搜索找到TEA的函数体,然后复制黏贴下来。之后同理找到黄色框框RSA涉及到的函数体。



找到之后,复制黏贴发现才1000行,之后我们要保证,这些js代码,能够脱离单独运行。在一个新的窗口打开,新建一个snippet文件。不要在qq邮箱登录地址的窗口打开,因为它的js文件已经加载了,你运行js代码,是不会报任何错的。

接下来就进行js文件修改,让它可以脱离原本的js文件加载运行起来。

4 修改js文件

前面有个uin2hex的函数,这个函数也复制进去,我们要获取salt,然后调用h函数看看,会不会报什么错。

4.1 $pt is not defined
$pt我觉得只是一个指明,代号这样的,完全可以删除,把所有涉及到的 $pt.XX全部删掉,涉及到 $pt的调用,改为 $.xx的调用,比如 var h = $.RSA.rsa_encrypt(g(u + c));改完之后再运行,控制台输入了一串

把这个复制黏贴,跟抓包里面的p比一下长度,发现是一模一样的,而且我们基本没有改动关键代码,我们有理由相信,这个就是我们要的加密后的密码。之后我们放进python中,看能不能直接调用这个js。在js里面写个函数getPassword,写个py文件调用这个函数,看打印效果。

function getPassword() {var n = "qerewtwret123214"var salt = getSalt(123456789)var verticode = "!C90"var safe = undefinedreturn $.Encryption.getEncryption(n, salt,verticode , safe)
}
class QQEmail(object):def getPass(self):js_path = "%s/aaa.js" % "/".join(os.path.abspath(__file__).split("/")[:-1])with open(js_path, 'r') as f:js_content = f.read()ctx = execjs.compile(js_content)new_pwd1 = ctx.call("getPassword")print(new_pwd1)if __name__ == '__main__':q = QQEmail()q.getPass()

4.2 $ is not defined
$ 这个没有定义,我也不知道怎么定义,所以干脆有关用$.xxxx的调用,把 $去掉。全局搜索 $. 然后删掉。

4.3 navigator is not defined
navigator包含浏览器有关的信息,比如Console输入navigator.appName,可以打印出"Netscape"

然后全局搜索navigator,看看哪些地方调用了它,之后console打印出来是什么,我们就替换成什么。

4.4 window is not defined
本来想仿照navigator一样进行替换,后来发现有些对象是没法替换的,我干脆直接注释掉了。所有有关windos的我都注释了。那这样做是否会产生问题,为了检测是否出现问题,我们在snippet里面测试下,注意,有个地方window先不要注释,看下图

这个window注释掉会报另一个错,我们等会儿解决,先保留是为了看其它出现window的代码的地方,注释掉是否有问题。结果依旧可以打印出一串。暂时我们认为没有问题,接下来把上图的window删除,我们继续往下走。

4.5 Cannot set property ‘TEA’ of undefined
程序没有办法访问到TEA,这就奇怪了,为啥程序可以访问 Encryption.getEncryption,却不能访问TEA.strToBytes。之后我就在TEA的函数体里进行了修改

这就要看模仿能力了,反正仿着Encryption修改funciton(t)函数体,修改地方有以下几点
1.函数体名修改

2.返回体修改

t.TEA = {encrypt: function(t, e) {return o(a(h(t, e)))},enAsBase64: function(t, e) {for (var i = h(t, e), n = a(i), o = "", p = 0; p < n.length; p++)o += String.fromCharCode(n[p]);return btoa(o)},decrypt: function(t) {return o(l(h(t, !1)))},initkey: function(t, e) {f = h(t, e)},bytesToStr: p,strToBytes: r,bytesInStr: o,dataFromStr: h};

换成这样

return {encrypt: function(t, e) {return o(a(h(t, e)))},enAsBase64: function(t, e) {for (var i = h(t, e), n = a(i), o = "", p = 0; p < n.length; p++)o += String.fromCharCode(n[p]);return btoa(o)},decrypt: function(t) {return o(l(h(t, !1)))},initkey: function(t, e) {f = h(t, e)},bytesToStr: p,strToBytes: r,bytesInStr: o,dataFromStr: h}


之后在snippet里面测试,发现可以运行,能打印一串出来。

4.6 btoa is not defined
在snippet里面能打印出来,但是在程序运行还是报错了,btoa是个啥子,百度一下。

这是Web的API,但是在Python中的execjs库无法使用 Web.API。这就有点犯愁了,看下代码。

可以看见,先使用g(h),然后调用btoa进行base64加密,之后替换一些特殊字符,就是我们真正需要的密码。那么我们先返回g(h)的结果,能不能我们自己仿照btoa的加密方式进行加密?然后再调用replace替换,就是说,我们自己写一个bota。
感谢这个博客:https://www.cnblogs.com/JokerWu/p/9456241.html
具体实现如下
首先js文件中

    function h(e, i, n, o) {n = n || "",e = e || "";for (var p = o ? e : t(e), r = g(p), s = t(r + i), a = TEA.strToBytes(n.toUpperCase(), !0), l = Number(a.length / 2).toString(16); l.length < 4;)l = "0" + l;TEA.initkey(s);var c = TEA.encrypt(p + TEA.strToBytes(i) + l + a);TEA.initkey("");for (var u = Number(c.length / 2).toString(16); u.length < 4;)u = "0" + u;var h = RSA.rsa_encrypt(g(u + c));return setTimeout(function () {d(488358, 1)}, 0), g(h)// btoa(g(h)).replace(/[\/\+=]/g, function(t) {//     return {//         "/": "-",//         "+": "*",//         "=": "_"//     }[t]// })}function Btoa(str) {return str.replace(/[\/\+=]/g, function (t) {return {"/": "-","+": "*","=": "_"}[t]})}...........return {getEncryption: h,getRSAEncryption: f,md5: t,salt: getSalt,getBtoa: Btoa   //注意这个哦,要调用Btoa的方法}function btoaReaplace(str) {var btoa  = Encryption.getBtoa(str);return btoa
}

然后py文件中

class QQEmail(object):def getPass(self):js_path = "%s/aaa.js" % "/".join(os.path.abspath(__file__).split("/")[:-1])with open(js_path, 'r') as f:js_content = f.read()ctx = execjs.compile(js_content)new_pwd1 = ctx.call("getPassword")new_pwd2 = new_pwd1.encode('latin1')new_pwd3 = base64.b64encode(new_pwd2)new_pwd4 = str(new_pwd3, 'utf-8')new_pwd5 = ctx.call("btoaReaplace", new_pwd4)# return new_pwd5print(new_pwd5)if __name__ == '__main__':q = QQEmail()q.getPass()

最后,p参数分析完毕

5 拼接参数

p参数解析出来之后,后面的就简单了。

  1. 访问qq邮箱登录地址,获取pt_login_sig
  2. 访问https://ssl.ptlogin2.qq.com/check,补齐参数,进行请求
  3. 访问https://ssl.ptlogin2.qq.com/login,补齐参数,进行请求
  4. 请求成功,获取里面的链接,进行下一步请求,这里设置禁止重定向allow_redirects=False,保存需要的cookies值,在response里面找到location,获取重定向的地址
  5. 访问重定向地址,请求成功后,获取下一个需要跳转的链接,请求该链接,这里依旧需要禁止重定向,成功后获取重定向地址
  6. 请求重定向地址,可以从response里面获取sid的值,如果你需要访问【收件箱,已发送等】需要sid的值。

需要注意下,下图的sid很重要,基本就是通行证。如果你请求失败了,请查看你的cookie值里面是否有sid这个值。

6 登录成功

总结

  1. 利用监听事件锁定js文件
  2. 函数调用层过多,可直接根据主函数锁定所需要的函数体
  3. 根据运行出现的各种问题进行修改/调试,利用scope,观察返回值是否相同,也可以查出错误
  4. btoa函数的分解
  5. 注意cookie值的变动

python之js破解qq邮箱登录相关推荐

  1. python自动登录qq邮箱_selenium+python实现自动登陆QQ邮箱并发送邮件功能

    本期做一个selenium详细实例,会把我在元素定位中遇到的一些阻塞和经验分享给大家. (浏览器为Chrome) (如果只需要最终的完整代码,请直接跳转到文章最后) 浏览器打开QQ邮箱登录网址 fro ...

  2. python实现kindle每天推送博客1----kindle推送原理,python实现qq邮箱登录及邮件发送

    kindle想每天看新闻,看博客, 其实自己用python写个代码就能很简单实现了. 1.kindle推送原理 kindle不仅可以买书看书,还可以自己推送内容 原理很简单,往你个人的kindle邮箱 ...

  3. QQ邮箱登录PC布局实战笔记一

    QQ邮箱布局实战(PC)笔记<一> 开篇说明: 这个系列的笔记算是作为我复习前端知识的一个系列吧.前端的知识很杂,各种小技巧很多,而且更新变化很快,不像我们在校学习的那些计算机基础理论知识 ...

  4. python基础编程:selenium+python实现自动登陆QQ邮箱并发送邮件功能

    本期做一个selenium详细实例,会把我在元素定位中遇到的一些阻塞和经验分享给大家. (浏览器为Chrome) (如果只需要最终的完整代码,请直接跳转到文章最后) 浏览器打开QQ邮箱登录网址 QQ邮 ...

  5. selenium+python实现自动登陆QQ邮箱,并发送邮件

    这里写自定义目录标题 selenium+pycharm实战,登录QQ邮箱,并发送邮件 浏览器打开QQ邮箱登录网址 元素定位,输入QQ账号和QQ密码 元素定位,写信界面 元素定位,邮件发送 元素定位总结 ...

  6. HTML+CSS 模拟QQ邮箱登录界面

    模拟QQ邮箱登录界面 index.html <!DOCTYPE html> <html lang="en"> <head><meta ch ...

  7. [实战篇]关于QQ邮箱登录之测试用例

    今天,我们来分析一个关于QQ邮箱登录模块的测试用例: 邮箱登录模块它就只有两个,一个是登录账号,一个是登录密码.在上一篇注册模块的文章中分析过,如果是一个输入框的话,你就直接对这一个输入框进行等价类划 ...

  8. QQ邮箱登录PC布局实战笔记二

    本文目标: 尽量100%还原QQ邮箱登录界面头部区域,掌握div之间的位置关系,掌握常见的定位技术和浮动技术.将头部所需要的HTML标签进行仔细学习. 开始准备: 浏览器:Firefox/Chrome ...

  9. html模仿qq邮箱,如何实现JS仿QQ邮箱收件人选择和搜索

    如何实现JS仿QQ邮箱收件人选择和搜索 导语:通过下面教程的学习,大家可以掌握如何实现JS仿QQ邮箱收件人选择和搜索,更多详情请关注应届毕业生考试网. 页面截图: 主要html代码: To: Subj ...

  10. QQ邮箱登录PC布局实战笔记四

    本文说明: 经过几次的努力,一个完整的QQ邮箱静态页面已经搭建完成,自己的确在一些细节方面并没有很好地和人家百分百一致,但是也是通过自己的方法,得到了功能的实现.老实来讲,HTML和CSS的布局是一件 ...

最新文章

  1. matlab ezplot hold,matlab中的ezplot函数
  2. 独家 | 无人驾驶项目实战: 使用OpenCV进行实时车道检测
  3. PHP开发如何实现多线程?
  4. AndroidStudio动态调试smali
  5. Ajax实现异步操作实例_针对XML格式的请求数据
  6. WPF 实现任务栏角徽
  7. 什么可以作为gcroot_面包果既能当水果又可以作为粮食,国内却无法普及,这是为什么?...
  8. go语言如何调用java接口,[译] 如何在 Go 中使用接口
  9. 疑似三星Galaxy S11入网:搭载骁龙865处理器+支持25W快充
  10. 21day学通python_python21day
  11. 不高兴INTEL挤牙膏,技术天才Jim Keller愤而辞职
  12. h5打开APP,如果未下载跳转下载页,如果已下载唤醒APP
  13. 非法集资(Illegal Fund-raising)
  14. 《惢客创业日记》2020.04.01-15(周三) 国家有难,匹夫有责(四)
  15. 得意狗寄给我特快专递
  16. 重置计算机网络设置路由器,路由器怎样重新设置_路由器重新设置怎么弄-系统城...
  17. Android常用颜色对照表
  18. Access 的 AutoExec 宏
  19. 【ps功能精通】4.简单背景图片抠图
  20. 数据库——《对数据进行排序》

热门文章

  1. 计算机漏洞安全相关的概念POC | EXP | VUL | CVE | 0DAY
  2. python就业班-淘宝-目录.txt
  3. Two‘s Complement(二进制补码)
  4. pytorch accuracy和Loss 的计算
  5. 英语4级的分数如何计算机,英语四级分数如何计算
  6. 仿苹果商店 html5效果,8个超炫酷仿苹果应用的HTML5动画
  7. 个人学习笔记---Linux内存:内存管理的实质
  8. ubuntu默认开启numlock
  9. 常用坐标系汇总(更新)
  10. Unity 3D学习(基础篇)——C#基础入门