xhs x-s参数逆向,2024.8.11更新
该内容需要有一定逆向知识储备
1.替换js
替换js文件的方案有很多,下面我介绍我自己比较喜欢的替换方案
- a.右键js文件右键选择在来源面板打开
- b.选择替换内容,再选择文件夹位置,js文件就是自动存储到本地。如果你修改了js文件网页所对应的js代码就会修改
2.打日志
打日志方法有很多,如果有其他更好的位置也可以进行打印
- 下面是我自己的打印方案
- 打印位置1,这里我判断_0x4ba869是否为数组,是的话就进行打印
- 打印位置2,运算符^的位置,可以全局搜索
- 断点位置1,我们在这里进行断点,这样xs就只执行一次,有利于分析,有能力的话,也可以补环境进行分析
3.找关键
我这边的定位是找32位key,因为上个版本就是3des黑盒找key,所以打印日志的时候,数组长度过滤出32位的进行打印,结果没找到。
我就怀疑修改了算法,所以重新从数组里面找找,看看有没有什么关键词。
这里看到4个256位的数组,这不就是aes的te0,te1,te2,te3吗?盲猜可能是aes加解密。
我们再往下找找看看,看一看待加密内容是什么,这里出现一个像待加密内容的数组,我们把它转换成字符串看看。
果然是上个版本的待加密内容 eDE9ZDEzZWMxY2I1Y2Y2Mxxxxxxxxxxx
我是怎么知道是字符串呢,因为101,68,69这些都是A-Za-z0-9的字节,所以一眼看出这是一段字符串
这段144位数组最后几位不是字符串字节,而且16位16的字节,盲猜padding
如果到这边还可以进行盲猜,盲猜是ecb还是cbc,正常来说cbc可能会偏多,所以就要找一下iv和key,如果是ecb就不要iv。
找iv方案
这里我介绍一下我找模式方案,判断是ecb还是cbc,
- ecb模式 待加密前16位字节转成大端的int32(正常是uint32,只是js是没有无符号的,所以改成int32进行统一)
- cbc模式 待加密前16位字节跟iv进行异或,公式:src[0:16] ^ iv[0:16],下图就是go的cbc源码
cbc加密逻辑
- 待加密数组为16位字节一轮进行计算(看key的长度,可能是16, 24, 32)
- 每一轮16位字节会跟iv进行异或(xor)计算
- 所以我们就关心第一轮计算
这里我先试了ecb模式,先搜索控制台看看是否存在,如果不存在再找找iv
果然没有,这时候就转战到cbc
上面cbc原理我们知道了,我们开始找跟待加密进行异或(xor)的内容
我从控制台找到一个符合结果,待加密^iv,这就是我们要的iv
109, 104, 97, 113, 104, 110, 106, 109, 114, 48, 114, 115, 111, 111, 51, 111,就是iv内容
接下来我们就是要开始找key了
4.寻找aeskey
我下面就通俗的说了,不扯什么roundkey,subbytes了
- 16位 aeskey一般会转换成 [4]uint32,4*4数组,[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],16个字节
- aeskey会跟每一轮的16位字节加密内容进行xor
- 流程:aeskey ^ (src[0:16] ^ iv)
- 有流程开始寻找key
src计算过程
scss
// src是待加密内容
// iv是aes key
// src: 101,68,69,57,77,109,89,53,78,122,66,104,78,68,69,51
// iv: 109,104,97,113,104,110,106,109,114,48,114,115,111,111,51,111
// dst: 8,44,36,72,37,3,51,88,60,74,48,27,33,43,118,92
function calc(src, iv) {
let res = [];
for (let i = 0; i < src.length; i++) {
res.push(src[i] ^ iv[i]);
}
return res;
}
console.log(calc(
[101,68,69,57,77,109,89,53,78,122,66,104,78,68,69,51],
[109,104,97,113,104,110,106,109,114,48,114,115,111,111,51,111]
))
// 转换成[u]uint32
function uint32FromBytesBigEndian(bytes) {
return (bytes[3] | (bytes[2] << 8) | (bytes[1] << 16) | (bytes[0] << 24)) >>> 0;
}
console.log(uint32FromBytesBigEndian([8,44,36,72])) // 运行结果137110600
console.log(uint32FromBytesBigEndian([37,3,51,88])) // 运行结果620966744
console.log(uint32FromBytesBigEndian([60,74,48,27])) // 运行结果1011494939
console.log(uint32FromBytesBigEndian([33,43,118,92])) // 运行结果556496476
上面已经把代码贴出来了,看不懂也没办法了。
我们把上面运行结果再控制台搜索,每一个出现的一个结果就是aeskey,一共有4个,4个组合起来就是aeskey
5.测试结果
pass