x-api-eid-token参数分析与加密算法还原

news2024/10/7 4:22:26

文章目录

  • 1. 写在前面
  • 2. 接口分析
  • 3. 算法实现

【🏠作者主页】:吴秋霖
【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!
【🌟作者推荐】:对爬虫领域以及JS逆向分析感兴趣的朋友可以关注《爬虫JS逆向实战》《深耕爬虫领域》
未来作者会持续更新所用到、学到、看到的技术知识!包括但不限于:各类验证码突防、爬虫APP与JS逆向分析、RPA自动化、分布式爬虫、Python领域等相关文章

作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!

1. 写在前面

  x-api-eid-token这个参数它是一个风控值,部分接口是需要用到的,在某些场景下固定虽可用。但是在一定的次数后就会失效出现风控!所以动态去生成这个参数携带请求在一些场景下是必要的,token的值通过其他的接口请求服务端生成给的

在这里插入图片描述

2. 接口分析

jsTk.do的这个接口就是生成x-api-eid-token的关键接口。但是请求的时候同样需要两个加密参数,如下所示:

在这里插入图片描述

其中a参数如何实现的?它通过一个自定义的b64编码做字符映射,通过charAt方法根据计算的索引值选择对应的字符附加到结果上!

最后,算法将生成一个自定义的Base64编码字符串。并且在末尾,这里有点小细节(参数添加一个斜杠),可以自己看a参数

a参数的加密入参是一个JSON串,主要就是哈希了一个指纹、版本号、接口路径、还有一些固参

然后再来说说d参数,这个参数会稍微复杂一些!在介绍这个参数之前,这里提一个其他的例子,可能接触过的就会熟悉了!某平台的gid参数,这个应该大部分人做过的人都了解吧!它就是设备指纹信息相关的一堆参数加密生成的,那么这里的d其实也是一样的

我们要实现的主要算法,就是包括生成用户设备和浏览器环境的伪指纹,然后通过自定义的b64编码方法对这些信息进行编码

这里的设备及浏览器信息包括的东西会比较多,比如某型号、渲染器信息、Canvas/WebGL指纹、插件信息、屏幕信息、时间信息…等等

总结:两个参数加密入参对象不一样,一个复杂一个简单!密文算法最终的实现都一样

3. 算法实现

接下来,说一下两个参数的算法实现与源码讲解!首先是a参数的算法实现代码,如下所示:

