Version 11.8.0.0
Babel Obfuscator
Enhancements
- FIPS-Enabled Hosts — Managed AES Encryption: Added an opt-in managed AES decryptor selected with
--use encryption=aesmanaged(or<Use>encryption=aesmanaged</Use>from MSBuild). Assemblies protected with Code (MSIL), String, Value/Array or Resource Encryption now start on hosts where the platform cryptographic provider is unusable — most notably Linux containers in a broken OpenSSL FIPS state, where the injected decryption runtime previously threw anOpenSslCryptographicExceptioninside the type initializer before any user code ran. The obfuscator still encrypts with the platform provider on the (healthy) build host and emits the same ciphertext; only the self-contained decryptor carried inside the assembly changes. Supported on .NET Framework and .NET (Core); netstandard and Mono keep their existing behavior. See the FIPS Compliance documentation page. Note the ~40 MB/s managed-decryptor throughput: avoid combining it withcache=falseCode Encryption on hot-path methods. - Performance — Large Assemblies: Rewrote three hot paths that dominated obfuscation of very large, code- and attribute-heavy assemblies, with output verified byte-identical to 11.7.0:
- Custom-attribute renaming (
RenameTypeAttributes) is now indexed instead of O(types × attributes). A 41 MB / ~69k-type attribute-heavy assembly (e.g. Microsoft.Graph) that previously did not finish the renaming phase now completes in ~20 s. - Call-graph
FindCallVerticesis O(vertices) instead of O(vertices × signatures) — 7–11× faster on DevExpress.XtraEditors / Spire.Pdf. - Virtual-member grouping in the Renaming phase is bucketed by name (2074 ms → 17 ms on DevExpress.XtraEditors). End-to-end this cut full-feature obfuscation of a 7.9 MB DevExpress assembly by ~24%.
- Custom-attribute renaming (
- Dynamic Target Runtime Detection: Added dynamic detection of the target runtime version for obfuscated assemblies.
- Hardware Dongle Binding Sample: Added a runnable cross-platform reference implementation showing how to bind a Code-Encryption-protected .NET application to a hardware licensing dongle (KEYLOK, SafeNet Sentinel, Wibu CodeMeter, Marx CrypToken, …) so that swapped or stubbed dongle DLLs cannot bypass the protection.
- [New] Warning OB0009 reports a demo-mode case that was impossible to diagnose from the output: when map files are supplied but cross assembly obfuscation is not licensed, the map is skipped and references to renamed external symbols keep their original names, so the assembly only failed at runtime with a
TypeLoadException. It is now reported at build time.
Bug Fixes
- Avalonia — Resource Encryption: Fixed obfuscated Avalonia applications crashing at startup with
FileNotFoundExceptiononavares://assets and XAML when Resource Encryption was enabled. Avalonia stores all of an assembly's XAML and assets in a single!AvaloniaResourcesblob that its asset loader reads directly, bypassing the decrypt hook Babel injects. That blob is now left unencrypted (all other resources are still encrypted), so Avalonia apps are fully obfuscatable with Resource Encryption on. WPF is unaffected. To ship a single-file Avalonia app, use assembly embedding (not merging). - WPF — Theme Dictionary Merge: Fixed control themes being lost when merging assemblies that both contain a BAML resource dictionary at the same path (typically
themes/generic.baml). Colliding neutral-cultureResourceDictionarystreams are now preserved under unique names and linked through a synthesized dictionary viaMergedDictionaries, keeping the primary assembly's lookup precedence. - MAUI/XAML —
x:Language Primitives: Fixed the XAML renamer dropping thex:prefix from language primitives inx:TypeArguments(e.g.x:Double→Double). This crashed .NET MAUI iOS Release builds that load XAML at runtime withXamlParseException ("Type Double not found"). - Renaming — Self-Referencing Type References: Fixed a renamed type leaving self-referencing
TypeReferences (own-module scope) with the old name, causingSystem.TypeLoadExceptionat type initialization. IL weavers such as ArxOne.MrAdvice — and C# top-level statements via the internalProgramtype — emitldtokenaliases that then failed to resolve. The self-module TypeRef fixup now runs for every renamed type. - Renaming — PropertyChanged String Rewrite: Fixed the post-rename
ldstrrewrite (which keepsOnPropertyChanged("PropName")working after renaming) incorrectly rewriting unrelated string-keyed API arguments — XAML control lookups, dictionary keys, custom registries — on any type deriving from anINotifyPropertyChangedbase. The rewrite is now limited to recognised PropertyChanged sinks. Reported on 8.7, reproduced on 11.7. - Control Flow — External-Dependency Host Types: Fixed randomly intermittent
FileNotFoundExceptionat runtime (for example SSIS0xC0011008) caused by control-flow dispatcher and switch-flattening helper methods being hosted in types that pull in an external assembly at load time. Host-type selection now rejects types with value-type fields (checked recursively, including generic arguments and nested value types) or base/interface types outside the module or core library, and rejects generic host types. - Licensing — Invalid License Silently Fell Back to Demo Mode: Fixed a license file supplied explicitly but not valid for the running version being neither honoured nor reported: the run silently continued in demo mode, producing a time-bombed assembly without the licensed features, which the user typically discovered much later. An explicitly provided license must now be valid for this product and version, otherwise Babel stops with
Error: the license provided is not valid for Babel Obfuscator <version>.and exits withLicensingFailure(1, or40under--strict-exit) without producing an assembly. Running with no license at all still starts demo mode with the reduced feature set, as before. - Trial Licenses on Linux: Licenses carrying a run-time or instance-count trial restriction could fail to validate on Linux hosts, including the Babel Obfuscator NuGet task in Linux containers. See the Babel Licensing 11.8.0.0 release notes for details.
Changes
- Self-Obfuscation Toolchain: The Babel Obfuscator NuGet package (and the babel/lic/HardwareId/Babel.Win binaries) are now self-obfuscated with the managed AES algorithm, so the distributed tools themselves start on broken-FIPS hosts.
Babel Licensing
Enhancements
- FIPS-Enabled Hosts — Startup Resilience: Babel Licensing now survives FIPS-enabled hosts whose container lacks a certified OpenSSL FIPS provider (for example a RHEL host running an Ubuntu-based .NET container, dotnet/dotnet-docker#5849), where license validation previously crashed with
BabelLicenseException: Internal error— .NETIsolatedStorageidentity hashing failing inSHA1.Createwitherror:03000086. The license store now falls back to a managed file store when IsolatedStorage cannot initialize, replaces the platform AES/DES ciphers in the encrypted date store with bit-compatible BouncyCastle ciphers (existing store files remain readable in both directions), and degrades to in-memory date tracking when no storage is usable — so license validation no longer touches the OS crypto stack. When the Babel Licensing Service is obfuscated with the Babel Obfuscator managed AES algorithm (--use encryption=aesmanaged), the obfuscated service also starts on broken-FIPS hosts. - Activation Licenses — Feature Propagation on Validate: Adding a feature to an activation license now reaches already-activated clients on the next validate, instead of requiring a full deactivate and re-activate. Both the activation and validate paths build and re-sign the per-machine node-locked license from the parent license (features, fields, restrictions, dates) plus the hardware binding through a shared helper.
Bug Fixes
- gRPC UserKey Authentication: Fixed all gRPC UserKey logins failing after the 11.7.0 security hardening.
GrpcAuthenticator.AuthenticateAsyncignored its username parameter and always sent the constructor-captured client id, routing UserKey logins to the two-argument identity-login path. An opt-inEnableLegacyUserKeyFallbackbridge (default off) lets operators with many already-deployed client applications restore compatibility without redeploying, while new installs stay on the corrected path. - Webhook Payload JSON Keys: Fixed license, order and report webhook payloads delivering single-letter JSON keys (
p,q,r, …) when the Licensing Service is obfuscated with symbol renaming. Payloads now use named DTOs that pin every key via[JsonPropertyName](camelCase), so the webhook contract is immune to symbol renaming and string encryption. - Trial Licenses — Linux Hosts Without a Shared Memory Region: Fixed a license carrying a run-time or instance-count trial restriction failing validation with
Object reference not set to an instance of an object, soIsValidreturnedfalsewhile the same license validated correctly on Windows and macOS. Reported on Linux containers.Application.StartTimeandApplication.InstanceCountread the shared memory region unconditionally, but the region is only populated when it can be opened, so where it could not be created both members threw andTrialRestriction.Validatefailed with an opaque error. The region is now tracked as optional and the two values degrade to per-process ones — the process start time and the existing process-count fallback — instead of throwing. A zeroed creation time is treated the same way, since it would otherwise make every trial run time look already elapsed. Not a regression: the behavior was identical in 11.6.0, 11.7.0, 11.7.0.3 and 11.8.0. - Linux — POSIX Semaphore Library Binding: Fixed the root cause of the failure above: the shared memory region could never be opened on a glibc Linux host. The
sem_*entry points guarding it were imported fromlibrt, a name the .NET runtime probes aslibrt.soandliblibrt.sobut never as the installedlibrt.so.1soname — the unversioned symlink ships with the development package, which container images do not carry — so every call failed to bind with aDllNotFoundException. Beyond breaking trial restrictions, this silently degradedApplication.StartTimeandApplication.InstanceCountto per-process values on all Linux hosts. The import now uses the soname, and aDllImportResolveradditionally trieslibpthread.so.0,libc.so.6and the musl libc names, covering glibc before and after the 2.34 merge ofsem_*into libc as well as musl. Cross-process instance counting and the shared application start time now behave on Linux as they always have on Windows. Alpine/musl hosts were not affected.SharedMemory.Openalso reports an unavailable region instead of throwing at the caller, so hosts with no named semaphores keep working through the per-process fallback. - Babel Licensing Service — Auto-Generated JWT Signing Key: Fixed every call made with an issued token failing with
401— and therefore no license being activatable — whenApplication:SigningKeywas left empty. The randomly generated startup key was assigned only to a detached copy of theApplicationconfiguration section, whileTokenServiceresolvesIOptionsSnapshot<ApplicationSettings>and re-binds from configuration, so tokens were signed with a key of padding spaces and validated against the generated one. The service log made this hard to diagnose, reporting a successful authentication right before the401. The generated key is now applied throughPostConfigure<ApplicationSettings>, so every bound options instance signs and validates with the same key. Configuring an explicit key remains the recommended production setting: a generated key changes at every restart and is not shared across instances.

