抖音网页端逆向系列02-a_bogus算法还原【V 1.0.1.19-fix.01】-综合交流论坛-五云学习-五云学习

抖音网页端逆向系列02-a_bogus算法还原【V 1.0.1.19-fix.01】

承接昨日分析,今日我们将进一步深入,通过增设更多断点并丰富日志输出内容,将运算符号+、-、*、/、%、&、|、^等纳入一级关注范畴,继而继续展开细致的分析工作。
抖音网页端逆向系列02-a_bogus算法还原【V 1.0.1.19-fix.01】

 
 
 
"加运算", "参数",v[p], "参数", E, "结果", v[p] + E
 
 
抖音网页端逆向系列02-a_bogus算法还原【V 1.0.1.19-fix.01】

 
 
 
添加图片注释,不超过 140 字(可选)
 
此外,我们还将为其他类型的运算添加相应的日志断点,以确保全面获取日志输出。接下来,我们将逐行深入分析这些日志,以揭示其背后的运算逻辑和细节。
抖音网页端逆向系列02-a_bogus算法还原【V 1.0.1.19-fix.01】

 
 
 
添加图片注释,不超过 140 字(可选)
 
在执行过程中,我们将采取逆向分析法,逐步追溯并尝试还原算法的细节。首先,我们需要定位并查阅与a_bogus第一个字符生成相关的日志信息,以此为切入点深入探究。
抖音网页端逆向系列02-a_bogus算法还原【V 1.0.1.19-fix.01】

 
 
 
添加图片注释,不超过 140 字(可选)
 
