好奇心から、プログラムの実行中にコードの一部を再配置できるかどうか疑問に思います。たとえば、関数があり、この関数は実行されるたびにメモリ内で置き換える必要があります。私たちの頭に浮かんだ 1 つのアイデアは、それを行うために自己変更コードを使用することです。一部のオンライン リソースによると、自己変更コードは Linux で実行できますが、そのような動的な再配置が可能かどうかはまだわかりません。誰もそれを経験したことがありますか?
3 に答える
はい、動的再配置は間違いなく可能です。ただし、コードが完全に自己完結型であること、または絶対参照によってグローバル/外部関数にアクセスすることを確認する必要があります。コードが完全に位置に依存しない場合、つまりコードが作成する唯一の参照がそれ自体に対して相対的である場合、設定は完了です。そうしないと、読み込み時に自分で修正を行う必要があります。
GCC を使用する-fpic
と、位置に依存しないコードを生成できます。-q
or--emit-relocs
をリンカーに渡すと、再配置情報が出力されます。ELF 仕様(PDF リンク) には、その再配置情報の使用方法に関する情報が含まれています。ELF を使用していない場合は、フォーマットに適したドキュメントを見つける必要があります。
カールが言うように、それは可能ですが、あなたはワームの缶を開けています. 実際には、これを行うのに苦労するのは学者かマルウェア作成者だけです (今は防炎マントを着ています)。
一部のコードを malloc されたヒープ領域にコピーし、関数ポインターを介して呼び出すことができますが、OS によっては、セグメントでの実行を有効にする必要がある場合があります。一部のコードをコード セグメントにコピーすることはできますが (次の関数を上書きしないように注意してください)、OS によってこのセグメントが読み取り専用になっている可能性があります。Linux カーネルを調べて、モジュールがどのようにロードされるかを確認してください。
これらのさまざまな関数がすべてコンパイル時に存在する場合は、単に関数ポインタを使用して、次に呼び出される関数を追跡できます。実行時に関数を絶対に変更する必要があり、その変更をその場で行うことができない場合は、作成/ロード時に新しい関数のアドレスで更新される関数ポインターを使用することもできます。システムの残りの部分は、関数ポインターを介して自己変更関数を呼び出すため、自己変更コードを知ったり気にしたりする必要はなく、修正を 1 か所で行うだけで済みます。