首页 > 其他分享 >js逆向实战之烯牛数据请求参数加密和返回数据解密

js逆向实战之烯牛数据请求参数加密和返回数据解密

时间:2024-09-22 15:16:16浏览次数:1  
标签:return 之烯 解密 js sig var data payload

声明:本篇文章仅用于知识分享

实战网址:https://www.xiniudata.com/industry/newest?from=data

请求参数加密

  1. 访问网址,往下翻翻,可以看到触发了如下的数据包,请求参数进行了加密。
    image
  2. 全局搜索list_industries_by_sort地址,有四处,都位于同一个文件中。
    image
    随便点一个看看,可以看到有payload关键字。
    image
    打断点,刷新界面触发断点,一步一步往下调试,可以看到payload传给了j.a.fetch()函数。
    image
  3. 定位j.a.fetch()函数。
    image
    打断点,跳转进来。可以看到明显给payloadsig赋值的语句。
    image
    最关键的就是如下这行代码。
var f = Object(u.c)(Object(u.d)(JSON.stringify(s.payload))), p = Object(u.e)(f);

涉及到一个变量和三个函数,一个一个看。
(1)变量s.payload:直接输出看即可。
image
(2)函数Object(u.c):控制台输出,定位。
image
(3)函数Object(u.d):控制台输出,定位。
image
(4)函数Object(u.e):控制台输出,定位。
image
上面三个函数的代码可以不用看,直接调用js代码就可以了。
4. 目前的js代码如下。

s = {
    "payload": {
        "sort": 1,
        "start": 20,
        "limit": 20
    }
}

function e1(e) {
    if (null == e)
        return null;
    for (var t, n, r, o, i, a, u, c = "", l = 0; l < e.length;)
        o = (t = e.charCodeAt(l++)) >> 2,
            i = (3 & t) << 4 | (n = e.charCodeAt(l++)) >> 4,
            a = (15 & n) << 2 | (r = e.charCodeAt(l++)) >> 6,
            u = 63 & r,
            isNaN(n) ? a = u = 64 : isNaN(r) && (u = 64),
            c = c + _keyStr.charAt(o) + _keyStr.charAt(i) + _keyStr.charAt(a) + _keyStr.charAt(u);
    return c
}

function e2(e) {
    if (null == (e = _u_e(e)))
        return null;
    for (var t = "", n = 0; n < e.length; n++) {
        var r = _p.charCodeAt(n % _p.length);
        t += String.fromCharCode(e.charCodeAt(n) ^ r)
    }
    return t
}

function sig(e) {
    return md5(e + _p).toUpperCase()
}

var f = e1(e2(JSON.stringify(s.payload)))
    , p = sig(f);

console.log(f);
console.log(p);

运行提示_u_e is not defined,去找一下补到代码中。
image
运行提示_p is not defined,去找_p
image
运行提示md5 is not defined,这里需要导入crypto-js库,可以通过npm install crypto-js命令下载。

const CryptoJS = require("crypto-js");

function sig(e) {
    return CryptoJS.MD5(e + _p).toUpperCase()
}

运行提示CryptoJS.MD5(...).toUpperCase is not a function,是因为在转换为大写之前需要先用toString函数转为字符串。
完整代码如下:

// query_parameter_encrypt.js

const CryptoJS = require("crypto-js");

s = {
    "payload": {
        "sort": 1,
        "start": 0,
        "limit": 20
    }
}

function _u_e(e) {
    if (null == e)
        return null;
    e = e.replace(/\r\n/g, "\n");
    for (var t = "", n = 0; n < e.length; n++) {
        var r = e.charCodeAt(n);
        r < 128 ? t += String.fromCharCode(r) : r > 127 && r < 2048 ? (t += String.fromCharCode(r >> 6 | 192),
            t += String.fromCharCode(63 & r | 128)) : (t += String.fromCharCode(r >> 12 | 224),
            t += String.fromCharCode(r >> 6 & 63 | 128),
            t += String.fromCharCode(63 & r | 128))
    }
    return t
}

var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
    , _p = "W5D80NFZHAYB8EUI2T649RT2MNRMVE2O";

function e1(e) {
    if (null == e)
        return null;
    for (var t, n, r, o, i, a, u, c = "", l = 0; l < e.length;)
        o = (t = e.charCodeAt(l++)) >> 2,
            i = (3 & t) << 4 | (n = e.charCodeAt(l++)) >> 4,
            a = (15 & n) << 2 | (r = e.charCodeAt(l++)) >> 6,
            u = 63 & r,
            isNaN(n) ? a = u = 64 : isNaN(r) && (u = 64),
            c = c + _keyStr.charAt(o) + _keyStr.charAt(i) + _keyStr.charAt(a) + _keyStr.charAt(u);
    return c
}

function e2(e) {
    if (null == (e = _u_e(e)))
        return null;
    for (var t = "", n = 0; n < e.length; n++) {
        var r = _p.charCodeAt(n % _p.length);
        t += String.fromCharCode(e.charCodeAt(n) ^ r)
    }
    return t
}

