難読化プロジェクト
難読化プロジェクトは、保護するアセンブリ、その依存関係、それぞれの設定をまとめたものです。Babel Desktop はプロジェクトをキャンバス上のグラフとして表示し、Babel Obfuscator のエンジンで実行します。
Babel Desktop は、プロジェクトを .babel ファイルとして保存します。これは MSBuild タスクが使用する MSBuild プロジェクト形式です。Babel Desktop で保存したプロジェクトは MSBuild でビルドでき、既存の .babel プロジェクトは Babel Desktop で開けます。
プロジェクトの作成
アセンブリを追加する
スタート画面の「アセンブリを追加」か、キャンバスのツールバーの「+ アセンブリを追加」(Ctrl+Shift+A、macOS では Cmd+Shift+A)をクリックします。ファイルマネージャーから .NET アセンブリをキャンバスにドラッグすることもできます。追加したアセンブリは、それぞれプライマリターゲットになります。プライマリターゲットとは、エンジンが難読化するキャンバス上のノードです。
依存関係を接続する
ターゲットにマージするアセンブリ、埋め込むアセンブリ、ターゲットが参照するアセンブリを追加します。手順は依存関係で説明しています。
各ターゲットを設定する
ノードを選択してプロパティパネルを開き、設定と XML ルールを編集します。ターゲットの設定を参照してください。
保存して実行する
「ファイル > 保存」(Ctrl+S、macOS では Cmd+S)でプロジェクトを保存し、「プロジェクトを実行」(Ctrl+Enter、macOS では Cmd+Enter)をクリックします。「保存」は開いている .babel ファイルに書き込み、ファイル名を尋ねるのは新しいプロジェクトの場合だけです。別の名前でコピーを保存するには、「ファイル > 名前を付けて保存…」(Ctrl+Shift+S、macOS では Cmd+Shift+S)を使用します。
最初からやり直すには、「プロジェクト: 新規作成」(Ctrl+N)またはキャンバスの「新しいプロジェクト」ボタンを使用します。コマンドパレットの「プロジェクト: 最近使用したプロジェクトを開く…」では、最近使ったプロジェクトを開き直せます。また、「プロジェクトを開く」ダイアログは、最後に開いたプロジェクトのフォルダーから始まります。現在のプロジェクトに未保存の変更がある場合、Babel Desktop は別のプロジェクトを作成したり開いたりする前に、変更を破棄するかどうかを確認します。ジョブの実行中は、先にその完了を待ってください。
プロジェクトのキャンバス
キャンバスには、各アセンブリがノードとして表示されます。表示位置を移動するには、背景をドラッグするか、ホイールをスクロールするか、2 本指でスワイプします。ポインターの位置を中心に拡大または縮小するには、ピンチするか、Ctrl(macOS では Cmd)を押しながらスクロールします。ズームボタンと「全体を表示」を使うと、グラフが画面に収まります。ノードはドラッグして配置できます。「表示 > グラフを自動レイアウト」(Ctrl+Shift+L、macOS では Cmd+Shift+L)を使うと、ターゲットが実行順に左から右へ並び、各ターゲットの依存関係はその左側に縦に並びます。ノードの位置はプロジェクトファイルに保存されます。



