0


解析某音X-Bogus参数

文章目录

写在前面

本文主要介绍从X-Bogus还原19位数组的过程,方便理解算法。

目标

// 从var x_bogus ='DFSzswVVUyXANrqJSkdAml9WX7jG';// 还原出var x_array =[64,0.00390625,1,28,7,22,69,63,0,186,99,164,90,214,32,0,190,144,201];

正向梳理

主要加密函数

function_0x2f2740(a, c, e, b, d, f, t, n, o, i, r, _, x, u, s, l, v, h, g){let w =newUint8Array(19);return w[0]= a,
    w[1]= r,
    w[2]= c,
    w[3]= _,
    w[4]= e,
    w[5]= x,
    w[6]= b,
    w[7]= u,
    w[8]= d,
    w[9]= s,
    w[10]= f,
    w[11]= l,
    w[12]= t,
    w[13]= v,
    w[14]= n,
    w[15]= h,
    w[16]= o,
    w[17]= g,
    w[18]= i,
    String.fromCharCode.apply(null, w);}function_0x46fa4c(a, c){let e, b =[], d =0, f ="";for(let a =0; a <256; a++){
        b[a]= a;}for(let c =0; c <256; c++){
        d =(d + b[c]+ a.charCodeAt(c % a.length))%256,
        e = b[c],
        b[c]= b[d],
        b[d]= e;}let t =0;
    d =0;for(let a =0; a < c.length; a++){
        t =(t +1)%256,
        d =(d + b[t])%256,
        e = b[t],
        b[t]= b[d],
        b[d]= e,
        f += String.fromCharCode(c.charCodeAt(a)^ b[(b[t]+ b[d])%256]);}return f;}function_0x2b6720(a, c, e){return String.fromCharCode(a)+ String.fromCharCode(c)+ e;}

主要算法

以上三个函数来自某音web端

webmssdk.js

。x_array打乱顺序后,经过上述三个函数的混淆,最终变成21个字节的乱码字符串,乱码字符串再经过一系列变换,得到28位的x_bogus。
具体过程如下:

var short_str ="Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=";functionU8ArrayToXBogus(array1){// 打乱数组顺序
    array2 =[array1[0], array1[2], array1[4], array1[6], array1[8], array1[10], array1[12], array1[14], array1[16], array1[18], array1[1], array1[3], array1[5], array1[7], array1[9], array1[11], array1[13], array1[15], array1[17]];// 再一次打乱顺序,得到19位乱码字符串
    u1 =_0x2f2740.apply(null,array2);// 对乱码字符串重新编码(实际上是异或加密)
    u2 =_0x46fa4c.apply(null,[String.fromCharCode(255),u1]);// 在乱码字符串开头添加两个固定字符
    u =_0x2b6720.apply(null,[2,255,u2]);var XBogus ="";// 每次循环生成4个字符,循环7次,每次使用乱码字符串的三个字符for(var i =0; i <=20; i +=3){var charCodeAtNum0 = u.charCodeAt(i);var charCodeAtNum1 = u.charCodeAt(i +1);var charCodeAtNum2 = u.charCodeAt(i +2);var baseNum = charCodeAtNum2 | charCodeAtNum1 <<8| charCodeAtNum0 <<16;var str1 = short_str[(baseNum &0xfc0000)>>18];var str2 = short_str[(baseNum &0x3f000)>>12];var str3 = short_str[(baseNum &0xfc0)>>6];var str4 = short_str[(baseNum &0x3f)>>0];
        XBogus += str1 + str2 + str3 + str4;}return XBogus;}

解析

x_array打乱顺序得到如下数组:

array2 =[64,1,7,69,0,99,90,32,190,201,0.00390625,28,22,63,186,164,214,0,144];
_0x2f2740.apply(null,array2)

得到:

var u1 ='@\x00\x01\x1C\x07\x16E?\x00ºc¤ZÖ \x00¾\x90É';// 数组形式// [64, 0, 1, 28, 7, 22, 69, 63, 0, 186, 99, 164, 90, 214, 32, 0, 190, 144, 201]
_0x2f2740

函数打乱数组顺序,并以字符串形式返回。

_0x46fa4c.apply(null,[String.fromCharCode(255),u1])

得到:

var u2 ='-%.8wE^\x8F9ñð\x10\x9E¹ý\x9CV,9';// 数组形式// [45, 37, 46, 56, 119, 69, 94, 143, 57, 241, 240, 16, 158, 185, 253, 156, 86, 44, 57]
_0x46fa4c

根据传入的第一个参数生成长度256的数组,u1与数组成员做异或运算,得到u2;
异或运算存在以下特征,明文与key异或得到加密结果,加密结果与key异或得到明文:

a =11,b =12;
a ^ b =7;
a ^7= b;
b ^7= a;

所以

_0x46fa4c.apply(null,[String.fromCharCode(255),u2])

可还原到u1。

_0x2b6720.apply(null,[2,255,u2])

得到:

u ='\x02ÿ-%.8wE^\x8F9ñð\x10\x9E¹ý\x9CV,9';// 数组形式
u_arr =[2,255,45,37,46,56,119,69,94,143,57,241,240,16,158,185,253,156,86,44,57]

取u_arr前三位,进行位运算得到第一个种子数字:

>>>(2<<16)|(255<<8)|45196397>>>hex(196397)'0x2ff2d'>>>

对种子数字再进行运算,这里需要配合二进制一起看:

