百某应JS逆向

https://ying.baichuan-ai.com/

 

目录

一、发起提问

二、观察发现有两个加密参数:X-Bc-Sig和X-Bc-Ts

​三、观察JS调用栈

四、从JS中搜索 X-Bc-Sig和X-Bc-Ts

五、断点并分析参数的生成方式

六、分析入参

七、发现关键的o方法调用了一个i()方法

八、验证结果

九、python执行Node.JS获取参数(本地安装了Node环境)

十、python本地执行JS(本地未安装Node.js环境)

十一、实际应用


一、发起提问

二、观察发现有两个加密参数:X-Bc-Sig和X-Bc-Ts

 三、观察JS调用栈

四、从JS中搜索 X-Bc-Sig和X-Bc-Ts

发现只有_app-xxxxx.js文件中存在X-Bc-Sig

五、断点并分析参数的生成方式

六、分析入参

一个参数是固定字符串:"uwlACMuXQApWgO0Q"

一个参数是时间戳组成的动态字符串:"1721891456251retry=3&thread_info=[object Object]"

七、发现关键的o方法调用了一个i()方法

找了一圈没找到i()方法,无奈我只好在控制台打印一下,看看这个i()是什么样的

断点挺住,在去控制台打印一下

七、模拟生成

1、先将关键的o方法复制出来

2、模拟i()方法

3、 调用o方法和截取逻辑复制过来

4、构建参数

我们可以看到n是当前时间戳 n = Date.now()

r是混淆参数 undefined

a是由时间戳组成的固定字符串

 

八、验证结果

 九、python执行Node.JS获取参数(本地安装了Node环境)

import execjs# JavaScript代码
js_code = """
const CryptoJS = require("crypto-js");function i() {return CryptoJS
}function o(t, e) {let r = i().enc.Utf8.parse("0000000000000000");return i().AES.encrypt(t, i().enc.Utf8.parse(e), {iv: r,mode: i().mode.CBC,padding: i().pad.Pkcs7}).toString()
}//构建入参
const n = '1721892945291'
const r = undefined
const a = `${n.toString()}retry=3&thread_info=[object Object]`// 执行关键o函数
let s = o(a, r ? r.substring(0, 16) : "uwlACMuXQApWgO0Q");
// 截取逻辑
s.length > 64 && (s = s.substring(0, 64))
result = {"x-bc-sig": s,"x-bc-ts": n.toString()
}
return result
"""# 编译JavaScript代码
ctx = execjs.compile(js_code)# 执行JavaScript代码并获取结果
result = ctx.call("JSON.stringify")# 输出结果
print(result)

十、python本地执行JS(本地未安装Node.js环境)

将crypto-js下载到本地:

crypto-js.min.js

CRYPTO-JS.MIN.JS: DOWNLOAD - CDNPKG

 
encryption.js
//encryption.js//引入本地加密库
const CryptoJS = require('./crypto-js.min.js');function i() {return CryptoJS
}function o(t, e) {let r = i().enc.Utf8.parse("0000000000000000");return i().AES.encrypt(t, i().enc.Utf8.parse(e), {iv: r,mode: i().mode.CBC,padding: i().pad.Pkcs7}).toString()
}//构建入参
const n = '1721892945291'
const r = undefined
const a = `${n.toString()}retry=3&thread_info=[object Object]`// 执行关键o函数
let s = o(a, r ? r.substring(0, 16) : "uwlACMuXQApWgO0Q");
// 截取逻辑
return s.length > 64 && (s = s.substring(0, 64)),{"x-bc-sig": s,"x-bc-ts": n.toString()}
import execjs# 读取crypto-js库文件和你的JavaScript代码
with open('crypto-js.min.js', 'r', encoding='utf-8') as file:crypto_js_code = file.read()with open('encryption.js', 'r', encoding='utf-8') as file:script_code = file.read()# 整合JavaScript代码
js_code = crypto_js_code + "\n" + script_code# 编译JavaScript代码
ctx = execjs.compile(js_code)# 执行JavaScript代码并获取结果
result = ctx.call("JSON.stringify")# 输出结果
print(result)

十一、实际应用

发现runs接口的签名和delete接口的签名有所不同

runs直接对时间戳签名就可以

delete接口需要对时间戳和id进行双重签名

我只能写成两个function来供python调用

