reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
133
our-skills/winui3-reverse-engineering/SKILL.md
Normal file
133
our-skills/winui3-reverse-engineering/SKILL.md
Normal file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
name: winui3-reverse-engineering
|
||||
description: "Reverse engineer WinUI 3 / .NET 8 MSIX applications: ILSpy decompilation, self-contained publish, MSIX packaging with self-signed cert, and side-by-side launch with modified code"
|
||||
---
|
||||
|
||||
# WinUI 3 Reverse Engineering Pipeline
|
||||
|
||||
## When to use
|
||||
Reverse engineering a WinUI 3 / Windows App SDK / .NET 8 MSIX-packaged desktop application. Produces editable C# source, rebuildable MSIX, and a running modified app side-by-side with the original.
|
||||
|
||||
## Prerequisites
|
||||
- ILSpy CLI (`dotnet tool install --global ilspycmd`)
|
||||
- .NET 8 SDK
|
||||
- Windows SDK (makeappx.exe, signtool.exe, makepri.exe)
|
||||
- PowerShell 5+
|
||||
- Target app installed as MSIX (in `C:\Program Files\WindowsApps\`)
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Locate the app
|
||||
```powershell
|
||||
Get-Process <AppName> | Select-Object Id,Path
|
||||
# Path will be like C:\Program Files\WindowsApps\<PackageFullName>\<App>.exe
|
||||
```
|
||||
|
||||
### 2. Identify the stack
|
||||
- `.dll` next to `.exe` = .NET app (check for `coreclr.dll`, `hostfxr.dll`)
|
||||
- Main `.dll` (3+ MB) = application logic; `.exe` (small) = native loader
|
||||
- `resources.pri` = XAML binary (XBF) + strings + images
|
||||
- `Watchers\` or similar = backend services (may be pkg-compiled Node.js)
|
||||
|
||||
### 3. Decompile C#
|
||||
```bash
|
||||
ilspycmd "C:\path\to\App.dll" -p -o "C:\output\src" --decompile-baml -r "C:\path\to\install\dir"
|
||||
```
|
||||
- `--decompile-baml` may not work for WinUI 3 (XBF v2.1, not BAML)
|
||||
- `-r` provides reference path for dependency resolution
|
||||
|
||||
### 4. Fix csproj
|
||||
- ILSpy generates bare `<Reference>` without HintPath for WinRT projections
|
||||
- Copy all DLLs from install dir to `libs/` folder
|
||||
- Add `<HintPath>libs\*.dll</HintPath>` for each reference
|
||||
- Set `<LangVersion>preview</LangVersion>` (ILSpy may emit unsupported version)
|
||||
- Set `<GenerateAssemblyInfo>False</GenerateAssemblyInfo>`
|
||||
|
||||
### 5. Fix common compile errors
|
||||
- **CS0136** (duplicate variable): rename one occurrence
|
||||
- **CS0104** (ambiguous `Color`): qualify as `Windows.UI.Color.FromArgb(...)`
|
||||
- **CS1061** (`PaneBackground` not on NavView): use `Background` instead
|
||||
- **CS1061** (`RequestedTheme` not on Window): set on `Content` element instead
|
||||
- ILSpy inlines `const` values — fix inline literals (e.g., `FindOrRegisterForKey("OriginalKey")` → `FindOrRegisterForKey(AppInstanceKey)`)
|
||||
|
||||
### 6. Publish self-contained
|
||||
```bash
|
||||
dotnet publish App.csproj -c Release -r win-x64 --self-contained true
|
||||
```
|
||||
- Framework-dependent publish fails in MSIX (no global .NET runtime visible)
|
||||
- Self-contained bundles .NET runtime into the package
|
||||
|
||||
### 7. Overlay original assets
|
||||
Copy from original MSIX to publish output (whitelist only, never overwrite published exe/dll):
|
||||
- `resources.pri` (XBF, strings, images)
|
||||
- `Assets/` folder
|
||||
- `Watchers/` folder (backend)
|
||||
- Locale directories (`xx-XX/`)
|
||||
- `Microsoft.UI.Xaml/` folder
|
||||
- Native WinUI DLLs (Microsoft.UI.Xaml.Controls.dll, CoreMessagingXP.dll, etc.)
|
||||
- `Microsoft.WindowsAppRuntime.dll`, `.Bootstrap.dll`, `.Bootstrap.Net.dll`
|
||||
|
||||
### 8. Create AppxManifest with new identity
|
||||
```xml
|
||||
<Identity Name="<OriginalName>Rev" Publisher="<OriginalPublisher>" Version="3.7.2.7" ProcessorArchitecture="x64" />
|
||||
```
|
||||
- Use same Publisher CN as original (for cert matching)
|
||||
- Bump version on each rebuild
|
||||
- Keep `runFullTrust` capability
|
||||
|
||||
### 9. Self-signed cert + MSIX packaging
|
||||
```powershell
|
||||
# Create cert matching manifest Publisher
|
||||
$cert = New-SelfSignedCertificate -Subject "CN=<PublisherCN>" -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 and Trusted People
|
||||
# Export PFX, sign MSIX with signtool
|
||||
# Register with Add-AppxPackage
|
||||
|
||||
# CRITICAL: Remove cert from all stores and delete PFX after install
|
||||
# See cleanup section below
|
||||
```
|
||||
|
||||
### 10. Launch and verify
|
||||
```powershell
|
||||
Start-Process explorer.exe -ArgumentList 'shell:AppsFolder\<PackageFamilyName>!App'
|
||||
Start-Sleep -Seconds 10 # WinUI 3 needs time to initialize
|
||||
# Verify: PID, Path (must be Rev package), MainWindowTitle, RAM > 100MB
|
||||
# UI Automation: [System.Windows.Automation.AutomationElement]::FromHandle()
|
||||
# Screenshot: System.Drawing.Bitmap + CopyFromScreen + GetPixel for color verification
|
||||
```
|
||||
|
||||
## Key gotchas
|
||||
- WinUI 3 XAML is compiled to XBF v2.1 in `resources.pri`, NOT BAML — ILSpy `--decompile-baml` won't extract it
|
||||
- `copy_all.ps1` that copies ALL MSIX files will overwrite rebuilt exe/dll with originals — always whitelist
|
||||
- `NODE_SEA_FUSE:0` = disabled SEA; check for `pkg` markers (`PRELUDE_POSITION`, `process.versions.pkg`) instead
|
||||
- pkg auto-extracts to `%TEMP%\<AppName>\<version>\dist` — check there before manual extraction
|
||||
- Cert in LocalMachine\Root with accessible PFX = code signing security risk — always cleanup after
|
||||
- `Start-Process` cannot launch `shell:AppsFolder` URIs directly — use `explorer.exe` as intermediary
|
||||
- Process may show 0x0 window for 10+ seconds before UI initializes — wait before screenshot
|
||||
|
||||
## XBF extraction (if needed)
|
||||
```powershell
|
||||
# Dump PRI
|
||||
makepri.exe dump /if "resources.pri" /of "dump.xml" /dt detailed /o
|
||||
# Extract XBF from Base64 in XML
|
||||
# XBF v2.1 offsets are relative to metadata start (byte 12), not absolute
|
||||
# Table entries are 12 bytes each (not 8 as in v1.0)
|
||||
# Node encoding differs from v1.0 — no working open-source parser exists
|
||||
```
|
||||
|
||||
## pkg-compiled Node.js backend detection
|
||||
- PE header: no CLR header (not .NET)
|
||||
- Search for `NODE_SEA_FUSE`, `pkg/prelude`, `process.versions.pkg`
|
||||
- `process.versions.pkg = '6.22.0'` confirms pkg version
|
||||
- Trailing data after PE sections (gzip compressed) = pkg payload
|
||||
- Auto-extraction: check `%TEMP%\<AppName>\` for already-extracted dist
|
||||
|
||||
## Security cleanup (MANDATORY after install)
|
||||
```powershell
|
||||
# Remove self-signed cert from all stores
|
||||
$certSubject = "CN=<PublisherCN>"
|
||||
# Remove from LocalMachine\Root, LocalMachine\TrustedPeople, CurrentUser\My
|
||||
# Delete PFX file
|
||||
# Verify: Get-ChildItem Cert:\... | Where-Object { $_.Subject -eq $certSubject } returns empty
|
||||
```
|
||||
Reference in New Issue
Block a user