none
DLL の参照を防ぐには? RRS feed

  • 質問

  •  現在開発しているソリューションには実行ファイル生成プロジェクト1つとDLL(クラスライブラリ)プロジェクト3つがあるのですが、これらのファイルを配布したときに、DLLをVisual Studio で参照されるとクラスやメソッドがそのまま使用されてしまう状態になってしまっています。

     これを、私が開発しているプロジェクトからのみ参照できるようにしたいのですが、何か方法はあるのでしょうか?(極力 internal を使うか、全てのコードを実行ファイルに埋め込む方法しか思いつきません。)

     <開発環境>

    • Visual C# 2005 Express Edition
    • Windows XP HomeEdition
    2006年2月18日 9:39

すべての返信

  • 全てのコードを実行ファイルに埋め込んだとしても、.exe を参照されたらクラスやメソッドを呼び出すことができてしまいますので、同じことですね。
    外部から呼び出されたくないコードをすべて .exe 内に入れた上で、さらにそれらをインライン展開することができたとすれば外部から呼び出すことはできなくなりそうですが、あまり現実的ではないでしょうね。

    Dotfuscator を使ってコードを難読化するしか手立てはないのではないでしょうか。

    # ところで、Express Edition に Dotfuscator は標準でついてくるんだったかな?

    2006年2月18日 10:26
  •  bear.mini さんありがとうございます。

    > 全てのコードを実行ファイルに埋め込んだとしても、.exe を参照されたらクラスやメソッドを呼び出すことができてしまいますので、同じことですね。

     なんとそうだったんですか! そうなると参照を防ぐのは難しそうですね。

    > # ところで、Express Edition に Dotfuscator は標準でついてくるんだったかな?

     これは Visual Studio とは別の付属ソフトなのでしょうか? そうだとしたら Express Edition にはないようです。(ソフト単体しかありません

    2006年2月19日 5:37
  • > > # ところで、Express Edition に Dotfuscator は標準でついてくるんだったかな?

    > これは Visual Studio とは別の付属ソフトなのでしょうか? そうだとしたら Express Edition にはないようです。(ソフト単体しかありません)

    そうですか、やはり Express Edition にはありませんでしたか。
    私は Professional Edition を使用していますが、「ツール」メニューの中に「Dotfuscator Community Edition」という項目があります。

    Dotfuscator 自体は Community Edition であれば無償で使用できたはずですので一度お試しになってみてはいかがでしょうか。

    以下の URL からダウンロードできるようです。
    http://www.gotdotnet.com/team/dotfuscator/

    # Express Edition にインストールして使用可能かどうかわかりませんが・・・

    より詳しい情報は Google などで検索するとたくさん見つかると思います。

    2006年2月19日 7:12
  • Express Edition って機能拡張をサポートしてないんでしたっけ?

    2006年2月19日 7:20
  •  Visual C# 2005 Express Edition のツールメニュー項目は下のような感じになっています。やはり、「Dotfuscator Community Edition」はないようです。

    • データベースへの接続
    • コード スニペット マネージャ
    • ツールボックス アイテムの選択
    • 外部ツール
    • 設定のインポートとエクスポート
    • ユーザー設定
    • オプション
    2006年2月19日 9:03
  • internalにしてInternalsVisibleToAttributeを使ってみるっていうのはどうでしょう?
    2006年2月19日 13:13
  •  すみません。ちょっと横道にそれてしまうのですが、publicKeyToken の値を調べる(または設定)にはどのようにしたらよいのでしょうか?

     アセンブリの署名をしてみて、System.Security.Policy.StrongName から publicKey の値を取得したら、ものすごい桁数が出力されたのでどうやら違うみたいです(約320桁)。(求める publicKeyToken の桁数は 16 桁ぐらいだと思います。)

     

    2006年2月19日 14:47
  • 自分はプログラムからコピペするのにType.AssemblyQualifiedNameとかから引っ張ってますね~

     

    2006年2月19日 15:06
  • TKY さんありがとうございます。

    [assembly:InternalsVisibleToAttribute("AssemblyB, PublicKey=32ab4ba45e0a69a1")]

    を使ってみましたが、どうもうまくいきません。今やっているプログラムは「a.dll」から「b.dll」を参照しているのですが、とりあえず両方署名して、b.dll の AssemblyInfo.cs に

    [assembly:InternalsVisibleToAttribute("a(/*a.dll のアセンブリ名*/), PublicKey=xxxxx(a.dll の PublicKeyToken)")]

    を追加しても「警告 1 アセンブリ参照 'a, PublicKey=xxxxxxx' は無効なため、解決できません。 」と出てきて、internal のクラスは「アクセスできない保護レベル」のエラーになってしまっています。

     で、ヘルプを見ると「/out コンパイラ オプション」を使うらしいのですが、この使い方がいまいち分かりません。a.dll プロジェクトのプロパティ→ビルドイベント→ビルド前に実行するコマンドラインに「/out;$(TargetFileName)」を入れるのかと思ったのですが、これでビルドすると、今までのエラーは消えるのですが「エラー 1 コマンド "/out;a.dll" はコード 9009 で終了しました。」というエラーが出てきてしまいます。

     多分「/out」の部分の使い方が悪いと思うのですが、どのようにしたらいいのでしょうか?ちなみに b.dll のひとつのクラスを a.dll の多数のコードファイルで参照している状態です。

    2006年2月19日 17:02
  •  オノデラ は書きました:

     現在開発しているソリューションには実行ファイル生成プロジェクト1つとDLL(クラスライブラリ)プロジェクト3つがあるのですが、これらのファイルを配布したときに、DLLをVisual Studio で参照されるとクラスやメソッドがそのまま使用されてしまう状態になってしまっています。

     これを、私が開発しているプロジェクトからのみ参照できるようにしたいのですが、何か方法はあるのでしょうか?(極力 internal を使うか、全てのコードを実行ファイルに埋め込む方法しか思いつきません。)

    Unmanaged の DLL にしても,第三者から使用できることには違いありませんよね?
    .NET のデメリットというわけではないことは予めご注意下さい.

    「実行可能ファイル」を一段抽象化して従来の NT-Loader のモジュールモデルを再構築した .NET では,例えばバイトストリームとしてアセンブリを CLR に渡すことも簡単にできるようになっています.従って,適当に変換されたバイトデータを実行時に展開することで,参照設定に加えることが出来ないが実行時にアセンブリに変換できるようなファイルを作ることができます.(もちろん自分自身もそのファイルをそのまま参照設定に加えることは出来なくなります)
    Assembly.Load メソッド (Byte[]) 

    非標準的な方法ですので,ポータビリティの低下や情報収集の困難さはありますが,どうしても必要ならこの方面を調べてみるのも1つの方法かと思います.
    Customizing the Microsoft.NET Framework Common Language Runtime
    に恐らく必要になるであろう背景知識が一通り書かれています.

    また従来からのコンポーネントのライセンス処理を応用する方法もあるのかもしれませんが,こちらは詳しく知りません.とりあえずポインタだけ.
    方法 : コンポーネントおよびコントロールのライセンス処理を行う

    2006年2月19日 19:51
  •  NyaRuRu さんありがとうございます。

    > Unmanaged の DLL にしても,第三者から使用できることには違いありませんよね?
    .NET のデメリットというわけではないことは予めご注意下さい.

     まあ、確かにそうですね。ただ .NET で作成した DLL が参照するだけで使えてしまうというのもどうかと思ったもので…。

    > 「実行可能ファイル」を一段抽象化して従来の NT-Loader のモジュールモデルを再構築した .NET では,例えばバイトストリームとしてアセンブリを CLR に渡すことも簡単にできるようになっています.従って,適当に変換されたバイトデータを実行時に展開することで,参照設定に加えることが出来ないが実行時にアセンブリに変換できるようなファイルを作ることができます.(もちろん自分自身もそのファイルをそのまま参照設定に加えることは出来なくなります)
    Assembly.Load メソッド (Byte[]) 

     確かに簡単にはアクセスできなくなるのはとてもいいのですが、自分自身もそのファイルをそのまま参照設定に加えることは出来なくなる」のは欠点かもしれませんね。(結構DLL の方も頻繁に書き換えているもので

    2006年2月20日 14:13
  •  オノデラ は書きました:

    自分自身もそのファイルをそのまま参照設定に加えることは出来なくなる」のは欠点かもしれませんね。(結構DLL の方も頻繁に書き換えているもので

    まあもしこの方法を使うなら,開発用の構成とリリース用の構成は分けるでしょうね.わざわざ面倒な構成で開発を行う必要はないと思います.

    ついでに言えば,ILMerge や Aspect Weaver などアセンブリマネジメントツールもありますし,必ずしも開発環境で得られたアセンブリをそのまま配布する必要は無いです.

    2006年2月20日 16:26
  •  みなさんいろいろアドバイスありがとうございました。

    とりあえずいろいろ調べたり検証してみて、対処法を考えてみました。

    1.参照の防止について

     クラスなどを internal で使用するようにして、モジュール間は InternalsVisibleToAttribute を使用してフレンド アセンブリとする。

    2.逆アセンブラの対処法

     Dotfuscator Community Edition を使用してコードを難読化させる(Standard Edition 以上?)。

     皆さんのおかげで今まで知らなかったことなど参考にでき、とても勉強になりました。ありがとうございます。

    2006年2月21日 16:04
  • .NET 1.1ならば、DLL中のメソッドでSystem.Refllection.Assembly.GetCallingAssembly()で、呼び出したアセンブリを得、それが想定されたアセンブリかどうかを調べます。署名までチェックすれば、DLLを作り直すとかプライベートキーを破るとかされない限り、実質的には使えません。

     

    2006年3月7日 13:49
  •  Kazuya さんありがとうございます。

     この場合、全てのメソッド内に記述しないといけないのでしょうか?私の場合、かなりの数があるので結構たいへんです(^^;)

     あと、プロパティとか enum なんかの場合はどうなのでしょうか?

     とりあえず今は、署名&フレンドアセンブラ&難読化で対処しようと思っています。

    2006年3月7日 15:01
  • PublicKey は,公開キーなので,
    公開キートークンではないので,ふつうは,
    ヘルプにあるような感じで短くなんてことはなく,もっと長いです。
    ヘルプはあくまで例でしょう。

    ふつうは,320桁あると思います。

    Visual C# 2005 Express でも,ふつうにやれるのを確認しているので,
    特に設定は必要ないようです。

    2006年3月7日 16:15
  • InternalsVisibleTo はお手軽で、カジュアルな使用を防ぐにはよいと思うのですが、単純にディスアセンブルして使いたいメソッドのシグナチャを適当に変えてアセンブルすることにより、まったく同じ機能のDLLを作ることができます。つまり、DLLの機能を使わせないという目的には無力です。また、難読化もロジックを盗まれにくくするためのものであり、丸ごと使うということを防ぐには力不足です。

    > この場合、全てのメソッド内に記述しないといけないのでしょうか?

    (実際にはこれでは問題なのですが)単にメソッドの先頭でチェックするだけでよいというのならば、public メソッドを抽出する正規表現は簡単なので、そのためのコードを挿入するのは容易です。プロパティは、実質的にはメソッドと同じです。適当なpublic メソッドを internalに書き換えることができるなら、これもできると思います。

    実用上は重要な少数の内部クラスやメソッドを間接的に使われることを防御すればよいので、そのスタティックコンストラクタやメソッドで自分自身の署名をチェックするという手もあります。(難読化は、もちろん必要)

    2006年3月9日 3:26