Skip to content

dreamland-blog/PerimeterX-SDK

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

PerimeterX SDK

本文我将重点分析下PerimeterX SDK的逆向分析

SSL检测

我在抓包的时候发现PerimeterX在我抓包初始化之前就已经完成了现在我来固定下SSL以便更好的抓包分析 直接搜索 perimeterx.net 这个关键词 SSL PerimeterX是okhttp3里的CertificatePinner里的add方法

Java.perform(function() {
    let okhttp3Pin = Java.use("okhttp3.CertificatePinner$Builder")
    okhttp3Pin["add"].implementation = function(pattern, pins) {
        return this
    }
})

抓包

有效载荷

现在我们已经破解了 SSL pinning,可以开始研究反机器人了。首先,确保强制关闭应用并清除缓存和存储空间。我在对任何应用进行逆向工程时都会确保这样做,因为大多数应用都会将某些内容放入缓存/存储空间,而反机器人通常会将之前会话的信息放入存储空间。 毫无疑问这个就是我们要分析的目标payload payload 如果细心你会发现这个是个base64的一个编码 payload

好的现在我们分析下这个解码后的参数 PX1214这个参数,如果你仔细的去在SDK中寻找的话这个其实就是x-px-device-fp是个常数 为了节省大家的时间,我会告诉大家接下来的几个值也可以这样做,如下所示:

描述 示例值 用途
PX91 屏幕宽度(像素) 1080 获取设备屏幕宽度
PX92 屏幕高度(像素) 2400 获取设备屏幕高度
PX316 是否有 SIM 卡 true 检查设备是否插入 SIM 卡
PX318 Android SDK 版本 "33" 标识操作系统 SDK 版本
PX319 操作系统内核版本 "5.10.101" 获取内核版本
PX320 设备型号 "SM-G988N" 标识设备型号
PX339 设备制造商 "samsung" 标识设备制造商
PX321 设备代号 "z3q" 标识设备代号
PX323 当前时间(秒) 1734567890 记录当前时间(Unix 时间戳)
PX322 操作系统 "Android" 固定标识 Android 系统
PX337 是否支持 GPS true 检查 GPS 硬件支持
PX336 是否支持陀螺仪 true 检查陀螺仪支持
PX335 是否支持加速度计 true 检查加速度计支持
PX334 是否支持以太网(SDK ≥ 24) false 检查以太网支持(Android 7.0+)
PX333 是否支持触摸屏 true 检查触摸屏支持
PX331 是否支持 NFC true 检查 NFC 支持
PX332 是否支持 Wi-Fi true 检查 Wi-Fi 芯片支持
PX344 网络运营商名称 "T-Mobile" 获取当前网络运营商名称
PX347 默认语言环境 "en_US" 获取设备默认语言和区域
PX418 电池温度 25 获取电池温度(单位可能为摄氏度)
PX420 电池电压 3700 获取电池电压(单位为毫伏)
PX340 SDK 版本(带前缀 'v') "v33" 标识 Android SDK 版本
PX342 应用版本 "2.3.1" 获取应用版本号(如 GrubHub)
PX341 应用名称 "GrubHub" 获取应用名称
PX348 应用包名 "com.grubhub.android" 获取应用包名
下面我们来到了PX326,PX327,PX328的生成位置了
PX328
PX326就是我们的UUID,PX327就是uuid以-分割的第一部分,PX328就是我们要分析的参数之一
const crypto = require('crypto');

function a(input) {
    const hash = crypto.createHash('sha1').update(input, 'utf8');
    return hash.digest('hex').toUpperCase();
}
datas="Pixel 5"+"00000199-f656-5976-0000-000000000001"+"00000199"
console.log(a(datas));

这个就是PX328的运算流程

PX256,PX257,PX259

PX256,PX259是在第一次请求中ob的参数

{
	"do": ["sid|a075a46c-abf8-11f0-8555-6c17dbda30bb", "appc|1|1760774493089|7d723aa87b31da59679ebd76ebf591d4bf0679f8240f1cee26faee2598ed163c|a0772f90-abf8-11f0-a025-27390821ff19", "appc|2|1760774493089|7d14acde7faecc20563deadb8c4d56c27001cc2829dc19e06b76172f0ed1890b,7d14acde7faecc20563deadb8c4d56c27001cc2829dc19e06b76172f0ed1890b|483|1601|1122|2659|2160|3882", "ipd|true"]
}

PX259是前面三个的工作量证明

/**
 * 简化版 AppcInstruction 函数:只关注计算 PX257
 * @param {string} appc APPC 2 指令字符串。
 * @param {Uint8Array} px320_bArr Px320 的基准字节数组
 * @returns {{PX256: string, PX259: number, PX257: string} | null} 计算结果对象,或 null (失败时)。
 */
function calculateAppcPX257(appc, px320_bArr = PX320_BYTES) {
    const parts = appc.split("|");

    // 1. 格式验证
    if (parts[1] !== "2" || parts.length !== 10) {
        return null;
    }

    const output = {
        PX256: parts[3],
        PX259: 0,
        PX257: "" 
    };

    // 2. 提取 PX259 (时间戳)
    const date = parseInt(parts[2], 10);
    if (isNaN(date)) {
        return null;
    }
    output.PX259 = date;

    // 3. 提取并转换 6 个数字
    const numbers = [];
    for (let i = 4; i < 10; i++) {
        const num = parseInt(parts[i], 10);
        if (isNaN(num)) {
            return null;
        }
        numbers.push(num | 0); 
    }
    
    // 4. 计算 mathOut (混淆值)
    // numbers: [374, 3542, 3311, 1478, 3717, 352]
    // 内部: pow(3311, 1478, 374, 352)
    const innerResult = pow(numbers[2], numbers[3], numbers[0], numbers[5]);
    // 外部: pow(innerResult, 3717, 3542, 352)
    const mathOut = pow(innerResult, numbers[4], numbers[1], numbers[5]);

    // 5. 提取 Px320 的前 4 字节整数 (res)
    let res = 0;
    if (px320_bArr.length >= 4) {
        // 读取大端序 32 位整数
        const dataView = new DataView(px320_bArr.buffer, px320_bArr.byteOffset, px320_bArr.byteLength);
        res = dataView.getInt32(0, false); 
    } 
    
    // 6. 计算最终的 PX257 (res ^ mathOut)
    const finalResult = (res ^ mathOut) | 0; 
    
    // 7. 转换为字符串并赋值
    output.PX257 = String(finalResult);
    
    return output;
}

About

PerimeterX第一部分&&逆向分析

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors