【JS逆向】XX云歌曲评论【AES+RSA】加密

注意:文章内容仅用于学习和技术交流,如有侵权请联系我删除。

学者应洁身自好,切勿做出违法的事情,旨在提供逆向思路。

➣➣欢迎关注本人微信公众号Anonymous NoteBook➣➣

分享好玩有趣的网络资源&软件工具~

分享各种技术性PDF资源/付费查询PDF资源~

分享各种编程语言、开发技术、分布式事务、大数据与云计算技术~

分享有关网络爬虫(Web爬虫逆向 | 安卓逆向)案例、数据挖掘、技术心得等~

aHR0cHM6Ly9tdXNpYy4xNjMuY29tLyMvc29uZz9pZD0xOTAxMDQ5Njcx

问题分析:

请求URL, 打开F12查看数据请求接口:

  

歌曲评论接口找到,但是请求参数是加密的,并且每次刷新页面和翻页,参数都在不断变化,猜测可能是加入了时间戳,具体还需分析后得知。

逆向分析:

全局搜索 ”encSecKey“ 关键字,在出现的结果中有一处很可疑:

 点进去看下:

猜测一下,这里很有可能就是加密所在,下个断,调试下:

断点停在这里,说明此处即为加密逻辑所在,并且根据调试的数据可以看出, 最终结果为拼接而成,这就很好办了,只要找到加密入口以及参数,就可以得出加密后的数据,”params“ 和 ”encSecKey“ 的结果都是从”bVj0x“ 这个结果中获取的,而”bVj0x“ 是调用了一些加密函数来处理原始数据的,继续看一下:

”bVj0x“ 调用的是window.asrsea 函数,真实调用的是函数d:

 函数d传入了一些参数,挨个分析下参数都是什么:

i9b  -- 是一个json对象,最后序列化为json字符串:

cursor---当前时间戳

pageSize、offset ---- 页面显示评论的数量

orderType ---- 评论排序方式

pageNo--- 页码

rid、threadId ---- R_SO_4_(歌曲id),可以在url中找到

第二、三、四个参数调用的都是bsP6J 函数,其中第三个参数传进去的是Xk6e.md参数,Xk6e.md是事先定义好的变量,往上翻就能找到:

 接着,跟进去bsP6J函数看下:

 做一些入队列操作,最后通过json组合在一起,后面就不一一调试了,跟着调试的节奏一步步深入,慢慢就很清晰,我们把所需的函数和变量都拷贝下来先粘贴到本地,缺什么补什么就ok了。

参数分析完毕,我们来分析下最后的处理函数d:

 跟进去d函数后发现,这里调用了很多的处理函数,rsa和aes 都是在这里处理的,我们下个断看下:

a函数:看到加入了随机数处理:

 b函数: aes加密逻辑:

初始向量iv、密钥、加密模式、填充方式一目了然,这是aes标准的加密方式,比较清晰。

c函数: rsa加密处理:

 跟进去RSAKeyPair函数:

 此文件里就是所有加密逻辑所在,同样根据一步步调试,找到我们所需的函数和变量,复制下来拷贝到本地js文件里,最后补上环境、变量,稍微修改下函数的调用方式,基本上就没多大问题了。

 可以看出结果输出正常,接下来我们通过构造py代码来模拟请求,来验证下是否可以正常请求并得到结果:

 Emmm~~

结果请求正常,这里只截取一小部分。

要想批量获取评论,可以写个for循环,动态设置页码,如果想要获取多个音乐的评论,可以先获取一部分的音乐id,把id加入队列,写个while循环去读队列数据,并且也可以加上多线程、异步协程并发爬取,具体根据自身需求而定。

至此,逆向完毕。

//***************************RSA加密*****************************
var ZERO_ARRAY = new Array(131);
for (var b = 0; b < ZERO_ARRAY.length; b++)
    ZERO_ARRAY[b] = 0;
var maxDigits, ZERO_ARRAY, bigZero, bigOne, dpl10, lr10, hexatrigesimalToChar, hexToChar, highBitMasks, lowBitMasks,
    biRadixBase = 2, biRadixBits = 16, bitsPerDigit = biRadixBits, biRadix = 65536, biHalfRadix = biRadix >>> 1,
    biRadixSquared = biRadix * biRadix, maxDigitVal = biRadix - 1, maxInteger = 9999999999999998;
dpl10 = 15,
    lr10 = biFromNumber(1e15),
    hexatrigesimalToChar = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"),
    hexToChar = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"),
    highBitMasks = new Array(0, 32768, 49152, 57344, 61440, 63488, 64512, 65024, 65280, 65408, 65472, 65504, 65520, 65528, 65532, 65534, 65535),
    lowBitMasks = new Array(0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535);
