WASM逆向

首先找到wasm初始化的位置,然后hook初始化后的实例

// === 封装:一键读取 WASM 内存中的字符串(修复版)===
(function initWasmStringReader() {
    try {
        const instance = window.wasmInstance;
        if (!instance) {
            console.error('❌ window.wasmInstance 未定义,请先加载 WASM 实例');
            return;
        }

        // 🔧 修复点:支持 .e 和通用查找
        const exportedMemory = 
            instance.exports.e ||                    // 你的实际导出名
            instance.exports.memory ||               // 标准名
            Object.values(instance.exports).find(
                val => val instanceof WebAssembly.Memory
            );

        if (!exportedMemory) {
            console.error('❌ 未找到 WebAssembly.Memory,当前导出项:', Object.keys(instance.exports));
            return;
        }

        const memory = exportedMemory;
        const u8 = new Uint8Array(memory.buffer);

        // 核心函数:通过地址读取字符串
        window.readWasmStr = function readWasmStr(ptr, maxLen = 1024) {
            // 输入校验
            if (typeof ptr !== 'number' || ptr < 0) {
                console.warn('⚠️ 无效地址:', ptr);
                return null;
            }
            if (ptr === 0) {
                console.log('📌 [0x0] null pointer');
                return null;
            }

            // 检查地址是否越界
            if (ptr >= u8.length) {
                console.warn(`⚠️ 地址 0x${ptr.toString(16)} 超出内存范围 (最大 0x${u8.length.toString(16)})`);
                return null;
            }

            // 查找 \0 结束符
            let end = ptr;
            let len = 0;
            while (len < maxLen && u8[end] !== 0 && end < u8.length) {
                end++;
                len++;
            }

            // 解码 UTF-8 字符串
            const str = new TextDecoder('utf-8').decode(u8.subarray(ptr, end));

            // 打印带格式的结果
            console.log(`📌 0x${ptr.toString(16)} (${ptr}):`, str);

            return str;
        };

        // ✅ 增强提示:显示内存大小
        const totalPages = memory.buffer.byteLength / 65536;
        console.log(`✅ readWasmStr(addr) 已就绪!内存页数: ${totalPages} (≈${(totalPages * 64).toFixed(1)}MB)`);
        console.log('📝 示例:readWasmStr(7798784)');
        console.log('🔍 提示:内存来自 exports.e,支持读取字符串');

    } catch (err) {
        console.error('❌ 初始化失败:', err);
    }
})();

因为我做的是图像解密,他的解密是在wasm中做的,我采用的是倒推的方式找的解密后js是在哪个交互函数中拿到结果的。同样进行hook

// 在 Console 中执行
const canvas = document.getElementById('click-grid-0');
const ctx = canvas.getContext('2d');

// 保存原始方法
const originalPutImageData = ctx.putImageData;
ctx.putImageData = function(...args) {
    console.debug('putImageData called with:', args);
    
    // 创建一个临时 canvas 来存放 ImageData
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = args[0].width;  // ImageData width
    tempCanvas.height = args[0].height; // ImageData height

    // 获取上下文并绘制 ImageData
    const tempCtx = tempCanvas.getContext('2d');
    tempCtx.putImageData(args[0], 0, 0);

    // 转换为 Base64(PNG 格式)
    const base64 = tempCanvas.toDataURL('image/png');

    // 输出 Base64 字符串
    console.log('Base64 URL:');
    console.log(base64);

    // 可选:在页面上显示该图片
    const img = document.createElement('img');
    img.src = base64;
    img.style.margin = '10px';
    img.style.border = '1px solid #ccc';
    document.body.appendChild(img);

    debugger; // 断点在这里,查看调用栈

    return originalPutImageData.apply(this, args);
};

因为wasm会开辟一块线下地址和js进行交互。实例化的时候会会返回wasm导出的地址。我们挂载到全局,然后封装一个方法,对内存的值进行读取,因为wasm基本都是对内存进行操作。

// === 封装:一键读取 WASM 内存中的字符串(修复版)===
(function initWasmStringReader() {
    try {
        const instance = window.wasmInstance;
        if (!instance) {
            console.error('❌ window.wasmInstance 未定义,请先加载 WASM 实例');
            return;
        }

        // 🔧 修复点:支持 .e 和通用查找
        const exportedMemory = 
            instance.exports.e ||                    // 你的实际导出名
            instance.exports.memory ||               // 标准名
            Object.values(instance.exports).find(
                val => val instanceof WebAssembly.Memory
            );

        if (!exportedMemory) {
            console.error('❌ 未找到 WebAssembly.Memory,当前导出项:', Object.keys(instance.exports));
            return;
        }

        const memory = exportedMemory;
        const u8 = new Uint8Array(memory.buffer);

        // 核心函数:通过地址读取字符串
        window.readWasmStr = function readWasmStr(ptr, maxLen = 1024) {
            // 输入校验
            if (typeof ptr !== 'number' || ptr < 0) {
                console.warn('⚠️ 无效地址:', ptr);
                return null;
            }
            if (ptr === 0) {
                console.log('📌 [0x0] null pointer');
                return null;
            }

            // 检查地址是否越界
            if (ptr >= u8.length) {
                console.warn(`⚠️ 地址 0x${ptr.toString(16)} 超出内存范围 (最大 0x${u8.length.toString(16)})`);
                return null;
            }

            // 查找 \0 结束符
            let end = ptr;
            let len = 0;
            while (len < maxLen && u8[end] !== 0 && end < u8.length) {
                end++;
                len++;
            }

            // 解码 UTF-8 字符串
            const str = new TextDecoder('utf-8').decode(u8.subarray(ptr, end));

            // 打印带格式的结果
            console.log(`📌 0x${ptr.toString(16)} (${ptr}):`, str);

            return str;
        };

        // ✅ 增强提示:显示内存大小
        const totalPages = memory.buffer.byteLength / 65536;
        console.log(`✅ readWasmStr(addr) 已就绪!内存页数: ${totalPages} (≈${(totalPages * 64).toFixed(1)}MB)`);
        console.log('📝 示例:readWasmStr(7798784)');
        console.log('🔍 提示:内存来自 exports.e,支持读取字符串');

    } catch (err) {
        console.error('❌ 初始化失败:', err);
    }
})();
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值