function sig(e) {
    return CryptoJS.MD5(e + _p).toString().toUpperCase();
}

function generate(s) {
    var payload = e1(e2(JSON.stringify(s.payload))), sign = sig(payload);
    return [payload, sign];
}

console.log(generate(s));

运行结果如下。
image
成功,接下来就是编写python代码获取数据了。

import requests
import json
import execjs


url = "https://www.xiniudata.com/api2/service/x_service/person_industry_list/list_industries_by_sort"

# 这里面最重要的就是content-type参数,否则获取不到数据
headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                         "Chrome/129.0.0.0 Safari/537.36",
           # "cookie": "btoken=82SLKQK1ESJ7A9NZ1C3ZAKREOC0I3AAC",
           # "referer": "https://www.xiniudata.com/industry/newest?from=data",
           # "origin": "https://www.xiniudata.com",
           "content-type": "application/json"}

# 生成payload和sig
s = {
    "payload": {
        "sort": 1,
        "start": 0,
        "limit": 20
    }
}

file = open("query_parameter_encrypt.js", mode="r")
exec_code = file.read()
exec_js = execjs.compile(exec_code)
payload, sig = exec_js.call("generate", s)
data = {
    "payload": payload,
    "sig": sig,
    "v": 1
}

# 注意需要转换为json数据传输
resp = requests.post(url, headers=headers, data=json.dumps(data))
print(json.loads(resp.text))

运行结果如下。
image

返回数据解密

  1. 一般来说对于返回数据的解密,常规操作是搜索interceptors,但是很可惜不适用于该网站。那就得想其他的办法。
    image
  2. 我们知道该数据包采用的是JSON格式数据,解密出来后肯定需要进行JSON解析,所以可以搜索JSON.parse关键字。
    image
    地方比较多,需要进行筛选。如果JSON.parse是该函数的第一行代码就铁定不是,因为是需要先解密再进行JSON解析的。点击几个,发现了一处跟加密逻辑很像的代码。(其实一般情况下加密逻辑和解密逻辑是写在一起的)
    image
  3. 打断点,一行一行调试。
    image
    可以看到s的值就是返回的数据,说明我们没找错地方。
    image
    y的值是明文了,所以解密逻辑肯定跟Object(u.a)Object(u.b)相关。
    找到这两个函数的定义。
    image
    image
  4. 接下来就跟加密逻辑一样了,把相关的js代码复制出来,把需要用到的变量和参数都补齐。
// response_data_decrypt.js

var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
              , _p = "W5D80NFZHAYB8EUI2T649RT2MNRMVE2O";

function d1(e) {
    var t, n, r, o, i, a, u = "", c = 0;
    for (e = e.replace(/[^A-Za-z0-9\+\/\=]/g, ""); c < e.length;)
        t = _keyStr.indexOf(e.charAt(c++)) << 2 | (o = _keyStr.indexOf(e.charAt(c++))) >> 4,
            n = (15 & o) << 4 | (i = _keyStr.indexOf(e.charAt(c++))) >> 2,
            r = (3 & i) << 6 | (a = _keyStr.indexOf(e.charAt(c++))),
            u += String.fromCharCode(t),
        64 != i && (u += String.fromCharCode(n)),
        64 != a && (u += String.fromCharCode(r));
    return u
}

function _u_d(e) {
    for (var t = "", n = 0, r = 0, o = 0, i = 0; n < e.length;)
        (r = e.charCodeAt(n)) < 128 ? (t += String.fromCharCode(r),
            n++) : r > 191 && r < 224 ? (o = e.charCodeAt(n + 1),
            t += String.fromCharCode((31 & r) << 6 | 63 & o),
            n += 2) : (o = e.charCodeAt(n + 1),
            i = e.charCodeAt(n + 2),
            t += String.fromCharCode((15 & r) << 12 | (63 & o) << 6 | 63 & i),
            n += 3);
    return t
}

function d2(e) {
    for (var t = "", n = 0; n < e.length; n++) {
        var r = _p.charCodeAt(n % _p.length);
        t += String.fromCharCode(e.charCodeAt(n) ^ r)
    }
    return t = _u_d(t)
}

function decrypt(e){
    return d2(d1(e));
}

e = '返回的加密数据';
//  console.log(decrypt(e));

运行结果如下。
image
成功。
5. 写python代码,将加密逻辑和解密逻辑进行融合。

from functools import partial
import subprocess

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

import requests
import json
import execjs

url = "https://www.xiniudata.com/api2/service/x_service/person_industry_list/list_industries_by_sort"

headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                         "Chrome/129.0.0.0 Safari/537.36", # "cookie": "btoken=82SLKQK1ESJ7A9NZ1C3ZAKREOC0I3AAC",
           # "referer": "https://www.xiniudata.com/industry/newest?from=data",
           # "origin": "https://www.xiniudata.com",
           "content-type": "application/json"}

# 生成payload和sig
s = {"payload": {"sort": 1, "start": 0, "limit": 20}}

