web逆向-xx乐

0. 思路来源

此文章仅用于技术交流

1. 什么是XX乐

XX乐是一种web端的网页反爬虫技术,其主要逻辑为对一个url连续请求三次,第一次为错误(状态码501)的请求,并且生成一个cookie,第二次同样为错误的请求,并且会携带此cookie发起请求,得到一段混淆的js代码,并且此代码运行后会生成最终的cookie,第三次携带此cookie即可获得正确的结果

2. 解题思路

    1. 发起第一次请求,获得cookie
    1. 携带cookie发起第二次请求
    1. 根据第二次请求获得的js代码运行后得到的cookie发起第三次请求

3. 思路

0x01 检查与分析

浏览器无痕窗口(无cookie)访问网址,通过F12检查三次请求
检查网络请求
在第二次请求的时候携带了一个新的cookie:__jsl_clearance_s,这个cookie即第一次请求返回的结果。
第二次cookie值
在第三次请求的时候也携带了此cookie,但是与第二次的不一样,是通过第二次返回的JS代码运行后获取的。
第三次cookie值

0x02 第一次请求与分析

因涉及到cookie的变换,这里使用session较为合适

import requests, re, execjs
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
}
url = "https://xx.xxxxxx.com/search/?kw=%E6%84%9F%E5%86%92"
session = requests.session()
response_1 = session.get(url, headers=headers).text

如图所示为第一次运行后的结果:
第一次运行的结果
返回的内容并不是全都需要,需要对结果进行处理

js_1 = re.findall('document.cookie=(.*?);loca', response_1)[0]

js_1的值
再通过第三方库execjs进行js的运行并且对结果进行处理并写入到session里

__jsl_clearance_s = execjs.eval(js_1).split(';')[0].split('=')[1]
session.cookies.set('__jsl_clearance_s', __jsl_clearance_s)

__jsl_clearance_s处理后的值

0x03 第二次请求与分析

按照上面的方式进行第二次的请求

response_2 = session.get(url=url, headers=headers).text
js_2 = re.findall('<script>(.*?)</script>', response_2)[0]

得到了一段比较长的js代码,其中的ha值代表了加密方式,总共有三种:sha1、sha256、md5。每次的加密方式总是随机生成。
第二次返回的JS代码
对返回的代码进行运行和分析,发现缺少环境,需要补充环境。
首先是补充最基本的window和document以及location环境,其次运行发现userAgent报错
JS代码-userAgent报错
在浏览器中进行调试。在源代码-事件侦听器断点-脚本 进行勾选,然后清理浏览器cookie重新请求。找到一直放行断点直至符合我们第二次请求返回的代码处,找到报错的位置进行输出查看
断点调试
在控制台输出混淆的代码即可发现是window[‘navigator’][‘userAgent’]
控制台调试
只需要对window下的navigator下的userAgent进行补环境即可。
当我们补完了环境,运行后发现既不报错也无任何数据输出。检查代码发现核心代码是使用了setTimeout计时器,原理是此方法设置了一个定时器,一旦定时器到期,就会执行一个函数或指定的代码片段。可以使用一个简单的箭头函数进行自定义。
JS代码解析
至此,我们的环境几乎补充完全,还需要考虑到两点:1. 这个js是Python请求获取到的,可以定义一个变量,在Python代码中把得到的JS代码和补环境中的变量进行替换即可使用。2. 我们运行了这个JS代码的目的是获得cookie,所以我们需要使用箭头函数定义一个变量来输出cookie。
补环境代码如下:

jscode = """window = global; window.navigator = {userAgent : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36'}; document = {}; location = {}; let fn = () => document.cookie; setTimeout = (arg1, arg2) => arg1(); code_"""

当我们运行整合后的Python代码时可能会报错:

UnicodeEncodeError: 'gbk' codec can't encode character '\xe5' in position 14296: illegal multibyte sequence

如果遇到这个错误,我们只需要在代码最上方添加如下三行代码即可解决:

import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding="utf-8")

PS:这个问题出现的原因是使用了pyexecjs,此库已经不维护了,有许多编码问题,想解决编码问题可以通过pip install pyexecjs2下载新的库使用

再使用execjs对代码进行处理并写入session

js_final = execjs.compile(jscode.replace('code_', js_2)).call('fn').split(';')[0].split('=')[1]
session.cookies.set('__jsl_clearance_s', js_final)

0x04 第三次请求

第三次可正常请求,即可得出结果:

response_3 = session.get(url=url, headers=headers).text

4. 总体代码

import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding="utf-8")

import requests, re, execjs

jscode = """window = global; window.navigator = {userAgent : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36'}; document = {}; location = {}; let fn = () => document.cookie; setTimeout = (arg1, arg2) => arg1(); code_"""

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
}
url = "https://xx.xxxxxx.com/search/?kw=%E6%84%9F%E5%86%92"

session = requests.session()
response_1 = session.get(url, headers=headers).text
js_1 = re.findall('document.cookie=(.*?);loca', response_1)[0]
__jsl_clearance_s = execjs.eval(js_1).split(';')[0].split('=')[1]
session.cookies.set('__jsl_clearance_s', __jsl_clearance_s)

# 第二次请求
response_2 = session.get(url=url, headers=headers).text
js_2 = re.findall('<script>(.*?)</script>', response_2)[0]
encrypt_type = re.findall('"ha":"(.*?)","is"', js_2)[0]
js_final = execjs.compile(jscode.replace('code_', js_2)).call('fn').split(';')[0].split('=')[1]
session.cookies.set('__jsl_clearance_s', js_final)

# 第三次请求
response_3 = session.get(url=url, headers=headers).text
print(response_3)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值