バージョン11.6.0.0
Babel Obfuscator
2026年2月20日にリリース
機能強化
- Babel UI - ルールのナビゲーション: XML の非同期解析によってルールの読み込みを改善し、大規模なルールセットでも UI の応答性を高めました。進行状況のオーバーレイとキャンセル機能を備えたスマートなルールナビゲーションを追加したほか、スレッド間の安全性に関する修正や、ルールツリーの操作中に UI がブロックされないようルールノードの展開ロジックを最適化しました。
- ジェネリック属性 (C# 11): ジェネリック型パラメーターを持つカスタム属性 (例:
MyAttribute<double>) の読み書きに対応しました。属性のコンストラクターシグネチャ内のElementType.Varを解決するため、アップストリームの Mono.Cecil からGenericParameterResolverを移植しています。ジェネリック属性を使用する .NET 9.0 アセンブリの処理時に発生していたNotImplementedException: Unknown primitive typeを修正します。 - ByRefLike ジェネリック制約 (.NET 9):
allows ref structジェネリック制約に対応するため、GenericParameterAttributes.AllowByRefLikeConstraint(0x0020) と、対応するGenericParameter.AllowByRefLikeConstraintプロパティを追加しました。 - アンマネージド呼び出し規約:
delegate* unmanaged関数ポインターに対応するため、MethodCallingConvention.Unmanaged(0x9) を追加しました。 - AggressiveOptimization 属性:
MethodImplAttributes.AggressiveOptimization(0x0200) と、対応するMethodDefinition.AggressiveOptimizationプロパティを追加しました。
バグ修正
- WriteCompressedInt32: ECMA-335 の符号付き整数の圧縮エンコーディングアルゴリズムを、
System.Reflection.Metadataと一致するように書き直しました。従来の実装では特定の負の値 (たとえば -9076) で誤ったエンコーディングが生成され、特定の定数値やカスタム属性の BLOB を含むアセンブリを書き出す際にメタデータが壊れるおそれがありました。 - インスタンスメソッドと静的メソッドの解決:
MetadataResolver.GetMethodがHasThisフラグを比較するよう修正し、名前と引数の型が同じ静的メソッドとインスタンスメソッドが同一と見なされないようにしました。これは静的な abstract/virtual インターフェイスメンバー (C# 11) を正しく解決するために必要です。 - AggressiveOptimization のタイプミス: Mono.Cecil と難読化ツールのプラグインコード全体で、
AggressiveOptimizatios→AggressiveOptimizationのタイプミスを修正しました。 - MaxStackSize の上書き (Android/ARM64 のクラッシュ): Mono.Cecil の
CodeWriter.ComputeHeader()がbody.max_stack_sizeを計算値で無条件に上書きし、制御フロー難読化のアルゴリズムによる調整 (goto は +3、switch は +1/2、if は +1) を破棄してしまう問題を修正しました。ARM64 の CoreCLR (たとえば .NET 10 Android) では、これがスタックフレームの破損を招き、難読化されたメソッドで引数が null になる形で現れていました。修正では、計算値とアルゴリズムによる調整値の大きい方を保持し、既存のReplaceCodeWriterの動作に合わせています。 - ControlFlowIfAlgorithm で MaxStackSize の調整が抜けていた問題: if スクランブルのアルゴリズムだけが
EndMethodでMaxStackSizeを調整していませんでした。分岐点に挿入するldc.i4.0/ldc.i4.1+brtrue/brfalseのパターンを考慮して、+1の調整を追加しました。 - ControlFlowGotoAlgorithm の後方条件分岐 (Android のクラッシュ): goto スクランブルのアルゴリズムは、
lastInstructionの後に不透明述語を挿入し、firstInstruction.Nextを対象とする後方条件分岐 (bgt/blt/beq) を生成していました。.NET Android (CoreCLR x86_64 のインタープリター/JIT) では、これらの後方条件分岐がループのバックエッジと誤解釈され、誤ったコード生成によって引数が null になる現象が起きていました。特に IF と GOTO の組み合わせでこの不具合が発生したのは、GOTO の後方条件分岐が IF で変換された分岐パターンの途中に飛び込むためです。修正では、不透明述語をfirstInstructionとその次の命令の間に配置するよう構造を変更し、すべての分岐を前方のみにしました。これにより、難読化の強度を保ったまま後方条件分岐がなくなります (逆コンパイラーは、不透明述語を評価しない限りどちらの前方経路が実行されるかを判断できません)。 - .NET Android/iOS の制御フロー:
ControlFlowAddMethodToken(token) とControlFlowStackUnderflow(underflow) が、.NET Android および iOS のアセンブリで無効化されていなかった問題を修正しました。これらの機能は MonoVM ではサポートされていませんが、無効化されるのは従来の Xamarin (MonoAndroid/Xamarin.iOS) アセンブリだけでした。最新の .NET Android/iOS アセンブリ (たとえばnet10.0-android) は.NETCoreAppに分類されるため、Mono 固有の無効化ロジックを通らなかったのです。token オプションが挿入するldtokenのデッドコードによって MonoVM の JIT がメソッドを誤コンパイルし、実行時に引数が null になることがありました。 - DynamicProxy とスタックに依存するメソッド (.NET 10): DynamicProxy を有効にすると
Assembly.GetExecutingAssembly()とAssembly.GetCallingAssembly()が誤ったアセンブリを返す問題を修正しました。これらのメソッドは内部のスタックウォーク (StackCrawlMark) で呼び出し元のアセンブリを判定します。デリゲート経由でプロキシ化されるとスタックフレームが増えるため、.NET 10 のランタイムは別のアセンブリ (たとえばSystem.Private.CoreLib) を解決し、そのLocationが空になるため、Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)が null を返していました。修正では、スタックに依存するメソッドを DynamicProxy の処理対象から除外し、直接呼び出しを維持します。
Babel Licensing
バグ修正
- Babel UI: 親となるアクティベーションライセンスの有効期限を変更しても、ノードロックライセンスのキーが再生成されず、データベースのレコードは更新されているのに署名済みライセンスキーには古い期限が残る問題を修正しました。
- Babel Licensingサービス: Management Controller からアクティベーションライセンスの有効期限を変更した際に、更新後の期限で ASCII 形式のライセンスキーが再生成されず、データベースは正しく更新されているのに署名済みキーが古いままになる問題を修正しました。
- ライセンスストアへの同時アクセス: 複数のプロセスが同時にライセンスストアへアクセスした際のファイルロック競合に対応するため、読み書きの再試行処理を追加し、断続的に発生していた「License component not available」エラーを防ぎました。

