前言
仅学习之用,勿商,侵删。
目标网站:aHR0cHMlM0EvL3d3dy5tYW9tYW96dS5jb20vJTIzL2J1aWxk
环境
node(执行破解js,提供接口)
python3.6(执行爬虫)
开始!
分析
请求页面,白白净净三条Ajax。
随便进去看看请求头和返回的数据。
好球,都是加密的数据。
接下来找到加密位置。
八仙过海,可以尝试直接搜索常见的关键词:md5,base64,RSA,ASE,encrypt,decrypt,JSON.parse等等。或者用油猴插件一次性hook一下。
这里找到加密位置,关键位置断点:
刷新页面,停在断点位置,发现aes_encrypt接收一个l变量,里面只有一个时间戳。
F8和F10配合使用,执行一下加密,返回来的e.data就是前面post请求的请求头加密参数。e.url就是我们要请求的url。
后面还有两个请求,类似操作都可以找到。
第二次请求
这里发现l变量多接收了一个Type参数。
第三次请求
这里发现l变量除多接收了一个Type参数,还有page参数,大胆怀疑这应该就是翻页参数,这个也就是我们需要的数据请求,在/index/build.json这个post请求里。
再继续执行,请求已经通过axios发送了,返回加密的数据需要在前端解密了。
第一个返回数据,e.data是一串加密数据。
进入aes_decrypt解密函数里,多观察几次,可以发现,l是aes的iv(偏移量),数值固定。
最后返回解密的数据。
第二次和第三次请求也是一样,返回数据进行AES解密,就不放截图了。
抠js代码
终于到了这一步了,曾经我也觉得抠代码是很复杂很麻烦的一件事(现在也是…),然后看那些大神写的逆向流程,很多到这里就直接结束了(可能是有麻烦吧,或者觉得没有必要了)。
其实经过前面的分析流程,这里的抠代码环节已经很清晰了。万事开头难,你动手去试试可能就会发现,其实还好。
我们把两个关键函数构造出来,接下来就是缺啥补啥了
function my_encrypt(l) {
data = aes_encrypt(JSON.stringify(l));
// console.log(data)
return data
}
function my_decrypt(e) {
data = aes_decrypt(e.replace(/^\s+|\s+$/gm, ""));
// console.log(e)
return data
}
为了不占用篇幅,完整的代码后面就放到github或者码云上吧。
破解后的js代码量很少,就一个md5和AES,可以直接用python代码进行重新构造。
这里采用直接运行js。
node运行js解密接口:http://127.0.0.1:3000/
python测试代码:
# -*- coding: utf-8 -*-
import time
import requests
url = "https://www.xxxx.com/index/build.json" # 保险一下
jm_url = "http://127.0.0.1:3000/"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)"
" Chrome/83.0.4103.97 Safari/537.36"
}
def get_payload(pages=1):
"""获取post的请求参数"""
now_time = int(round(time.time() * 1000))
data = {
"data": {"Type": 0, "page": pages, "expire": now_time}
}
print(data)
# 获取加密请求参数
_payload = requests.post(url=jm_url + 'my_encrypt', json=data).text
print(_payload)
return _payload
def get_html(data):
"""请求页面,返回加密的数据"""
response = requests.post(url=url, headers=headers, data=data)
_encrypt_data = response.text
print(_encrypt_data)
return _encrypt_data
def get_decrypt_html(en_data):
"""获取解密数据"""
data = {
"data": en_data
}
response = requests.post(url=jm_url + 'my_decrypt', data=data)
html = response.text
print(html)
if __name__ == '__main__':
page = 2 # 页码
payload = get_payload(pages=page)
encrypt_data = get_html(payload)
get_decrypt_html(encrypt_data)