1. 首页 科技 视界 正文

                如何搞定知乎模拟登陆的加密难题?

                2019年03月24日 23:34:34  来源:CSDN  编辑:发情的大叔

                原标题:如何搞定知乎模拟登陆的加密难题?

                作者 | sergiojune

                责编| 郭芮

                声明:以下内容仅交流学习,请勿用于非法用途。

                如果你现在想模拟登陆知乎,会发现 fromdata 是一串加密的字符串:

                看了之后是不是很痛苦?你是不是就想使用 selenium 来模拟登陆??#36824;?#22909;像知乎对 selenium 也进行了相应的反?#26469;?#29702;,哈哈。但是我不也想用 selenium,效率太慢了,直接破解 js 才是我最?#19981;?#25361;战的。

                好,我现在教你如何用 js 硬撸破解。废话不多说,直接进入正题。

                找出signature加密

                加密位置这个相对来说是比较难找?#27169;?#38656;要?#32422;?#23545;那些混淆过的 js 进行一遍又一遍的搜寻,有时候你看到头皮发麻也不一定找得到,再加上这个加密?#38382;?#26159;一堆字符串,连个键都没有,搜索的条件都没有。这怎么办呢?我们可以去百度或者谷歌看看前人是怎么搞的。

                你直接搜索知乎模拟登陆的话,会发现以前的知乎的 fromdata 是键值?#38382;降模?#26377;以下键值对:

                ?#28526;?#20063;可以看看之前的破解思路,看到了上面的 signature 是通过加密来?#27169;?#29468;测知乎应该也是对之前的键值加密的 fromdata 进行加密?#27169;?#22312;控制台搜搜 signature 看看有没有线索:

                提示:按下 ctrl + shift + f 可出现搜索框

                一搜,果然有,看了看,signature 的加密过程和以前的还是一样?#27169;?#35777;明我的猜想正确了,说明是通过之前的 fromdata 的键值对进行加密成的一堆字符串,现在就看看 signature 是如何加密的。

                如果你对加密有点了解的话,还容易通过上面代码知道这是通过 hmac 加密,哈希算法是 sha1,密钥为 d1b964811afb40118a12068ff74a12f4,加密数据有四个,为 clientId、grantType、timestamp 和 source,这些值都可以在上面通过调试出来?#27169;?#23601;不多说了。如下:

                找出fromdata的完整键值对

                在知道 signature 是如何加密的之后,我们还需要找出完整的 fromdata 先,?#36824;?#22312;上面的调试中,你会发现也有几个 fromdata 值,但是不全。

                这时候如果我们得继续搜索 signature 的话,找了一整天你都会发现不到什么线索,这时候我们可以通过登陆的 url 进行突破,看看 url 是哪个路径,然后一顿搜。

                其登陆url是 https://www.zhihu.com/api/v3/oauth/sign_in。那我们可以直接搜 sign_in 试试。搜了发现和上面的 signature 是在同一个 js 文件上?#27169;?#24863;觉应该有戏。

                这个和登陆地址完全匹配,应该就是这个了,可以进行调试一波:

                这不出来了,经过多次调试,发现大多数值都是固定?#27169;?#21482;有 signature 和 timestamp 不是,其他的就是账号密码之类?#27169;?#36824;有个验证码 captcha ?#32422;八?#30340;类型 lang,signature 上面的已经找出来了,timestamp 很明显就是时间戳,其他的就不多说了。

                现在的 fromdata 已经全部找出来了,我们离加密字符串又近了一步,如果你直接用这个表单进行模拟登陆,会给你返回下面错误

                Missing argument grant_type

                可见我们还得找出这个 fromdata 的加密方法。

                找出 fromdata 加密位置

                如果你是第一次找这个,估计你得不断地翻 js,也不一定能找得到,或者你可以根据下面这个调用函数过程来找:

                会发现很多,?#36824;?#20320;懂套路的话都知道加密一般?#21152;?#21040; encrypt 名字之类?#27169;?#21487;以直接根据这个名字搜:

                一搜果然有这个,通过查看你很容易就找到这个:

                这个一通过调试,你可以看到,我们的加密字符串出来了,是不是很激动,我当时找到了这个的时候激动不得了。

                这个是加密的字符串

                这个就是我们需要找的

                历尽千辛万苦,终于找出了庐山真面目,激动不?先不要激动先,这只是加密的位置,后面的才是最难?#27169;?/p>

                找出 fromdata 加密的所有方法

                知道位置后,我们可以直?#24433;?#36825;个加密的 js 方法都扣出来,放在一个 html 文件内执行就好。

                在上面找出位置之后,很容易就可以看到这个完整的一个的加密方法:

                按这个半括号向上找,你就可以找到一个完整的加密方法,这个就是整个 fromdata 的加密方法。挺容易找?#27169;?#22914;果觉得不方便找?#27169;?#21487;以先将这个 js 文件里面的代码复制下来,然后到 Sublime Text 软件上找,这个可以折叠,也比?#20808;?#26131;找,找出来是这样子:

                格?#20132;?#20043;后有 400 多行,而且全是混淆,难看得一批。

                为了看看这个正确不正确,我们可以把函数里面的内容直接拿出来,就是去掉最外层的函数,然后调用下面的函数 Q,把我们的 fromdata 传进去:

                最后将上面的 Java 给弄成一个 html 文件,放在 标签内即可:

                格式就和上面一样,然后直接?#23081;?#35272;器上打开这个 html 文件,你会看到这个:

                这个就是我们一直努力在找的 fromdata 加密字符串。

                弄完这个之后,我们继续使用 Python 来操作了,因为这个加密的方法格?#20132;?#20043;后有 400 多行,实在太多,也全都是混淆,如果想用 Python 来实现的话也不是不可能,就是成本太大了,需要的时间太多了,我们还不如直接使用 Python 的 execjs 来执行 Java 代码直接获得就可以了,这个简单方便。

                我们除了使用 execjs 来执行,还可以使用 selenium 运行这个html 文件也是可以?#27169;?#20294;是我并不想用 selenium 这个工?#25784;?#36824;是?#19981;?#25240;腾,所以忽略了,想用的可以试试。

                但是这里又会有一个问题,我们?#23081;?#35272;器打开的是为它提供了一个浏览器的运行环境,我们在 Python 使用的 execjs 提供的是 node 环境,两个环境的不一样,就会产生不同的效果,下面我们可以选择使用 webstorm 编辑器来提供 nodejs 环境来进行尝试以下。

                在 node 环境调试加密代码

                你可以拿上面的 Java 代码在 webstorm 运行,你就会看到:

                TypeError: __g._encrypt is not a function

                所以我们需要调试,需要把那些在浏览器上只有的对象,比如 window、navigator 之类的对象给弄掉,从而在 node 上用不用的代码代替相同的效果即可。

                要调试我们先要找到代码运行的开端,可以很容易找到:

                可以看到,这里它会先去判断有没有 window 这个对象来判断是不是在浏览器上面运行?#27169;?#25152;以我们可以直?#24433;?#23427;修改成 true 或者其他表示成 true 的值都可以。

                再次运行,可以看到这个错误:

                ReferenceError: atob is not defined

                这个 atob 是将 base64 加密的字符串给解密,在 node 环境下是没有这个方法?#27169;?#25105;们需要使用 Buffer.toString()替代即可。

                运行之后,还是报这个错误:

                TypeError: __g._encrypt is not a function

                注意:这个是大坑,估计一般人每个一两天还搞不定,这个是因为上面的解密?#27169;?#20294;是上面的并不一样,你可以在上面的两个函数加断点,分别在浏览器和 node 环境下运行,可以看到解密的数据是不一样?#27169;?#26159;因为在浏览器上的 base64 加密的是 binary 编码,解密之后也就同样需要使用 binary 编码。这个是我在知乎的?#35797;?#25991;件上搜索 atob 这个方法,然后慢慢查找看到?#27169;?#24403;时也差不多心态崩了,还好坚持下来了。而我在 node 环境?#38470;?#23494;之后使用了默认的编码,所以解密的数据出错了。当我们加上 binary 编码之后,再运行:

                这时,错误不再是上面那个了,变成了另一个,证明解密正确了,再来看看下面这个错误:

                execption at 11: ReferenceError: window is not defined

                原来是 window 对象惹的祸,这个时候就需要我们伪造 window 对象了,至于怎样伪造呢,我们可以调试出错的地方,看看它使用了什么方法,就直接使用适合 node 运行的相同效果的代码代替就可以了,经过多次调试,需要我们伪造 window 和 navigator 这两个对象,下面就是伪造之后的代码:

                这个时候再运行看看:

                可以看到成功了,上面的红色字是一个提示,关于 Buffer ?#27169;?#36825;个我们忽略就行,接下来就可以使用 Python 环境进行测试了。

                果然,都出来了,哈哈,注意需要先安装 PyExecJS 库,自行安装,然后在测试的时候记得导入 execjs 即可。现在这个 fromdata 算是大功告成了,接下来就是登陆验证下我们搞得这个加密对不对了。

                模拟登陆知乎

                这个知乎的登陆也是坑满满,我也给踩了几个,这个就直接说?#24433;桑?#20854;他的就不多说了。

                我只是用手机号来登陆?#27169;?#20063;可以用邮箱登陆,过程都差不多的。

                1. 网址的请求头

                请求登陆的网址的请求头需要带上这几个:

                不带 content-type 的话,会给你返回这个错误:

                Missing argument grant_type

                不带 x-zse-83 的话,会给你返回这个错误:

                请求?#38382;?#24322;常,请升级?#31361;?#31471;后重试

                至于 agent-user 那就更不需要说了。

                2. 请求顺序

                知乎这个登陆是首先请求验证码地址,看需要不需要填写验证码,如果需要填就再请求一次,而且还需要再再请求一次查看是否输入验证码正确,不正确就重复上面步骤,当不需要填写验证码的时候就可以直接请求登陆网址了。

                还有上面的三次请求的验证码地址的请求方法都是不一样?#27169;?#21738;种方法自行调试即可。

                3. 验证验证码

                在验证验证码的时候请求头的 content-type 不要填写值为 multipart/form-data,如果填了请求验证码的时候会给你返回这个错误:

                {"error":{"message":"Missing argument input_text","code":400}}

                它的意思是说没有带上验证码验证,当我们去掉的这个字段的时候,就可以验证了。

                验证验证码的时候请求?#20998;?#38656;要有一个 user-agent 就可以了。

                4. 请求的所有阶段带上 cookie

                知乎这个有个 cookie 值是验证码票据,是从第一次请求验证码地址来?#27169;?#23601;是下面这个:

                如果不带 cookie请求或者请求顺序不一样?#21152;?#21487;能给你返回这个错误:

                {"error":{"message":"缺少验证码票据","code":120002,"name":"ERR_CAPSION_TICKET_NOT_FOUND"}}

                5.XXX

                你还想要?没有了,坑暂时只有这么多,最后给你们看下登陆成功的结果:

                写在最后

                这个登陆折腾了差不多一周了,实际来说可能是三周,因为从刚开始看不懂 js 代码,就跑去学了两周 js,现在总?#32654;?#35828; js 也可以说上手了,以后或许?#19981;?#20351;用 nodejs 搞点爬虫,挺好玩的。

                如果你上面看不懂不要紧,可以先去学习下 js,推荐大家去廖雪峰的官网看 Java 教程,写得蛮不错的。

                至于代码,暂时?#36824;?#24067;了,如果你一步一步按照我方法来弄的话估计也可以,前提的有 js 基础最好。

                折腾这个,掉了不少头发,但听说转发是生发之道,所以你们懂?#27169;?/p>

                作者:sergiojune,一个热爱折腾Python的学者。本文为作者投稿,首发于作者个人公众号日常学python,版权归对方所有。

                举报本文
                +10
                +10

                依据《信息网络传播权保护条例?#36820;?#20108;十二条之规定,即“避风港原则?#20445;?#26412;站所有文章及内容系第三方作者上传,如有侵权行为请及时联?#24403;?#31449;?#22836;?#21024;除,本站不对内容传播行为承担赔偿责任。

                跟贴 0
                参与 0
                发贴
                网友评论仅供其表达个人看法,并不表明E都市立场。
                11选5任3必中计算方法