NOTE DI RILASCIO

Le novità di Babel.

Modifiche al motore, agli strumenti di licensing e all’area di lavoro Desktop, dalle note di rilascio del prodotto.

Rilasciata il 6 marzo 2026

Versione 11.6.0.0

Babel Obfuscator

Rilasciata il 20 febbraio 2026

Miglioramenti

  • Babel UI - navigazione delle regole: Migliorato il caricamento delle regole con il parsing XML asincrono e una maggiore reattività dell'interfaccia con insiemi di regole di grandi dimensioni. Aggiunta una navigazione intelligente delle regole con overlay di avanzamento e possibilità di annullare, corretti alcuni problemi di sicurezza tra thread e ottimizzata la logica di espansione dei nodi delle regole per evitare il blocco dell'interfaccia durante le operazioni sull'albero.
  • Attributi generici (C# 11): Aggiunto il supporto alla lettura e alla scrittura di attributi personalizzati con parametri di tipo generici (ad esempio MyAttribute<double>). Portato GenericParameterResolver dall'upstream di Mono.Cecil per risolvere ElementType.Var nelle firme dei costruttori degli attributi. Risolve NotImplementedException: Unknown primitive type durante l'elaborazione di assembly .NET 9.0 che usano attributi generici.
  • Vincolo generico ByRefLike (.NET 9): Aggiunti GenericParameterAttributes.AllowByRefLikeConstraint (0x0020) e la corrispondente proprietà GenericParameter.AllowByRefLikeConstraint per supportare il vincolo generico allows ref struct.
  • Convenzione di chiamata Unmanaged: Aggiunta MethodCallingConvention.Unmanaged (0x9) per supportare i puntatori a funzione delegate* unmanaged.
  • Attributo AggressiveOptimization: Aggiunti MethodImplAttributes.AggressiveOptimization (0x0200) e la corrispondente proprietà MethodDefinition.AggressiveOptimization.

Correzioni di bug

  • WriteCompressedInt32: Riscritto l'algoritmo di codifica ECMA-335 degli interi con segno compressi per allinearlo a System.Reflection.Metadata. L'implementazione precedente produceva codifiche errate per alcuni valori negativi (ad esempio -9076), il che poteva corrompere i metadati durante la scrittura di assembly con determinati valori costanti o blob di attributi personalizzati.
  • Risoluzione tra metodi di istanza e statici: Corretto MetadataResolver.GetMethod perché confronti il flag HasThis, così un metodo statico e uno di istanza con lo stesso nome e gli stessi tipi di parametri non vengono più considerati identici. Questo è necessario per la corretta risoluzione dei membri di interfaccia statici astratti o virtuali (C# 11).
  • Refuso in AggressiveOptimization: Corretto il refuso AggressiveOptimizatios → AggressiveOptimization in Mono.Cecil e nel codice del plugin dell'offuscatore.
  • Sovrascrittura di MaxStackSize (crash su Android/ARM64): Risolto il comportamento di CodeWriter.ComputeHeader() in Mono.Cecil, che sovrascriveva incondizionatamente body.max_stack_size con il valore calcolato, scartando le correzioni apportate dagli algoritmi di offuscamento del flusso di controllo (goto +3, switch +1/2, if +1). Su CoreCLR ARM64 (ad esempio .NET 10 Android) questo causava una corruzione dello stack frame che si manifestava come valori di parametro null nei metodi offuscati. La correzione conserva il maggiore tra il valore calcolato e quello corretto dall'algoritmo, in linea con il comportamento già presente in ReplaceCodeWriter.
  • ControlFlowIfAlgorithm senza correzione di MaxStackSize: L'algoritmo di scrambling degli if era l'unico algoritmo di flusso di controllo a non correggere MaxStackSize nel proprio EndMethod. Aggiunta la correzione +1 per tenere conto del pattern ldc.i4.0/ldc.i4.1 + brtrue/brfalse che inserisce nei punti di diramazione.
  • ControlFlowGotoAlgorithm, salto condizionale all'indietro (crash su Android): L'algoritmo di scrambling dei goto inseriva predicati opachi dopo lastInstruction con un salto condizionale all'indietro (bgt/blt/beq) verso firstInstruction.Next. Su .NET Android (interprete/JIT CoreCLR x86_64) questi salti condizionali all'indietro venivano interpretati come back-edge di un ciclo, causando una generazione di codice errata che si manifestava con valori di parametro null. In particolare, era la combinazione IF+GOTO a innescare il problema, perché il salto condizionale all'indietro del GOTO finiva in mezzo ai pattern di diramazione trasformati dall'IF. La correzione ristruttura il predicato opaco collocandolo tra firstInstruction e l'istruzione successiva, in modo che tutti i salti siano solo in avanti. Questo elimina il salto condizionale all'indietro mantenendo la stessa forza di offuscamento (i decompilatori continuano a non poter determinare quale percorso in avanti venga preso senza valutare il predicato opaco).
  • Flusso di controllo su .NET Android/iOS: Risolto il fatto che ControlFlowAddMethodToken (token) e ControlFlowStackUnderflow (underflow) non venivano disattivati per gli assembly .NET Android e iOS. Queste funzionalità non sono supportate su MonoVM, ma venivano disattivate solo per gli assembly Xamarin legacy (MonoAndroid/Xamarin.iOS). Gli assembly .NET Android/iOS moderni (ad esempio net10.0-android) sono classificati come .NETCoreApp e aggiravano quindi la logica di disattivazione specifica per Mono. Il codice morto ldtoken inserito dall'opzione token poteva far compilare male i metodi al JIT di MonoVM, con parametri null a runtime.
  • Metodi sensibili allo stack con DynamicProxy (.NET 10): Risolto il comportamento di Assembly.GetExecutingAssembly() e Assembly.GetCallingAssembly() che restituivano l'assembly sbagliato quando DynamicProxy è attivo. Questi metodi usano un percorso interno dello stack (StackCrawlMark) per determinare l'assembly chiamante. Quando venivano sottoposti a proxy tramite un delegate, i frame aggiuntivi facevano risolvere al runtime di .NET 10 un assembly diverso (ad esempio System.Private.CoreLib) con Location vuota, facendo restituire null a Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location). La correzione esclude i metodi sensibili allo stack dall'elaborazione di DynamicProxy, preservando le chiamate dirette.

Babel Licensing

Correzioni di bug

  • Babel UI: Risolto il problema per cui le chiavi delle licenze node-locked non venivano rigenerate quando cambiava la data di scadenza della licenza di attivazione padre, così la chiave di licenza firmata conservava date di scadenza obsolete pur essendo aggiornati i record nel database.
  • Servizio Babel Licensing: Risolto il problema per cui la chiave di licenza ASCII non veniva rigenerata con le date di scadenza aggiornate quando la data di scadenza di una licenza di attivazione veniva modificata tramite il Management Controller, così la chiave firmata restava obsoleta pur essendo il database aggiornato correttamente.
  • Accesso concorrente all'archivio delle licenze: Aggiunta una logica di ritentativo per la lettura e la scrittura dell'archivio delle licenze, in modo da gestire i conflitti di lock sui file quando più processi vi accedono contemporaneamente, evitando gli errori intermittenti "License component not available".