JS调试技巧:如何让时间和随机数“听你指挥”?升级版!

admin 2026-04-16 04:03:37 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文针对JS逆向中固定随机数易被检测导致死循环的问题,提出升级Hook方案。核心是采用伪随机数组重放或伪随机算法替代固定返回值,使结果确定且不重复,从而绕过反爬检测。该思路同样适用于固定时间。建议在逆向分析中使用此法提升Hook隐蔽性,并在数组越界时用原生函数兜底以防报错。 综合评分: 85 文章分类: 逆向分析,WEB安全,爬虫


cover_image

JS调试技巧:如何让时间和随机数“听你指挥”?升级版!

原创

LLLibra146 LLLibra146

LLLibra146

2025年5月28日 08:02 北京

在小说阅读器读本章

去阅读

大家好,之前写过一篇JS调试技巧:如何让时间和随机数“听你指挥”?的文章,讲到了如何固定时间和随机数,让随机的结果变得固定。本篇文章分享一种升级版的方法,让固定方法不那么容易被发现。

固定随机数

上一篇文章中提到,使用 hook 方法固定随机数,如果只是单纯的固定随机数让其返回一个固定的值,在某些情况下容易被发现,一旦被检测到随机数的返回值固定不变,就会导致代码死循环或者报错。

猿人学 2024 新春题目就会检测随机数,如果我固定 0.5 的话,就会卡死浏览器,猜测应该是走了错误的分支。

这个时候,要如何让随机数的结果“固定”,但是又不“固定”呢?答案就是伪随机数。

伪随机数的生成有两种方式,一种是伪随机数数组,使用一个固定的数组来模拟,另一种就是伪随机算法。

伪随机数数组

伪随机数数组的实现方案有两种,一种是使用固定的随机数数组来模拟随机数,另一种就是使用伪随机数算法,来动态的计算随机数。一个是实时计算,另一个是提前计算然后存储起来,大同小异。

这里我使用固定的随机数数组来模拟伪随机数,首先看下之前的固定随机数的方案:

// 备份原函数
const originalRandom = Math.random;
// 重写为固定返回值
Math.random = function() {
    return 0.123456789; // 替换为所需固定值
};
// 防止检测:伪装原生函数特征
Math.random.toString = function() {
    return "function random() { [native code] }";
};

为了能获取一些随机数用于填充数组,要先修改上面的方法,新建一个数组来存储获取到的随机数,然后运行一遍程序,填充数组后再重放即可。

const originalRandom = Math.random;
let list = [];
Math.random = function () {
    let value = originalRandom();
    list.push(value);
    return value;
};

执行上面的 hook,list 数组会被填充,获取 list 数组的值并保存下来。

const originalRandom = Math.random;
let list = [0.1, 0.2, 0.3, 0.4, 0.5];
let count = 0
Math.random = function () {
    return list[count++];
};

修改 hook 代码后使用数组的值重放即可,后面无论如何调用随机数函数,都会获得一个固定的随机数序列。

这里会有一个问题,如果 hook 以后随机数调用的次数超出了数组的长度怎么办?

这个时候需要定义一个比较长的数组,或者使用后备方案,如果真的超出了,为了不报错就使用真实的随机数函数好了。

修改代码如下:

const originalRandom = Math.random;
let list = [0.1, 0.2, 0.3, 0.4, 0.5];
let count = 0
Math.random = function () {
    return list[count++] || originalRandom();
};

在数组越界后调用真实的随机数即可。

伪随机算法

如果不想保存一个很大的数组,可以考虑使用伪随机算法,伪随机算法可以保证对于同一个种子,输出相同的随机数。举个例子:

function createXorshift32(seed) {
var state = typeof seed === 'number' ? seed : 1;

returnfunction() {
    var x = state;
&nbsp; &nbsp; x ^= x <<&nbsp;13;
&nbsp; &nbsp; x ^= x >>&nbsp;17;
&nbsp; &nbsp; x ^= x <<&nbsp;5;
&nbsp; &nbsp; state = x;
&nbsp; &nbsp;&nbsp;return&nbsp;(x >>>&nbsp;0) /&nbsp;0xFFFFFFFF;&nbsp;// 转为 [0, 1)
&nbsp; };
}

// 使用示例
var&nbsp;xorshift = createXorshift32(456);
console.log(xorshift());

