5.8 KiB
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
.dllnext to.exe= .NET app (check forcoreclr.dll,hostfxr.dll)- Main
.dll(3+ MB) = application logic;.exe(small) = native loader resources.pri= XAML binary (XBF) + strings + imagesWatchers\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-bamlmay not work for WinUI 3 (XBF v2.1, not BAML)-rprovides 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 asWindows.UI.Color.FromArgb(...) - CS1061 (
PaneBackgroundnot on NavView): useBackgroundinstead - CS1061 (
RequestedThemenot on Window): set onContentelement instead - ILSpy inlines
constvalues — 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/folderWatchers/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
runFullTrustcapability
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-bamlwon't extract it copy_all.ps1that copies ALL MSIX files will overwrite rebuilt exe/dll with originals — always whitelistNODE_SEA_FUSE:0= disabled SEA; check forpkgmarkers (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-Processcannot launchshell:AppsFolderURIs directly — useexplorer.exeas 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