skuukzky
文章9
标签0
分类2

文章分类

a_bogus-1.1.17版本插桩分析及还原

a_bogus-1.1.17版本插桩分析及还原

抖音 a_bogus 分析

1
2
3
4
5
6
7
8
9
10
摘选至52破解  https://www.52pojie.cn/thread-1974900-1-1.html
1. device_platform=*** + dhzx 进行2次sm3加密
2.dhzx 进行一次sm3加密
3.根据轨迹生成一个乱码,将该乱码和ua传入加密,加密后的结果再次进行sm3
4.多次时间戳操作具体操作看日志很清楚
5.轨迹加密成[x,x1,x2,x3]
6.6**3,6**1对这两个数操作
7.1721|403|1721|987|1728|987|1728|1117|MacIntel 对这个数charCodeAt放到一个数组
8.随机数和一些加密数组的操作,随机数生成一些数组的操作
9.最后根据上面的加密结果生成一个数组,然后传入一个乱码和这个数组加密,最后的魔改base64加密得到最终结果

分析

url 加密

插装点 var R = T.apply(E, j); 日志断点 "apply::: ","R:",R,"E:",E,"T:",T,"j:",j

接下来分别给 运算符插装 如 + - / >> << & * | ^ 日志断点例如 "v:",v,"p:",p,"v[p]:",v[p],"r:",r,"v[p] = v[p] / r :::",v[p] / r

image-20241101164546792