4 つのアセンブリをマージするプライマリターゲット
ノードにポインターを 0.5 秒間置くか、キーボードでノードに移動すると、そのカードが開きます。プライマリターゲットのカードには、状態、実行順序、マージ、埋め込み、参照するアセンブリの数、マップリンク、入力ファイルのパスが表示されます。実行後は難読化スコアも表示されます。
依存関係
ノードの上下のアンカーは依存関係を接続します。ソースアセンブリの下のアンカーからターゲットの上のアンカーへドラッグするか、2 つのアンカーを順にクリックします。新しい依存関係は、次の 3 種類のいずれかになります。
| 種類 | 効果 |
|---|---|
| マージ | ソースアセンブリはターゲットにマージされ、ターゲットと一緒に難読化されて、単一の出力アセンブリになります。アセンブリのマージを参照してください。 |
| 埋め込み | ソースアセンブリはターゲットのリソースとして格納され、実行時に読み込まれます。アセンブリの埋め込みを参照してください。 |
| 参照 | ソースアセンブリは、ターゲットの参照を解決するためだけに使用されます。 |
種類は Babel Desktop が自動的に選択します。ターゲットがソースアセンブリの完全な ID(名前、バージョン、カルチャ、公開キートークン)を参照している場合、新しい依存関係はマージになり、そうでない場合は参照になります。種類を変更するには、依存関係の線をクリックし、ポップオーバーでマージ、埋め込み、参照のいずれかを選択して、「適用」をクリックします。コマンドパレットの「アセンブリ: 依存関係を自動的に追加…」コマンドと、「アセンブリ: マージ入力 を追加…」、「アセンブリ: 埋め込みアセンブリ を追加…」、「アセンブリ: 参照 を追加…」の各コマンドを使うと、ファイル選択ダイアログから依存関係を追加できます。
マージ入力として使われるアセンブリはキャンバスに残りますが、マージ先の一部になるため、単独では難読化されません。
実行順序とマップファイル
左右のアンカーは、一方が他方より先に実行されるように 2 つのターゲットを接続します。先に実行するターゲットの右のアンカーから、後に実行するターゲットの左のアンカーへドラッグします。すると、Babel Desktop が接続の目的を尋ねます。
| 選択肢 | 効果 |
|---|---|
| 実行順序のみ | フローエッジです。ターゲット A がターゲット B より先に実行されます。A から B へは何も渡されません。 |
| マップ ファイルを渡す | マップリンクです。「MAP」というラベル付きで描画されます。A が XML のリネームマップを書き出し、B がそれを読み込むため、B は A のパブリックシンボルの新しい名前を使用します。A は B より先に実行されます。アセンブリ間のリネームを参照してください。 |
マップリンクを作成すると、先のターゲットの「Generate Map Out File」がオンになり、そのマップが後のターゲットの「Map In Files」に追加されます。先のターゲットに出力パスもマップのパスも設定されていない場合、マップは入力ファイルの隣の決まった場所(たとえば BabelOut/Library2.dll.map.xml)に書き出されるため、後のターゲットは必ずマップを見つけられます。マップリンクは個別には保存されません。Babel Desktop はこの 2 つの設定からマップリンクを読み取るため、手作業で書いたプロジェクトや Babel UI で作成したプロジェクトでも、マップリンクが表示されます。
各ノードにはステップ、つまりフロー内で実行される順番が表示されます。フローとは、フローエッジ、マップリンク、またはマージ、埋め込み、参照の依存関係によって結び付けられたターゲットのグループです。互いに結び付いていないターゲットは、別々のフローになります。フロー内では、ターゲットはステップの順に実行され、順序を決めるものがない部分ではプロジェクト内の順序で実行されます。フローエッジは、標準の MSBuild ターゲット依存関係としてプロジェクトに保存されます。
Babel Desktop は、自分自身へのリンクと重複するエッジを受け付けません。また、ターゲットが互いを待ち合うことになる接続も拒否します。ディスクから開いたプロジェクトのターゲットが互いのマップファイルを待ち合っている場合でも、プロジェクトは開けます。その場合、Babel Desktop は Library1.dll → Library2.dll → Library1.dll のように循環を示すエラーを表示し、リンクを 1 つ削除するまでプロジェクトは実行されません。エッジやマップリンクを削除するには、それをクリックして Delete または Backspace を押します。Esc を押すと、作成中の接続がキャンセルされるか、選択が解除されます。
入力の置き換え
設定を失わずに、ターゲットをアセンブリの新しいビルドに向けるには、ノードを選択して、コマンドパレットから「アセンブリ: 設定を保持して入力を置換…」を実行します。「アセンブリ: 選択したターゲットを削除」は、ターゲットとそのエッジを削除します。
セットアップコマンド
コマンドパレットには、プロジェクトを 1 回の操作で設定するコマンドが 3 つあります。先にアセンブリを追加してから、アプリケーションに合ったコマンドを実行してください。



