Unity + WebGL Modules Exposer (Global)

Expose UnityLoader, UnityModule and the WASM module (aka 'Module') globally in 'window' to use for reverse engineering browser games much easier.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Unity + WebGL Modules Exposer (Global)
// @namespace    wasm-hunter
// @version      2.0
// @author       EnterpriseExperience
// @description  Expose UnityLoader, UnityModule and the WASM module (aka 'Module') globally in 'window' to use for reverse engineering browser games much easier.
// @match        https://www.gaming-style.com/*
// @run-at       document-start
// @grant        none
// @license      MIT
// ==/UserScript==

// do not change the '@match' argument to anything else, it won't work otherwise.
// logging is just purely to ensure the script runs more smoothly.

(function () {
    const g = window
    const found = {
        unity_loader:false,
        unity_module:false,
        wasm:false
    }

    function log(...a){
        console.log("[WASM-HUNTER]",...a)
    }

    function expose(name,obj){
        try{
            if(obj) g[name] = obj
        }catch(e){}
    }

    function normalizemodule(v){
        if(!v){
            return null
        }

        if(v.HEAPU8 || v.HEAP8 || v.wasmMemory){
            return v
        }

        if(v.Module && (v.Module.HEAPU8 || v.Module.HEAP8 || v.Module.wasmMemory)){
            return v.Module
        }

        if(v.asm && (v.HEAPU8 || v.HEAP8)){
            return v
        }

        return null
    }

    function scanforunityloader(win){
        if(found.unity_loader) return

        try{
            if(win.UnityLoader){
                expose("UnityLoader",win.UnityLoader)
                found.unity_loader = true
                log("UnityLoader captured")
            }
        }catch(e){}
    }

    function scanformodule(win){
        if(found.unity_module) return

        try{
            for(const k in win){
                const v = win[k]
                if(!v) continue

                const m = normalizemodule(v)

                if(m){
                    expose("UnityModule",m)
                    expose("Module",m)
                    found.unity_module = true
                    log("Unity Module detected via key.")
                    break
                }
            }
        }catch(e){}
    }

    function scanwindow(win){
        try{
            scanforunityloader(win)
            scanformodule(win)

            if(win.frames){
                for(let i=0;i<win.frames.length;i++){
                    try{
                        scanwindow(win.frames[i])
                    }catch(e){}
                }
            }
        }catch(e){}
    }

    const scan_interval = setInterval(()=>{
        scanwindow(g)

        if(found.unity_loader && found.unity_module && found.wasm){
            clearInterval(scan_interval)
            log("All targets captured")
        }

    },2000)

    function captureinstance(instance,module){
        if(found.wasm) return
        found.wasm = true

        expose("wasmInstance",instance)
        expose("wasmModule",module)

        const exports = instance.exports
        expose("wasmExports",exports)

        log("WASM objects captured successfully.")

        if(exports.__indirect_function_table){
            expose("wasmTable",exports.__indirect_function_table)
        }
    }

    const orig_instantiate = WebAssembly.instantiate
    WebAssembly.instantiate = async function(...args){
        const result = await orig_instantiate.apply(this,args)

        if(result && result.instance){
            captureinstance(result.instance,result.module)
        }

        return result
    }

    if(WebAssembly.instantiateStreaming){
        const orig_streaming = WebAssembly.instantiateStreaming

        WebAssembly.instantiateStreaming = async function(...args){
            const result = await orig_streaming.apply(this,args)

            if(result && result.instance){
                captureinstance(result.instance,result.module)
            }

            return result
        }
    }

    const orig_instance = WebAssembly.Instance
    WebAssembly.Instance = function(module,imports){
        const inst = new orig_instance(module,imports)
        captureinstance(inst,module)
        return inst
    }
    WebAssembly.Instance.prototype = orig_instance.prototype

    const orig_compile = WebAssembly.compile
    WebAssembly.compile = async function(...args){
        const mod = await orig_compile.apply(this,args)

        expose("compiledWasmModule",mod)

        log("WASM compiled")

        return mod
    }

    log("Unity WASM scanner started")
})()