>>> short_str ="Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=">>> binex =lambda x:'0'*(24-len(bin(x))+2)+bin(x).replace('0b','')>>> binex(0x2ff2d)'000000101111111100101101'>>> binex(0xfc0000)'111111000000000000000000'>>> binex(0xfc0000&0x2ff2d)'000000000000000000000000'>>> binex(0x3f000)'000000111111000000000000'>>> binex(0x3f000&0x2ff2d)'000000101111000000000000'>>> binex(0xfc0)'000000000000111111000000'>>> binex(0xfc0&0x2ff2d)'000000000000111100000000'>>> binex(0x3f)'000000000000000000111111'>>> binex(0x3f&0x2ff2d)'000000000000000000101101'

实际上是将一个24位二进制数拆分为4个6位二进制数字,得到4个下标:

>>>bin((0x2ff2d&0xfc0000)>>18)'0b0'>>>bin((0x2ff2d&0x3f000)>>12)'0b101111'>>>bin((0x2ff2d&0xfc0)>>6)'0b111100'>>>bin((0x2ff2d&0x3f)>>0)'0b101101'

换算成十进制,分别是

0,47,60,45
>>> short_str[0]'D'>>> short_str[47]'F'>>> short_str[60]'S'>>> short_str[45]'z'

与原始字符串的

DFSzswVVUyXANrqJSkdAml9WX7jG

的前四个字符一致。
再进行六次循环,即可得到完整的x_bogus。

逆向梳理

前面的内容已经把整体的思路写出来了,再简单梳理一下流程吧。

>>> short_str.index('D')0>>> short_str.index('F')47>>> short_str.index('S')60>>> short_str.index('z')45>>>0<<18|47<<12|60<<6|45<<0196397>>> binex(0<<18|47<<12|60<<6|45<<0)'000000101111111100101101'>>>hex(0<<18|47<<12|60<<6|45<<0)'0x2ff2d'>>>0x2ff2d>>16&0xff2>>>0x2ff2d>>8&0xff255>>>0x2ff2d>>0&0xff45

这样就成功还原了数组u_arr的第0到第2个成员,再来看第二组:

>>> short_str.index('s')9>>> short_str.index('w')18>>> short_str.index('V')56>>> short_str.index('V')56>>> binex(9<<18|18<<12|56<<6|56<<0)'001001010010111000111000'>>>hex(9<<18|18<<12|56<<6|56<<0)'0x252e38'>>>9<<18|18<<12|56<<6|56<<02436664>>>0x252e38>>16&0xff37>>>0x252e38>>8&0xff46>>>0x252e38>>0&0xff56

也成功还原了u_arr的第3到第5个成员。

结论

根据上述分析,可整理出还原函数:

functionXBogusToU8Array(x_bogus){
    u ="";for(i =0;i<x_bogus.length;i+=4){
        seed =0;
        seed |= short_str.indexOf(x_bogus[i])<<18;
        seed |= short_str.indexOf(x_bogus[i +1])<<12;
        seed |= short_str.indexOf(x_bogus[i +2])<<6;
        seed |= short_str.indexOf(x_bogus[i +3])<<0;
        u += String.fromCharCode(seed >>16&0xff);
        u += String.fromCharCode(seed >>8&0xff);
        u += String.fromCharCode(seed &0xff);}
    u2 =_0x46fa4c.apply(null,[String.fromCharCode(255),u.slice(2)]);
    a = u2.charCodeAt(0),r = u2.charCodeAt(1),c = u2.charCodeAt(2),_ = u2.charCodeAt(3),
    e = u2.charCodeAt(4),x = u2.charCodeAt(5),b = u2.charCodeAt(6),u = u2.charCodeAt(7),
    d = u2.charCodeAt(8),s = u2.charCodeAt(9),f = u2.charCodeAt(10),l = u2.charCodeAt(11),
    t = u2.charCodeAt(12),v = u2.charCodeAt(13),n = u2.charCodeAt(14),h = u2.charCodeAt(15),
    o = u2.charCodeAt(16),g = u2.charCodeAt(17),i = u2.charCodeAt(18);
    arr =[a, c, e, b, d, f, t, n, o, i, r, _, x, u, s, l, v, h, g];
    arr =[arr[0],arr[10],arr[1],arr[11],arr[2],arr[12],arr[3],arr[13],arr[4],arr[14],arr[5],arr[15],
           arr[6],arr[16],arr[7],arr[17],arr[8],arr[18],arr[9]];
    arr[1]= arr[1]+0.00390625;return arr;}

测试

在这里插入图片描述

进阶

x_array可拆分成8个部分:

x_array =[64,0.00390625,1,28,7,22,69,63,0,186,99,164,90,214,32,0,190,144,201];// 第一部分,固定值
x_1 =[64];// 第二部分,UA加密过程使用的salt,小数在运算过程中会取整
x_2 =[0.00390625,1,28];// 第三部分,Query String Parameters经过md5变换得到
x_3 =[7,22];// 第四部分,form data经过md5变换得到,[69,63]对应的是空字符串
x_4 =[69,63];// 第五部分,UA和x_2经过一系列变换得到long_str,long_str经过md5变换得到x_5
x_5 =[0,186];// 第六部分,32位时间戳转换为byte数组
x_6 =[99,164,90,214];// 第七部分,canvas生成dataurl,与3735928559经过位运算得到32位数字,转换为byte数组
x_7 =[32,0,190,144];// 第八部分,0和前面18个数字逐个进行异或得到
x_8 =[201];

由此可见,X-Bogus会对params、form-data、user-agent、时间、canvas进行校验。

写在后面

本文章中所有内容仅供学习交流使用,不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
若有侵权,请联系我立即删除。

标签: 安全 javascript

本文转载自: https://blog.csdn.net/ljc545w/article/details/128834402
版权归原作者 勇敢自由 所有, 如有侵权,请联系我们删除。

“解析某音X-Bogus参数”的评论:

还没有评论