JS逆向:知乎登录加密分析

前言

知乎登录踩坑记。。

分析

打开主页,登录,抓包三连。根据响应内容,可以确定这个就是登录的包:

表单内容里直接就是一串加密字符串:
全局搜索一下URL,并没有找到什么有用的东西:
下个XHR断点看看
body就是加密的参数了。我们向上找body的生成。翻到最后一个,发现还是加密的:
image.png
那么高度怀疑是在异步进行加密。我们在URL的地方打个断点。
发现这个地方是明文。回到XHR断点处,查看异步栈,在中间的一个地方找到了同样的位置:
那大概的地方我们已经知道了
调试一下这些地方,必有收获。通过不断下断调试我们找到了这里:
o还是明文,来到下面他就变成密文了
找找a赋值的地方,定位到这个地方:
控制台输出,证实确实是在这里加密的。那就进去看看,发现代码并不多,400多行,找到函数的尾:
头:
把代码剪出来。
这段代码和头条的混淆非常像,看着是400行,实际他比4000多行的代码难调多了。真正的逻辑代码,在这个巨长无比的加密字符串里:
页面初始化时先解密字符串,拿到真正的逻辑代码,再逐个调用。和webpack的代码加载类似,往往会伴随着pop、push、call、apply等关键字。我们既然扒下来了,就不管他,直接改代码加环境。
先改成自执行,把开头传入的webpack参数删掉:

执行一下,居然没报错,必有蹊跷。文件里搜索try,把try都干掉。
就这一处。。改完了执行还是不报错。算了,我们自己加。文件开头定义个window,然后把函数末尾的exports改成window,把加密函数导出。

运行:
找不到atob,补个atob方法。
注意!此处有坑!如果你去百度找node base64,很容易就找到下面这类的办法:
然后你拖到node里执行,发现和浏览器执行得到的结果不一样。懵了。这个倒也是base64,但是和浏览器的atob、btoa是有差别的。浏览器中这两个函数,不仅仅是对base64和ASCII码转换,还涉及了编码问题。比如atob,实际是把ASCII字符编码成binary数据。binary是JS的一个字符集,在node里需要显式的指定。所以在node里改写btoa和atob应该是以下的形式:
然后就是补环境了:
缺什么就去浏览器里找,补上就行。
随便输个密码测试一下:

完事。












你不会以为真结束了吧?

某乎可没有这么简单。我们把同样的代码在浏览器中新建一个脚本调试:
为避免冲突,把加密方法挂在window.test_default上。然后运行。
结果不一样!我们被他给骗了。
前面也说了,知乎的混淆和头条的很像,在那400多行代码里必然会有一个程序入口,我们可以通过在程序入口处插桩输出参数,对比node环境和浏览器环境的不同。
浏览器中snippet脚本修改:
输出:node:
浏览器:
确实有一些不同,但是并没有什么卵用。。。什么都看不出来。
其他地方也是,虽然有一些地方不一样,但是改过来也并没有得到想要的结果,看着打印出来的参数也总是感觉差了点什么。换一个解密的地方插桩,也就是这里:
看到第三行和第四行userAgent和webdriver的地方,解密对象不一样。我们加两行代码,当k(e.b[this.h])等于userAgent的时候断下来,看看有什么不同:vscode:
浏览器:
可以看到这个数组中的第0个元素,就是Navigator,但是输出出来就是一个空对象了,而我们的navigator里面却有一个userAgent,那么问题可能就出在这里。
我们给他强制改成一样不就完了吗。

做个判断,如果解密后的值为userAgent或webdriver时,把e.r强制改成浏览器里执行的结果。运行一下:
我们发现运行结果没变,然后在userAgent和webdriver的之间多出来一行。。。肯定又触发了什么检测的机制,走了不一样的流程。那我们试着不让这行返回。定义一个全局变量count:
然后如果count不等于4,就把k(e.b[this.h])解密的结果赋给e.r,否则就什么都不做:
这个方法真鸡贼。。。但是很有效:
我们已经拿到了和浏览器一样的执行结果。

虽然找到了解决办法,得到正确的结果。但是这个办法不是我想要找到的办法,就这样稀里糊涂的过了自己也没什么收获。于是我花了很久去研究到底是触发了什么检测导致的结果不同,最后终于找到了关键点。其实答案我们早就找到了,只是没去注意而已。

在我们第一次插桩的地方,有这样一行结果:

getOwnPropertyDescriptor(),这个方法是什么意思呢?MDN搜索一下:

写个demo:
不出意外的话,浏览器里的应该也是undefined。
果然是这样。所以就是,他这个加密,早就知道我们的navigator是假的,一直在陪我们玩。。检测的方式就是通过Object.getOwnPropertyDescriptor方法。
我们再回去改下代码,把之前改动的全删了,环境改成这样:

执行一下:

结束~~

总结

算是见识到逻辑混淆的厉(e)害(xin)了,真的是一不注意就进坑。。他不对也不给你报错,就走一个相反的逻辑给个错误的执行结果就行了,然后也不好排查问题所在。知乎的这个算是个低配版的头条_signature吧,头条的那个要更恶心一点。年轻人就要多踩坑···

本文分析过程仅供学习交流,并无任何个人以及商业或其他用途。如有不慎侵权,请联系我删除。

你可能感兴趣的:(JS逆向:知乎登录加密分析)