var Xk6e_emj = {
    "色": "00e0b",
    "流感": "509f6",
    ...........
    //此处省略多行
    ...........
    "惊恐": "8W8ju",
    "大笑": "d"
};
var Xk6e_md = ["色",    ...........
    //此处省略多行
    ...........];

function RSAKeyPair(a, b, c) {
    this.e = biFromHex(a),
        this.d = biFromHex(b),
        this.m = biFromHex(c),
        this.chunkSize = 2 * biHighIndex(this.m),
        this.radix = 16,
        this.barrett = new BarrettMu(this.m)
}

function encryptedString(a, b) {
    for (var f, g, h, i, j, k, l, c = new Array, d = b.length, e = 0; d > e;)
    ...........
    //此处省略多行
    ...........
    }
    return g.substring(0, g.length - 1)
}

...........
//此处省略多行函数
...........
function charToHex(a) {
    var h, b = 48, c = b + 9, d = 97, e = d + 25, f = 65, g = 90;
    return h = a >= b && c >= a ? a - b : a >= f && g >= a ? 10 + a - f : a >= d && e >= a ? 10 + a - d : 0
}

function hexToDigit(a) {
    var d, b = 0, c = Math.min(a.length, 4);
    for (d = 0; c > d; ++d)
        b <<= 4,
            b |= charToHex(a.charCodeAt(d));
    return b
}

function biFromHex(a) {
    var d, e, b = new BigInt, c = a.length;
    for (d = c,
             e = 0; d > 0; d -= 4,
             ++e)
        b.digits[e] = hexToDigit(a.substr(Math.max(d - 4, 0), Math.min(d, 4)));
    return b
}

function biAdd(a, b) {
    var c, d, e, f;
    if (a.isNeg != b.isNeg)
           ...........
    //此处省略多行
    ...........
    }
    return c
}

function biSubtract(a, b) {
    var c, d, e, f;
    if (a.isNeg != b.isNeg)
            ...........
    //此处省略多行
    ...........
            c.isNeg = a.isNeg
    }
    return c
}

function biHighIndex(a) {
    for (var b = a.digits.length - 1; b > 0 && 0 == a.digits[b];)
        --b;
    return b
}

function biNumBits(a) {
    var e, b = biHighIndex(a), c = a.digits[b], d = (b + 1) * bitsPerDigit;
    for (e = d; e > d - bitsPerDigit && 0 == (32768 & c); --e)
        c <<= 1;
    return e
}

function biMultiply(a, b) {
    var d, h, i, k, c = new BigInt, e = biHighIndex(a), f = biHighIndex(b);
    for (k = 0; f >= k; ++k) {
            ...........
    //此处省略多行
    ...........
    }
    return c.isNeg = a.isNeg != b.isNeg,
        c
}

