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.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==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")
})()