コマンドパレットのセットアップコマンド
| コマンド | 効果 |
|---|---|
| 難読化: メイン アセンブリへのマージを設定 | ほかのすべてのターゲットをメインアセンブリにマージし、プロジェクトの出力ファイルが 1 つになるようにします。メインアセンブリは、プロジェクトで唯一の .exe です。該当するものがない場合や複数ある場合は、最初のターゲットがメインアセンブリになります。エンジンがマージできないアセンブリは、そのまま残されます。 |
| 難読化: パブリック難読化を設定 (すべてのアセンブリ) | 一緒に配布する一連のアセンブリを、パブリックシンボルがリネームされるように準備します。各ターゲットには「obfuscate public」という名前の XML ルールが追加され、リネームマップを書き出すようになります。ほかのターゲットに依存するターゲットは、マップリンクを通じて依存先のマップを読み込みます。 |
| 難読化: レベルを設定… | 選択したターゲットに、3 段階の保護レベルのいずれかを適用します。 |
各レベルは次のオプションを設定し、それ以外のオプションは変更しません。
| レベル | 保護 |
|---|---|
| 軽量 | 型、メソッド、フィールド、プロパティ、イベントのリネーム。制御フロー、暗号化機能、解析対策の保護はオフになります。 |
| バランス | リネーム、goto アルゴリズムによる制御フロー難読化、文字列暗号化、ILDASM の抑止。 |
| 最大 | リネーム、goto、switch、case、if、チェーン状態による制御フロー難読化、ストリーム文字列暗号化、値の暗号化、MSIL 暗号化、改ざん検出、デバッグ保護、ILDASM の抑止。ライセンスにストリームアルゴリズムが含まれていない場合は、既定の文字列暗号化が使用されます。 |
マージとパブリック難読化を設定する 2 つのコマンドは、パッケージターゲット(.apk、.appx、.xap)をスキップします。3 つのコマンドはいずれも、ジョブの実行中や、適用待ちの編集がある間は実行されません。これらのコマンドは開いているプロジェクトを変更しますが、保存はしないので、先にキャンバスとプロパティパネルで結果を確認できます。高いレベルの後に低いレベルを適用すると、追加されていた保護は再びオフになります。
ターゲットの設定
ノードを選択してキャンバス右上の「プロパティ」ボタンをクリックするか、選択したノードで Enter を押すと、プロパティパネルが開きます。「設定」タブには、選択したターゲットの Babel Obfuscator のオプションがすべて表示され、「リネーム」、「制御フロー」、「コード暗号化」、「最適化」、「署名と保護」、「ファイルと依存関係」、「Output & diagnostics」、「Advanced」のグループに分かれています。「設定を検索」に入力すると、一覧が絞り込まれます。



選択したターゲットのプロパティパネル
設定には MSBuild タスクのオプション名が使われているため、各設定の働きは Babel タスクリファレンスと各保護機能のページで確認できます。各オプションには、その型に合ったコントロールが用意されています。スイッチにはチェックボックス、アルゴリズムにはリスト、パスにはファイルやフォルダーの選択ダイアログ、フィルターとプロパティマップにはエディターが使われます。



コード暗号化の設定:文字列、MSIL、値の暗号化
「Control Flow Obfuscation」のような複合オプションでは、プロパティごとに 1 つのコントロールが表示されます。次の図は制御フローのスイッチを示しています。最後の chain は、Ultimate エディションのチェーン状態アルゴリズムをオンにします。



