解析某音X-Bogus参数

news2024/11/16 18:50:53

文章目录

    • 写在前面
    • 目标
    • 正向梳理
      • 主要加密函数
      • 主要算法
      • 解析
    • 逆向梳理
    • 结论
    • 测试
    • 进阶
    • 写在后面

写在前面

本文主要介绍从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 = new Uint8Array(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=";
function U8ArrayToXBogus(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) | 45
196397
>>> 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 << 0
196397
>>> binex(0 << 18 | 47 << 12 | 60 << 6 | 45 << 0)
'000000101111111100101101'
>>> hex(0 << 18 | 47 << 12 | 60 << 6 | 45 << 0)
'0x2ff2d'
>>> 0x2ff2d >> 16 & 0xff
2
>>> 0x2ff2d >> 8 & 0xff
255
>>> 0x2ff2d >> 0 & 0xff
45

这样就成功还原了数组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 << 0
2436664
>>> 0x252e38 >> 16 & 0xff
37
>>> 0x252e38 >> 8 & 0xff
46
>>> 0x252e38 >> 0 & 0xff
56

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

结论

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

function XBogusToU8Array(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进行校验。

写在后面

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/192756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Dubbo 入门系列之快速部署一个微服务应用

本文将基于 Dubbo Samples 示例演示如何快速搭建并部署一个微服务应用。 背景 Dubbo 作为一款微服务框架&#xff0c;最重要的是向用户提供跨进程的 RPC 远程调用能力。如上图所示&#xff0c;Dubbo 的服务消费者&#xff08;Consumer&#xff09;通过一系列的工作将请求发送给…

FatFs文件系统(只针对SPI-Flash)总结

作用 当我们利用SPI操作Flash时往往读写的都是一段连续的扇区&#xff0c;而FatFs文件系统可以将我们要写入的数据拆分成不连续的扇区见缝插针写入&#xff0c;类似与链表一块扇区指向下一块扇区&#xff0c;不需要物理逻辑地址连续也可以读取整个文件。 这是为啥嘞&#xff…

从零开始部署“生产级别”的主从模式Mysql

从零开始部署“生产级别”的主从模式Mysql 1. 撰写的缘由 Mysql 在日常应用中使用范围非常广泛&#xff0c;它的部署&#xff0c;其实一个docker run 就可以搞定了&#xff0c;但是这种单个standalone模式下&#xff0c;非常不具备高可用性。 测试环境和开发可以随便用&…

集团审计BI项目的特点

审计到底做哪些事情呢&#xff1f;如果之前大家没有接触的话&#xff0c;试着想一下&#xff0c;可能都会想到审计工作做的应该是跟监督有关的事情。实际上&#xff0c;现代审计职责不仅仅只是监督&#xff0c;还要兼顾到服务&#xff0c;具有监督和服务的双重属性。 什么是审…

stm32学习笔记-2 软件安装及创建工程

2 软件安装及创建工程 [toc] 注&#xff1a;笔记主要参考B站 江科大自化协 教学视频“STM32入门教程-2023持续更新中”。 注&#xff1a;工程及代码文件放在了本人的Github仓库。 2.1 软件安装 软件安装的步骤有&#xff1a; 安装Keil5 MDK。Keil5 MDK专门用于给ARM系列单片…

网络安全规划实践

在企业IT战略规划方面&#xff0c;很多时候我们会自动忽略网络安全规划&#xff0c;一是不够重视&#xff0c;从公司到技术部门&#xff0c;对网络安全的认识有限&#xff0c;重视不够&#xff0c;不愿意花钱。 二是技术部门自身原因&#xff0c;不愿意多花成本和精力去规划&am…

推荐14款最受欢迎的3d建模软件

最好的 3D 建模软件可以毫不费力地设计出最奇特的创意&#xff0c;并将它们变成令人惊叹的 3D 可视化效果。如果您确切知道要设计的模型类型&#xff0c;请查看此 3D 建模软件列表&#xff0c;比较 15 种一流的 3D 建模平台&#xff0c;然后选择最适合您的一款。最佳 3D 建模软…

金兔迎福报、新春第一炮【2022 中国开源年度报告】!

【中国开源年度报告】由开源社从 2015 年发起&#xff0c;是国内首个结合多个开源社区、高校、媒体、风投、企业与个人&#xff0c;以纯志愿、非营利的理念和开源社区协作的模式&#xff0c;携手共创完成的开源研究报告。后来由于一些因素暂停&#xff0c;在 2018 年重启了这个…

【王道数据结构】第一章 | 绪论 | 数据结构与算法的概念

目录 1.1数据结构的基本概念 1.2数据结构的三要素 1&#xff09;.数据的逻辑结构&#xff1a; 2&#xff09;.数据的存储结构&#xff08;物理结构&#xff09;&#xff1a; 3&#xff09;.数据的运算 4&#xff09;.数据类型和抽线数据类型 1.3算法的基本概念 1.4 空间…

人大金仓数据库分区表

分区表 声明式创建分区 按列创建分区&#xff08;PARTITION BY LIST&#xff09; 将学员表student按所在城市使用partition by list创建分区 创建分区表&#xff08;基表&#xff09; 创建格式 create table 表名&#xff08;字段名 数据类型&#xff09;PARTITION BY LI…

Redis哨兵工作原理 | 黑马Redis高级篇

哨兵的作用 Redis提供了哨兵机制来实现主从集群的自动故障恢复 监控&#xff1a;sentinel会不断检查master和slave是否按照预期工作 自动故障恢复&#xff1a;如果master故障&#xff0c;sentinel会将一个slave变为master&#xff0c;当故障实例恢复后也以新的master为主 通…

低代码平台助力交通行业数字化科学管理

编者按&#xff1a;本文分析了交通行业的数字化转型需求&#xff0c;并指出了适合交通行业的低代码平台的特性&#xff0c;最后通过相关案例进行了功能展示。关键词&#xff1a;对接能力&#xff0c;国产化&#xff0c;数据引擎&#xff0c;智能化交通运输是国民经济先导性、战…

3、基本的SELECT语句

文章目录1. SQL概述1.1 SQL背景知识1.2 SQL语言排行榜1.3 SQL 分类2 SQL语言的规则与规范2.1 基本规则2.2 SQL大小写规范 &#xff08;建议遵守&#xff09;2.3 注 释2.4 命名规则&#xff08;暂时了解&#xff09;2.5 数据导入指令3 基本的SELECT语句3.0 SELECT...3.1 SELECT …

大数据技术架构(组件)15——Hive:内置UDAF函数

1.4.10、内置UDAF函数1.4.10.1、count--可以发现count(id)会把idnull的值剔除掉select count(1),count(*),count(distinct id),count(id) from test1.4.10.2、sumselect sum(1) from test;1.4.10.3、avg该函数太简单了&#xff0c;就不给大家演示了1.4.10.4、min该函数太简单了…

Hive(5):数据定义语言(DDL)

1 数据定义语言&#xff08;DDL&#xff09;概述 1.1 DDL语法的作用 数据定义语言 (Data Definition Language, DDL)&#xff0c;是SQL语言集中对数据库内部的对象结构进行创建&#xff0c;删除&#xff0c;修改等的操作语言&#xff0c;这些数据库对象包括database&#xff…

面试官问 ,Mybatis SELECT 查询, 集合或者单个对象,如果数据库不存在数据,需要判空吗?

前言 于昨日下班时段&#xff0c;本人正在与生活作斗争&#xff0c;收到了金三银四一线作战小队成员紧急反应的战况问题。 不熟悉的或者是不知道怎么去看源码的看官&#xff0c;上车了。 正文 这面试题问的&#xff0c; 考察的是什么&#xff1f; ① mybatis框架的应用掌握情…

如何实现报表集成?(三)——资源集成

在上一篇&#xff0c;我们介绍了用户同步和单点登录&#xff0c;帮助用户了解什么是用户同步、如何做用户验证&#xff0c;以及如何实现单点登录。 这一篇&#xff0c;我们看下如何做资源集成。行文过程中得到了来自报表软件厂商 Smartbi 的报表产品&#xff1a;电子表格软件的…

leetcode-每日一题-1663-具有给定数值的最小字符串(简单,贪心)

很久没有做过贪心类型的题目了&#xff0c;因为用的很少&#xff0c;大多都用的dp&#xff0c;这道题第一眼看过去以为是dp&#xff0c;因为力扣里面的中等题很多都是dp&#xff0c;但仔细一看发现是贪心&#xff0c;思路其实很简单&#xff0c;先全部最小&#xff0c;中间插一…

机械设备ERP系统可以给企业带来哪些好处?

随着信息化技术的进步与智能制造的发展趋势&#xff0c;很多制造企业也在一直探寻适合自己的信息化管理转型之路。机械设备EPR系统对于机械设备制造企业来说就是关键一环。要充分发挥出机械设备ERP系统的赋能作用&#xff0c;必不可少的是从生产制造的各个环节出发&#xff0c;…

ONLYOFFICE 文档 v7.3 现已发布:表单角色、SmartArt、安全性设置、查看窗口等功能

在 ONLYOFFICE 最新版本的在线编辑器中现已提供高级表单、SmartArt 图形插入、增强密码保护和公式计算、幻灯片特殊粘贴项等多项功能。继续阅读以了解所有更新。 字段填写接收人角色 现在&#xff0c;数字表单将更加高效。您可为需要填写表单的用户分配各种角色&#xff0c;简…