--- name: vibeproxy-reverse-engineering description: "Reverse engineer VibeProxy (WinUI 3 .NET 8 MSIX app) — ILSpy decompile, self-contained publish, MSIX repackage, and fork 9router backend" --- # VibeProxy Reverse Engineering Pipeline ## Target VibeProxy = WinUI 3 / .NET 8 MSIX app (`AtC.VibeProxy_3.7.2.0_x64__g8zz5t3ayajdt`). Backend = `VibeProxyServices.exe` = pkg-compiled OmniRoute v3.8.50 (MIT). 9router = separate npm package (`9router@0.5.50`, MIT, `github.com/decolua/9router`). ## Phase 1: Decompile C# (ILSpy) ```powershell # Locate MSIX install $pkg = Get-AppxPackage -Name "AtC.VibeProxy" $installDir = $pkg.InstallLocation # C:\Program Files\WindowsApps\AtC.VibeProxy_3.7.2.0_x64__g8zz5t3ayajdt # Decompile VibeProxy.dll with ILSpy CLI ilspycmd -p --decompile-baml "$installDir\VibeProxy.dll" -o C:\Users\User\tmp\VibeProxy_src2\ ``` ### Build fixes required - `LangVersion=preview` in csproj - HintPaths to `libs/` directory (copy 244 DLLs from MSIX) - Fix `CS0136` duplicate variables (rename `upd` → `ins` in SqliteStatsService.cs) - Fix inline literal `FindOrRegisterForKey("VibeProxy_SingleInstance")` → use const ### Self-contained publish (NOT framework-dependent) ```powershell dotnet publish VibeProxy.csproj -c Release -r win-x64 --self-contained true ``` Original runtimeconfig uses `includedFrameworks` (self-contained). Rebuilt uses `framework` (FDD). Must publish self-contained or app crashes with "No frameworks were found". ## Phase 2: MSIX Repackage ### Staging (CRITICAL — never pack from output dir directly) 1. Copy from `bin\Release\net8.0\win-x64\publish\` (NOT `bin\Release\net8.0\`) 2. Overlay original `resources.pri`, `Assets/`, `Watchers/`, `Microsoft.UI.Xaml/`, locale dirs, native WinUI DLLs 3. EXCLUDE stale `AppxSignature.p7x`, `AppxBlockMap.xml`, `AppxMetadata/CodeIntegrity.cat` 4. Write new `AppxManifest.xml` with bumped version and `Publisher` matching cert Subject exactly ### Cert + Sign + Install ```powershell # Create self-signed cert $cert = New-SelfSignedCertificate -Subject "CN=" -KeyUsage DigitalSignature -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3","2.5.29.19={text}") # Add to Trusted Root + Trusted People (LocalMachine) # Export PFX # Pack & makeappx pack /d $staging /p $msixPath /nv # Sign & signtool sign /fd SHA256 /a /f $certPath /p $password $msixPath # Install Add-AppxPackage -Path $msixPath ``` ### Launch via AppsFolder ```powershell Start-Process explorer.exe -ArgumentList 'shell:AppsFolder\!App' ``` `Start-Process` cannot launch `shell:AppsFolder` URIs directly — use `explorer.exe`. ### Verification - `Get-AppxPackage` shows correct version + InstallLocation - Hash installed `VibeProxy.dll` == publish hash - Process alive ≥5s with growing RAM - `MainWindowTitle` = custom title (not "VibeProxy.exe") - UI Automation confirms text elements - Pixel sampling confirms color changes ### CLEANUP (mandatory after install) Remove self-signed cert from `LocalMachine\Root`, `LocalMachine\TrustedPeople`, `CurrentUser\My`. Delete PFX file. Trusted root + accessible private key = arbitrary code signing. ## Phase 3: Design changes (code-behind only) XAML is compiled to XBF v2.1 in `resources.pri` — NOT decompilable. Changes only via C# code-behind in `MainWindow.cs` constructor after `InitializeComponent()`: ```csharp AppTitleTextBlock.Text = "VibeProxy [ENI]"; AppTitleTextBlock.Foreground = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 168, 85, 247)); NavView.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 20, 15, 35)); ContentFrame.BorderBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 168, 85, 247)); ContentFrame.BorderThickness = new Thickness(2); ``` **Gotchas:** - `Color` is ambiguous between `System.Drawing.Color` and `Windows.UI.Color` — qualify as `Windows.UI.Color.FromArgb(...)` - `NavigationView.PaneBackground` doesn't exist in WinUI 3 — use `NavView.Background` - `Window.RequestedTheme` not available in WinUI 3 — set on child elements - `NavView.SelectedItem = NavView.MenuItems[0]` MUST be preserved (don't accidentally replace with design code) ## Phase 4: 9router fork (backend) ### Clone real upstream (NOT npm pack) ```bash git clone https://github.com/decolua/9router.git 9router_fork cd 9router_fork git checkout -b eni-custom ``` ### Build ```bash npm install # WITH devDependencies (next build needs them) npx next build --webpack # or: npm run build ``` ### Run dev (no build needed) ```bash PORT=20130 API_KEY_SECRET=eni-test-key DATA_DIR=./data node node_modules/next/dist/bin/next dev --port 20130 ``` ### API endpoints - `/api/health` → `{"ok":true}` (no auth) - `/v1/models` → 679 models (Bearer auth) - `/api/v1/chat/completions` → POST (needs configured providers in DB) - `/api/monitoring/health` → VibeProxy health check endpoint ### API key generation ```javascript // Format: {prefix}-{machineId}-{keyId}-{crc8} // prefix: "sk" (default) or "eni" (custom) // CRC = HMAC-SHA256(API_KEY_SECRET, machineId + keyId).slice(0,8) ``` ### VibeProxy ↔ 9router integration VibeProxy expects OmniRoute API (`/api/monitoring/health`, `/api/providers/{id}/login`, `/api/oauth/`). 9router has different API (`/api/health`, `/api/v1/chat/completions`). Direct swap of VibeProxyServices.exe with 9router won't work — API incompatible. VibeProxyServices.exe = pkg-compiled OmniRoute, NOT 9router. OmniRoute installs 9router as embedded service via `npm install 9router`. ## Key paths - ILSpy output: `C:\Users\User\tmp\VibeProxy_src2\` - OmniRoute clone: `C:\Users\User\Projects\OmniRoute_fork\` (v3.8.50, MIT) - 9router clone: `C:\Users\User\Projects\9router_fork\` (v0.5.50, MIT) - MakeAppx: `C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\makeappx.exe` - Signtool: `C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe` ## What's NOT recovered - XAML markup (24 XBF v2.1 files in resources.pri — format undocumented) - ILSpy artifacts (`Unknown result type` in 61+ files — WinRT projection IL) - Sourcemaps (production build, all empty) - VibeProxy-specific backend delta (diff between OmniRoute git and extracted dist not proven)