阅读本文前
在阅读本文前,你需要具有以下所有知识,否则你无法读懂:
- HTML + JS 基础
- HTTP 基本知识
- 简单的密码学知识(MD5、AES)
- 浏览器调试工具使用
- 高中英语以上水平
- 强记忆力
- 强逻辑思维能力
你会学到什么
在阅读本文后,你会学到一些常见的反爬虫方式,以及如何阅读被混淆后的 JS 代码。
免责声明
本文仅供学习研究使用,请勿将此技术用于违法用途。
起因
我从某个视频网站(会引起版权争议故不透露地址)上,想把他的视频下载下来,然后发现事情并没那么简单,于是就开始了长达 6 个小时的逆向研究。
目标网站情况
目标网站是调用了第三方 API 来获取解析后的某视频平台播放地址,该第三方 API 使用了多重反爬虫机制,逆向难度非常大。
分析
一、打开控制台,无限 debugger(难度 ★)
在这个网站,你无法使用鼠标右键,可以按下 F12 打开控制台,但是当控制台打开后,就进入了无限 debugger 状况:
对于这种反爬虫手段,有两种解决方法:第一种是关闭断点功能:
但是对于后续的步骤,需要进行断点调试,故此方法不可行。第二种方法是设置条件断点,即在该无限 debugger 处设置不进行暂停:
但是,在 Firefox 浏览器中,似乎对于这种有无限 debugger 的情况,非常容易直接卡死,于是我尝试 Chrome,它不会卡死,但是无法设置不暂停断点,最后我无奈尝试 Edge ,发现居然完美解决了上述一切问题(微软还是 NB)。因此,建议全程使用 Edge 进行调试:
二、请求分析(难度 ★★)
接下来是对请求进行分析,当视频加载出来能播放后,停止记录请求,从后往前看如下:
红框部分便是视频流,后缀名为 .ts
,这是 TS 格式的分段视频流,因此,如果我们想要下载完整的视频,就需要找到所有的视频地址。
我们继续向前分析,发现了这个请求:
显然,这个就是所有视频地址的列表,我们着重分析这项请求。
首先查看他的请求报文:
它的参数太多了,而且大部分含义十分难理解,可以推测整串 URL 可能是通过某种方式(请求、嵌入页面)直接获得的,我们继续向前寻找:
我们在他的前面几个请求,找到了这条请求,响应体有 url
字段,但是可能是经过加密无法直接读懂,这个暂时没关系,我们看看它的请求参数:
看来,这个请求可以作为我们分析的起点,只要得出它的每个参数的来源即可。
三、Iframe & Referer(难度 ★★)
我们查看上一步骤最后那个请求的调用栈:
这里,我们找到了发起这个请求的页面来源,但是和当前页面的 URL 不一致,经过审查元素,发现当前页面是使用了 iframe 嵌套了其他页面:
他居然嵌套了四层 iframe,最底下那层没有任何内容,所以可以忽略,因此,我们可以从第三层的入手,这也与前面请求的调用栈显示的一致。
从他的 URL 来看,后面跟了个请求参数 url
,参数值是某视频网站的视频播放页,这个非常简单易懂。我们使用浏览器直接打开这个 URL,但是显示了 404 Not Found:
不要被状态码迷惑了,服务器是可以返回任意状态码的。比如,你在 GitHub 上有个私人仓库,当你自己访问这个仓库的 URL 时,会显示仓库的内容,但是如果是没有权限的人访问,也会显示 404。
这样做的好处是,如果按照规范返回状态码 401 或者 403,会有暗示说虽然你不能访问到内容,但是说明这个东西是存在的。因此,用户访问没有权限的页面返回 404 也是对隐私的一种保护。
回到正题,为什么会发生明明写在 iframe 上有内容,浏览器直接打开就 404 了呢?
原因很简单,这是反爬虫最基本的操作,即 Referer 标头检测。这是一个请求头,定义该请求的来源,比如,我在 http://a.com/
网站,向 http://b.com/
发出请求,按照默认值,Referer 标头会被浏览器自动设置为 http://a.com/
,当然你也可以选择不发送,但这个不在这篇文章的讨论范围之内。
另外注意一下,Referer 头名字实际上是当初制定规范时的一个拼写错误,为了不影响后续的兼容性,只好将错就错,正确拼法为 Referrer。
那么,如果直接浏览器输入 URL 访问 http://b.com/
,Referer 头会被设置为空,即不会被发送。
回到正题,该请求是通过 iframe 发送的,不存在手动设置其他请求头的可能,因此,只剩下 Referer 头的可能性。为了后面方便调试,我们需要安装一个能自由设置 Referer 头的浏览器插件,Edge 里面这个插件叫《Referer Manager》,FireFox 和 Chrome 里面叫《Referer Control》。
装好插件后,我们进入插件页面,将 Referer 设置为自身(不含参数)。
我们再次刷新页面,如果设置成功,会发现已经能正常加载出页面来了,和最开始那个页面上面看到的一样。这样,我们的问题就被简化在处理这个页面上了:
我们再次查看网络请求记录,和之前的也是一样的:
但是,我们在当前页面还发现了一个 iframe:
同样的,我们为该 url 配置好 Referer 头,然后浏览器直接打开。但是,这次 Referer 头不能设置为自己(jx.sigujx.com),需要设置为上一页面的 URL(api.sigujx.com),不然会被跳转回 api.sigujx.com。
四、寻找请求参数来源(难度 ★★★★★)
这是本篇最难的,也是我迄今为止见过最麻烦的反爬虫。
还是之前那个请求(sigu_jx.php),我们点击最后一个 “(anonymous)”,找到他的调用位置。