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

文章目录

  • 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的数据,如下所示:

在这里插入图片描述

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

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

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

【操作系统期末速成】 EP04 | 学习笔记(基于五道口一只鸭)

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、正文&#xff1a;☀️☀️☀️2.1 考点七&#xff1a;进程通信2.2 考点八&#xff1a;线程的概念2.3 考点九&#xff1a;处理机调度的概念及原则2.4 考点十&#xff1a;调度方式与调度算法 一、前言&#x1f680;…

DM 的断点续传测试

作者&#xff1a; 大鱼海棠 原文来源&#xff1a; https://tidb.net/blog/4540ae34 一、概述 DM有all、full、incremental三种数据迁移同步方式&#xff08;task-mode&#xff09;&#xff0c;在all同步模式下&#xff0c;因一些特殊情况&#xff0c;需要变更上游MySQL的数…

【解释】i.MX6ULL_IO_电气属性说明

【解释】i.MX6ULL_IO_电气属性说明 文章目录 1 Hyst1.1 迟滞&#xff08;Hysteresis&#xff09;是什么&#xff1f;1.2 GPIO的Hyst. Enable Field 参数1.3 应用场景 2 Pull / Keep Select Field2.1 PUE_0_Keeper — Keeper2.2 PUE_1_Pull — Pull2.3 选择Keeper还是Pull 3 Dr…

Coursera耶鲁大学金融课程:Financial Markets 笔记Week 03

Financial Markets 本文是学习 https://www.coursera.org/learn/financial-markets-global这门课的学习笔记 这门课的老师是耶鲁大学的Robert Shiller https://en.wikipedia.org/wiki/Robert_J._Shiller Robert James Shiller (born March 29, 1946)[4] is an American econom…

Analyze an ORA-12801分析并行 parallel 12801 实际原因

"ORA-06512: at "PKG_P_DATA", line 19639 ORA-06512: at "PKG_P_DATA", line 19595 ORA-06512: at "PKG_P_DATA", line 14471-JOB 调用 -ORA-12801: error signaled in parallel query server P009, instance rac2:dwh2 (2) Error: ORA-12…

Python实现无头浏览器采集应用的反爬虫与反检测功能解析与应对策略

Python实现无头浏览器采集应用的反爬虫与反检测功能解析与应对策略 随着网络数据的快速增长&#xff0c;爬虫技术在数据采集、信息分析和业务发展中扮演着重要的角色。然而&#xff0c;随之而来的反爬虫技术也在不断升级&#xff0c;给爬虫应用的开发和维护带来了挑战。为了应…

Linux多进程和多线程(三)进程间通讯-信号处理方式和自定义处理函数

进程间通信之信号 信号信号的种类 信号在操作系统中的定义如下: 信号的处理流程在 Linux 中对信号的处理⽅式 自定义信号处理函数 信号的发送 kill() 函数:raise() 函数: 示例 : 创建⼀个⼦进程&#xff0c;⼦进程通过信号暂停&#xff0c;⽗进程发送 终⽌信号等待信号 pause()…

【嵌入式Linux】<总览> 多线程(更新中)

文章目录 前言 一、多线程 1. 概述 2. 创建线程 3. 线程退出 4. 线程回收 5. 线程分离 6. 线程取消 7. 线程的ID比较 二、线程同步 前言 记录学习多线程的知识重点与难点&#xff0c;若涉及版权问题请联系本人删除&#xff01; 一、多线程 1. 概述 线程是轻量级的…

期末考试后班主任如何发布学生成绩?

期末考试成绩一出&#xff0c;家长们便急切地想要了解孩子的学习情况。以往&#xff0c;老师们需要一个个私信家长&#xff0c;将成绩单发送出去&#xff0c;这项工作既繁琐又耗时。期末之际&#xff0c;老师们的工作本就繁重&#xff0c;如何有效减轻他们的负担&#xff0c;让…

构建现代医疗:互联网医院系统源码与电子处方小程序开发教学

