24

コードを逆コンパイルから保護する方法を検討していました。

ここには、コードを保護するための可能な方法として、難読化とコードパッキングを説明するいくつかの優れたスレッドがあります。ただし、いずれも理想的ではありません。文字列メソッド/プロパティ名が使用されている場合、難読化はリフレクションでは機能しません。多くの人は、難読化の使用をまったく推奨していません。

それで、私は現在、上記のいずれにも進まないことに決めました。ただしある種の暗号化が必要なコードの部分があります。たとえば、IP、ログイン、およびパスワードを含むデータベース接続文字列は、const string電子メールアカウントデータと同じように、コード内に単純に格納されます。

ASP.NETには、機密データをファイルに移動して暗号化するオプションがありますが.config、これにはサーバーキーが必要です。つまり、単一のコンピューターにリンクされている必要があります。私はそれについてあまり読んでいませんでしたが、デスクトップアプリケーションにも同様の何かが利用できると思います。しかし、アプリケーションがインストールされているすべてのコンピューターで動作するには、これが必要です。

そしてここに質問があります:逆コンパイルされたコードと一緒に読むことができないようにそのようなデータをエンコード/保護する方法はありますか?

4

7 に答える 7

22

最初のアドバイスは、機密性の高いものをコードに直接保存しないことです。どんなに巧妙に難読化しようとしても、いつでもリバースエンジニアリングできます。

パスワードをいくつかに分割し、コード内のさまざまな場所に配置し、一連の関数を実行してから最終的に使用するなどについて読んだことがあります...これにより困難になりますが、アプリケーションをいつでも監視できますデバッガーを使用すると、最終的には秘密情報を取得できるようになります。

私があなたのシナリオを正しく解釈すると、あなたが持っているのは、あるクライアントの構内に展開されるコードであり、あなたのコードはデータベースに接続され(私はクライアントの監督下にあると思います)、それに接続するにはパスワードが必要です。このパスワードはそのクライアントに認識されているため、クライアントからパスワードを隠そうとしても意味がありません。あなたがたいのは、そのパスワードを知らないはずの人からのそのパスワードへのアクセスを制限することです。

これを実現するには、通常、機密情報を、非常に制限されたアクセス許可を持つ必要があるフォルダー内の別のファイルに配置します。アクセスできるのは、アプリケーションと少数の選択されたユーザーのみです。その後、アプリケーションは実行時に必要なときに情報にアクセスします。

さらに、個別のファイルを暗号化することは問題であることが判明します-そうすると、何らかの方法で再度保護する必要があるキーが含まれます-無限再帰が進行中です:)ファイルへのアクセスを保護することで十分なことがよくありますが、本当に可能な限り安全である必要がある場合、解決策はファイルにパスワードベースの暗号化を使用することです。ただし、ここでの考え方は、パスワードをシステムのさらに別の場所に保存するのではなく、帯域外情報(物理的な保管庫など)として保存し、アプリケーションの起動時にパスワードを入力することです。これにも問題があります。アプリケーションを(再)起動するには人の物理的な存在が必要ですが、アプリケーションが実行されているマシンのRAMからパスワードを取得することもできます。しかし、それはおそらく、専用のハードウェアなしでできる最善の方法です。

パスワードベースの暗号化に代わるもう1つの優れた方法は、Windowsの分離ストレージなどのOS固有の「パスワードボールト」に依存することです。これは、暗号化をまったく行わないこととパスワードを帯域外に保持することの間のトレードオフのようなものです。

于 2011-10-21T17:38:49.723 に答える
12

これは暗号化の答えではありませんが、これを「保護」する1つの方法は、Webサービスを介してすべてのデータベース呼び出しを行うことです。次に、接続資格情報が安全なサーバーに保存され、クライアントはそこを介してすべての呼び出しを渡します。

再配布可能なものに機密情報が保存されているものはありません...

于 2011-10-21T13:02:22.090 に答える
6

私は過去にこの問題に取り組み、問題に対処する3つの方法を考え出しましたが、どれも完璧かどうかはわかりません。

  1. 値を難読化または暗号化し、最高のものを期待します。もちろん、暗号化は、キーが残りのキーと一緒に配信される必要があるため、単なる追加レベルの難読化です。
  2. 代わりに一方向の暗号化を使用して、キー自体の必要性を排除します。秘密鍵を使用して公開鍵を生成します。これは、ライセンスまたはパスワードの検証に使用できます。秘密鍵を使用してライセンスを生成しますが、公開鍵を使用してそれらを検証できます。または、秘密鍵を使用して、検証できるパスワードを生成しますが、公開鍵を使用して元に戻すことはできません。
  3. ASP.NETで使用されているものと同様の独自のシステム固有のキー生成メカニズムを作成します。インストールまたはサイトごとに一意のキーを生成することにより、ステップ1で暗号化/難読化を元に戻す人の影響を制限できます。
于 2011-10-21T13:05:46.997 に答える
4