//引入本地加密库
const CryptoJS = require('./crypto-js.min.js');function i() {return CryptoJS
}function o(t, e) {let r = i().enc.Utf8.parse("0000000000000000");return i().AES.encrypt(t, i().enc.Utf8.parse(e), {iv: r,mode: i().mode.CBC,padding: i().pad.Pkcs7}).toString()
}function runs_sign() {//构建入参const n = Date.now()const r = undefinedconst a = `${n.toString()}retry=3&thread_info=[object Object]`// const a = `${n.toString()}id=6042075`// 执行关键o函数let s = o(a, r ? r.substring(0, 16) : "uwlACMuXQApWgO0Q");// 截取逻辑return s.length > 64 && (s = s.substring(0, 64)),{"x-bc-sig": s,"x-bc-ts": n.toString()}
}function delete_sign(id) {//构建入参const n = Date.now()const r = undefinedconst a = `${n.toString()}id=${id}`// 执行关键o函数let s = o(a, r ? r.substring(0, 16) : "uwlACMuXQApWgO0Q");// 截取逻辑return s.length > 64 && (s = s.substring(0, 64)),{"x-bc-sig": s,"x-bc-ts": n.toString()}
}

    def get_runs_sign_and_timestamp(self):"""获取访问签名和时间戳"""# 读取crypto-js库文件和你的JavaScript代码with open('crypto-js.min.js', 'r', encoding='utf-8') as file:crypto_js_code = file.read()with open('encryption.js', 'r', encoding='utf-8') as file:script_code = file.read()# 整合JavaScript代码js_code = crypto_js_code + "\n" + script_code# 编译JavaScript代码ctx = execjs.compile(js_code)# 执行JavaScript代码并获取结果result = ctx.call("runs_sign")return result['x-bc-sig'], result['x-bc-ts']def get_delete_sign_and_timestamp(self, id):"""获取删除签名和时间戳"""# 读取crypto-js库文件和你的JavaScript代码with open('crypto-js.min.js', 'r', encoding='utf-8') as file:crypto_js_code = file.read()with open('encryption.js', 'r', encoding='utf-8') as file:script_code = file.read()# 整合JavaScript代码js_code = crypto_js_code + "\n" + script_code# 编译JavaScript代码ctx = execjs.compile(js_code)# 执行JavaScript代码并获取结果result = ctx.call("delete_sign", id)return result['x-bc-sig'], result['x-bc-ts']

十二、技巧①

当我们找不到某个函数在哪里的时候,只要在控制台打印这个函数,然后在控制台点击打印的结果,即可跳转到该函数。

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

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

相关文章

前后端项目打包对比——关于Spring Boot Maven Plugin配置的问题

Spring Boot Maven Plugin 配置详解 Spring Boot Maven Plugin 配置详解1. 添加插件到 pom.xml2. 插件配置2.1 基本配置2.2 配置参数详解默认行为说明简单配置示例为什么这样的配置能工作?进一步说明 2.3 高级配置 3. 使用插件打包应用程序3.1 打包成 JAR 文件3.2 打…

ElasticSearch(六)— 全文检索