function customBase64Encode(input) {
    input = JSON.stringify(input);
    input = encodeURIComponent(input);
    const base64Chars = "23IL<N01c7KvwZO56RSTAfghiFyzWJqVabGH4PQdopUrsCuX*xeBjkltDEmn89.-";
    let encoded = "";
    let i = 0;

    while (i < input.length) {
        const char1 = input.charCodeAt(i++);
        const char2 = input.charCodeAt(i++);
        const char3 = input.charCodeAt(i++);
        
        const enc1 = char1 >> 2;
        const enc2 = ((char1 & 3) << 4) | (char2 >> 4);
        const enc3 = ((char2 & 15) << 2) | (char3 >> 6);
        const enc4 = char3 & 63;

        if (isNaN(char2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(char3)) {
            enc4 = 64;
        }

        encoded += base64Chars.charAt(enc1) + base64Chars.charAt(enc2) + base64Chars.charAt(enc3) + base64Chars.charAt(enc4);
    }

    return encoded + "/";
}

function generateEncryptedKey() {
    const keyPair = KEYUTIL.generateKeypair("EC", "secp256r1");
    const privateKeyObj = keyPair.prvKeyObj;
    const publicKeyObj = keyPair.pubKeyObj;
    
    const publicKeyPEM = KEYUTIL.getPEM(publicKeyObj);
    const privateKeyPEM = KEYUTIL.getPEM(privateKeyObj, "PKCS8PRV");

    return [publicKeyPEM, privateKeyPEM];
}

const keyPair = generateEncryptedKey();
console.log(keyPair);
console.log(customBase64Encode(keyPair[1]));

上面a参数的算法函数实现的主要功能如下:

对象序列化为JSON串,进行URI编码
用自定义的b64编码表将编码后的字符串转换为自定义的Base64字符串
最终返回这个自定义编码字符串,并在末尾附加一个斜杠

接下来说一说d参数的算法实现,这里作者实现了一个随机生成CSS的属性伪造环境算法,目的就是增加设备指纹的一个复杂性,实现算法如下:

function generateCSSAttributes() {
    const predefinedColors = [
        "rgb(240, 240, 240)", "rgb(109, 109, 109)", "rgb(192, 192, 192)", 
        "rgb(204, 204, 204)", "rgb(102, 102, 102)", "rgb(247, 247, 247)", 
        "rgb(127, 127, 127)", "rgb(99, 99, 206)", "rgb(221, 221, 221)", 
        "rgb(136, 136, 136)", "rgb(107, 107, 107)", "rgb(128, 128, 0)", 
        "rgb(105, 105, 105)", "rgb(255, 140, 0)", "rgb(112, 128, 144)"
    ];
    const basicColors = ["rgb(0, 0, 0)", "rgb(255, 255, 255)"];
    const cssProperties = [
        "ActiveBorder", "ActiveCaption", "AppWorkspace", "Background", 
        "ButtonFace", "ButtonHighlight", "ButtonShadow", "ButtonText", 
        "CaptionText", "GrayText", "Highlight", "HighlightText", 
        "InactiveBorder", "InactiveCaption", "InactiveCaptionText", 
        "InfoBackground", "InfoText", "Menu", "MenuText", "Scrollbar", 
        "ThreeDDarkShadow", "ThreeDFace", "ThreeDHighlight", 
        "ThreeDLightShadow", "ThreeDShadow", "Window", "WindowFrame", 
        "WindowText"
    ];

    const cssAttributes = {};

    cssProperties.forEach(property => {
        const randomIndex = Math.floor(Math.random() * 30);
        if (randomIndex <= 14) {
            cssAttributes[property] = predefinedColors[randomIndex];
        } else {
            cssAttributes[property] = basicColors[Math.floor(Math.random() * 2)];
        }
    });

    return cssAttributes;
}

看代码我们可以看到主要就是预设了多种这个RGB的颜色,这个算法的话不难,我们知道大致的思路就可以。因为开源的也很多可以参考~

下面说说随机指纹的部分,主要就是浏览器跟设备构造的一些信息进行加密。通过哈希的计算对什么Canvas/WebGL的指纹信息进行加密,这里作者放出核心的finger思路,然后Demo实现如下所示:

// 生成一个随机的 UUID 作为指纹信息
function generateUUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

// 生成随机的屏幕信息
function generateScreenInfo() {
    var resolutions = [
        { width: 2160, height: 3840 },
        { width: 1440, height: 2560 },
        { width: 1080, height: 1920 },
        { width: 900, height: 1600 },
        { width: 2160, height: 4096 }
    ];

    var randomIndex = Math.floor(Math.random() * resolutions.length);
    var screen = resolutions[randomIndex];

    return {
        width: screen.width,
        height: screen.height,
        availableHeight: screen.height - 50 // 假设减去了一定高度
    };
}

// 创建一个包含指纹信息和屏幕信息的对象
var deviceInfo = {
    fingerprint: generateUUID(),
    screen: generateScreenInfo()
};

// 输出设备信息
console.log("Device Information:", deviceInfo);

核心就是随机字符去计算哈希,也就是Canvas的指纹信息!然后WebGL同样的操作。把浏览器设备的信息构造出来即可

最后,我们来看一下最终的算法效果,运行JS得到加密参数a、d的值,如下所示:

在这里插入图片描述

拿到请求参数的加密值后,就可以开始去构造请求接口的Python代码,把整个流程给串起来!比如说我们要拿价格或者商品详情的数据进行分析,那么不去处理xx-x-eid-token
的这个风控参数,在一段时间跟次数后就会出现问题

作者编写了一下Python的调用算法与爬虫的Demo,实现代码如下所示(小细节,tls检测过一下,用第三方的模块~~):

import time
import json
import execjs
from loguru import logger
from curl_cffi import requests

def get_token(ua):
    with open("get_api_eid_token.js", encoding='utf-8') as f:
        ctx = execjs.compile(f.read())
    res = ctx.call("getTokenParam",ua) 
    return res
    
def get_h5st(params, aid, ua):
    with open("h5st_4.7.3.js", encoding='utf-8') as f:
        ctx = execjs.compile(f.read())
    res = ctx.call("web_h5st", params, aid, ua) 
    return res

headers = {} # 自行获取
cookies = {} # 自行获取

# 你懂的~
token_api = 'https://gia.jd.com/jsTk.do?a={}'
res = json.loads(get_token(headers['user-agent']))
payload = "d={}".format(res["d"])
response = requests.post(token_api.format(res['a']), headers=headers, cookies=cookies, data=payload).json()
logger.info(f'x-api-eid-token接口请求: {response}')

好,测试运行一下上面的Python代码,先尝试获取xx-x-eid-token的数据,如下所示:

在这里插入图片描述

解决完这个风控参数,在某些场景下配合提交到请求参数中去动态的使用,效果会更加稳定!最终测试结果如下所示:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1879541.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面试框架一些小结

springcloud的⼯作原理 springcloud由以下⼏个核⼼组件构成&#xff1a; Eureka&#xff1a;各个服务启动时&#xff0c;Eureka Client都会将服务注册到Eureka Server&#xff0c;并且Eureka Client还可以反过来从Eureka Server拉取注册表&#xff0c; 从⽽知道其他服务在哪⾥ …

【嵌入式DIY实例】-LCD ST7735显示网络时间

LCD ST7735显示网络时间 文章目录 LCD ST7735显示网络时间1、硬件准备2、代码实现本文将介绍如何使用 ESP8266 NodeMCU Wi-Fi 板实现互联网时钟,其中时间和日期显示在 ST7735 TFT 显示屏上。 ST7735 TFT是一款分辨率为128160像素的彩色显示屏,采用SPI协议与主控设备通信。 1…

管理上的一些思考

1 前言 管理可分为自我管理、平级管理、向下管理和向上管理。 顾名思义&#xff0c;自我管理就是对自己工作、生活等各方面的规划和执行&#xff0c;不涉及与其他人互动、配合等。我们设定人生目标、年度计划、月计划等&#xff0c;都可以认为是自我管理。《增广贤文》有段很…

数据结构与算法笔记:实战篇 - 剖析Redis常用数据类型对应的数据结构

概述 从本章开始&#xff0c;就进入实战篇的部分。这部分主要通过一些开源醒目、经典系统&#xff0c;真枪实弹地教你&#xff0c;如何将数据结构和算法应用到项目中。所以这部分的内容&#xff0c;更多的是知识点的回顾&#xff0c;相对于基础篇和高级篇&#xff0c;其实这部…

找不到mfc100.dll文件怎么办?推荐这7个解决方法快速解决mfc100.dll丢失问题

使用电脑中&#xff0c;会遇到各种各样的问题&#xff0c;比如找不到mfc100.dll&#xff0c;或mfc100.dll丢失导致软件程序无法继续运行&#xff0c;就是日常中比较常见的问题之一&#xff0c;今天我教大家遇到这个mfc100.dll丢失问题时候&#xff0c;要怎么解决&#xff0c;以…

多见线程方法

多见线程方法 本节的类代码可以查看上一节的类代码 线程暂停 Thread.sleep(1000);//暂停1000毫秒这就有点像在时间里面学习的*sleep()*函数了 package multiThread2;public class main {public static void main(String[] args) {Animal a1 new Animal("张三",1…

Springboot 整合 DolphinScheduler(一):初识海豚调度

目录 一、什么是 DolphinScheduler 二、DolphinScheduler 的特性 三、DolphinScheduler 核心架构 四、单机环境部署流程 1、下载安装包 2、上传至服务器&#xff0c;解压缩 3、单机启动 4、登录 dolphinscheduler UI 5、配置数据库【非必需】 &#xff08;1&#xff…

timm中模型更换huggingface模型链接

现在timm默认使用huggingface的链接了&#xff0c;错误链接如下&#xff1a; (MaxRetryError("HTTPSConnectionPool(hosthuggingface.co, port443): Max retries exceeded with url: /timm/swinv2_tiny_window8_256.ms_in1k/resolve/main/model.safetensors (Caused by C…

Docker Compose 入门

想象一下在服务器上运行静态页面的场景。对于这项任务&#xff0c;NGINX 服务器是一个不错的选择。我们在 static-site/index.html 路径下有一个简单的 HTML 文件&#xff1a; 通过使用 Docker&#xff0c;我们将使用以下官方镜像运行 NGINX 服务器 docker run --rm -p 8080:…

C++ 之插件机制初试

C 之插件机制 C 插件架构允许一个应用程序以动态链接库&#xff08;DLLs 在 Windows&#xff0c;或 .so 在 Unix-like 系统&#xff09;的形式加载和使用插件。以下是构建 C 插件架构的一般步骤和考虑因素&#xff1a; 定义插件接口 首先&#xff0c;定义一个插件接口&#…

R包的4种安装方式及常见问题解决方法

R包的4种安装方式及常见问题解决方法 R包的四种安装方式1. install.packages()2. 从Bioconductor安装3. 从本地源码安装4. 从github安装 常见问题的解决1. 版本问题2. 网络/镜像问题3.缺少Rtools R包的四种安装方式 1. install.packages() 对于R自带的包的安装一般都可以通过…

LeetCode热题100刷题2:283. 移动零、11. 盛最多水的容器、15. 三数之和、42. 接雨水

283. 移动零 挺简单的没啥说的 class Solution { public:void moveZeroes(vector<int>& nums) {//快慢指针 // 快指针负责往前遍历&#xff0c;慢指针记录快指针遍历过的把0撵走的最后一个元素的位置// 然后快指针遍历完之后&#xff0c;慢指针到结尾直接赋0就行in…

Python逻辑控制语句 之 判断语句--if语句的基本结构

1.程序执行的三大流程 顺序 分支&#xff08;判断&#xff09; 循环 2.if 语句的介绍 单独的 if 语句,就是 “如果 条件成⽴,做什么事” 3.if 语句的语法 if 判断条件: 判断条件成立&#xff0c;执行的代码…

PyCharm 2024.1 版本更新亮点:智能编程,高效协作

目录 1. 前言2. 更新内容2.1 智能编码体验2.1.1 Hugging Face 文档预览2.1.2 全行代码补全 2.2 提升编辑器体验2.2.1 粘性行功能2.2.2 编辑器内代码审查 2.3 全新终端体验&#xff08;测试版&#xff09;2.3.1 新终端 Beta 2.4 智能助手&#xff08;特定版本和专业用户&#xf…

操作符详解(下) (C语言)

操作符详解下 操作符的属性1.优先级2.结合级 表达式求值1.整型提升2.如何进行整形提升呢&#xff1f;3.算术转换4.问题表达式解析 操作符的属性 C语言的操作符有2个重要的属性&#xff1a;优先级、结合性&#xff0c;这两个属性决定了表达式求值的计算顺序。 1.优先级 优先级…

MSPM0G3507——定时器例程讲解4——timx_timer_mode_periodic

以下示例以周期模式配置TimerG并切换LED。周期从500ms开始&#xff0c;每次切换减少50ms&#xff0c;直到周期为100ms&#xff0c;然后重复。设备在等待中断时保持待机模式 #include "ti_msp_dl_config.h"/* ((32KHz / (321)) * 0.5s) 45 - 1 495 due to N1 ticks …

时间复杂度计算

要求算法的时间复杂度时&#xff0c;我们可以分析给定表达式 的阶。让我们来逐步分析&#xff1a; 分析阶的定义&#xff1a; 当我们说一个表达式的时间复杂度是 ( O(g(n)) )&#xff0c;我们指的是当 ( n ) 趋近无穷大时&#xff0c;表达式的增长率与 ( g(n) ) 的增长率相似。…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验11 IP数据报的发送和转发流程

一、实验目的 1.观察IP数据报的发送和转发流程&#xff1b; 二、实验要求 1.使用Cisco Packet Tracer仿真平台&#xff1b; 2.观看B站湖科大教书匠仿真实验视频&#xff0c;完成对应实验。 三、实验内容 1.构建网络拓扑&#xff1b; 2.观察主机发送IP数据报的过程 3.观察路…

pytest-命令行参数

命令行参数 使用 Pytest 执行用例时&#xff0c;我们经常都是通过命令行来执行的&#xff0c;有同学要说了&#xff0c;我一般是通过编辑器里面直接就执行了&#xff1b;在实际项目中编写用例调试用例&#xff0c;使用编辑器执行用例没问题&#xff0c;但在 CI 集成环境下&…

中霖教育:二级建造师能同时报名参加多个省份的考试吗?

【中霖教育口碑】【中霖教育好吗】 二级建造师考试能同时报名参加多个省份吗?原则上是可以的。 二级建造师的报名过程需满足各省份设定的特定标准&#xff0c;申请者需提供相应省份注册的工程建设企业的工作年限证明&#xff0c;并在报名表上加盖章以证明企业身份。 部分省…