「Control Flow Obfuscation」のプロパティ
署名キーやマップファイルのパスワードなどは、現在のセッションの間だけ保持されます。プロジェクトファイルに書き込まれることはないため、再起動後はもう一度入力します。実行中にエンジンがパスワードを必要とした場合は、Babel Desktop が入力を求めます。
Babel Desktop は、コメント、カスタムプロパティ、カスタム MSBuild タスクなど、.babel ファイルのうち自身が編集しない部分をそのまま保持します。MSBuild のインポート、条件、カスタムタスクは評価しないため、これらに依存するプロジェクトは MSBuild でビルドする必要があります。
マップファイル
プロパティパネルの「マップ ファイル」グループには、選択したターゲットのマップに関する設定がまとめられています。
- 「リネーム マップを書き出す」は、ターゲットのマップファイルの書き出しをオンまたはオフにします。その下のパスはマップの書き出し先で、既定では難読化されたアセンブリの隣です。「変更…」で別のファイルを選択できます。
- 「ほかのターゲットのマップ」には、このターゲットを終点とするマップリンクが一覧表示されます。ターゲット名をクリックすると、そのターゲットが選択されます。
- 「その他のマップ ファイル」には、このターゲットが読み込むマップのうち、プロジェクト内のどのターゲットも書き出さないものが一覧表示されます。以前のビルドで難読化したライブラリのマップなどです。「マップ ファイルを追加…」で追加し、「削除」で取り除きます。
XML ルール
「XML ルール」タブでは、選択したターゲットのインラインの XML 難読化ルールを編集します。エディターは XML を構文強調表示し、「検証」は Babel のルールスキーマに照らして XML を検査して、各エラーの行と列を報告します。「XML を開く」はルールファイルをエディターに読み込み、「XML ファイルを保存」はエディターの内容をファイルに書き出し、「アセンブリに適用」はルールをターゲットに格納します。インラインルールはプロジェクトファイルに保存されます。



ターゲットのインライン XML ルール
エンジンプラグイン
Babel Obfuscator のプラグインは、「エンジン プラグイン: DLL パスを設定」でターゲットごとに設定します。「エンジン プラグイン: 引数名を検出」はプラグインが宣言している引数名を読み取るので、それを基に引数を入力できます。プラグインはエンジン内で実行される .NET コードです。信頼できるプラグインだけを使用してください。
プロジェクトの実行
キャンバス右上の「プロジェクトを実行」をクリックするか、Ctrl+Enter(macOS では Cmd+Enter)を押すか、「実行 > 難読化を実行」を選択します。ターゲットが独自の出力パスを設定していないかぎり、難読化されたアセンブリは各入力アセンブリの隣の BabelOut フォルダーに書き出されます。実行を開始する前に、Babel Desktop は出力先を確認します。入力アセンブリ、キーファイル、プラグインを上書きすることはなく、既存の出力ファイルを置き換える前には確認を求めます。
「アクティビティ」パネルには、進行中のフェーズ、進行状況インジケーター、エンジンログが表示されます。「ログ」タブには、エンジンがターゲットの「Verbose Level」に応じて出力するすべてのメッセージが一覧表示され、警告とエラーは「問題」タブにもまとめられます。各ターゲットノードは、キャンバス上で自身の状態を示します。「ジョブをキャンセル」をクリックすると、実行が停止します。ターゲットは 1 つずつ順に実行され、あるターゲットが失敗すると、それより後のターゲットは実行されません。



「アクティビティ」パネルに表示された完了済みの実行
実行後は、「アクティビティ」パネル上部のボタンで、出力フォルダーを開いたり、難読化されたアプリケーションを起動したりできます。「ファイル > 出力ファイルの場所を表示」と「実行 > 難読化されたアプリを実行」(Ctrl+F5、macOS では Cmd+F5)でも同じ操作ができます。Babel Desktop は、Windows の実行可能ファイルは直接起動し、.NET アプリケーションは .runtimeconfig.json ファイルがある場合に dotnet 経由で起動します。ライブラリの場合、起動の操作は表示されません。
難読化スコア
実行が完了すると、各ターゲットのカードに 0 から 100 までの難読化スコアが表示されます。期待した保護が実行で適用されたかどうかを手早く確認するためのものです。カードを開くには、ターゲットにポインターを置きます。



