Files
Senbei/web/README.md
T
Momoko-Ayase 0c3f29f93a Split web/ into senbei-wasm crate + static assets
The Rust bindings move from web/src to a top-level senbei-wasm crate (still
outside the workspace, own Cargo.lock), matching the other senbei-* crates.
web/ keeps only the static frontend; wasm-pack emits the JS/wasm package into
web/pkg/ via --out-dir. JS glue renamed senbei_web -> senbei_wasm with the
crate.
2026-08-30 22:44:15 +08:00

3.2 KiB

Senbei web

Senbei running in the browser: the unpacker core compiled to WebAssembly, wrapped in a small static page. Everything is client-side — files are read into the page, unpacked locally, and offered back as downloads. Nothing is uploaded; there is no server component.

Features

  • A legal notice is shown as a blocking dialog on page open; the tool is unusable until it is acknowledged.
  • Dropped files land in a file list, not unpacked immediately: review the batch, remove mistakes, then press Unpack. A module and its ._ companion can be dropped in any order (or in separate drops) — companions auto-pair by name (Foo.dll._Foo.dll) and show as a badge on the module's row; removing a module removes its companion too.
  • Rows show state at a glance: black while staged, an animated blue bar while unpacking, green on success (with a download button) and red on failure.
  • Drop one or more protected .exe / .dll modules → get <name>.unpack.* downloads.
  • Drop an il2cpp global-metadata.dat → de-obfuscated global-metadata.unpack.dat (only when tokens actually change).
  • Each output passes the same static integrity check as the CLI; suspect outputs are flagged with the specific defects found.

Architecture notes

  • Every unpack runs in a disposable Web Worker (fresh wasm instance per file): the UI stays responsive on 100 MB+ modules, and a wasm trap is isolated to that worker.
  • Why workers matter for correctness: the DLL-first routing probe relies on catch_unwind to reject EXE-shell-layout DLLs, and panics cannot be caught in WebAssembly — the probe traps the whole call. When a DLL unpack traps, the app retries once in a new worker with the forced-EXE pipeline (unpack_file_force_exe), reproducing the CLI's dll-first/exe-fallback outcome. Spliced companion inputs skip the probe entirely (they are always EXE-shell layout), exactly like the CLI.
  • Rust panic messages are forwarded to the browser console (console_error_panic_hook) — check devtools when reporting an issue.

Building

Requires a Rust toolchain (rust-toolchain.toml in the repo root pins one, including the wasm32-unknown-unknown target) and wasm-pack.

cd senbei-wasm
wasm-pack build --target web --release --out-dir ../web/pkg

This produces web/pkg/ (git-ignored). Then serve the web/ directory with any static file server and open index.html:

python -m http.server -d web 8000
:: -> http://localhost:8000

(Opening index.html via file:// won't work — ES modules require HTTP.)

Layout

senbei-wasm/   the senbei-wasm cdylib crate (own Cargo.lock, outside the
               workspace; depends on the senbei-pe/-io/-metadata crates)
└── src/lib.rs #[wasm_bindgen] bindings: detect / unpack_file /
               unpack_file_force_exe / deobfuscate_metadata
web/
├── index.html the page
├── app.js     dropzone, file list, worker orchestration, downloads
├── worker.js  one-shot unpack worker (fresh wasm instance per file)
├── style.css
└── pkg/       wasm-pack output (git-ignored; build from senbei-wasm/)