声明
本博文所讨论的技术仅用于研究学习,旨在增强读者的信息安全意识,提高信息安全防护技能,严禁用于非法活动。任何个人、团体、组织不得用于非法目的,违法犯罪必将受到法律的严厉制裁。
流量分析,数据接口均已做脱敏处理,若造成侵权,请立即联系博主删除!
逆向目标
目标:计算所有机票价格的平均值;
链接:BRWJ2YmdUFp1VdEyUbAcWGW4cfrjRrTLmWwfZZTiEvmN1ikY;
简介:获取所有页面中机票的价格,并计算所有机票价格的平均值,需注意数据均为模拟数据,请正确识别;
逆向分析
0x01 跳过断点
当我们按 F12 进入调试控制台时,发现此处有 debugger
,直接右键将其 nop 掉。
0x02 分析接口
通过 API 接口我们能够发现,数据内容没有被加密,因此,我们只需要遍历所有页面的 API 接口,即可获取到全部机票价格,那么,我们的目标就是逆向 API 接口上的参数 m
。
page: 2
m: 9ded2bedaa92ac18c32ce095e44a6765丨1723437277
根据观察推测 m
应该分为两部分:cipher | timestamp
,接下来去请求调用堆栈中寻找蛛丝马迹。
发现一个 request
函数,步入相应位置,映入眼帘的就是时间戳的计算,应该就是我们要找寻的关键函数了。
由上图可知,JS 代码被略微混淆了,通过 JS 在线解密工具来进行解密:
一眼就看到了 m
参数:
_0x5d83a3['m'] = _0x57feae '丨' _0x2268f9 / ( - 1 * 3483 -9059 13542);
接下来,我们就开始分析 cipher
和 timestamp
部分。
0x03 timestamp 分析
柿子要挑软的捏,我们先来研究时间戳这块,主要就是由两个步骤构成,转换后的代码如下所示:
代码语言:javascript复制function getTimestamp() {
const _0x2268f9 = Date['parse'](new Date()) (16798545 -72936737 156138192)
return _0x2268f9 / (-1 * 3483 -9059 13542)
}
验证一下没啥问题,继续往下走。
0x04 cipher 分析
根据代码分析,cipher
由 oo0O0()
函数与 window['f']
参数构成:
_0x57feae = oo0O0(_0x2268f9['toStr' 'ing']()) window['f'];
全局搜索 oo0O0()
函数,如下图所示:
oo0O0()
函数的主要目的是隐藏和执行某些动态生成的 JavaScript 代码,可以分为以下三个部分进行理解:
第一部分的主要作用是构建 window.b
:
for (var i = 0, len = window.a.length; i < len; i ) {
console.log(window.a[i]);
window.b = String[document.e document.g](window.a[i][document.f document.h]() - i - window.c)
}
上述代码通过 window.a
的每个元素,计算一个字符的 ASCII 值,减去一个值,并将结果拼接到 window.b
中。这里使用了动态属性名来访问 String
对象的 fromCharCode
方法。
第二部分的主要作用是定义和使用 J
函数。J
是一个用于解码和处理字符串的函数,这个函数利用了 Base64 解码和 RC4 加密算法来解密字符串。
第三部分的主要作用是解密和执行代码:
代码语言:javascript复制eval(atob(window['b'])[J('0x0', ']dQW')](J('0x1', 'GTu!'), 'x27' mw 'x27'));
上述代码的解释如下:
atob(window['b'])
:对window.b
进行 Base64 解码。J('0x0', ']dQW')
和J('0x1', 'GTu!')
:解码后的字符串通过J
函数进一步处理。eval(...)
:执行解密后的 JavaScript 代码。
其中,J('0x0', ']dQW')
和 J('0x1', 'GTu!')
是固定的,直接通过动调获取返回值,如下图所示:
因此,第三部分代码可以转换为:
代码语言:javascript复制eval(atob(window['b'])['replace']('mwqqppz', 'x27' mw 'x27'));
而 atob(window['b'])
也可以直接解码,其实际作用是给 window.f
赋值,window.f = hex_md5(mwqqppz)
如下图所示:
在上述代码中还用到了几个常量,通过全局搜索即可获得,代码如下所示:
代码语言:javascript复制document.e = 'fromC';
document.f = 'charCo';
document.g = 'harCode';
document.h = 'deAt';
window.a = '...'
window.c = 5
window.a
太大了,这里就不做展示了。
0x05 验证结果
将我们上述的所有分析进行整理,代码如下所示:
代码语言:javascript复制window = {
a: '...',
c: 5,
}
document = {
e: 'fromC',
f: 'charCo',
g: 'harCode',
h: 'deAt',
}
function oo0O0(mw) {...}
然后再来验证一下,通过动调获取到当前的一个加密结果,如下图所示:
我们也将时间戳改成 1723453378000,代码如下所示:
代码语言:javascript复制function results() {
// const _0x2268f9 = Date['parse'](new Date()) (16798545 -72936737 156138192)
const _0x2268f9 = 1723453378000
return {timestamp: _0x2268f9 / 1000, cipher: oo0O0(_0x2268f9) window.f}
}
console.log(results())
运行结果如下所示:
与实际结果相符,证明我们逆向的没有问题。
最终利用
使用 Python 编写脚本去尝试请求数据,代码如下所示:
代码语言:javascript复制import execjs
import requests
with open('CodeJs.js', 'r', encoding='utf8') as f:
js_code = f.read()
context = execjs.compile(js_code).call('results')
m = f'{context["cipher"]}丨{context["timestamp"]}'
url = "..."
response = requests.get(f'{url}?page=1&m={m}')
print(response.text)
运行结果:
利用成功,那我们开始计算所有机票价格的平均值,代码如下所示:
代码语言:javascript复制url = "..."
total_sum = 0
total_cnt = 0
for i in range(5):
response = requests.get(f'{url}?page={i 1}&m={m}')
data = response.json()["data"]
cnt_ = len(data)
sum_ = sum(item["value"] for item in data)
total_sum = sum_
total_cnt = cnt_
print(f"P{i 1} sum is {sum_}, cnt is {cnt_}")
print("All:", total_sum)
print("Average:", total_sum / total_cnt)
运行结果:
至此,我们就成功完成了逆向目标。
后记
在本文中,我们深入探讨了混淆源码的逆向分析过程,通过一系列的步骤逐步破解了复杂的混淆技术。从跳过断点到分析接口,再到 timestamp 和 cipher 的深入研究,我们不仅掌握了如何应对复杂的 JS 混淆技术,也提供了针对性的解决策略。
以上就是博文 JS 逆向实战:深入解析 JS 源码混淆案例 的所有内容了,希望本篇博文对大家有所帮助!欢迎大家持续关注我的博客,一起分享学习和成长的乐趣!✨
严正声明:本博文所讨论的技术仅用于研究学习,旨在增强读者的信息安全意识,提高信息安全防护技能,严禁用于非法活动。任何个人、团体、组织不得用于非法目的,违法犯罪必将受到法律的严厉制裁。