function biMultiplyDigit(a, b) {
    var c, d, e, f;
    for (result = new BigInt,
                ...........
    //此处省略多行
    ...........
        result
}

function arrayCopy(a, b, c, d, e) {
    var g, h, f = Math.min(b + e, a.length);
    for (g = b,
              ...........
    //此处省略多行
    ...........
        c[h] = a[g]
}

function biShiftLeft(a, b) {
    var e, f, g, h, c = Math.floor(b / bitsPerDigit), d = new BigInt;
    for (arrayCopy(a.digits, 0, d.digits, c, d.digits.length - c),
               ...........
    //此处省略多行
    ...........
        d
}

function biShiftRight(a, b) {
    var e, f, g, h, c = Math.floor(b / bitsPerDigit), d = new BigInt;
    for (arrayCopy(a.digits, c, d.digits, 0, a.digits.length - c),
                ...........
    //此处省略多行
    ...........
        d
}

function biMultiplyByRadixPower(a, b) {
    var c = new BigInt;
    return arrayCopy(a.digits, 0, c.digits, b, c.digits.length - b),
        c
}

function biDivideByRadixPower(a, b) {
    var c = new BigInt;
    return arrayCopy(a.digits, b, c.digits, 0, c.digits.length - b),
        c
}

function biModuloByRadixPower(a, b) {
    var c = new BigInt;
    return arrayCopy(a.digits, 0, c.digits, 0, b),
        c
}

function biCompare(a, b) {
    if (a.isNeg != b.isNeg)
        ...........
    //此处省略多行
    ...........
    return 0
}

function biDivideModulo(a, b) {
    var f, g, h, i, j, k, l, m, n, o, p, q, r, s, c = biNumBits(a), d = biNumBits(b), e = b.isNeg;
    if (d > c)
        return a.isNeg ? (f = biCopy(bigOne),
                ...........
    //此处省略多行
    ...........
    }
    return g = biShiftRight(g, i),
        f.isNeg = a.isNeg != e,
    a.isNeg && (f = e ? biAdd(f, bigOne) : biSubtract(f, bigOne),
        b = biShiftRight(b, i),
        g = biSubtract(b, g)),
    0 == g.digits[0] && 0 == biHighIndex(g) && (g.isNeg = !1),
        new Array(f, g)
}

function biDivide(a, b) {
    return biDivideModulo(a, b)[0]
}

function biModulo(a, b) {
    return biDivideModulo(a, b)[1]
}

function biMultiplyMod(a, b, c) {
    return biModulo(biMultiply(a, b), c)
}

function BarrettMu(a) {
    this.modulus = biCopy(a),
           ...........
    //此处省略多行
    ...........
}

function BarrettMu_modulo(a) {
    var i, b = biDivideByRadixPower(a, this.k - 1), c = biMultiply(b, this.mu), d =     ...........
    //此处省略多行
    ...........
    return h
}

function BarrettMu_multiplyMod(a, b) {
    var c = biMultiply(a, b);
    return this.modulo(c)
}

function BarrettMu_powMod(a, b) {
    var d, e, c = new BigInt;
    for (c.digits[0] = 1,
           ...........
    //此处省略多行
    ...........
    }
    return c
};

//***************************RSA加密*****************************

j9a_gQ1x = function (i9b) {
    return GQ9H(i9b, "function")
};
var GQ9H = function (i9b, v9m) {
    try {
        v9m = v9m.toLowerCase();
        if (i9b === null)
            return v9m == "null";
        if (i9b === undefined)
            return v9m == "undefined";
        return {}.toString.call(i9b).toLowerCase() == "[object " + v9m + "]"
    } catch (e) {
        return !1
    }
};
j9a_bg9X = function (k9b, cI0x, O9F) {
    if (!k9b || !k9b.length || !j9a_gQ1x(cI0x))
        return this;
    if (!!k9b.forEach) {
        k9b.forEach(cI0x, O9F);
        return this
    }
    for (var i = 0, l = k9b.length; i < l; i++)
        cI0x.call(O9F, k9b[i], i, k9b);
    return this
};
var bsP6J = function (cxG5L) {
    var m9d = [];
    j9a_bg9X(cxG5L, function (cxF5K) {
        m9d.push(Xk6e_emj[cxF5K])
    });
    return m9d.join("")
};

function a(a) {
    var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";
    for (d = 0; a > d; d += 1)
        e = Math.random() * b.length,
            e = Math.floor(e),
            c += b.charAt(e);
    return c
};

function d(d, e, f, g) {
    var h = {}
        , i = a(16);
    return h.encText = bb_(d, g),
        h.encText = bb_(h.encText, i),
        h.encSecKey = c(i, e, f),
        h
};

function c(a, b, c) {
    var d, e;
    return d = new RSAKeyPair(b, "", c),
        e = encryptedString(d, a)
};

function bb_(a, b) {
    var c = CryptoJS.enc.Utf8.parse(b)
        , d = CryptoJS.enc.Utf8.parse("0102030405060708")
        , e = CryptoJS.enc.Utf8.parse(a)
        , f = CryptoJS.AES.encrypt(e, c, {
        iv: d,
        mode: CryptoJS.mode.CBC
    });
    return f.toString()
};
j9a_cq9h = function (gE1x) {
    return j9a_wV6P(gE1x, "&", !0)
};
j9a_wV6P = function (gE1x, VZ6T, cKS7L) {
    if (!gE1x)
        return "";
    var bv9m = [];
    for (var x in gE1x) {
        bv9m.push(encodeURIComponent(x) + "=" + (!!cKS7L ? encodeURIComponent(gE1x[x]) : gE1x[x]))
    }
    return bv9m.join(VZ6T || ",")
};


//调用入口函数
function getParams(song_id, comm_num) {
    var i9b = {
        "rid": "R_SO_4_" + song_id, // R_SO_4_XXXXX(歌曲id)
        "threadId": "R_SO_4_" + song_id,// R_SO_4_XXXXX(歌曲id)
        "pageNo": "" + comm_num,
        "pageSize": "20",
        "cursor": new Date().getTime().toString(),
        "offset": "40",
        "orderType": "1",
        "csrf_token": ""
    };
    var bVj0x = d(JSON.stringify(i9b), bsP6J(["流泪", "强"]), bsP6J(Xk6e_md), bsP6J(["爱心", "女孩", "惊恐", "大笑"]));
    // console.log(bVj0x)
    data = j9a_cq9h({
        params: bVj0x.encText,
        encSecKey: bVj0x.encSecKey
    })
    // console.log(data)
    return data
}


完事~~~  收工~~~~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值