本篇文章&#xff0c;笔者将探讨互联网医院系统的源码结构和电子处方小程序的开发&#xff0c;帮助读者更好地理解和掌握这些前沿技术。 一、互联网医院系统源码结构 互联网医院系统通常由多个模块组成&#xff0c;每个模块负责不同的功能。以下是一个典型的互联网医院系统的主…

【云原生】Prometheus 使用详解

目录 一、前言 二、服务监控概述 2.1 什么是微服务监控 2.2 微服务监控指标 2.3 微服务监控工具 三、Prometheus概述 3.1 Prometheus是什么 3.2 Prometheus 特点 3.3 Prometheus 架构图 3.3.1 Prometheus核心组件 3.3.2 Prometheus 工作流程 3.4 Prometheus 应用场景…

Linux 进程信号篇

文章目录 1. 生活中的信号2. 信号的概念3. 信号的产生3.1 系统调用3.2 软件条件3.2 异常3.3 Core和Term的区别 4. 信号的保存5. 信号的处理5.1 地址空间的进一步理解5.2 键盘输入数据的过程5.3 理解OS如何正常运行5.3.1 OS如何运行5.3.2 如何理解系统调用 5.4 内核态和用户态 6…

容器技术-docker4

一、docker资源限制 在使用 docker 运行容器时&#xff0c;一台主机上可能会运行几百个容器&#xff0c;这些容器虽然互相隔离&#xff0c;但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制&#xff0c;那么容器之间会互相影响&#xff0c;小的来说…

容器技术-docker2

容器化技术Docker Docker介绍 官网&#xff1a; docker.io docker.com 公司名称&#xff1a;原名dotCloud 14年改名为docker 容器产品&#xff1a;docker 16年已经被更名为Moby docker-hub docker.io docker容器历史 和虚拟机一样&#xff0c;容器技术也是一种资源隔…

为什么前端传了token,后端一直获取不到?一直报跨域错误?

这是我的前端代码 这是我的后端拦截器 那就需要了解一下 预检请求 对于非简单请求&#xff08;如PUT、DELETE或包含自定义HTTP头的请求&#xff09;&#xff0c;浏览器会先发送一个OPTIONS请求到目标服务器&#xff0c;询问是否允许该跨域请求。这个过程称为预检请求。 当opt…

(超详细)数据结构——“栈”的深度解析

前言&#xff1a; 在前几章我们介绍了线性表的基本概念&#xff0c;也讲解了包括顺序表&#xff0c;单链表&#xff0c;双向链表等线性表&#xff0c;相信大家已经对线性表比较熟悉了&#xff0c;今天我们要实现线性表的另一种结构——栈。 1.栈的概念 栈&#xff1a;一种特殊…

熊猫烧香是什么?

熊猫烧香&#xff08;Worm.WhBoy.cw&#xff09;是一种由李俊制作的电脑病毒&#xff0c;于2006年底至2007年初在互联网上大规模爆发。这个病毒因其感染后的系统可执行文件图标会变成熊猫举着三根香的模样而得名。熊猫烧香病毒具有自动传播、自动感染硬盘的能力&#xff0c;以及…

动手学深度学习(Pytorch版)代码实践 -计算机视觉-39实战Kaggle比赛:狗的品种识别(ImageNet Dogs)

39实战Kaggle比赛&#xff1a;狗的品种识别&#xff08;ImageNet Dogs&#xff09; 比赛链接&#xff1a;Dog Breed Identification | Kaggle 1.导入包 import torch from torch import nn import collections import math import os import shutil import torchvision from…

x-file-storage一行代码进行文件上传,摆脱阿里云,腾讯云,华为云等不同云的学习,简单高效

问题&#xff1a; 不使用x-file-storage时如果使用某个云首先需要学习他的sdk,这样很麻烦&#xff0c;而x-file-storage集成了各种云的上传&#xff0c;只需要进行配置即可一行代码进行上传 使用 官方地址&#xff1a;X File Storage 一行代码将文件存储到本地、FTP、SFTP、…