Obfuscar を使った自作 .NET アプリの難読化入門

難読化とは?

.NET アプリケーションはバイナリから可読なソースコード形式への逆コンパイルが比較的容易にできます。

難読化はアプリの解読・改ざんを防ぐためのあらゆる措置のことです。

難読化の最も単純な事例はクラス名・メソッド名の置換です。名前から役割が類推されることを防ぎます。

難読化の必要性は?

オープンソースで開発しているアプリなら特に必要はないと思います。

そうでないのであれば多かれ少なかれやっておいた方が良いのではないかと思います。

ツールの使い方を一度覚えてしまえば簡単ですし、ビルドプロセスに組み込んでしまえばツールを直接使うこともほとんどなくなります。

この記事では自分が使っている難読化ツールの使い方を紹介したいと思います。

難読化ツール Obfuscar

難読化をサポートするツールは数多くあります。今回紹介する難読化ツールはその中の1つです。

  • Obfuscar, The Open Source Obfuscator for .NET Applications

これはオープンソースで開発されている難読化ツールです。

ざっくりまとめると以下の難読化ができます。

  • クラス名・メソッド名の難読化
  • 文字列リテラルの難読化

それぞれがどんなものか簡単に説明します。

クラス名・メソッド名の難読化は、メソッド名を A, B, C とかに置換してくれる機能のことです。

置換結果をファイルに出力する機能も持っています。

元のクラス名・メソッド名を逆引きが必要になる場合があります。例外発生時やログ解析時などです。そのためこの置換結果はとても重要です。

次に文字列リテラルの難読化は、プログラム中に直接書き込んだ固定文字列を逆コンパイルで直接読めなくする機能のことです。

特に後者の文字列リテラルの難読化が自分にとっては欲しい機能でした。

その他 Obfuscarの特徴を簡単に説明します。

  • コマンドラインで動作する。
  • 難読化の設定や処理対象とするバイナリの指定などは設定ファイルに記述する。

コマンドラインで実行できるためビルドプロセスに簡単に組み込めます。

本記事では簡単な設定ファイルの例を示します。特別なことがない限りはそのままで大体いけるはずです。

Obfuscar の使い方

まずは Obfuscar をインストールしましょう。以下、手順です。

  1. Obfuscar のページで DOWNLOADS タブを選択する。
  2. 2.0_rc7_bin.zip をダウンロードする。
  3. ダウンロードした ZIP ファイルを解凍する。
  4. 解凍したフォルダにパスを通す(PATH 環境変数に追加する)。

次に設定ファイルを用意します。

以下のファイルを obfuscar.xml とでも名前を付けて保存してください。ァイル名は任意です。

<?xml version='1.0'?>

<Obfuscator>
  <Var name="InPath" value=".\" />
  <Var name="OutPath" value=".\Out" />
  <Var name="KeepPublicApi" value="true" />
  <Var name="HidePrivateApi" value="true" />
  <Var name="HideStrings" value="true" />

  <Module file="$(InPath)\Xxx.exe" />
</Obfuscator>

Xxx.exe の部分は対象となる .NET アプリケーションのファイル名を指定します。

.NET アプリケーションと同じディレクトリにファイルを置き、そのディレクトリで以下のコマンドを実行してください。

Obfuscar.Console obfuscar.xml

Out ディレクトリが作成され、その中に難読化された .NET アプリケーションが格納されているはずです。

これだけです。

本当に難読化はうまくいっているの?

難読化がうまくいっているかどうかを確認するには実際に逆コンパイルをして確認してみるのが良いでしょう。

以下の記事を参考に ILSpy というツールを使ってみてください。

難読化前のファイルと難読化後のファイルを逆コンパイルして、ソースを見てみてください。

設定ファイルに書いてある内容の説明

設定ファイルに書いてある内容は以下の通りです。

  • KeepPublicApi: 公開 API の難読化を行うかどうかを設定する。
    • true の場合は公開クラス・メソッド名の置換を行わない。
    • true に設定しているので Public な API を難読化対象から除外している。
  • HidePrivateApi: 非公開 API の難読化を行うかどうかを設定する。
    • true の場合は公開クラス・メソッド名の置換を行う。
    • true に設定しているので Private な API を難読化対象にしている。
  • HideStrings: 文字列リテラルの難読化を行うかどうかを設定する。
    • true の場合は文字列リテラルの難読化を行う。
    • true に設定しているので文字列リテラルの難読化を行っている。

このような設定にしているのには意味があります。

できる限り難読化をしたいので KeepPublicApi を false にしたいところなのですがうまくいかない場合があります。

自分が作っている .NET アプリケーションは WPF アプリケーションなのですが、KeepPublicApi を false にすると正常に動作しませんでした。

Windows フォームアプリケーションなら動作するかもしれません。解決は難しく Public API の難読化はあきらめるのが無難と判断しました。

Module には難読化対象となるバイナリを指定します。

もしも DLL があり、その DLL も難読化の対象にしたい場合はその分だけ DLL を並べれば大丈夫です。

ビルドプロセスに組み込む

以下の設定を行うことで Visual Studio のビルドプロセスに難読化の作業を組み込むことができます。

  • 設定ファイルをプロジェクトに追加する。
  • 設定ファイルのプロパティ「出力ディレクトリにコピー」を「新しい場合はコピーする」に設定する。
  • プロジェクトの設定の「ビルドイベント」「ビルド後に実行するコマンドライン」に以下の記述を追加する。
    • Obfuscar.Console 設定ファイル名

以降、ビルド時に難読化が自動で行われるようになります。

この記事で紹介している設定ファイルを使っているのであれば、 ビルド後、Debug/Release のディレクトリを見ると Out ディレクトリができているはずです。

中に難読化後のバイナリができているはずです。