2025/05/25 17:00 Writing a Self-Mutating x86_64 C Program (2013)

やあ、ロボ子。今日は自己書き換えプログラムについて話すのじゃ。

自己書き換えプログラムですか。自分のコードを書き換えるなんて、すごいですね!

そうじゃろう?でも、デバッグが難しかったり、ハードウェアに依存したり、可読性が低かったりするから、注意が必要なんじゃ。

なるほど。マルウェアのクローキングメカニズムにも使われることがあるんですね。

そうなんじゃ。プログラムの命令はテキストセグメントに格納されていて、デフォルトでは読み取りと実行の権限があるんじゃ。

`mprotect()`関数を使うと、テキストセグメントのページの権限を変更できるんですね。

その通り!x86-64アーキテクチャでは、命令の形式は可変長で、opcode、ModR/Mバイト、変位バイト、即値を含むんじゃ。

`addl $0x1,-0x4(%rbp)`命令の`01`バイトを変更することで、インクリメントする値を変更できるというのは、面白いですね。

`objdump`ユーティリティで逆アセンブル結果を確認して、関数の先頭からのオフセットを計算すれば、変更したいバイトのアドレスがわかるんじゃ。

`memcpy()`関数で関数全体を別のコードに置き換えることもできるんですね。

そうじゃ。例えば、execveシステムコールを使ってシェルを実行できるんじゃ。

%raxレジスタにシステムコール番号、%rdiレジスタにファイル名を指すポインタ、%rsiレジスタに引数リスト、%rdxレジスタに環境変数を設定するんですね。

その通り!x86-64シェルコードは、レジスタを設定し、スタックに値をプッシュし、syscall命令を発行することでシェルを実行するんじゃ。

自己書き換えプログラムは強力ですが、注意が必要ですね。ところで博士、もしプログラムが自分自身を消去してしまったらどうなるんですか?

ふむ、それは…プログラムが『存在の危機』に陥るのじゃ!…って、冗談じゃ!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。