您的位置:首页 > 游戏 > 游戏 > 百某应JS逆向

百某应JS逆向

2024/12/23 11:56:22 来源:https://blog.csdn.net/wenxingchen/article/details/140689937  浏览:    关键词:百某应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环境)

十一、无Node环境执行

十二、实际应用

十三、技巧①


一、发起提问

二、观察发现有两个加密参数: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环境)

将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)

十一、无Node环境执行

首先修改主文件encryption.js的引入部分

再用python文件进行读取并合并两个js文件即可

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("runs_sign")# 输出结果
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']

十三、技巧①

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com