一、背景与目标
背景说明
当前在广告投放页面、营销活动页等场景中,为了提升用户转化率,通常采用简化注册流程(如手机号+验证码)来降低使用门槛。然而,这种方式也容易被黑产利用,如:
- 批量使用虚假手机号刷注册;
- 自动化程序(爬虫、脚本)绕过前端验证;
为解决这一问题,传统防刷手段(如滑块验证、图形验证码)虽然一定程度上能抵御攻击,但易被模拟、识别成本低,影响用户体验。
为提升安全性与隐蔽性,我们计划引入 WebAssembly(WASM)技术,利用其"运行在沙盒环境中的高性能、强封装性(代码以二进制格式分发)、天然的低可读性(相较于 JS)"特性,构建客户端逻辑保护的"黑盒"机制,显著提高逆向分析和自动化脚本编写的攻破门槛。
二、WebAssembly 简介
WebAssembly(WASM) 是一种低级二进制字节码格式,专为 Web 设计。支持 C/C++、Rust 等语言编译生成,能在现代浏览器中以接近原生速度运行。
主要特点:
- 高性能:执行速度比 JavaScript 快 1.5~10 倍
- 跨平台:所有现代浏览器均支持
- 安全性:沙盒隔离,无法直接访问 DOM、网络、文件系统
- 可移植性:多语言编译,便于代码复用
三、Rust 开发 WASM 的防破解优势
- 使用 Rust 编译生成的 WASM 模块在防破解方面具备以下优势:
-
二进制格式不可读性
- WASM 模块为二进制格式,远高于明文 JS 的读取难度。
- 攻击者需借助 Ghidra/IDA Pro 反编译,逆向成本高。
-
复杂控制流与编译优化
- Rust 编译器进行大量内联和控制流重构,丢失原始变量名称和高层结构,使得还原高层逻辑变得更复杂,逆向工作量显著增加。
-
内存安全机制
- Rust 的所有权和借用机制确保内存安全,减少常见的缓冲区溢出、空指针等漏洞,降低利用漏洞进行逆向的风险。
-
支持额外混淆
- 在编译前可以结合自定义混淆、加密与代码重构技术,进一步隐藏敏感算法和密钥,提升破解门槛。
-
成熟工具链
- 工具链如 wasm-pack 和 wasm-bindgen 生成的 WASM 模块结构严谨、经过优化,其复杂性为逆向工程提供了额外障碍。
前后端交互
利用 WASM 作为"黑盒",通过非对称加密技术确保客户端与后端的通信安全,防止中间人攻击和信息篡改,同时增加人机校验和防护,确保不被机器人刷页面。

四、防护架构
1. JavaScript 防护措施
-
代码混淆工具:
- JavaScript Obfuscator:控制流扁平化、字符串加密
- UglifyJS/Terser:基础压缩优化
- Closure Compiler:高级优化

1.1 环境检测与反调试
编号 | 技术 | 原理 |
---|---|---|
1 | debugger 语句 |
强制中断 |
2 | 窗口尺寸检测 | 判断开发者工具是否打开 |
3 | 时间差检测 | 判断代码执行延迟是否异常 |
4 | 无限循环断点 | 干扰调试器 |
5 | 内存占用监控 | 判断内存异常波动 |
6 | 页面破坏 | 清空页面、跳转 |
7 | 反 Hook | 检测函数是否被重写 |
8 | Web Worker 检测 | 多线程监控 |
9 | 域名校验 | 防调试伪造运行环境 |
1.2 WASM 防护措施