[ -1 ]apply::: ƒ charCodeAt() { [native code] } 参数d= £Rp`"6¼+½¢è&ý=ßË城›4øbòKéç—j¡Wj™ˆî/–Î)<tüÈG€åáµ¹Þ¬$¸?ÕEýÁ€Ðò¯tO‘¾ËT$|Tâ¸GG6,û"’øwÆh°å¶„ç|“ïX*œJ?…x4õ”äó#¬¿võHë0£kuã0c–í<´U 参数e= [0] 结果m= 163
bdms_1.0.1.19_fix.js:2 [ 0 ]&运算 参数 163 参数 255 结果 163
bdms_1.0.1.19_fix.js:2 [ 0 ]<<运算 参数 163 参数 16 结果 10682368
bdms_1.0.1.19_fix.js:2 [ 1 ]入栈 £Rp`"6¼+½¢è&ý=ßË城›4øbòKéç—j¡Wj™ˆî/–Î)<tüÈG€åáµ¹Þ¬$¸?ÕEýÁ€Ðò¯tO‘¾ËT$|Tâ¸GG6,û"’øwÆh°å¶„ç|“ïX*œJ?…x4õ”äó#¬¿võHë0£kuã0c–í<´U
bdms_1.0.1.19_fix.js:2 [ 3 ]入栈 (10) [Array(2), {…}, '£Rp\x07\x7F`"6\x12¼+½¢è&ý=ßËå\x9F\x8E\x9B4\x0EøbòKéç\x97j¡Wj\x99\x88î\x07/\x96Î)<tüÈG\x80…øwÆh°å¶\x84ç\x1A|\x93ïX*\x9CJ?\x85x4õ\x94äó#¬\x02¿võHë0£k\buã0\x16c\x96í<\x03´U\x7F', 's4', '=', {…}, 'Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe', '', empty, 1]0: (2) [{…}, {…}]1: {0: '£Rp\x07\x7F`"6\x12¼+½¢è&ý=ßËå\x9F\x8E\x9B4\x0EøbòKéç\x97j¡Wj\x99\x88î\x07/\x96Î)<tüÈG\x80…øwÆh°å¶\x84ç\x1A|\x93ïX*\x9CJ?\x85x4õ\x94äó#¬\x02¿võHë0£k\buã0\x16c\x96í<\x03´U\x7F', 1: 's4', length: 2}2: "£Rp\u0007`\"6\u0012¼+½¢è&ý=ßË城›4\u000eøbòKéç—j¡Wj™ˆî\u0007/–Î)<tüÈG€å\u0006áµ¹\u0003Þ¬$¸?ÕE\u001eýÁ€Ðò¯tO‘¾ËT$\u001a|Tâ¸GG6,û\u001e\"’\u001aøwÆh°å¶„ç\u001a|“ïX*œJ?…x4õ”äó#¬\u0002¿võHë0£k\buã0\u0016c–í<\u0003´U"3: "s4"4: "="5: {s0: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', s1: 'Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=', s2: 'Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=', s3: 'ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe', s4: 'Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe'}6: "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"7: "Y7sjkHtEmNRVFdKtYKEoe3HlnCIlNTuypFixSLFTGGUOYXUOoRNKknCIrxLSUMrmvbpwkK27KfMAPdVbMtXhZFHkLmpfSOty3G2Cn7fL2qJ6bPiZvrRuCJbxLiPbUS4Yu/I9i/W5lsMFIdOWVNChAp37w/3rmcjdFH-7V/ujY9umUA8jho/Ia3jpzhXe"8: 118183679: 141length: 10[[Prototype]]: Array(0)at: ƒ at()concat: ƒ concat()constructor: ƒ Array()copyWithin: ƒ copyWithin()entries: ƒ entries()every: ƒ every()fill: ƒ fill()filter: ƒ filter()find: ƒ find()findIndex: ƒ findIndex()findLast: ƒ findLast()findLastIndex: ƒ findLastIndex()flat: ƒ flat()flatMap: ƒ flatMap()forEach: ƒ forEach()includes: ƒ includes()indexOf: ƒ indexOf()join: ƒ join()keys: ƒ keys()lastIndexOf: ƒ lastIndexOf()length: 0map: ƒ map()pop: ƒ pop()push: ƒ push()reduce: ƒ reduce()reduceRight: ƒ reduceRight()reverse: ƒ reverse()shift: ƒ shift()slice: ƒ slice()some: ƒ some()sort: ƒ sort()splice: ƒ splice()toLocaleString: ƒ toLocaleString()toReversed: ƒ toReversed()toSorted: ƒ toSorted()toSpliced: ƒ toSpliced()toString: ƒ toString()unshift: ƒ unshift()values: ƒ values()with: ƒ with()Symbol(Symbol.iterator): ƒ values()Symbol(Symbol.unscopables): {at: true, copyWithin: true, entries: true, fill: true, find: true, …}[[Prototype]]: Object 9
bdms_1.0.1.19_fix.js:2 [ 0 ]apply::: ƒ charCodeAt() { [native code] } 参数d= £Rp`"6¼+½¢è&ý=ßË城›4øbòKéç—j¡Wj™ˆî/–Î)<tüÈG€åáµ¹Þ¬$¸?ÕEýÁ€Ðò¯tO‘¾ËT$|Tâ¸GG6,û"’øwÆh°å¶„ç|“ïX*œJ?…x4õ”äó#¬¿võHë0£kuã0c–í<´U 参数e= [1] 结果m= 82
bdms_1.0.1.19_fix.js:2 [ 1 ]&运算 参数 82 参数 255 结果 82
bdms_1.0.1.19_fix.js:2 [ 1 ]<<运算 参数 82 参数 8 结果 20992
bdms_1.0.1.19_fix.js:2 [ 0 ]|运算 参数 10682368 参数 20992 结果 10703360
bdms_1.0.1.19_fix.js:2 [ 1 ]入栈 £Rp`"6¼+½¢è&ý=ßË城›4øbòKéç—j¡Wj™ˆî/–Î)<tüÈG€åáµ¹Þ¬$¸?ÕEýÁ€Ðò¯tO‘¾ËT$|Tâ¸GG6,û"’øwÆh°å¶„ç|“ïX*œJ?…x4õ”äó#¬¿võHë0£kuã0c–í<´U
bdms_1.0.1.19_fix.js:2 [ 3 ]入栈 (10) [Array(2), {…}, '£Rp\x07\x7F`"6\x12¼+½¢è&ý=ßËå\x9F\x8E\x9B4\x0EøbòKéç\x97j¡Wj\x99\x88î\x07/\x96Î)<tüÈG\x80…øwÆh°å¶\x84ç\x1A|\x93ïX*\x9CJ?\x85x4õ\x94äó#¬\x02¿võHë0£k\buã0\x16c\x96í<\x03´U\x7F', 's4', '=', {…}, 'Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe', '', empty, 2]0: (2) [{…}, {…}]1: {0: '£Rp\x07\x7F`"6\x12¼+½¢è&ý=ßËå\x9F\x8E\x9B4\x0EøbòKéç\x97j¡Wj\x99\x88î\x07/\x96Î)<tüÈG\x80…øwÆh°å¶\x84ç\x1A|\x93ïX*\x9CJ?\x85x4õ\x94äó#¬\x02¿võHë0£k\buã0\x16c\x96í<\x03´U\x7F', 1: 's4', length: 2}0: "£Rp\u0007`\"6\u0012¼+½¢è&ý=ßË城›4\u000eøbòKéç—j¡Wj™ˆî\u0007/–Î)<tüÈG€å\u0006áµ¹\u0003Þ¬$¸?ÕE\u001eýÁ€Ðò¯tO‘¾ËT$\u001a|Tâ¸GG6,û\u001e\"’\u001aøwÆh°å¶„ç\u001a|“ïX*œJ?…x4õ”äó#¬\u0002¿võHë0£k\buã0\u0016c–í<\u0003´U"1: "s4"length: 2[[Prototype]]: Object2: "£Rp\u0007`\"6\u0012¼+½¢è&ý=ßË城›4\u000eøbòKéç—j¡Wj™ˆî\u0007/–Î)<tüÈG€å\u0006áµ¹\u0003Þ¬$¸?ÕE\u001eýÁ€Ðò¯tO‘¾ËT$\u001a|Tâ¸GG6,û\u001e\"’\u001aøwÆh°å¶„ç\u001a|“ïX*œJ?…x4õ”äó#¬\u0002¿võHë0£k\buã0\u0016c–í<\u0003´U"3: "s4"4: "="5: s0: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="s1: "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe="s2: "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe="s3: "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe"s4: "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"[[Prototype]]: Object6: "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"7: "Y7sjkHtEmNRVFdKtYKEoe3HlnCIlNTuypFixSLFTGGUOYXUOoRNKknCIrxLSUMrmvbpwkK27KfMAPdVbMtXhZFHkLmpfSOty3G2Cn7fL2qJ6bPiZvrRuCJbxLiPbUS4Yu/I9i/W5lsMFIdOWVNChAp37w/3rmcjdFH-7V/ujY9umUA8jho/Ia3jpzhXe"8: 118183679: 141length: 10[[Prototype]]: Array(0) 9
bdms_1.0.1.19_fix.js:2 [ 0 ]apply::: ƒ charCodeAt() { [native code] } 参数d= £Rp`"6¼+½¢è&ý=ßË城›4øbòKéç—j¡Wj™ˆî/–Î)<tüÈG€åáµ¹Þ¬$¸?ÕEýÁ€Ðò¯tO‘¾ËT$|Tâ¸GG6,û"’øwÆh°å¶„ç|“ïX*œJ?…x4õ”äó#¬¿võHë0£kuã0c–í<´U 参数e= [2] 结果m= 112
bdms_1.0.1.19_fix.js:2 [ 1 ]&运算 参数 112 参数 255 结果 112
bdms_1.0.1.19_fix.js:2 [ 0 ]|运算 参数 10703360 参数 112 结果 10703472

第一个字符串代码还原

import { assert } from "console"

const SALT_2: any = {
    "s0": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    "s1": "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
    "s2": "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
    "s3": "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe",
    "s4": "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"
}

const obj = {
    "0": "Bâ®ö<0\u0012¤)͈„QüÜ\u00184©¦¤ß`\u0003WÛVu9°j¹ÒNÂa妵?§øºÌ\u0007©í\u000f^\"¾\u0003|¤\u0001Þ­aÓmè‘c:ÔrâÀýñG¬EªÀ “9R¦»÷ $+‰\u0010ü ›b3\\\b5‚¦­Ê^Å\u0000l ÷uz",
    "1": "s3"
}
export function sign() {
    // 栈指针位置
    let token = ``
    const a = 16515072
    const params = obj["0"]
    const sign = obj["1"]
    const signValue = SALT_2[sign]
    // step 1
    const t0 = params.charCodeAt(0)
    const t1 = t0 & 255;
    const t2 = t1 << 16; // 4325376

    // step2
    const t3 = params.charCodeAt(1)
    const t4 = t3 & 255;
    const t5 = t4 << 8
    const t6 = t2 | t5; // 4383232

    // step3
    const t7 = params.charCodeAt(2)
    const t8 = t7 & 255; // 174
    const t9 = t8 | t6;  // 4383406

    // 计算第1个字符串
    const t10 = t9 & a; // 4194304
    const t11 = t10 >> 18; // 16
    const t12 = signValue.charAt(t11)
    token += t12;
    assert(token === `f`)

    // 计算第2个字符串
    const t13 = t9 & 258048;// 188416
    const t14 = t13 >> 12;
    const t15 = signValue.charAt(t14)
    token += t15;
    assert(token === `fm`)

    // 计算第3个字符串
    const t16 = t9 & 4032 ;// 640
    const t17 = t16 >> 6;
    const t18 = signValue.charAt(t17)
    token += t18;
    assert(token === `fmU`)

    // 计算第4个字符串
    const t19 = t9 & 63 ;// 640
    const t20 = signValue.charAt(t19)
    token += t20;
    assert(token === `fmUm`)

    // 计算第6个字符串
    const t21 = params.charCodeAt(3)
    const t22 = t21 & 255;
    const t23 = t22 << 16; // 16121856

    const t24 = params.charCodeAt(4)
    const t25 = t24 & 255;
    const t26 = t25 << 8;
    const t27 = t23 | t26; // 16137216

    const t28 = params.charCodeAt(5)
    const t29 = t28 & 255;
    // 关键值
    const t30 = t27 | t29; // 16137264
    const t31 = t30 & a; // 15990784

    const t32 = t31 >> 18;
    const tt33 = signValue.charAt(t32)
    token += tt33;
    assert(token === `fmUmt`)

    const t34 = t30 & 258048;
    const t35 = t34 >> 12;
    const t36 = signValue.charAt(t35)
    token += t36;
    assert(token === `fmUmtN`)

    console.log({ token })

    return token;
}

 

