Files
hello_js_reverse_skill/templates/wasm-loader/main.js
T
白夜 fb14cf7916 refactor: 将文件从子目录提升到仓库根目录
所有文件从 hello_js_reverse_skill/ 子目录移至仓库根目录,
使项目结构更清晰,便于作为 Skill 直接引用。

Made-with: Cursor
2026-03-18 22:55:27 +08:00

161 lines
5.0 KiB
JavaScript

/**
* 主脚本模板 - WASM 加载还原
*
* 适用场景:加密函数通过 WebAssembly 实现
* 流程:
* 1. 下载/加载 .wasm 文件
* 2. 补全运行环境
* 3. 调用 WASM 导出的加密函数
* 4. 使用加密结果构造请求
*
* TODO: 根据逆向分析结果修改配置和逻辑
*/
const { loadWasmFromFile, loadWasmFromURL, analyzeWasm } = require('./utils/wasm-loader');
const { patchWasmBindgen } = require('./utils/env-patch');
const axios = require('axios');
const path = require('path');
// ============ 配置区域 ============
const CONFIG = {
name: '示例项目 - WASM加密',
description: '采集全部5页数据',
baseURL: 'https://target.com',
dataEndpoint: '/api/data',
// WASM 文件路径或 URL
wasmSource: './main.wasm', // 本地文件
// wasmSource: 'https://target.com/main.wasm', // 远程 URL
// WASM 导出函数名
encryptFunction: 'encode',
// WASM 类型: 'plain' | 'emscripten' | 'wasm-bindgen' | 'go'
wasmType: 'plain',
totalPages: 5,
delay: 1500,
cookies: {},
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
},
};
// ============ 主逻辑 ============
let wasmExports = null;
async function initWasm() {
console.log('[*] 加载 WASM 模块...');
// 根据 WASM 类型补全环境
if (CONFIG.wasmType === 'wasm-bindgen') {
patchWasmBindgen();
}
// 分析 WASM 结构
if (CONFIG.wasmSource.startsWith('http')) {
console.log('[*] 从远程下载 WASM...');
const result = await loadWasmFromURL(CONFIG.wasmSource);
wasmExports = result.exports;
console.log('[+] WASM 导出函数:', Object.keys(result.exports).filter(k => typeof result.exports[k] === 'function'));
} else {
const wasmPath = path.resolve(CONFIG.wasmSource);
// 先分析 WASM 结构
const analysis = await analyzeWasm(wasmPath);
console.log('[*] WASM 导出:', analysis.exports.map(e => `${e.name}(${e.kind})`).join(', '));
console.log('[*] WASM 导入:', analysis.imports.map(i => `${i.module}.${i.name}`).join(', '));
const result = await loadWasmFromFile(wasmPath);
wasmExports = result.exports;
}
// 验证加密函数存在
if (typeof wasmExports[CONFIG.encryptFunction] !== 'function') {
throw new Error(`WASM 导出函数 "${CONFIG.encryptFunction}" 不存在。可用函数: ${Object.keys(wasmExports).filter(k => typeof wasmExports[k] === 'function').join(', ')}`);
}
console.log(`[+] WASM 加载成功,加密函数: ${CONFIG.encryptFunction}`);
}
function generateEncryptedParam(page) {
// TODO: 根据逆向分析修改参数生成逻辑
const timestamp = Math.floor(Date.now() / 1000);
// 调用 WASM 导出的加密函数
const encrypted = wasmExports[CONFIG.encryptFunction](timestamp, page);
// TODO: 根据实际格式组装参数
return `${encrypted}|${timestamp}|${page}`;
}
async function fetchPage(page) {
const m = generateEncryptedParam(page);
const response = await axios.get(`${CONFIG.baseURL}${CONFIG.dataEndpoint}`, {
params: { page, m },
headers: {
...CONFIG.headers,
Cookie: Object.entries(CONFIG.cookies).map(([k, v]) => `${k}=${v}`).join('; '),
Referer: CONFIG.baseURL,
},
});
return response.data;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
console.log(`[*] 项目:${CONFIG.name}`);
console.log(`[*] 目标:${CONFIG.description}`);
console.log('');
// 初始化 WASM
await initWasm();
console.log('');
// 验证:测试加密函数
const testResult = generateEncryptedParam(1);
console.log(`[*] 加密测试: page=1 → m=${testResult}`);
console.log('');
// 采集数据
const allData = [];
for (let page = 1; page <= CONFIG.totalPages; page++) {
try {
const responseData = await fetchPage(page);
const pageData = responseData.data || [];
allData.push(...pageData);
console.log(`[+] 正在采集第 ${page}/${CONFIG.totalPages} 页... ✓ 获取 ${pageData.length} 条数据`);
if (page < CONFIG.totalPages) {
await sleep(CONFIG.delay + Math.random() * 500);
}
} catch (error) {
console.error(`[-] 第 ${page} 页采集失败: ${error.message}`);
}
}
console.log(`\n[+] 采集完成,共 ${allData.length} 条数据`);
// TODO: 计算结果
const result = allData.reduce((sum, item) => sum + (item.value || 0), 0);
console.log('\n' + '='.repeat(30) + ' 计算结果 ' + '='.repeat(30));
console.log(`答案:${result}`);
console.log('='.repeat(70));
}
main().catch(error => {
console.error('\n[!] 运行错误:', error.message);
process.exit(1);
});