C 共有ライブラリのリバース エンジニアリングをより困難にするための予防措置に関心があります。
完全に防ぐことは不可能に思えますが、時間がかかる可能性のある対策を講じることはできます。
コードの難読化、コンパイラの最適化オプション、コンパイラのデバッグ フラグなど (特に gcc コンパイラに興味があります)
$または工数などの観点から、〜5KLOC C共有ライブラリ(.soサイズ〜200kb)のリバースエンジニアリングの相対的な難しさについての考えにも興味があります.
C 共有ライブラリのリバース エンジニアリングをより困難にするための予防措置に関心があります。
完全に防ぐことは不可能に思えますが、時間がかかる可能性のある対策を講じることはできます。
コードの難読化、コンパイラの最適化オプション、コンパイラのデバッグ フラグなど (特に gcc コンパイラに興味があります)
$または工数などの観点から、〜5KLOC C共有ライブラリ(.soサイズ〜200kb)のリバースエンジニアリングの相対的な難しさについての考えにも興味があります.
これらは私が知っているいくつかのトリックです:
オプションとともに使用strip
して、--strip-unneeded
再配置に必要なシンボルを除くすべてのシンボルを削除します (共有ライブラリについて話しているため)。
strip --strip-unneeded libmylib.so
標準の libc と静的にリンクします。これにより、ライブラリ/バイナリが大きくなり、実行するコードが増え、関数をライブラリ関数から分離するのが難しくなるため、難読化も行われます。
gcc -static ...
コンパイラに小さな関数をインライン化させます。これにより、小さな関数を呼び出す代わりにコードに埋め込むため、コードと標準ライブラリ コードを区別することがほとんど不可能になります。
そうは言っても、上記の手段を使用したバイナリがあり、数時間でそれをリバース エンジニアリングできたことを付け加えなければなりませんsymtab
。教祖。
最も一般的なアンチリバース技術の問題は、それらがよく知られており、それらを克服するためのツールがあることです. もちろん、シンボルの削除と難読化は必須ですが、これは名前/シンボルを隠すだけです。
リバーサーの仕事をさらに難しくしたい場合は、自分でコード操作を考え出してください。カスタムの呼び出し規則を使用するなど、非常に簡単なこともありますが、これにより、すべての逆アセンブラーが関数の開始と終了を認識できなくなります。
コードを元に戻すためのツールが既に作成されていないため、これらの種類の単純なトリックは非常に効果的です。ご覧のとおり、ほぼすべての商用パッカーまたは暗号化ツールには、ワンクリック アンパッカーが既に存在します。
- コードの難読化は必要ありません (C# や Java のように)。
内部変数と関数の名前がオブジェクト コードに存在しません。
ただし、エクスポートされた関数の名前は、共有オブジェクト ファイルにそのまま表示されます。これは合理的に聞こえます。
-gcc
最適化フラグ-O2
またはを使用することをお勧めします-O3
。
コンパイラの最適化を使用すると、オブジェクト コードはソース コードと大きく異なる場合があります。元の C ソース コードに戻ることは実際には非常に困難です。
ただし、アセンブリ レベルでエンジニアを元に戻すことは常に可能です。通常、すべてのプログラムが価値があるわけではありません。C でプログラム全体をリバース エンジニアリングするよりも、アセンブリで興味深い部分をリバース エンジニアリングする方が簡単です。
それほどではありません。デバッグ シンボルを削除し、すべての内部シンボル (ライブラリのクライアントにはリンク先のシンボルが必要なため、外部シンボルではない)を難読化したら、できることはあまりありません。命令がオペコードに 1 対 1 でマッピングされるため、アセンブリの逆アセンブリは非常に簡単です。一方、コンパイラによって生成されたアセンブリ コードを理解することは非常に困難です。これは、奇妙な最適化と効率化のためのトリックがたくさんあるためです。
その点で、GCC を最高の最適化まで上げることが、おそらく使用できる最高の難読化のトリックの 1 つです。
現代のコンピューティング能力を考慮すると、逆アセンブル自体はそれほど時間はかからず、その時点で人間が解読する必要があります。
興味深いのは、リバース エンジニアリングを行わないために何が重要なのかということです。金融データなどを安全に保つ暗号化とセキュリティは、ほとんどがオープン ソースです。それとも、これは独自のソフトウェア保護の問題ですか?
コードをスイッチ/ケースの難読化と混合します(非線形にします)。
C ++テンプレートを使用して、コンパイル時に変数/文字列を暗号化します。整数型をdouble型にカプセル化して、反転を少し難しくすることができます。
実際のコードの間にアセンブリ難読化マクロを挿入します(jmp x、db 0E8h、xなど)。
BOOSTを使用してください;)それは本当にリバースエンジニアリングを苦痛にします...;)