Python爬虫实战H05js逆向破解时间戳反爬图文教程

2024-12-27阅读数:57
上一篇:Python爬虫实战H06初识浏览器指纹:Selenium是如何被反爬的图文教程
下一篇:Python爬虫实战H04js加密混淆及简单反调试图文教程

打开Python爬虫实战练习页面js逆向破解时间戳反爬_H05_Spiderbuf,可以看到页面内容是由NordPass发布的2022年全球最常用密码列表,只是一个简单的表格,数据也不多。

在网页上点击右键 > 显示网页源代码,可以看到网页结构也并不复杂。HTML代码并不多,总共就85行,但在源码当中没有看到页面上显示的内容,这种情况一般是由JavaScript动态加载并渲染内容的。

F12打开谷歌浏览器开发者工具,刷新一下页面,看到network(网络)这里加载了几个文件,其中有一个JavaScript文件是值得注意的,因为其它几个文件名就能猜到它的作用,唯独有一个是看似无意义的。

3NjU0MzIx.js

还有一个很长的字符串,我们点击它,右边就会展开详情,Headers里有api这样的关键字,api通常是后台返回数据的。我们切换到Response(响应)标签,能够看到后台返回了一个json。

[
    {
        "ranking": 1,
        "passwd": "password",
        "time_to_crack_it": "\u003c 1 Second",
        "used_count": 4929113,
        "year": 2022
    },
    {
        "ranking": 2,
        "passwd": "123456",
        "time_to_crack_it": "\u003c 1 Second",
        "used_count": 1523537,
        "year": 2022
    },
    ...

找到了数据返回的接口,而且拿到了明文json,那按理说我们这次的爬虫分析工作就差不多了,但当我们把刚才分析的api请求链接放到浏览器地址栏打开时,发现获取不到数据,也就说,我们要么继续分析这个请求链接是怎么构造的,要么就使用selenium这样的模拟浏览器。

先不管三七二十一,丢到selenium里运行一下再说。

client = webdriver.Chrome()
client.get('https://spiderbuf.cn/playground/h05')
print(client.page_source)
client.quit()

发现打印出来的HTML源码里已经出现我们想要的数据的,到了这里我们就可以直接解析HTML代码获取数据就可以了。

但这一关写的是js逆向破解时间戳反爬,所以我们可以尝试着分析请求参数的构造,这时候就要想起我们刚才提到的3NjU0MzIx.js文件的。

点击打开这个文件,发现是混淆过的JavaScript代码,一大堆杂乱无章的代码,对于新手来说有点无从下手,这个时候就需要在浏览器里面调试了。

我们已经从上面的分析中知道,JavaScript代码中构造了一些请求参数,并向后台发起了请求且处理了返回的数据。现在JavaScript向后台发起请求用得比较多的是fetch函数,该函数会把返回的响应内容封闭成一个叫Promise的数据结构。

要在浏览器里面调试JavaScript代码,就要在开发者工具里切换到Sources(源码),点开左边的树形,找到我们要调试的JavaScript文件3NjU0MzIx.js,点击它就能在右边看到代码详情。

JavaScript代码

使用上面说的fetch作为关键字搜索一个源码,看看能不能找到。因为JavaScript代码混淆通常为低、中、高几个级别,混淆等级越高,混淆程度越高,但混淆会对代码性能有一定的影响。混淆等级不高的时候,有部分代码是没有被混淆的。

那我们现在遇到的这个JS文件就是属于混淆程度不高的,因为使用fetch作为关键字搜索就搜到了:

_0xcec9d2();
var timeStamp = Math[_0x1d6c('0x29')](new Date()[_0x1d6c('0x9')]() / 0x3e8);
var _md5 = md5(timeStamp);
var s = btoa(timeStamp + ',' + _md5);
fetch('./h05/api/' + s)['then'](function(_0x35f53c) {
    return _0x35f53c[_0x1d6c('0x14')]();
})[_0x1d6c('0x8')](function(_0x21c749) {

而且还有惊喜,fetch这一行代码上面两行也是明文,这样再往上推一行也要猜到混淆的那一行就是获取了当前的时间戳并放到了变量timeStamp里面。结合起来就是获取了时间戳放到timeStamp变量,然后对这个时间戳计算了一个MD5哈希值并放到_md5变量里面,再把这个时间戳跟哈希值组装成一个字符串并进行Base64编码。

不用进行动态调试就得到了这样的结果,是一个挺大的惊喜了。有人说这怎么感觉像是猜的?

没错,调试代码有很多时候就是先猜测再验证的,但猜测的依据是你对代码的熟悉程度跟经验。如果你不熟悉JavaScript,那根本想不到使用fetch关键字进行搜索。这也是为什么很多人在网上看人家逆向破解,貌似学会了,但一旦自己动手去分析的时候就变了无头苍蝇的原因。

到了这里,我们就可以使用Python构造合法的请求了。

url = 'http://spiderbuf.cn/h05/api/'
timestamp = str(int(time.time()))
md5_hash = hashlib.md5()
md5_hash.update(timestamp.encode('utf-8'))
md5 = md5_hash.hexdigest()
s = ('%s,%s' % (timestamp, md5))
print(s)
payload = str(base64.b64encode(s.encode('utf-8')), 'utf-8')
print(payload)
html = requests.get(url + payload, headers=myheaders).text
print(html)

完整示例代码:示例代码