Files
reverse-skills-max/our-skills/winui3-reverse-engineering/SKILL.md

5.8 KiB

name, description
name description
winui3-reverse-engineering 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

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#

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

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

<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

# 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

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)

# 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)

# 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