reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
134
our-skills/reverse-winui3-pkg-app/SKILL.md
Normal file
134
our-skills/reverse-winui3-pkg-app/SKILL.md
Normal file
@@ -0,0 +1,134 @@
|
||||
---
|
||||
name: reverse-winui3-pkg-app
|
||||
description: "Reverse engineer a WinUI 3 (.NET 8) desktop app with a pkg-compiled Node.js backend: ILSpy decompilation, XBF extraction from resources.pri, pkg payload extraction, self-contained publish, MSIX packaging with self-signed cert, and side-by-side launch"
|
||||
---
|
||||
|
||||
# Reverse Engineering WinUI 3 + pkg-compiled Node.js Applications
|
||||
|
||||
## When to use
|
||||
Reversing a Windows desktop app that is:
|
||||
- WinUI 3 / Windows App SDK (.NET 8) frontend
|
||||
- pkg-compiled Node.js backend (VibeProxyServices.exe pattern)
|
||||
- Installed as MSIX in `C:\Program Files\WindowsApps\`
|
||||
|
||||
## Phase 1: Locate and identify
|
||||
|
||||
```powershell
|
||||
# Find running process
|
||||
Get-Process | Where-Object { $_.ProcessName -match 'TargetApp' }
|
||||
# Get install path
|
||||
(Get-Process TargetApp).Path
|
||||
```
|
||||
|
||||
Identify app type by inspecting install directory:
|
||||
- `coreclr.dll`, `hostfxr.dll` → .NET 8 app
|
||||
- `VibeProxy.dll` (main logic) + `VibeProxy.exe` (thin launcher) → ILSpy target
|
||||
- `resources.pri` → XBF/XAML resources embedded
|
||||
- `Watchers\*.exe` (large, 100MB+) → likely pkg-compiled Node.js backend
|
||||
|
||||
## Phase 2: Decompile C# with ILSpy
|
||||
|
||||
```bash
|
||||
# Install ILSpy CLI
|
||||
dotnet tool install --global ilspycmd
|
||||
|
||||
# Decompile main DLL with reference path for WinRT projections
|
||||
ilspycmd "C:\path\to\App.dll" -p -o "C:\output\src" -r "C:\path\to\install\dir"
|
||||
```
|
||||
|
||||
Key fixes after decompilation:
|
||||
- `LangVersion` in csproj: change to `preview` (ILSpy may set unsupported version)
|
||||
- `CS0136` duplicate variables: rename second occurrence
|
||||
- `FindOrRegisterForKey("literal")`: ILSpy inlines string constants — fix call site to use const
|
||||
- `Color` ambiguity: qualify as `Windows.UI.Color.FromArgb(...)` not `Color.FromArgb(...)`
|
||||
- `NavigationView.PaneBackground` doesn't exist in WinUI 3 — use `NavView.Background` instead
|
||||
- `Window.RequestedTheme` not available — set theme on child elements instead
|
||||
|
||||
## Phase 3: Extract XBF from resources.pri
|
||||
|
||||
```bash
|
||||
# Dump PRI with makepri
|
||||
makepri.exe dump /if "resources.pri" /of "dump.xml" /dt detailed /o
|
||||
|
||||
# Extract XBF binaries from Base64 in dump XML (PowerShell script)
|
||||
# XBF entries have type="EmbeddedData" with Base64Value
|
||||
```
|
||||
|
||||
XBF v2.1 format (WinUI 3):
|
||||
- Header: 12 bytes (magic + metaSize + nodeSize)
|
||||
- Offsets are relative to byte 12 (meta_start)
|
||||
- String table: uint32 count, then length-prefixed UTF-16LE strings with 2-byte padding
|
||||
- Type/Property tables: 12 bytes per entry (not 8)
|
||||
- Node section starts at `12 + metaSize`
|
||||
- Node encoding differs from XBF v1.0 — existing tools (LibXbf) don't work
|
||||
|
||||
## Phase 4: Extract pkg backend
|
||||
|
||||
pkg self-extracts to `%TEMP%\AppName\version\dist` at runtime.
|
||||
Check there first — no need to parse the 298MB binary.
|
||||
|
||||
```powershell
|
||||
Get-ChildItem "$env:TEMP\AppName" -Recurse
|
||||
```
|
||||
|
||||
If not extracted yet, identify pkg version:
|
||||
- Search binary for `process.versions.pkg` → e.g. `'6.22.0'`
|
||||
- Search for `NODE_SEA_FUSE` — if `:0`, it's pkg not SEA
|
||||
- Trailing data after PE sections is gzip-compressed pkg payload
|
||||
|
||||
## Phase 5: Build and package
|
||||
|
||||
```bash
|
||||
# Self-contained publish (critical — FDD won't work in MSIX)
|
||||
dotnet publish App.csproj -c Release -r win-x64 --self-contained true
|
||||
```
|
||||
|
||||
Create staging directory from publish output, then overlay original:
|
||||
- `resources.pri` (XBF, strings, images)
|
||||
- `Assets/` folder
|
||||
- `Watchers/` folder
|
||||
- Locale directories (`xx-XX/`)
|
||||
- `Microsoft.UI.Xaml/` folder
|
||||
- Native WinUI DLLs (whitelist — never overwrite published exe/dll)
|
||||
|
||||
## Phase 6: MSIX packaging with self-signed cert
|
||||
|
||||
```powershell
|
||||
# Create cert matching manifest Publisher
|
||||
$cert = New-SelfSignedCertificate -Subject "CN=PublisherFromManifest" ...
|
||||
# Add to Trusted Root and Trusted People
|
||||
# Pack with makeappx
|
||||
makeappx.exe pack /d staging /p App.msix /nv
|
||||
# Sign with signtool
|
||||
signtool.exe sign /fd SHA256 /a /f cert.pfx /p password App.msix
|
||||
# Install
|
||||
Add-AppxPackage -Path App.msix
|
||||
```
|
||||
|
||||
Requirements:
|
||||
- `AllowAllTrustedApps=1` and `AllowDevelopmentWithoutDevLicense=1` in registry
|
||||
- Manifest Publisher must exactly match cert Subject
|
||||
- Bump version on each rebuild
|
||||
- Remove stale `AppxSignature.p7x`, `AppxBlockMap.xml`, `AppxMetadata/` from staging
|
||||
|
||||
## Phase 7: Launch and verify
|
||||
|
||||
```powershell
|
||||
# Launch via AppsFolder (not Start-Process directly)
|
||||
Start-Process explorer.exe -ArgumentList 'shell:AppsFolder\PackageFamilyName!App'
|
||||
# Wait 8-15 seconds for WinUI window
|
||||
# Verify: PID path matches Rev package, MainWindowTitle set, RAM > 150MB
|
||||
```
|
||||
|
||||
UI verification:
|
||||
- UI Automation: `[System.Windows.Automation.AutomationElement]::FromHandle($hwnd)`
|
||||
- Screenshot + pixel sampling for color/design changes
|
||||
- Don't trust `base.Title` alone — custom title bar uses `AppTitleTextBlock.Text`
|
||||
|
||||
## Known limitations
|
||||
|
||||
- XAML markup (XBF v2.1) cannot be decompiled — original `resources.pri` is used
|
||||
- ILSpy leaves `Unknown result type` comments in 61+ files (WinRT projection IL)
|
||||
- `copy_all.ps1` pattern overwrites rebuilt exe/dll — always rebuild AFTER copying
|
||||
- `Window.RequestedTheme` not available in WinUI 3 — set theme on child elements
|
||||
- Process may take 10-15 seconds to create window handle after launch
|
||||
Reference in New Issue
Block a user