たくさんの方法がありますが、実際には、コードを本当に保護したいのであれば、唯一の解決策は「プロの」製品を使用することです:-)車輪の再発明を試みないでください。これらの製品には通常、文字列を暗号化するオプションがあります。本当の問題は別の問題です。プロの製品がなくても(プロの製品があれば)、エキスパートはブレークポイントを設定して、ライブラリメソッドに渡されたパラメーター(たとえば、接続を開くパラメーター)を確認できます。さて...本当にコードの文字列を暗号化したいのなら、それはとても簡単です。しかし、それは役に立ちますか?いいえ。

さて、誰もこれを「答えではない」とマークしないように、簡単な暗号化/復号化コードを投稿します。

// Generate key. You do it once and save the key in the code
var encryptorForGenerateKey = Aes.Create();
encryptorForGenerateKey.BlockSize = 128;
encryptorForGenerateKey.KeySize = 128;
encryptorForGenerateKey.GenerateKey();
encryptorForGenerateKey.GenerateIV();

var key = encryptorForGenerateKey.Key;
var iv = encryptorForGenerateKey.IV;

// Encrypt: this code doesn't need to be in the program. You create a console
// program to do it
var encryptor = Aes.Create();
var encryptorTransformer = encryptorForGenerateKey.CreateEncryptor(key, iv);

string str = "Hello world";
var bytes = Encoding.UTF8.GetBytes(str);
var encrypted = encryptorTransformer.TransformFinalBlock(bytes, 0, bytes.Length);
var encryptedString = Convert.ToBase64String(encrypted);

Console.WriteLine(encryptedString);

// Decrypt: this code needs to be in the program

var decryptor = Aes.Create();
var decryptorTransformer = decryptor.CreateDecryptor(key, iv);

byte[] encrypted2 = Convert.FromBase64String(encryptedString)

var result = decryptorTransformer.TransformFinalBlock(encrypted2, 0, encrypted2.Length);

var str2 = Encoding.UTF8.GetString(result);

このコードは明らかに安全ではありません。誰でもプログラムを逆コンパイルし、を追加しConsole.WriteLine(str2)て再コンパイルすることができます。

于 2011-10-21T12:58:31.977 に答える
4

もちろん、コンパイルする前に文字列を暗号化することもできますが、単純なdbまたはhttp urlを使用している場合は、コードでプレーンテキストで暗号化する必要があります。

この場合、実際の保護はありません。誰もが指定されたメソッドをリッスン(ブレークポイント)でき、呼び出されると、コードを実際に読まなくても何が起こっているかを確認できます。したがって、これに対する実際の保護はありません。また、ある時点で難読化を使用して、そのプレーンテキスト文字列で.NETメソッドを呼び出すと、誰でもそれを読むことができます。

たとえば、暗号化された文字列を格納するためのCOMまたはC++dllを配置できます。管理されていないdllは逆コンパイルできませんが、専門家はもちろんdllの逆アセンブルを理解できます。そして、前に述べたように、いつかあなたはプレーンなデータを必要とするでしょう、そしてその瞬間、持続することができる保護はありません。

あなたができる唯一のことはあなたのアーキテクチャを変えることです。

たとえば、データベースがオンラインで、アプリケーションがクライアントアプリケーションの場合、Webサービスを使用して接続できます。そうすれば、ユーザーが実際に使用する必要のあるWebサービスのみを公開でき、ユーザーがSQLクエリを作成するリスクはありません。次に、クライアントではなくサーバーに保護ロジックを追加できます。

すべてがオフラインの場合、できることはあまりありません。単純な文字列暗号化を使用して生活を困難にすることはできますが、それが本当の保護になることは決してありません。

于 2011-10-21T13:40:43.617 に答える
3

Lucasがコメントで指摘したように、1つしかない場合は、アプリケーションを逆コンパイルする人は誰でもそれをリバースエンジニアリングして、データベースのパスワードを復号化できます。

クレデンシャルの保存について、私の通常の慣習は、常にそれらをアプリケーション構成ファイルに保存することです。その後、セキュリティで保護する必要がある場合は、SecureStringと暗号化を使用します。そして、これは、資格情報だけでなく、あらゆる種類の構成情報に対して機能する可能性があります。構成ファイルの保護に関する非常に優れた記事がここにあります:.NETapp.configファイルでのパスワードの暗号化

于 2011-10-21T14:16:47.653 に答える
1

たぶん、web.configの暗号化についてもう少し読む必要がありますhttp://learn.iis.net/page.aspx/141/using-encryption-to-protect-passwords/

そうでなければ、あなたができることはあまりありません。リフレクターツールを持っている人なら誰でもデータを開いて見ることができるため、機密データをコードに保存することはできません。コードや変数をすべての人に表示しないようにする場合は、プライベートサーバー上に、データを受け入れ、魔法のように変換してクライアントに返すWebサービスを作成する必要があります。このようにして、データの投稿と取得の間のすべてが秘密にされます。

于 2011-10-21T13:00:18.347 に答える