16

コンパイルされたバイナリから文字列を削除/難読化するにはどうすればよいですか? 目標は、人々が内部の関数/メソッドの名前を読まないようにすることです。

これは、NDK ツール (GCC を含む) を使用して Android 用の C++ コードからコンパイルされた動的ライブラリ (.so) です。

私はコンパイルして、デバッグシンボルを削除するために-O3既に使用していますが、関数/メソッドのすべての名前はまだ読み取り可能です。arm-eabi-strip -g mylib.sostrings mylib.so

4

4 に答える 4

26

これらの文字列は、ライブラリが実行時にロードされるときに使用される ダイナミック シンボル テーブルにあります。readelf -p .dynstr mylib.soこれらのエントリが表示されます。

strip -gはデバッグ シンボルを削除しますが、実行時に必要になる可能性があるため、動的シンボル テーブルからエントリを削除することはできません。あなたの問題は、ライブラリの外部から呼び出されることのない関数の動的シンボル テーブルにエントリがあることです。あなたがそれを言わない限り、コンパイラ/リンカーは、どの関数が外部 API の一部を形成しているか (したがって、動的シンボル テーブルにエントリが必要)、どの関数がライブラリ専用であるか (したがって、エントリは不要) を知る方法がありません。動的シンボル テーブル)、すべての非静的関数の動的シンボル テーブル エントリを作成するだけです。

どの関数がプライベートであるかをコンパイラに通知するには、主に 2 つの方法があります。

  1. プライベート関数をマークしますstatic。明らかに、これは単一のコンパイル単位内でのみ必要な関数に対してのみ機能しますが、一部のライブラリではこの手法で十分な場合があります。

  2. gcc の「visibility」属性を使用して、関数を可視または非表示としてマークします。2 つのオプションがあります。すべてのプライベート関数を非表示としてマークするか、-fvisibility=hiddenコンパイラ オプションを使用してデフォルトの可視性を非表示に変更し、すべてのパブリック関数を可視としてマークします。後者は、誤って関数を追加したり、非表示としてマークするのを忘れたりすることを心配する必要がないことを意味するため、おそらく最良のオプションです。

関数がある場合:

int foo(int a, int b);

非表示にするための構文は次のとおりです。

int foo(int a, int b) __attribute__((visibility("hidden")));

可視としてマークするための構文は次のとおりです。

int foo(int a, int b) __attribute__((visibility("default")));

詳細については、この件に関する優れた情報源であるこのドキュメントを参照してください。

于 2010-06-02T16:37:20.733 に答える
7

これを実現する商用の難読化ツールがいくつかあります。基本的に、彼らは外出先ですべてのシンボルを書き直します。このようなもの:

void foo()

になる

void EEhj_y33() // usually much, much longer and clobbered

変数名も、構造体/共用体のメンバーと同じように扱われます (設定した難読化のレベルによって異なります)。

それらのほとんどは、コードベースをスキャンし、辞書を作成してから、出力のシンボル名を文字化けした混乱に置き換えて、通常どおりコンパイルできるようにすることで機能します。

それらの使用はお勧めしませんが、利用可能です。意味のあるシンボル名を難読化するだけでは、ライブラリやプログラムがどのように機能するかを発見しようと決心している誰かを止めることはできません。さらに、システム コールを追跡する人については何もできません。本当に、ポイントは何ですか?「カジュアルなオブザーバー」を寄せ付けないようにするのに役立つと主張する人もいますが、私は、誰かが走っていてltrace stracestrings通常はカジュアルではない.

シンボルではなく、文字列リテラルを意味しない限り? コードを使用する前に復号化する必要がある暗号化された形式でリテラルを保存しない限り、それらについてできることは何もありません。それはただの無駄ではなく、何の利益にもならないひどい無駄です。

于 2010-05-20T14:32:17.507 に答える
3

すべてのソースファイルに対してg++の非表示の可視性を正しく指定していると仮定すると(他の投稿者が推奨しているように)、このGCCバグに遭遇する可能性があります:http: //gcc.gnu.org/bugzilla/show_bug .cgi?id = 38643

表示されているシンボルをバイナリにダンプしてみてください(readelf -Wa mylib.so | c++filt | less); デマングル後にvtableシンボルとVTTシンボルのみが表示される場合は、gccバグが問題である可能性があります。

編集:可能であれば、GCC 4.4.0以降を試してください。修正されているようですが、

于 2010-07-11T06:11:15.830 に答える
-2

それらは避けられません。これらの文字列は、ローダーが実行時に共有ライブラリをリンクする手段です。

于 2010-05-20T10:03:43.583 に答える