js逆向:某Q音乐平台请求数据模拟生成

@

内容仅供学习使用,不能用于商业活动,且不能在该网站高用户访问时频繁访问,以免对对应服务器造成影响。

1. 加密原理

该音乐平台加密数据为如下图片这个:
PixPin_2025-09-21_16-05-10
所加密的数据data和这篇文章里的数据一样,具体请看:js逆向:某音乐平台请求参数sign签名模拟生成

加密后的数据会随着data字符串(json数据)的长度而变化,因此加密数据的长度是不固定的。另外,最好学习一下这几个涉及到加密的类或函数,如下:

crypto
TextEncoder
crypto.subtle.encrypt

具体可以参考官方文档,链接为:SubtleCrypto.importKey()方法的使用。另外,因为涉及到加密操作的函数或类需要异步操作,读者最好有一定的异步操作的基础。基本加密原理就是利用方法crypto.getRandomValues()生成一个长度为12的加密密钥数组arr12(说的称呼可能不怎么对吧,不过总之这里会和后续加密操作联系就行。)吧!这个arr12会和上述的data数据进行一系列操作,最终结果会得到一个数组arr2,得到arr2后会再和arr12进行拼接或组合操作吧,变为一个数组arr3,如果用Python代码描述就是arr3 = arr12.extend(arr2)。(这里使用的列表类型),最后把这个arr3根据其值进行一些操作得到一个下标index,通过这个index得到字符c(str1 = ''ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'',c=str1[index]),最后拼接所有的c即可(这里涉及到arr3中3个元素得到4个字符,因为data长度不固定,因此,arr3的长度也是不固定,所以可能会存在最后依次遍历时arr3中只有1个元素或2个元素,这里需要额外讨论一下)。这里是我的一个猜测,上述代码中提到的那些函数或类我其实也并不是很了解,在上述理解中arr3 =arr12.extend(arr2)这里为什么要进行这一步呢?我想因为传到后端之后,后端进行解密操作,才能直到你具体data是什么,因为arr12初始是随机生成的,不固定的,不传到到后端,后端根本无法解密。后端解密之后然后进行sign签名参数的验证,然后辨别你的sign参数是否正确。

2. 参考代码

async function getImportKey(){
    const arr1 = [
        "raw",
        new Uint8Array([189, 48, 95, 16, 208, 255, 116, 182, 239, 84, 218, 184, 53, 181, 225, 207]),
        {
            name: "AES-GCM",
            length: 128
        },
        false,
        ["encrypt"]
    ]
    const subtle_2 = crypto.subtle;
    const importKey_2 = subtle_2.importKey;
    return await importKey_2.apply(subtle_2, arr1);
}

async function getArr(str1,uint8Arr12){
    const cryptoKey_2 = await getImportKey();
    // CryptoKey 类型对象
    const textEncoder_2 = new TextEncoder();
    const encode = textEncoder_2.encode;
    const arr2 = encode.call(textEncoder_2,str1);
    // Uint8Array类型的数组

    const subtleCrypto_2 = crypto.subtle;
    const encrypt_2 = subtleCrypto_2.encrypt;
    const obj_2 = {'name':'AES-GCM',"iv":uint8Arr12};
    return await encrypt_2.call(subtleCrypto_2,obj_2,cryptoKey_2,arr2);
}

async function main1(str1){
    const uint8Array8_2 = new Uint8Array(12); // 长度为12
    // const uint8Arr12 = crypto.getRandomValues(uint8Array8_2);
    // 每次结果都不一样的,长度为12的Uint8Array类型的数组
    const uint8Arr12 = new Uint8Array([211, 252, 76, 150, 99, 43, 95, 77, 49, 242, 104, 169]); // 测试使用
    const res = await getArr(str1,uint8Arr12);
    // ArrayBuffer 类型的数据
    const normalArr = Array.from(new Uint8Array(res));
    const normalArr2 = Array.from(uint8Arr12);
    const arr = normalArr2.concat(normalArr);
    let ans = '';
    const str2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    for(let i = 0;i < arr.length;i += 3){
        // 每三个元素值最后拼成4个字符
        let a = arr[i],b = arr[i+1],c = arr[i+2];
        let a1 = a << 16,b1 = b << 8,d = a1 | b1,e = d | c,
            f = e >> 18,g = f & 63,
            f1 = e >> 12,g1 = f1 & 63,
            f2 = e >> 6,g2 = f2 & 63,
            g3 = e & 63;

        ans += str2[g] + str2[g1];
        if(b === undefined){
            ans += "==";
        }else if(c === undefined){
            ans += str2[g2] + '=';
        }else{
            ans += str2[g2] + str2[g3];
        }
    }
    console.log(ans)
    return ans;
}

const str1 = 
// console.log(main1(JSON.stringify(str1)));
console.log(main1(str1));

参考代码中str1中有一个数据涉及隐私问题,因此没有粘贴上去了,可以直接去小编这篇文章里去复制就行。js逆向:某音乐平台请求参数sign签名模拟生成。。。

posted @ 2025-09-21 16:06  坚持不懈的大白  阅读(32)  评论(0)    收藏  举报
@format