2009-04-25 9 views
1

GNUツール(gcc、binutilsなど)を使用して、アセンブリ命令のすべての出現をノーオペレーションに変更することは可能ですか?具体的には、-pgオプションを使用してgccのは、以下のアセンブリ(ARM)を生成します。命令をノーオペレーションしようとする

0x0: e1a0c00d mov ip, sp 
    0x4: e92dd800 stmdb sp!, {fp, ip, lr, pc} 
    0x8: e24cb004 sub fp, ip, #4 ; 0x4 
    0xc: ebfffffe bl 0 <mcount> 

私はこの最後の命令のアドレスを記録したいし、次のコード

0x0: e1a0c00d mov ip, sp 
    0x4: e92dd800 stmdb sp!, {fp, ip, lr, pc} 
    0x8: e24cb004 sub fp, ip, #4 ; 0x4 
    0xc: e1a00000 nop   (mov r0,r0) 
のようにNOPに変更します

Linuxカーネルは実行時にこれと同様のことをすることができますが、私はビルド時の解決策を探しています。

答えて

4

RISC-ish固定長命令フォーマットでは、これは確かに簡単です。 x86。

オブジェクトファイルを開き、.textセクション内の命令を変更し、提供されたAPIを使用して再度書き出すには、libelf(nice tutorial here:http://people.freebsd.org/~jkoshy/download/libelf/article.html)またはlibbfd(http://sourceware.org/binutils/docs-2.19/bfd/index.html)を使用するのは比較的簡単です。それが努力する価値があるかどうかは、非技術的な考慮事項に依存します(私はちょっと不思議ですが...)。

これは、クロス開発環境で動作する必要がある場合は、libelfまたはlibbfdを使用していくつかの皺があるかもしれないことに言及することは重要です。

+0

ポイントは有効ですが、x86では 'nop'は1バイト命令ですので、削除する可変長命令で必要なだけ多く書くことができます。 –

+1

可変長命令の場合に問題になる部分は、命令パターンをノーオペレーションにすることを探しています。なぜなら、指定されたバイトオフセットがそのオフセットの前の命令。バイナリのリバースエンジニアリングを克服する(または少なくとも妨げる)ために時々使用される命令の途中で分岐するような賢い手書きのアセンブラトリックを考えると、さらに悪いことです。 –

+0

True;私はその方向から考えていませんでした。いい視点ね。 –

6

gcc -Sでコードをコンパイルして、オブジェクトファイルまたは実行可能ファイルに完全にコンパイルする代わりに、アセンブラリストを出力することができます。次に、no-opsで目的の命令を置き換えて(たとえば、sedを使用)、そこからコンパイルを続行します。

オリジナルのソースコードを持たないオブジェクトファイルやライブラリに対しても同様にしたい場合は、代わりにobjdump(1)などのツールを使用して解凍し、指示のアドレスを取得する必要がありますあなたは交換したい。次に、オブジェクトファイルヘッダーを解析して、それらの命令のファイル内のオフセットを見つけ、オブジェクトファイル内のno-opsで機械命令を直接置き換えます。これは少し難解ですが、実行可能です。

+0

置き換え時にデータを上書きしないようにしてください(バイナリデータやソース内の文字列など)。 – strager

+0

実際、 'gcc -S'はデータ用のアセンブリコード(プロダクトデータディレクティブ)を生成しませんが、objdumpは通常、コードを含むセグメントを分解するだけのスマートですが、これらのテクニックはどちらもランタイムコード生成または自己修正コード。しかし、それは単に問題を求めているだけです。 –