- 编译优化与混淆 :Rust 编译时启用
-O3
优化,结合 LLVM 混淆插件(如 ollvm)进行控制流扁平化、指令替换等。 - 动态生成和更新:服务端按 session 或定期生成不同混淆策略或密钥的 WASM 模块,前端动态加载。
- 避免硬编码密钥:密钥由服务器动态分发,通过安全 JS-WASM 接口传入。
示例代码:WASM 中进行 HMAC 签名
use wasm_bindgen::prelude::*;
use hmac::{Hmac, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac<Sha256>;
#[wasm_bindgen]
pub fn sign_data(data: &[u8], key: &[u8]) -> Vec<u8> {
let mut mac = HmacSha256::new_from_slice(key)
.expect("Invalid key length");
mac.update(data);
mac.finalize().into_bytes().to_vec()
}
浏览器运行示例:

1.3 WASM 虚拟机扩展方案
我们在 WebAssembly 之上再创建一个私有独立的 VM,二进制的 js 文件,直接在 wasm 环境执行。

1.4 WASM 动态加载/热更新代码示例
为了提升安全性,可以根据 session 或策略动态加载不同的 WASM 文件,增加破解难度。
// 动态加载不同 session 的 wasm 文件
async function loadWasmBySession(sessionId) {
const wasmUrl = `/wasm/module_${sessionId}.wasm`;
const wasm = await fetch(wasmUrl).then(res => res.arrayBuffer());
// ...后续初始化
}
1.1 环境检测与反调试
前端反调试/环境检测常用代码片段:
// 检测 DevTools 是否打开
function isDevToolsOpen() {
const threshold = 160;
const widthThreshold = window.outerWidth - window.innerWidth > threshold;
const heightThreshold = window.outerHeight - window.innerHeight > threshold;
return widthThreshold || heightThreshold;
}
// 检测是否自动化环境
function isAutomation() {
return navigator.webdriver || /puppeteer|selenium|playwright/i.test(navigator.userAgent);
}
2. 人机对抗技术
2.1 设备指纹识别
设备指纹识别
作用: 通过设备指纹识别,浏览器可以为每个设备生成独一无二的标识。这样,即使用户使用不同的浏览器、在不同的时间登录网站,只要设备不变,网站就能识别出是同一个用户。
- Canvas 指纹: 通过绘制图形并捕获其结果生成指纹。Canvas 指纹可以揭示出不同设备的图形渲染方式
- WebGL 特征分析: 通过分析 WebGL 渲染的不同特征,来判断设备的 GPU 和驱动特性。
- 性能指标采样: 收集浏览器性能指标,如加载时间,这些信息通常无法被机器人伪造。
将采集到的原始数据(鼠标轨迹点、时间戳)传入 WASM 模块,在 WASM 内部进行复杂的特征计算、评分或签名,而不仅仅是 JS 检测。这能保护核心检测算法和阈值不被轻易窥探和绕过。
2.2 检测自动化机器人
静态分析
原理: 检测访问者的浏览器环境,判断是否存在自动化脚本特征:
- User-Agent 分析: 识别伪造的 User-Agent。
- Navigator API: 检测是否运行于虚拟化环境,如 Puppeteer。
- 浏览器特性: 检测 WebRTC、Canvas 指纹、WebGL 伪造情况。
硬件/软件环境分析
原理: 检测设备是否运行于自动化环境:
-
检测虚拟机: 判断 WebGL、GPU 渲染是否为虚拟机模拟的。
-
检测自动化工具:
- 通过 navigator.webdriver 判断是否运行于自动化测试环境。
- 识别 Puppeteer/Playwright/Selenium 相关属性。
检测特征列表
维度 | 特征 | 判断点 | 技术来源 |
---|---|---|---|
📡 网络 | STUN 获取公网IP | IP地理位置、VPN判断 | WebRTC |
🧠 行为 | 鼠标轨迹等 | 是否规律/完美 | JS轨迹捕捉 |
🧱 指纹 | 屏幕/字体等 | 模拟器特征、重复值 | FingerprintJS |
⚙️ 环境 | DevTools检测 | resize/UA 校验 | JS侦测 |
📞 手机段 | 虚拟运营商号段 | 170/171等 | 号段库 |
🔄 重复性 | 本地存储/IP冲突 | 频繁访问、复制行为 | 前端+后端 |
2.3 行为分析
原理: 通过鼠标、键盘、触摸等操作,判断访问者是否是机器人:
- 监听事件:键盘、鼠标、滚动、触摸等;
- 记录轨迹点、点击位置、输入间隔等特征;
- 真实用户通常有不规律的鼠标移动、点击、滚动等行为。
前端可以通过监听键盘、触摸事件,记录用户操作轨迹、点击频率、滚动行为等,然后结合预设的规则判断是否符合人类行为模式。

总结: 记录用户首次触摸屏幕时间,记录用户的点击按钮的区域坐标范围,记录用户输入手机号的间隔时间,正常用户操作间隙一定是随机的。
2.1 设备指纹识别
常用设备指纹采集代码片段:
// Canvas 指纹
function getCanvasFingerprint() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('fingerprint', 2, 2);
return canvas.toDataURL();
}
五、接口加密方案
-
多重加密机制
- 采用 AES-256-CBC、HMAC-SHA256 以及 RSA 等加密方式保护数据传输与接口会话,确保前后端通信不可被篡改或重放。
-
签名/加密在 WASM 内完成
- JS 只进行数据组织与传输
- 防止 Token 被 JS 层篡改或抓包
JS 与 WASM 交互完整示例:
// 假设已通过 wasm-pack 生成 wasm 包并引入
import init, { sign_data } from './your_wasm_pkg';
async function getSignature(phone, timestamp, fingerprint, key) {
await init(); // 初始化 WASM
// 数据拼接与编码
const encoder = new TextEncoder();
const data = encoder.encode(`${phone}|${timestamp}|${fingerprint}`);
const keyBytes = encoder.encode(key);
// 调用 WASM 签名
const signature = sign_data(data, keyBytes);
// 转为 base64 便于传输
return btoa(String.fromCharCode(...signature));
}
六、优雅降级策略
一旦识别出可疑访问:
- 前端接口返回虚假数据;
- 页面照常展示,不影响用户体验;
- 恶意机器人无法进行有效数据刷取。
总结: 在面对异常情况时,我们将采取优雅的降级策略。一旦检测到疑似机器人访问或刷量行为,系统会自动进行降级处理,以维护服务的稳定性与公平性。在此过程中,相关接口会返回经过特殊处理的迷惑数据,干扰恶意行为的进一步操作。同时,页面将继续按照正常流程运行,确保用户的操作体验不受任何影响,从而在保障系统安全的同时,最大程度地满足合法用户的需求。
七、总结
通过使用 Rust 开发并编译成 WebAssembly 的方式,可以在一定程度上构建一个"黑盒"前端加密模块,利用 WASM 的二进制不可读性、复杂控制流和内存安全机制提高逆向破解的难度。整体破解成本显著提高。因此,WASM 加密作为多层安全防护的一部分,与后端验证、流量控制及行为监测等措施配合,形成一个更完善、更高效的防刷体系,从而提升转化率并优化用户体验。