执行结果:

image-20250527231646750

可以看到,针对相同的种子,获取的随机数是相同的。

当然这里大家也可以使用自己的伪随机算法,或者自己创造一个都可以,其实伪随机算法就是一个比较简单的计算,根据输入计算输出即可,只要结果符合随机数的范围。

还有更多伪随机算法我这里只写一个,大家可以自行搜集。

function&nbsp;createMulberry32(seed)&nbsp;{
var&nbsp;state =&nbsp;typeof&nbsp;seed ===&nbsp;'number'&nbsp;? seed :&nbsp;1;

returnfunction()&nbsp;{
&nbsp; &nbsp; state +=&nbsp;0x6D2B79F5;
&nbsp; &nbsp;&nbsp;var&nbsp;t = state;
&nbsp; &nbsp; t =&nbsp;Math.imul(t ^ t >>>&nbsp;15, t |&nbsp;1);
&nbsp; &nbsp; t ^= t +&nbsp;Math.imul(t ^ t >>>&nbsp;7, t |&nbsp;61);
&nbsp; &nbsp;&nbsp;return&nbsp;((t ^ t >>>&nbsp;14) >>>&nbsp;0) /&nbsp;0xFFFFFFFF;
&nbsp; };
}

// 使用示例
var&nbsp;mulberry = createMulberry32(789);
console.log(mulberry());

有了伪随机算法后,更改随机数 hook 方案为以下代码即可:

let&nbsp;count =&nbsp;0
Math.random =&nbsp;function&nbsp;()&nbsp;{
&nbsp; &nbsp;&nbsp;return&nbsp;createXorshift32(count++)()
};

function&nbsp;createXorshift32(seed)&nbsp;{
&nbsp; &nbsp;&nbsp;var&nbsp;state =&nbsp;typeof&nbsp;seed ===&nbsp;'number'&nbsp;? seed :&nbsp;1;

&nbsp; &nbsp;&nbsp;returnfunction()&nbsp;{
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;var&nbsp;x = state;
&nbsp; &nbsp; &nbsp; &nbsp; x ^= x <<&nbsp;13;
&nbsp; &nbsp; &nbsp; &nbsp; x ^= x >>&nbsp;17;
&nbsp; &nbsp; &nbsp; &nbsp; x ^= x <<&nbsp;5;
&nbsp; &nbsp; &nbsp; &nbsp; state = x;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;(x >>>&nbsp;0) /&nbsp;0xFFFFFFFF;&nbsp;// 转为 [0, 1)
&nbsp; &nbsp; };
}

运行结果如下:

image-20250527232021998

结果符合预期。只是数据不是特别“随机”,这个就需要大家去调整伪随机算法了。

注:以上部分方案来自于零点大佬的 B 站视频(https://www.bilibili.com/video/BV1Eu4m1A7Zm/),在此感谢零点大佬的分享。

固定时间

固定时间的方案和固定随机数相同,只不过时间是递增的,也可以使用数组保存起来重放,具体代码就留给大家自行实现啦。

总结

以上就是升级版的固定随机数和时间的方案了,对于猿人学 2024 新春题目可以达到完美的固定效果,大家感兴趣可以尝试一下。

最近一直有小伙伴问我有没有交流群,为了能让大家更好的交流,我组建了一个逆向交流群,想要进群的小伙伴可以在后台点击“联系我”菜单或者扫码,添加微信并且备注“交流群”,我会拉你进群。

推荐阅读:

AST 技巧:模版(template)的高级用法

如何在浏览器中使用 AST 实时反混淆?(附AST模版可直接使用)

AST 使用技巧:如何快速分析混淆代码结构

在 JS逆向时如何 hook 属性?

如何 “正确” hook JS方法

无需登录,满血版DeepSeek R1,很强!

一日一技:反爬虫的极致手段,几行代码直接炸了爬虫服务器

JS调试技巧:如何让时间和随机数“听你指挥”?

【Windows版】tcpdump + wireshark 联动 frida,实现APP无感抓取HTTPS数据包

AST 技巧:还在手动扣代码?AST技术帮你自动扣代码


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:LLLibra146 LLLibra146 LLLibra146《JS调试技巧:如何让时间和随机数“听你指挥”?升级版!》

评论:0   参与:  0