A1ForceMauiObfuscate

.NET MAUI · after the build

Rename the code. Leave the app standing.

MauiObfuscate runs on the Release assembly. It renames types and members, flattens control flow, packs string literals, and stops the app when a debugger is attached. XAML, images, and fonts stay as they are.

A MAUI screen keeps its visible names while the assembly renames the view model behind it. HomePage.xaml Hello Sign in x:Name TitleLabel kept x:Class HomePage kept Screen text is not rewritten Assembly names LoginViewModel a UserService.Load b HomePage unchanged CreateMauiApp startup stays

The pass

It starts from a build you already made.

The tool does not compile the app and does not need the MAUI workload. It reads the built assembly and its portable PDB, then writes the obfuscated bytes back under the same file name.

  1. 1

    Group the files

    Source paths from the PDB decide the file. ViewModels, models, and services are renamed. Views, XAML, platforms, and startup files are not.

  2. 2

    Read DLL + PDB

    Sequence points tie IL back to a source file. A type with no sequence points is left alone unless you list it explicitly.

  3. 3

    Rename

    Names are short and deterministic. Namespaces stay. Virtuals, interface methods, and constructors are not renamed.

  4. 4

    Write back

    The obfuscated bytes replace App.dll. The build output is parked as App.dll.original, with a rename map beside it.

Protections

Three more passes, each one optional.

They run after renaming, on the app and on every dependency you included. Set protections in maui-obfuscation.json to turn one off.

Straight-line blocks become states of one switch dispatcher. block switch (state) 0 → 1 → 2 one dispatcher

Control-flow flattening

A method body becomes a state machine. A switch picks the next block. Methods that already have exception handlers are left alone.

A readable string is stored compressed, then restored when the method runs. Welcome back Packed in the assembly. Inflated when the method runs.

String packing

Literals leave the method body. They sit in one compressed table and come back as the original string at the call.

Startup checks for an attached debugger and stops the process. start debugger process stops

Anti-debug

A module initializer runs before the app. If a debugger is attached, the process stops. A normal launch continues.

What moves

An exclude always wins.

If a file matches a group that is turned off, it stays. That is how a view model sitting under Platforms, or a generated file, is protected. A dependencies entry can rename another assembly, including a wildcard such as MyCompany.*, and updates the calls in the app.

Left as written

MauiProgram.cs
CreateMauiApp stays
Keep
Views/HomePage.xaml
Markup and x:Name fields
Keep
Platforms/…/MainActivity.cs
Platform entry points
Keep

Renamed in the assembly

LoginViewModel
becomes a short stable name
Rename
UserModel
Models group is on
Rename
UserService.Load
Services group is on
Rename

What the app still needs

The loader looks up names. Those names stay.

The public surface of an x:Class type is kept, including properties the XAML binds to. x:Name fields stay even when they are private. [Obfuscation(Exclude = true)] opts a member out.

A public property on an included view model is renamed. If XAML or a string looks that name up, turn the group off or mark the member excluded. The rename map is how you read a stack trace afterwards.

Three names the obfuscator refuses to change: the page class, its x:Name field, and CreateMauiApp. HomePage — class kept TitleLabel — x:Name kept CreateMauiApp — kept Private helpers on that page can still be renamed.