一、match系列查询 前面讲到的query中的查询,都是精准查询。可以理解成跟在关系型数据库中的查询类似。match系列的查询,是全文检索的查询。会通过分词进行评分,匹配,再返回搜索结果。 1.1 match 查询 "query": {&qu…

c++笔记4

目录 深度优先搜索DFS DFS的复杂度 DFS与递归 递归与暴力枚举 递归树 DFS与栈 DFS的搜索剪枝 搜索剪枝与优化 可行性剪枝 最优化剪枝 减少等效的分支 优化搜索顺序 搜索的记忆化 搜索的复杂度 大多时候,搜索的复杂度都是指数级的。各种剪枝方案&#…

Flink 技术与应用(一)

Flink技术与应用(初级篇) 起源 Apache Flink 是一个开源的大数据处理框架,其起源可以追溯到一个名为 Stratosphere 的研究项目,旨在建立下一代大数据分析引擎,2010 年,从 Stratosphere 项目中分化出了 Fl…

「Unity3D」场景中的距离单位Unit与相关设置PixelsToUnits、PixelsPerUnit

GameObject在场景的位置Position,并没有明确是什么具体单位——如:Transform的x、y、z,或RectTransform的PosX、PosY、PosZ。而RectTransform在面板上显示的Width和Height,也没有具体单位,其实并不是像素。 事实上&am…

百易云资产管理运营系统 comfileup.php 文件上传致RCE漏洞复现(XVE-2024-18154)

0x01 产品简介 百易云资产管理运营系统,是专门针对企业不动产资产管理和运营需求而设计的一套综合解决方案。该系统能够覆盖资产的全生命周期管理,包括资产的登记、盘点、评估、处置等多个环节,同时提供强大的运营分析功能,帮助企业优化资产配置,提升运营效率。 0x02 漏…

C++内存管理(候捷)第五讲 笔记

GNU C对allocators的描述 new_allocator 和malloc_allocator,它们都没有特别的动作,无非底部调用operator new和malloc。它们没有用内存池 区别:::operator new是可重载的 智能型的allocator,使用内存池,分一大块然后…

【PyTorch】基于YOLO的多目标检测项目(一)

【PyTorch】基于YOLO的多目标检测项目(一) 【PyTorch】基于YOLO的多目标检测项目(二) 目标检测是对图像中的现有目标进行定位和分类的过程。识别的对象在图像中显示有边界框。一般的目标检测方法有两种:基于区域提议的…

如何找到最快解析速度的DNS

如何找到最快解析速度的DNS DNS,即域名系统(Domain Name System),是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使用户更方便地访问互联网,而不用记住能够被机器直接读取的IP数…

6.乳腺癌良性恶性预测(二分类、逻辑回归、PCA降维、SVD奇异值分解)

乳腺癌良性恶性预测 1. 特征工程1.1 特征筛选1.2 特征降维 PCA1.3 SVD奇异值分解 2. 代码2.1 逻辑回归、二分类问题2.2 特征降维 PCA2.3 SVD奇异值分解 1. 特征工程 专业上:30个人特征来自于临床一线专家,每个特征和都有医学内涵;数据上&…

7月25日JavaSE学习笔记

线程的生命周期中,等待是主动的,阻塞是被动的 锁对象 创建锁对象,锁对象同一时间只允许一个线程进入 //创建锁对象Lock locknew ReentrantLock(true);//创建可重入锁 可重入锁:在嵌套代码块中,锁对象一样就可以直接…

进销存系统开发,进销存源码解析,添加商品选择商品

点击添加商品信息(可以) (关键字范围:商品名称,简拼,条形码,SKU,规格,参数,尺寸,接口,CPU,品牌) function cwpd_selSaleGoodsNewMore_Vtax2024(domid,width…

sed利用脚本处理文件

一、sed是什么 sed 命令是利用脚本来处理文本文件。它可以依照脚本的指令来处理、编辑文本文件。主要用来自动编 辑一个或多个文件、简化对文件的反复操作、编写转换程序等。 二、sed的原理 读入新的一行内容到缓存空间; 从指定的操作指令中取出第一条指令&…

【时时三省】(C语言基础)分支语句2

山不在高,有仙则名。水不在深,有龙则灵。 ——csdn时时三省 多分支语句 if(表达式1) 语句1; else if(表达式2) 语句2; else 语句3; 如果表达式1成立语句1会执行 如果不成立表达式2执行 如果表达式2成…

【运维笔记】数据库无法启动,数据库炸后备份恢复数据

事情起因 在做docker作业的时候,把卷映射到了宿主机原来的mysql数据库目录上,宿主机原来的mysql版本为8.0,docker容器版本为5.6,导致翻车。 具体操作 备份目录 将/var/lib/mysql备份到~/mysql_backup:cp /var/lib/…

Multiview LM-ICP 配准算法

Multiview LM-ICP 配准算法针对一些大型的物体(比如建筑物)或者需要精细化建模的物体(比如某个文物),仅仅进行成对的配准难以还原物体的全貌和细节。所以,多个视角的配准十分关键。 多视角的配准存在以下两…

[STM32]FlyMcu同时烧写BootLoader和APP文件-HEX文件组成

目录 一、前言 二、HEX文件的格式 三、组合HEX文件 四、使用FlyMcu烧录 一、前言 如题,BootLoader每次烧写都是全部擦除,当我们烧写APP程序的时候,BootLoader程序将不复存在,很多开发者或许只有USB转TTL模块,没有其…

grep命令搜索部分命令

首先 然后可以输入|以及grep命令 比如 bjobs| grep "3075*"bjobs| grep "3075"这个结果是这样的,

MYSQL 第四次作业

任务要求: 具体操作: 新建数据库: mysql> CREATE DATABASE mydb15_indexstu; Query OK, 1 row affected (0.01 sec) mysql> USE mydb15_indexstu; Database changed 新建表: mysql> CREATE TABLE student( ->…

遇到总条数count(*)返回不了数据

文章目录 前提1.准备数据1.1 建表语句1.2 插入数据 2.程序代码3.返回结果与分析4.验证 前提 获取h_user表中count(*)字段的值打印出来,打印出来是0,数据库中执行sql返回不是0。端点调试找到原因。下面先把数据库表数据及程序贴出来。 1.准备数据 1.1 …