至此,我们已经可以发现一些潜在的规律。首先,我们需要确定关键值,然后根据数组[258048, 4032, 63]中的元素分别计算索引,并从字典中取出相应的字符串进行拼接,最终形成a_bogus。

import { assert } from "console"

const SALT_2: any = {
    "s0": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    "s1": "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
    "s2": "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
    "s3": "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe",
    "s4": "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"
}

const obj = {
    "0": "Bâ®ö<0\u0012¤)͈„QüÜ\u00184©¦¤ß`\u0003WÛVu9°j¹ÒNÂa妵?§øºÌ\u0007©í\u000f^\"¾\u0003|¤\u0001Þ­aÓmè‘c:ÔrâÀýñG¬EªÀ “9R¦»÷ $+‰\u0010ü ›b3\\\b5‚¦­Ê^Å\u0000l ÷uz",
    "1": "s3"
}
export function sign() {
    // 栈指针位置
    let token = ``
    const a = 16515072
    const params = obj["0"]
    const sign = obj["1"]
    const signValue = SALT_2[sign]
    const f1 = (v: number) => {
        [16515072, 258048, 4032, 63].map((val, i) => {
            const t1 = v & val;
            const t2 = i % 4
            if (t2 === 0) {
                const t3 = t1 >> 18
                const t4 = signValue.charAt(t3)
                token += t4;
            }
            if (t2 === 1) {
                const t3 = t1 >> 12
                const t4 = signValue.charAt(t3)
                token += t4;
            }
            if (t2 === 2) {
                const t3 = t1 >> 6
                const t4 = signValue.charAt(t3)
                token += t4;
            }
            if (t2 === 3) {
                const t4 = signValue.charAt(t1)
                token += t4;
            }
        })
    }
    let toSignValue = 0;
    for (let i = 0; i < params.length; i++) {
        const t0 = params.charCodeAt(i)
        const t1 = t0 & 255;
        const t2 = i % 3
        if (t2 === 0) {
            const t3 = t1 << 16;
            toSignValue = t3;
            continue;
        }
        if (t2 === 1) {
            const t3 = t1 << 8;
            toSignValue = toSignValue | t3;
            continue;
        }
        if (t2 === 2) {
            toSignValue = toSignValue | t1;
            f1(toSignValue)
            continue;
        }
    }
    console.log({ token })

    return token;
}

 

至此,a_bogus算法的还原工作已经顺利完成。在下一节中,我们将不再全面探讨参数obj,而是聚焦于其他关键环节。
 
各位亲爱的家人们,我目前正在积极寻找与逆向爬虫相关的工作机会。如果您手头有合适的职位,或者知道相关的工作信息,非常希望能得到您的内推帮助!
请登录后发表评论