然后我们发包 再打上 xhr 断点 接着利用正则搜索我们的参数 [^']device_platform= 查看日志发现 在拼接参数然后再末尾拼接 dhzx 进行 sm3 加密 然后在基础上再进行一次 sm3 加密。比如 `sm3.sum(sm3.sum(url_search_params + suffix))

至于怎么知道是 sm3 的。我们可以手动点击日志中的 reset 函数 开发者工具会自动跳动函数 发现内部是个 sum 函数 我们可以全部扣出来 你也可以拿着部分代码放入百度 也能搜索到关于 sm3 加密的相关的细节

image-20241101165036648

同样的dhzx也是做了如上的两次 sm3 加密。

ua 加密

魔改的 rc4 算法 key 是String.fromCharCode.apply(null, [0.00390625, 1, 0) 在日志中是 '\x00\x01\x00'

加密文本则为 ua 请求头。

正常的 rc4 算法为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function rc4_encrypt(plaintext, key) {
  var s = [];
  for (var i = 0; i < 256; i++) {
    s[i] = i;
  }
  var j = 0;
  for (var i = 0; i < 256; i++) {
    j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
    var temp = s[i];
    s[i] = s[j];
    s[j] = temp;
  }

  var i = 0;
  var j = 0;
  var cipher = [];
  for (var k = 0; k < plaintext.length; k++) {
    i = (i + 1) % 256;
    j = (j + s[i]) % 256;
    var temp = s[i];
    s[i] = s[j];
    s[j] = temp;
    var t = (s[i] + s[j]) % 256;
    cipher.push(String.fromCharCode(s[t] ^ plaintext.charCodeAt(k)));
  }
  return cipher.join("");
}

第一出魔改点是倒取的 256 空数组 在日志呈现为

image-20241106213922476

第二处是 rc4 的密钥生成部分魔改

image-20241106214414876

应该是在把源码上的j + s[i]变为了 j * s[i]

加密部分还是 RC4 的原生 xor,实际上各种加密算法的魔改基本都是在密钥轮进行的,很少有魔改加密轮的。

还原后的代码应该是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function rc4_encrypt(plaintext, key) {
  var s = [];
  for (var i = 0; i < 256; i++) {
    s[i] = 255 - i;
  }

  var j = 0;
  for (var i = 0; i < 256; i++) {
    j = (j * s[i] + j + key.charCodeAt(i % key.length)) % 256;
    var temp = s[i];
    s[i] = s[j];
    s[j] = temp;
  }
  console.log(s);
  var i = 0;
  var j = 0;
  var cipher = [];
  for (var k = 0; k < plaintext.length; k++) {
    i = (i + 1) % 256;
    j = (j + s[i]) % 256;
    var temp = s[i];
    s[i] = s[j];
    s[j] = temp;
    var t = (s[i] + s[j]) % 256;
    cipher.push(String.fromCharCode(s[t] ^ plaintext.charCodeAt(k)));
  }
  return cipher.join("");
}

搜索部分发现和网页上是一样的人,如果不放心 后续 ua 还会进行 base64,sm3 加密可以进行结果对比。

image-20241106215618229

继续观察日志

image-20241106220614649

发现了一个=号。一般=号的出现在 base64 中比较常见 所以我们可以猜测他是对我们上一步的 rc4 做了 base64 加密

直接加密的结果是不对的 但我第二框圈出来了 很像一个 base64 的码表变化 我们在替换这个码表进行加密发现结果就对的上了。

image-20241106220930960

继续查看日志 我们看到了上文 sm3 的加密函数和结果 这次加密的内容是 base64 加密的结果 同样运行一下发现结果一样。
image-20241106221518206

版本号处理

1
2
3
4
5
6
7
version = "1.0.1.17-fix.01";
version_arr = version.split(".").map((item) => {
  // 尝试将字符串转换为数字
  const number = Number(item);
  // 如果转换成功且为整数,则返回该数字,否则返回0
  return Number.isInteger(number) ? number : 0;
});

直接 split 后数字化

短数组生成

可以先用工具固定时间戳 方便对比最终的结果。

然后根据 e 的索引进行 分析

image-20241108142224516

其中 e+1 是因为他代码中是递减的处理到这个代码时候索引应该+1 才是对应的。

对着日志继续分析,逻辑很清晰。

image-20241108142434106

随机数生成算法

代码抄至 github 的开源项目

1
2
3
4
5
6
7
8
function gener_random(random, option) {
  return [
    (random & 255 & 170) | (option[0] & 85),
    (random & 255 & 85) | (option[0] & 170),
    ((random >> 8) & 255 & 170) | (option[1] & 85),
    ((random >> 8) & 255 & 85) | (option[1] & 170),
  ];
}

两个位置用到,分别是:

1
2
3
n[86] = gener_random(Math.random() * 65535, [n[25][0], n[25][1]]).concat(
  gener_random(Math.random() * 65535, [n[25][2], n[25][3]])
);

1
n[89] = gener_random(Math.random() * 65535, [3, 82])`

短数组转长数组

这个是最重要的一部分 也是 ab 生成的关键数组了

先是 xor 生成校验位,然后拼接生成短数组 n[88]。

接着各种运算符操作把 99 位数组变成了 134 位数组。

image-20241108142834384

这里我给七神要了一份还原好后的代码。太多了 自己看的会很头疼

生成 ab

版本号数组拼接上面的 134 数组后 RC4,然后 8 位数组 String.fromCharCode 生成的字符串再拼接,最后同样的魔改 B64,得到的结果就是最终 ab。

1
2
3
4
5
6
7
8
9
10
n[90] = generateExpandArray(n[88]);

// console.log(generateExpandArray(n[90])); generateExpandArray 是99->134转化函数。
arr_133 = n[86].concat(n[90]);
n[91] = rc4_encrypt(
  String.fromCharCode.apply(null, arr_133),
  String.fromCharCode(211)
);
n[92] = String.fromCharCode.apply(null, n[89]) + n[91];
n[93] = result_encrypt(n[92], "s4"); //result_encrypt 魔改base64函数

最终结果

游客身份的二级评论 。

image-20241108143229432

评论下的继续展开

image-20241108143931244

尾章

绝大部分文笔都是抄了这篇文章 字节系 a_bogus 最新版本插桩分析及还原因为这篇比较新,而且写的文采也比我好就直接拿来复制粘贴了。

文章参考了:
字节系 a_bogus 最新版本插桩分析及还原 ,
某音 a_bogus 纯算分析 https://www.52pojie.cn/thread-1928860-1-1.html ,
a_bogus 逆向纯算

视频参考了:
最新抖音 JS 逆向 a_bogus【纯算版】 讲得不错就是没后续了。

以及老大哥七神的帮助。

本文作者:skuukzky
本文链接:https://lpy30m.github.io/skuukzky.github.io/2024/11/08/%E9%80%86%E5%90%91/a-bogus-1-1-17%E7%89%88%E6%9C%AC%E6%8F%92%E6%A1%A9%E5%88%86%E6%9E%90%E5%8F%8A%E8%BF%98%E5%8E%9F/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可