web-dev-qa-db-ja.com

C / C ++はC#よりも逆コンパイルが難しいのですか?

ここでトップアンサーを参照してください: 難読化よりもソースコードレベルでの難読化の方が効果的ですか? 具体的には、「 C/C++」

ライセンスごとに500ドルで販売される新しいアプリケーションを作成する予定なので、逆コンパイラを回避したいと思います。

C#は避けるべきですか、それともこの種のことを防ぐのに十分な難読化ツールを使用していますか?

5
Michael

C#アセンブリには、c ++アセンブリにはないメタデータが含まれているため、逆コンパイルに役立ちます。 C#は、C++のマシンコード出力よりも元のソースコードにはるかによくマッピングされる中間言語にもコンパイルされます。難読化ツールは役立ちますが、preventリバースエンジニアリングはできません。あなたはそれをより難しくすることができるだけです。

実際には、とにかくあなたのコードを無料で欲しがる人はいません。企業は合法的にライセンスを取得したいと考えています。彼らはあなたのコードをハッキングして無料のライセンスを取得するという厄介な問題(または法的な暴露)に行きたくありません。ライセンスあたり500ドルで、通常の消費者をターゲットにしている可能性は低いため、ソフトウェアのハッキングに興味を持つのは、いずれにせよターゲット市場にいない人々だけです。

したがって、ライセンススキーム、インストールコード、フォーンホームなど、ソフトウェアのセキュリティを確保するための最新の手段を講じるなど、賢明な予防策を講じ、新しい機能を追加してソフトウェアをより優れた魅力的なものにし、提供する言語を選択することに注力してください。最高の生産性であなたを。

注意:ハッカーに時折盗まれない場合、ソフトウェアは十分に重要ではありません。その時点で、削除通知を発行してより優れた技術的ソリューションに取り組むために誰かを雇うことができるでしょう。

14
Robert Harvey

基本的に、実行可能プログラムはすべて分解して検査することができます。リバースエンジニアが元のソースコードを簡単に再作成できるかどうかは、実行可能ファイル内に存在する元のソースコードに関する情報またはメタデータの量に依存します。リバースエンジニアは、元の変数名、関数、データ構造などを発見できますか?コンパイラーは基本的にソースコードを「圧縮」し、それをネイティブのマシンコードや中間ランタイムによって処理されるバイトコードなど、マシンの実行により適した形式に変換します。しかし、一般的に言えば、圧縮は不可逆的です。つまり、元のソースコードに関する多くの情報がそこにはありません。ただし、特定のコンパイラ出力は他の出力よりも損失が大きくなります。

CおよびC++は通常、ネイティブマシンコードに直接コンパイルします。しかし、C標準もC++標準も、コンパイラーによって作成されたバイナリー実行可能ファイルのレイアウトを記述していません。たとえば、最適化C++コンパイラは、特定の変数宣言の最適化や、関数とクラス全体の削除など、パフォーマンスを向上させるために多くのことを自由に実行できます。元のC++コードに関する情報は、バイナリ実行可能ファイルに存在する必要はほとんどありません。リバースエンジニアはそれを逆アセンブルできますが、CまたはC++コードをアセンブリから収集することは、推測と解釈の行為です。

ただし、C#はCIL(Common Intermediate Language)にコンパイルされます。通常、クラス構造を含むオブジェクト指向の概念など、元のソースコードに関する多くの情報は、C++コンパイラから生成された高度に最適化されたx86マシンコードの読み取りよりも、CILの読み取りから収集できます。

6
Charles Salvia

C#は必ずしも回避する必要はありません。私は Dotfuscator チームのPreEmptive Solutionsで働いていますが、これはかなり公平な回答です。 (プラグなし:))

C#はメタデータを含み、ほとんどのC#コードは「検証可能なコード」と呼ばれる一連の規則に準拠する必要があるため、C#は本質的にソースコードに逆コンパイルするのが簡単です。デコンパイラーは、これらのルールの順守と添付のメタデータを利用して、同等のC++デコンパイラーよりも優れた逆コンパイルを行います。 ILを完全に理解することは困難ですが、基本的に、コード内の各クラスにはメタデータが含まれます。 .Netは、作成したアセンブリ/ APIを使用するためにヘッダーファイルまたはシンボルファイルを出荷する必要がないようにする方法です。検証可能なコードビットの場合、基本的には、.Netランタイムが「安全」であることを検証できるコードのみを使用できることを意味します。ランタイムは静的分析機能に制限があるため、「安全で正しい」ことを確認できるコードはたくさんありますが、ランタイムで確認することはできません。逆コンパイラは、この一連のルールを利用します。

C#で製品を出荷していて、保護するIPがある場合、基本的に難読化製品を使用する必要があります。 Javaのような類似した言語/ランタイムでも同じです。 .Netの難読化製品はさまざまなことを行います。

  • 制御フローを難読化します(ifステートメントをgotoでループに変換し、すべてを並べ替えます)
  • 実際のコードを「隠す」ためにガベージ操作なしの命令を注入する
  • メタデータの名前を変更して、本当に役に立たないようにします。 (FooBarのようなクラス名をaに変換します)
  • クラスの構造を変更する(5つのメソッドを、5つのメソッドからすべての引数を取る単一のメソッドに移動する)
  • 検証不可能なコードまたはメタデータを挿入します(これは通常、難読化解除ツールによって簡単に無効化されます)
  • プレーンテキストではないように文字列を暗号化する
  • 添付された構成ファイル、XAMLページなどのリソースを暗号化する
  • 改ざん防止機能を追加(アプリケーションが変更されたことの検出)

使用する難読化ツールに応じて、これらのメソッドは、すべての意図と目的のために、ILに飛び込んで手動で解読することなくコードが巨大な「ブラックボックス」になるようにすることができます(非常に時間がかかります)。

C++には、難読化がそれほど重要ではないという利点があります。メタデータがないので、逆コンパイラーは非常に困難です。ただし、x86アセンブリを読み取ることができるハッカーはまだたくさんいます。また、C++アプリケーションは非常に一般的にクラックされます。 (良い)C++の難読化プログラムも入手がはるかに困難です。これは、逆コンパイルするのと同じくらい難読化するのが難しいためです。 .Netには、コードをreadしてコードを難読化するために使用する一連のルールがあります。 C++にはこれらのルールはありません。

つまり、要約すると

  • C#は基本的に難読化が必要
  • C++は逆コンパイルがはるかに困難ですが、難読化のサポートが欠けています
  • どちらを選択しても、いつでもクラックすることができます。あなたができることはそれを遅くするか、必要な時間量のためにクラックするのを望ましくないようにすることです

また、もう1つ注意点として。検証可能なコードを生成するC#難読化プログラムは、.Netの十分に新しいバージョンがある限り、基本的にあらゆる場所で実行されるアプリケーションを提供します。検証可能なコードを生成しないC#難読化プログラムは通常どこでも機能しますが、保証されていません。マイクロソフトが次のバージョンの.NetでJITの最適化を行い、検証できない難読化されたコードを破壊する可能性があります。 C++コードは本質的に通常「どこでも」実行されませんが、通常は実行されます。難読化されたC++コードは、意図するあらゆる場所で機能する可能性がありますが、保証はされません。正確でスレッドセーフなC++を作成するのは非常に難しく、難読化ツールがそれを台無しにすることについて心配する必要はほとんどありません。

2
Earlz