WebSocket爬虫与JS逆向实战

声明:本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!由于本人水平有限,如有理解或者描述不准确的地方,还望各位大佬指教!!


练习网站:

Q3JhenkgUHJvTW9ua2V5IGh0dHBzOi8vd3d3LnBhbnpob3UuZ292LmNuL3p3Z2tfMTU4NjEvemZ4eGdremwvZmR6ZGdrbnJfNTgzNTQxNi9senlqXzU4MzU0MTcvemZ3al81ODM1NDE4L2luZGV4Lmh0bWw=

网站分析:

打开开发者工具,发现数据走的是wss协议,如图

WebSocket爬虫与JS逆向实战_第1张图片

 前面的文章中也有介绍过,以下特征就是代表着wss协议

WebSocket爬虫与JS逆向实战_第2张图片

既然知道了数据走的wss协议,那么我们就看他的wss链接,如图。但是我们发现wss链接是由几个加密值拼接的,那么我们的任务就是破解加密值以及寻找解密方法和入口

实战操作:

想必细心的大佬们都能发现,在ajax接口中,其响应的cookie值是和wss链接是吻合的,如图,那么,我们就可以大胆的请求这个接口了

WebSocket爬虫与JS逆向实战_第3张图片

然后接口还需要传参,参数值是加密的,那么我们就需要破解加密参数

又经过跟栈,找到了参数的加密入口,i 即为加密值,我们又发现请求接口时,请求头有对Fetch-Mode(为定值)和etag两个值有校验,那么我们同时还要拿到etag的值

WebSocket爬虫与JS逆向实战_第4张图片

而 i 的值是有 r 函数对 L 进行操作的,那么我们可以模拟 L 的生成(对url进行改变即可),但是我们却没有 r 函数

 往上检查js代码,发现了 r 的生成位置

看到 r = n(42),并跟进去,就知道 r 是由webpack生成的,这里的webpack的处理可以参考前面文章,这里就不做过多介绍了

WebSocket爬虫与JS逆向实战_第5张图片 当 r 和 etag 复原之后,就可以正常生成加密参数了, 如图

WebSocket爬虫与JS逆向实战_第6张图片

运行结果如图

 那么我们就能拿到ajax接口的响应cookie值了,就可以生成wss链接了,如图

import execjs
from spider_util.utils import *

def data_sign():
    # 读取js文件
    with open('./2.js', 'r', encoding='utf-8') as f:
        reader = f.read()
    # 加载编译读取内容
    loader = execjs.compile(reader)
    # 调用js文件中的方法
    r = loader.call('fjm_panzhou_sdk')
    # 返回结果
    return r

data_sign = data_sign()
etag = data_sign[0]
param = data_sign[1]

headers = {
    "content-type": "application/json; charset=UTF-8",
    "etag": etag,
    "fetch-mode": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
}
url = "https://www.panzhou.gov.cn/1ywuKELSO2ahQuWZ/api/v1/sessions"
data = {
    "data": param
}
data = json.dumps(data, separators=(',', ':'))
response = requests.post(url, headers=headers, data=data)
wss_param1 = response.cookies.get('dGg2aCfMMK97Ro270mqBFu5qjC8TQbL2opnHvbEpM', '')
wss_param2 = response.cookies.get('FW9uCWqlVzC22m1KfCMCjfvFHpRMsgt', '')
print(wss_param1, wss_param2)
wss_url = f"wss://www.panzhou.gov.cn/1ywuKELSO2ahQuWZ/pr/{wss_param1}/b/ws/m01j9wq8pw/{wss_param2}" # oiysmb2g7k
print(wss_url)

 然后用wss协议发送请求链接,接收服务器响应结果,就能拿到数据了,但是却请求失败了

import websocket
import _thread as thread
import time

cookie = f'FW9uCWqlVzC22m1KfCMCjfvFHpRMsgt={wss_param2};dGg2aCfMMK97Ro270mqBFu5qjC8TQbL2opnHvbEpM={wss_param1}'

headers2 = {
    "Pragma": "no-cache",
    "Origin": "https://www.panzhou.gov.cn",
    "Accept-Language": "zh-CN,zh;q=0.9",
    "Sec-WebSocket-Key": "krDSpbfAbFkDxWiFXTQWxA==",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
    "Upgrade": "websocket",
    "Cache-Control": "no-cache",
    "Cookie": cookie,
    "Connection": "Upgrade",
    "Sec-WebSocket-Version": "13",
    "Sec-WebSocket-Extensions": "permessage-deflate; client_max_window_bits"
}

def on_message(ws, message):
    """收到对方消息处理方法"""
    print("对方发来的消息:", "".join(url_unquote(message)))
    time.sleep(5)   # 控制发送频率
    ws.send('ping')        # 我方决定再回一个消息

def on_error(ws, error):
    """ 错误处理方法 """
    print(error)

def on_close(ws,code,msg):
    """ 关闭处理方法 """
    print("代号:",code)
    print("对方关闭发来的消息:", msg)
    print("### 程序结束 ###")

def on_open(ws):
    """ 运行入口 """
    def run(*args):
        ws.send('ping')    # 我方发送第一个消息
    thread.start_new_thread(run, ())   # 开启线程
    
# websocket.enableTrace(True)    # 是否打开日志信息
ws = websocket.WebSocketApp(wss_url,
                            header=headers2,       # 设置请求头
                            on_open=on_open,     # 设置运行入口
                            on_message=on_message,   # 设置收到消息处理
                            on_close=on_close,  # 发生关闭处理
                            on_error=on_error,    # 错误处理
                            )
ws.run_forever()

这个问题基本上有两种原因,第一是wss_url不完全正确,第二就是请求头有其他检测。而小编已经对可能校验的cookie进行处理了,那目前只剩下wss_url的准确性了。经过仔细观察链接发现,如图参数值也是有变动的

而该参数就与上面ajax请求传参的tabId长度相等,且该值也是变动的。那么小编就且将两者值保持对应,再次进行wss请求

这次请求就能正常返回数据了,结果如图

WebSocket爬虫与JS逆向实战_第7张图片

WebSocket爬虫与JS逆向实战_第8张图片

WebSocket爬虫与JS逆向实战_第9张图片

实战总结:

js逆向的过程就是这样,是一个不断研究和自我推敲的过程,不过是大佬还是新手小白,都是需要一步一步去入口,定位加密参数,寻找解密方法,完成参数复原,模拟正常浏览器请求服务器。所以小编还是希望大家在这个过程中能不断尝试,不断进步

那么,今日的分享就到这里,想要学习更多的python爬虫和js逆向的相关技巧和知识的小伙伴们一定要点下关注哟,后期会不定时分享相关干货内容

你可能感兴趣的:(javascript,websocket,爬虫,webpack,python)