JS逆向-sig、sign请求参数加密反爬(案例:红人点集)

前言

该文章为学习使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!如有侵权,请私信联系作者删除~

需求

采集目标网站数据:http://www.hh1024.com/
通过抓包分析模拟登录需要还原请求参数sig和p,加密算法为标准MD5。然后获取返回的token参数,用于数据抓取。数据接口需要携带请求参数sign,加密算法为SHA256。

步骤

1、抓包,分析加密参数
2、模拟登录,还原sig参数算法,获取token值
3、传入token,还原sign参数算法,采集网站数据

随便输入账号和密码抓包

在这里插入图片描述
可发现加密参数pwd和sig,pwd通过名字可知是密码通过加密算法得出的密文,t是时间戳。pwd和sig是32位的字符串,先盲猜是MD5算法加密

pwd算法还原

在这里插入图片描述
通过请求调用栈堆,我们进入handleLogin。进入源代码后在上方我们可以看到pwd的加密函数为Object(S[“a”])(t.loginForm.password)。

在这里插入图片描述

下断点调试

在这里插入图片描述
t.loginForm.password就是我们输入的密码
加密函数生成的字符串为32位,先盲猜是标准的MD5算法,通过更换‘1’,得到密文’c4ca4238a0b923820dcc509a6f75849b’。可知该函数为标准的MD5加密算法。
接下来用python模拟生成

def get_pwd(password):
    md5 = hashlib.md5()
    md5.update(password.encode('utf-8'))
    pwd = md5.hexdigest()
    return pwd

sig参数分析
通过全局搜索‘sign:’,我们可以看到这块代码就是定义sig参数的

在这里插入图片描述

sig = l = Object(g[“a”])(P(S(e)))

通过调试
在这里插入图片描述
S(e) = 我们需要传入的参数
(P(S(e))) = 将我们的参数进行拼接和转为字符串并且在最后加入了‘JzyqgcoojMiQNuQoTlbR5EBT8TsqzJ’一个固定参数,我们可以拆开这样看:

180294454321
f3c5fce4ca420c753fc9c6a7c46cccc
1674093990981
1
JzyqgcoojMiQNuQoTlbR5EBT8TsqzJ

Object(g[“a”])()也是一个标准的MD5加密算法

通过以上信息我们就可以在python进行还原:

class HRDJ_Spieder:
    def __init__(self):
        self.t = str(round(time.time() * 1000))
        self.phoneNum = "12345678901"
        self.password = '123123'

    def md5(self, n):
        """定义一个MD5加密函数"""
        md5 = hashlib.md5()
        md5.update(n.encode('utf-8'))
        result = md5.hexdigest()
        return result

    def get_pwd(self):
        """:return pwd"""
        pwd = self.md5(self.password)
        return pwd

    def get_sig(self):
        """:return sig"""
        p = self.phoneNum + self.get_pwd() + self.t + '1' + 'JzyqgcoojMiQNuQoTlbR5EBT8TsqzJ'
        sig = self.md5(p)
        return sig

    def login(self):
        """:return token"""
        url = 'https://user.hrdjyun.com/wechat/phonePwdLogin'
        data = {
            "phoneNum": self.phoneNum,
            "pwd": self.get_pwd(),
            'sig': self.get_sig(),
            "t": self.t,
            "tenant": "1"
        }
        data = json.dumps(data)
        headers = {
            "Content-Type": "application/json",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
        }
        resp = requests.post(url, data=data, headers=headers)
        if resp.json()['status'] == 0:
            print('登录成功!')
            return resp.json()['data']['token']
        else:
            print('登录失败!')

if __name__ == '__main__':
    hs = HRDJ_Spieder()
    hs.login()

数据接口抓包分析
在这里插入图片描述

登录后,我们以历史商品带货榜为接口去抓包分析

在这里插入图片描述
token我们已经获取了,param是我们的查询参数,因此需要还原sign参数就可以了

sign参数还原
通过全局搜索’sign:‘,可定位到以下代码
在这里插入图片描述
sign由E(n, e)生成,方法代码就在断点的上方
E返回k(“param=” + JSON.stringify(n) + “&timestamp=” + e + “&tenant=1&salt=” + C)
在这里插入图片描述

C是一段固定字符串"kbn%&)@<?FGkfs8sdf4Vg1*+;`kf5ndl$"
k方法是一个加密算法,生成64位字符,通过更换加密内容,可得知是标准SHA256加密算法
e是时间戳
n是查询参数param

完整代码

import hashlib
import json
import time
import requests


class HRDJ_Spieder:
    def __init__(self):
        self.t = str(round(time.time() * 1000))
        self.phoneNum = "账号"
        self.password = '密码'

    def md5(self, n):
        """定义一个MD5加密函数"""
        md5 = hashlib.md5()
        md5.update(n.encode('utf-8'))
        result = md5.hexdigest()
        return result

    def get_pwd(self):
        """:return pwd"""
        pwd = self.md5(self.password)
        return pwd

    def get_sig(self):
        """:return sig"""
        p = self.phoneNum + self.get_pwd() + self.t + '1' + 'JzyqgcoojMiQNuQoTlbR5EBT8TsqzJ'
        sig = self.md5(p)
        return sig

    def login(self):
        """:return token"""
        url = 'https://user.hrdjyun.com/wechat/phonePwdLogin'
        data = {
            "phoneNum": self.phoneNum,
            "pwd": self.get_pwd(),
            'sig': self.get_sig(),
            "t": self.t,
            "tenant": "1"
        }
        data = json.dumps(data)
        headers = {
            "Content-Type": "application/json",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
        }
        resp = requests.post(url, data=data, headers=headers)
        if resp.json()['status'] == 0:
            print('登录成功!')
            return resp.json()['data']['token']
        else:
            print('登录失败:', resp.json()['message'])

    def SHA256(self, n):
        sha256 = hashlib.sha256()
        sha256.update(n.encode('utf-8'))
        result = sha256.hexdigest()
        return result

    def get_data(self, token):
        url = 'https://ucp.hrdjyun.com:60359/api/dy'
        headers = {
            "Content-Type": "application/json;charset=UTF-8",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
        }
        self.t = str(round(time.time() * 1000))

        data = {
            'param': '{\"no\":\"dy0009\",\"data\":{\"days\":1,\"type\":1,\"dyCatName\":\"\",\"categoryName\":\"\",\"startDay\":\"2023-01-18\"}}',
            'sign': '',
            'tenant': '1',
            'timestamp': self.t,
            'token': token
        }
        p = 'param={\"no\":\"dy0009\",\"data\":{\"days\":1,\"type\":1,\"dyCatName\":\"\",\"categoryName\":\"\",\"startDay\":\"2023-01-18\"}}&timestamp=' + self.t + '&tenant=1&salt=' + 'kbn%&)@<?FGkfs8sdf4Vg1*+;`kf5ndl$'
        sign = self.SHA256(p)
        data['sign'] = sign
        data = json.dumps(data)
        resp = requests.post(url=url, headers=headers, data=data)
        print(resp.json())


if __name__ == '__main__':
    hs = HRDJ_Spieder()
    token = hs.login()
    hs.get_data(token)

网站有个坑,请求提交的表单定义了是json格式,因此我们需要把data转为json才能发送请求,否则会报错

最后

欢迎联系作者交流更多

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值