reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
130
our-skills/reverse-winui3-app/SKILL.md
Normal file
130
our-skills/reverse-winui3-app/SKILL.md
Normal file
@@ -0,0 +1,130 @@
|
||||
---
|
||||
name: reverse-winui3-app
|
||||
description: "Use when reverse engineering a WinUI 3 / .NET 8 MSIX-packaged Windows application — covers ILSpy decompilation, PRI/XBF extraction, and pkg-compiled Node.js backend identification"
|
||||
---
|
||||
|
||||
# Reverse Engineering WinUI 3 + pkg-compiled Node.js Applications
|
||||
|
||||
## When to use
|
||||
- Target is a Windows MSIX-packaged app (WinUI 3 / Windows App SDK)
|
||||
- App has a separate backend executable compiled with `pkg`
|
||||
- Need to extract C# source, XAML (XBF), and JS backend code
|
||||
|
||||
## Phase 1: Locate and identify the target
|
||||
|
||||
```powershell
|
||||
# Find running process
|
||||
Get-Process <name> | Select Id,Path
|
||||
# Or search MSIX install
|
||||
Get-ChildItem "C:\Program Files\WindowsApps" -Directory -Filter "*<name>*"
|
||||
```
|
||||
|
||||
Identify app type by inspecting install directory:
|
||||
- `coreclr.dll`, `hostfxr.dll`, `*.dll` (managed) → .NET / WinUI 3
|
||||
- `VibeProxy.exe` (small, ~400KB) = native launcher; `VibeProxy.dll` (large) = main logic
|
||||
- `Watchers\*.exe` (large, 100MB+) = likely pkg-compiled Node.js backend
|
||||
|
||||
## Phase 2: Decompile .NET frontend (ILSpy)
|
||||
|
||||
```bash
|
||||
# Install ILSpy CLI
|
||||
dotnet tool install --global ilspycmd
|
||||
|
||||
# Decompile with BAML support and reference path
|
||||
ilspycmd "target.dll" -p -o "output_dir" --decompile-baml -r "install_dir"
|
||||
|
||||
# Fix csproj: LangVersion=preview, add HintPath for all references
|
||||
# Copy dependency DLLs to libs/ folder (include large ones >15MB separately)
|
||||
# Fix CS0136 (duplicate variable names) by renaming
|
||||
# Build: dotnet build -c Release
|
||||
```
|
||||
|
||||
Key limitations:
|
||||
- WinUI 3 XAML compiles to XBF (not BAML) — `--decompile-baml` won't extract it
|
||||
- `Unknown result type` comments in 60+ files = WinRT projection IL artifacts
|
||||
- Smoke-launch fails: WinRT activation requires MSIX package identity
|
||||
|
||||
## Phase 3: Extract XBF from resources.pri
|
||||
|
||||
```bash
|
||||
# Find makepri.exe in Windows SDK
|
||||
# Dump PRI to XML (detailed format for Base64 data)
|
||||
makepri.exe dump /if "install_dir\resources.pri" /of "dump.xml" /dt detailed /o
|
||||
```
|
||||
|
||||
```powershell
|
||||
# Extract XBF binaries from PRI dump XML
|
||||
[xml]$xml = Get-Content "dump.xml" -Raw
|
||||
$xbfNodes = $xml.SelectNodes("//NamedResource[contains(@name,'.xbf')]")
|
||||
foreach ($node in $xbfNodes) {
|
||||
$name = $node.GetAttribute("name")
|
||||
$uri = $node.GetAttribute("uri")
|
||||
$pathPart = $uri -replace "ms-resource://[^/]+/Files/", ""
|
||||
$candidate = $node.SelectSingleNode("Candidate")
|
||||
if ($candidate.GetAttribute("type") -eq "EmbeddedData") {
|
||||
$b64 = $candidate.SelectSingleNode("Base64Value")
|
||||
$bytes = [System.Convert]::FromBase64String($b64.InnerText)
|
||||
[System.IO.File]::WriteAllBytes($outPath, $bytes)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
XBF v2.1 format notes:
|
||||
- Header: magic(4) + metaSize(uint32) + nodeSize(uint32) = 12 bytes
|
||||
- Metadata at byte 12: version(2x uint32) + 6 table offsets (uint64, relative to byte 12) + hash (64 bytes)
|
||||
- Table entries are 12 bytes each (not 8 as in v1.0)
|
||||
- Node encoding differs from v1.0 — no existing tool supports v2.1
|
||||
- Best path to XAML: runtime-hook `LoadComponent` in live app, serialize visual tree
|
||||
|
||||
## Phase 4: Identify and extract pkg-compiled backend
|
||||
|
||||
### Identify pkg binary
|
||||
```
|
||||
PE header: NOT .NET (no CLR header)
|
||||
Search for: "process.versions.pkg", "pkg/prelude", "/snapshot/"
|
||||
NODE_SEA_FUSE:0 = disabled (stock Node, not SEA)
|
||||
pkg version found in binary (e.g., '6.22.0')
|
||||
```
|
||||
|
||||
### Extract via runtime unpacking
|
||||
pkg extracts itself to `%TEMP%\<ServiceName>\<package-name>\<version>\dist` at runtime.
|
||||
Check if the app has been run:
|
||||
```powershell
|
||||
Get-ChildItem "$env:TEMP" -Directory -Filter "*<ServiceName>*"
|
||||
Get-ChildItem "$env:TEMP\*<ServiceName>*\*" -Recurse
|
||||
```
|
||||
|
||||
If found, copy the `dist` directory — it contains:
|
||||
- `server.js` / `server-ws.mjs` (entry points, readable)
|
||||
- `.build/next/` (Next.js standalone build)
|
||||
- `.build/next/server/chunks/` (minified but readable JS, 3000+ files)
|
||||
- `.build/next/server/app/api/` (API routes)
|
||||
- `package.json` (identifies upstream package + version)
|
||||
|
||||
### Match with upstream
|
||||
Check `package.json` name + version against GitHub:
|
||||
- If MIT/Apache licensed → full source available upstream
|
||||
- Clone the repo for complete TypeScript source (2,600+ .ts/.tsx files)
|
||||
- Compare extracted dist with git clone to find local modifications
|
||||
|
||||
## Phase 5: Full inventory checklist
|
||||
|
||||
| Item | Source | Method |
|
||||
|------|--------|--------|
|
||||
| C# source | VibeProxy.dll | ILSpy decompile |
|
||||
| XBF (compiled XAML) | resources.pri | makepri dump + extract |
|
||||
| Assets/icons | MSIX install dir | Copy |
|
||||
| Locales | MSIX install dir | Copy (check all dirs) |
|
||||
| config.yaml | Watchers/ | Copy |
|
||||
| Backend dist | %TEMP% (runtime) | Copy after app run |
|
||||
| Backend source | GitHub (if MIT) | git clone |
|
||||
| Build verification | dotnet build | Must be GREEN |
|
||||
| Sourcemaps | .build/next/ | Usually absent in prod |
|
||||
|
||||
## Common pitfalls
|
||||
- Don't claim "full source" without building and smoke-testing
|
||||
- XBF v2.1 ≠ BAML — `--decompile-baml` produces nothing for WinUI 3
|
||||
- SEA fuse `:0` means stock Node.js, not SEA — look for `process.versions.pkg` instead
|
||||
- 210MB gzip trailing data in PE = pkg payload, not SEA blob
|
||||
- Sourcemaps in production Next.js builds are typically empty (`{"sources":[],"sections":[]}`)
|
||||
- WinUI 3 apps cannot launch standalone without MSIX registration
|
||||
Reference in New Issue
Block a user