## https://sploitus.com/exploit?id=2E03DFDA-D902-5B1E-98E4-75EC5243C83B
# Shockwave POC
# Shockwave POC — Comparação DirPlayer vs LibreShockwave (WASM, Shockwave/Director no Browser)
6 de junho de 2026
Proof of Concept técnica para avaliar viabilidade de rodar jogos **Shockwave/Director (.dcr)** legados no navegador moderno via **WebAssembly**. Comparação lado a lado de 2 runners independentes: **DirPlayer v0.5.1** (Ruffle fork Rust→WASM para Director) e **LibreShockwave Nightly 06062026** (Java→TeaVM→WASM). Backend PHP minimal (router MIME fix, upload/asset/manifest/cleanup APIs), frontend 2 páginas idênticas com console de debug unificado, upload ZIP/.dcr com extração automática e manifesto JSON. Assets de teste reais: **Phosphor Beta 2.043** (jogo 3D FPS Shockwave completo). Zero framework, zero composer, zero DB, zero build, totalmente offline.
## Arquitetura: POC Isolada — 2 Runners WASM + PHP API Minimal
```
0-POC/Shockwave_POC/
├── router.php # Built-in server router: .wasm → application/wasm
├── shockwave-poc-dirplayer.php # Página DirPlayer v0.5.1
├── shockwave-poc-libreshockwave.php # Página LibreShockwave Nightly
├── poc.css # Dark theme, canvas full-size, console log color-coded
├── poc.js # Console interceptor, upload handler, result panel
├── api/
│ ├── upload.php # POST multipart .dcr/.zip → extrai + manifesto JSON
│ ├── asset.php # GET asset com path traversal protection + CORP headers
│ ├── manifest.php # GET manifesto .mp_shockwave.json
│ └── cleanup.php # POST limpeza uploads >1h
├── assets/vendor/
│ ├── bootstrap/ # Bootstrap 5.3.3 local (CSS + Bundle JS)
│ └── jquery/ # jQuery 3.7.1 local
├── runners/
│ ├── dirplayer/ # DirPlayer v0.5.1: dirplayer-polyfill.js + ruffle/ + .wasm
│ └── libreshockwave/ # LibreShockwave: libreshockwave.js + player-wasm.wasm (~33MB) + runtime.js
└── uploads/ # 4 uploads de teste Phosphor Beta 2.043 pré-carregados
```
Fluxo: usuário abre página → seleciona .dcr ou .zip → upload via AJAX → backend extrai ZIP se necessário → gera manifesto JSON com entrypoints → frontend popula seletor entrypoint → usuário clica "Carregar" → runner WASM carrega jogo no `` → console unificado loga tudo.
## DirPlayer v0.5.1: Ruffle Fork para Director (Rust→WASM)
- **Origem:** `github.com/igorlira/dirplayer-rs` — fork do Ruffle focado em Director/Shockwave
- **Stack:** Rust → WASM via `wasm-pack`
- **Arquivos:** `dirplayer-polyfill.js` (IIFE) + `ruffle/dirplayer_ruffle.js` + `c04588933f7297820bf4.wasm`
- **API:** `window.DirPlayer = {init, configureFlash}`, `window.dirplayer_RufflePlayer.newest().createPlayer().load(url)`
- **Correção documentada:** `player.load()` direto (não `player.ruffle().load()`)
- **Status:** "A testar" (README)
## LibreShockwave Nightly: Java → TeaVM → WASM
- **Origem:** `github.com/Quackster/LibreShockwave` — reimplementação Java do player Shockwave
- **Stack:** Java (LibreShockwave) → **TeaVM** → WASM
- **Arquivos:** `libreshockwave.js` + `player-wasm.wasm` (~33 MB) + `player-wasm.wasm-runtime.js`
- **API:** `LibreShockwave.create('stage', {autoplay, onLoad, onError, onFrame}).load(url)`
- **Threading:** **SharedArrayBuffer** — requer `COOP/COEP` headers
- **Correção documentada:** `ImageData` SharedArrayBuffer fix (cópia antes de `new ImageData`)
## Backend PHP: API Minimal + Router MIME Fix
### router.php — Built-in Server WASM MIME Fix
```
// Fix: PHP built-in server não serve .wasm com MIME correto
if (preg_match('/\.wasm$/', $_SERVER['REQUEST_URI'])) {
header('Content-Type: application/wasm');
readfile(__DIR__ . $_SERVER['REQUEST_URI']);
exit;
}
// Demais arquivos servidos normalmente
```
Resolve `WebAssembly.instantiateStreaming` warning no console.
### api/upload.php — Upload + Extração ZIP + Manifesto
- Valida extensão: `.dcr, .dir, .dxr, .zip` (blocklist: .php, .phar, .exe, .sh)
- Tamanho máx: 100MB
- Se ZIP: `ZipArchive` extrai preservando estrutura → detecta `.dcr` raiz como entrypoints
- Gera `uploads/{id}/.mp_shockwave.json` manifesto
- Retorna JSON: `{success, upload_id, entrypoints[]}`
### api/asset.php — Serving Seguro
- `realpath()` + prefix check → **path traversal protection**
- Extension blocklist novamente
- MIME correto (inclui `application/wasm`)
- Headers: `Cross-Origin-Resource-Policy: cross-origin`, `Cache-Control`
### COOP/COEP Headers (LibreShockwave)
```
// shockwave-poc-libreshockwave.php (TOP, antes de qualquer output)
header('Cross-Origin-Opener-Policy: same-origin');
header('Cross-Origin-Embedder-Policy: require-corp');
```
Obrigatório para `SharedArrayBuffer` (threading TeaVM).
## Frontend: Console Debug Unificado (poc.js)
- Intercepta: `console.log/info/warn/error` + `unhandledrejection` + `window.onerror`
- Wrapper `fetch` + `XHR` → loga request/response com timestamps
- Tags coloridas no painel: `[log]` cinza, `[info]` azul, `[warn]` amarelo, `[error]` vermelho, `[fetch]` ciano, `[xhr]` magenta
- Stack trace capturado em erros
- Upload handler: `FormData`, progress, popula seletor entrypoint do manifesto
- Painel resultado manual: radio Aprovado/Parcial/Reprovado + observação + copy JSON
## Assets de Teste: Phosphor Beta 2.043
- Jogo Shockwave 3D FPS completo (`www.rasterwerks.com/game/phosphor/`)
- Entrypoint `.dcr` + assets `.dat/.cct/.ini`
- 4 uploads de teste pré-carregados em `uploads/`
- Teste real de carga 3D, texturas, fÃsica, input
## Deploy
1. PHP 8.x + `fileinfo` + `json` (extensão `zip` opcional para .zip)
2. `php -S localhost:8080 router.php` (dev)
3. Produção: Apache/Nginx com `COOP/COEP` headers configurados + `.wasm` MIME
4. Abrir `shockwave-poc-dirplayer.php` ou `shockwave-poc-libreshockwave.php`
## Limitações Conhecidas
- **LibreShockwave ~33 MB WASM** — carregamento lento primeira vez (cache browser ajuda)
- **DirPlayer integração "A testar"** — API pode mudar, compatibilidade incerta
- **COOP/COEP quebra** se servido via proxy/reverse proxy sem repassar headers
- **PHP built-in server apenas dev** — produção precisa Apache/Nginx
- **Zero persistência resultados** — apenas painel manual (JSON export)
- **Sem testes automatizados**
- **Zero TypeScript, zero build tool**
- **SharedArrayBuffer** não funciona em contextos cross-origin sem COOP/COEP
- **TeaVM runtime** single-threaded fallback se SAB indisponÃvel (mais lento)
POC técnica valiosa para preservação digital de conteúdo Shockwave/Director. Para versão robusta: indexação automática de assets .dcr web (commoncrawl/wayback), fallback Ruffle nativo (SWF), wrapper Electron/Tauri para desktop (bypassa COOP/COEP), streaming WASM (instantiation streaming), testes automatizados com Playwright + fixtures .dcr conhecidos, CI/CD, documentação API runners.
Autor: Keven Castilho (kevencastilho.github.io). Jun/2026. PHP 8.x + Vanilla JS ES6+ (poc.js console interceptor, upload handler) + DirPlayer v0.5.1 (Rust→WASM via Ruffle fork) + LibreShockwave Nightly (Java→TeaVM→WASM ~33MB) + Bootstrap 5.3.3/jQuery 3.7.1 local. Zero framework, zero composer, zero DB, zero build. Offline-first.