4 つのアセンブリをマージするターゲットの難読化スコア
スコアは、5 つの保護レイヤーの点数を合計したものです。各バーには、そのレイヤーが獲得した点数と満点が表示されるので、スコアが低いときにどのレイヤーが不足しているかがわかります。
| レイヤー | 点数 | 獲得条件 |
|---|---|---|
| リネーム | 30 | 対象となるシンボルのうち、リネームされたものの割合 |
| 制御フロー | 25 | スクランブルされたメソッドの割合。分岐のないメソッドは変更されないため、メソッドの半数がスクランブルされていれば満点になります |
| 文字列暗号化 | 15 | 暗号化された文字列 |
| コード保護 | 15 | MSIL 暗号化(7)、動的プロキシ呼び出し(4)、値の暗号化(4) |
| 解析対策 | 15 | 改ざん検出、デバッグ保護、ILDASM の抑止(各 5 点) |
スコアの評価は、35 未満が「弱い」、35 以上が「普通」、60 以上が「良好」、80 以上が「強力」です。スコアは、プロジェクトの最後に完了した実行の統計から算出されます。ターゲットにマージされたアセンブリは、そのターゲットのスコアに算入され、独自のスコアは表示されません。まだ実行していないターゲットには、スコアは表示されません。
スコアは実行で適用された保護を数えたもので、その結果が特定のツールにどれだけ長く耐えられるかを示すものではありません。低いスコアが適切な場合もあります。パブリック API を持つライブラリはパブリックな名前を維持するため、リネームの点数は低くなります。
フローの並列実行
互いに参照しないライブラリのように、独立したフローが複数あるプロジェクトでは、それらを同時に難読化できます。「設定 > 難読化」で「独立したフローを並列実行する」をオンにし、同時に実行するフローの数を 2 から 4 の範囲で選択します。このオプションは既定ではオフです。
各フローは専用のエンジンプロセスで実行され、フロー内のターゲットはこの場合も順番に実行されます。Babel Desktop は、単一の実行のときと同じように、どのフローを開始するよりも前にプロジェクト全体を検査します。フローの実行中は次のようになります。
- 進行状況インジケーターには、予定されているターゲットのうち完了した数が表示されます。ログの各行は、
[Library1.dll]のようにアセンブリ名で始まります。 - ターゲットが失敗すると、そのターゲットのフローが停止します。ほかのフローは続行され、実行は失敗として報告されます。
- 「ジョブをキャンセル」は、すべてのフローを停止します。
- 複数のターゲットが証明書のパスワードを必要とする場合、Babel Desktop は、必要としているアセンブリの名前を示して 1 つずつ入力を求めます。
エンジンプロセスの起動にはそれぞれ数秒かかるため、並列実行で時間を節約できるのはアセンブリが大きい場合です。小さなプロジェクトでは、ターゲットを 1 つずつ順に実行したほうが早く終わることがあります。フローティングライセンスの場合、Babel Desktop は一度に 1 つのフローだけを実行します。
コマンドパレットの「ツール: ジョブの警告」は現在の実行の警告を一覧表示し、「ツール: 警告リファレンス」は、エンジンの警告コードとその説明を検索できるカタログを開きます。



エンジンの警告リファレンス
実行結果
実行後、キャンバスのツールバーの「実行結果」ボタンをクリックすると、保護の統計が開きます。履歴から実行を選び、難読化されたアセンブリとレポートを選択します。
| レポート | 内容 |
|---|---|
| リネーム | 型、メソッド、フィールド、プロパティ、イベントについて、リネームされた数と総数。カバレッジのチャートも表示されます |
| 制御フロー | スクランブルされたメソッド、挿入された分岐命令、反復回数と、名前空間および型ごとのツリーマップ。完全な統計を収集した場合は、変換前後の循環的複雑度も表示されます |
| 文字列暗号化 | 暗号化アルゴリズムと、メソッドごとの暗号化された文字列 |
| コード暗号化 | 名前空間および型ごとの暗号化されたメソッド |
| 動的プロキシ | ターゲットメソッドごとの、プロキシ化された呼び出しとデリゲート型 |
| 最適化 | デッドコード除去と最適化のカウンター |
| 実行時間 | エンジンの各フェーズの所要時間 |
表は検索と並べ替えができ、ツリーマップでは名前空間から型へドリルダウンできます。「出力を表示」、「エンジン ログを表示」、「統計データを表示」は、それぞれ出力フォルダー、完全なエンジンログ、その実行の生の統計ファイルを開きます。Babel Desktop は、直近 30 回分の実行結果を保持します。



リネームの統計



制御フローの統計
統計ファイルには、元のシンボル名と文字列の値が含まれています。XML マップファイルと同じく、配布するアプリケーションと一緒にしないでください。
スタックトレースのデコード
保護されたアプリケーションの難読化されたスタックトレースを、XML マップファイルを使って元の名前に戻すには、スタックデコーダーを使用します。