file1 = open("query_parameter_encrypt.js", mode="r")
exec_code1 = file1.read()
exec_js1 = execjs.compile(exec_code1)
payload, sig = exec_js1.call("generate", s)
data = {"payload": payload, "sig": sig, "v": 1}

resp = requests.post(url, headers=headers, data=json.dumps(data))
# 得到返回的响应数据
response_data = json.loads(resp.text)['d']
# print(response_data)


# 调用解密逻辑
file2 = open("response_data_decrypt.js", mode="r")
exec_code2 = file2.read()
exec_js2 = execjs.compile(exec_code2)
ming_str = exec_js2.call('decrypt', response_data)
print(ming_str)

运行结果如下。
image
跟页面上显示的对应。
image
大功告成。

标签:return,之烯,解密,js,sig,var,data,payload
From: https://www.cnblogs.com/sbhglqy/p/18425125

相关文章

  • 初学者学node.js
    对于初学者来说,学习Node.js是一个很好的选择,因为它可以帮助你理解后端开发,并且由于其基于JavaScript,如果你已经有了一些前端开发的基础,那么学习曲线会相对平缓一些。以下是一些建议帮助你开始学习Node.js:1.**了解基础**:  -确保你已经熟悉了JavaScript的基本语法和概念。......
  • Go语言基础-常见编码(Json、Base64)
    编码jsonjson是go标准库里自带的序列化工具,使用了反射,效率比较低easyjson值针对预先定义好的json结构体对输入的json字符串进行纯字符串的截取,并将对应的json字段赋值给结构体easyjson-allxxx.go生成go文件中定义的结构体对应的解析xxx.go所在的package不能是mainfunce......
  • (免费送源码)Node.js网上购物商城 计算机毕业设计原创定制
    摘 要随着社会的发展,计算机的优势和普及使得网上购物商城的开发成为必需。网上购物商城主要是借助计算机,通过对首页、站点管理(轮播图、公告栏)用户管理(管理员、注册用户)内容管理(商城资讯、资讯分类)商城管理(商城中心、分类列表、订单列表)等信息进行管理。减少管理员的工作,......
  • 如何在Nextjs中添加RBAC授权
    基于角色的访问控制(rbac)是现代web应用程序中的一项重要功能,使管理员能够根据用户在系统中的角色来管理用户权限。在next.js应用程序中实现rbac涉及几个关键步骤:定义角色和权限、将其与身份验证集成以及在应用程序中实施访问控制。本指南将引导您完成向next.js应用程序......
  • 如何在Reactjs中制作动态进度条
    使用react和循环进度组件构建性能仪表板在本博客中,我们将探讨如何使用react构建性能指标仪表板。仪表板显示不同绩效指标(例如可访问性、seo和最佳实践)的循环进度指示器。进度指示器逐渐填满,模拟加载动画。该项目使用tailwindcss进行样式设计,并组合了多个组件来创建灵活且......
  • 如何解决 Nextjs 中的水合错误
    “水合失败,因为服务器渲染的html与客户端不匹配......”如果您一直使用next.js来构建应用程序,您一定遇到过上述错误或类似的错误。这称为水合错误。当我第一次开始使用next.js时,我曾经遇到过这个错误,但我不知道该怎么做,也从不去查找它,因为它当时并没有真正影响我的代码......
  • 水母搜索算法(JS)优化BP神经网络原理及Matlab代码
    目录0引言1数学模型2优化方式3Matlab代码3.1伪代码3.2 JS主函数代码3.2JS-BP4视频讲解0引言水母搜索算法(JellyfishSearch,JS)是由Jui-ShengChou在2020年基于水母搜索行为提出的群智能算法。该算法模拟水母搜索行为的包括它们的洋流跟随,它们在水母群中的运......
  • 水母搜索算法(JS)优化支持向量机原理及Matlab代码
    目录0引言1数学模型2优化方式3Matlab代码3.1伪代码3.2 JS主函数代码3.2JS-SVM4视频讲解0引言水母搜索算法(JellyfishSearch,JS)是由Jui-ShengChou在2020年基于水母搜索行为提出的群智能算法。该算法模拟水母搜索行为的包括它们的洋流跟随,它们在水母群中的运......
  • 水母搜索算法(JS)优化长短期记忆神经网络原理及Matlab代码
    目录0引言1数学模型2优化方式3Matlab代码3.1伪代码3.2 JS主函数代码3.2JS-LSTM4视频讲解0引言水母搜索算法(JellyfishSearch,JS)是由Jui-ShengChou在2020年基于水母搜索行为提出的群智能算法。该算法模拟水母搜索行为的包括它们的洋流跟随,它们在水母群中的......
  • 如何使用nodejs显示“Hello World”的教程
    安装Node.js打开浏览器:打开GoogleChrome或MicrosoftEdge。下载Node.js:访问Node.js网站。选择适合您的操作系统的最新版本,例如Windows64位。单击最新版本(例如版本2.46.0)下载安装程序。安装Node.js:下载完成后,打开安装程序文件。按照屏幕上显示的安装步骤进行操作。完......