Linux シャットダウン機能

Linux シャットダウン機能

私はLinuxシステムコールメカニズムを理解しようとしています。本を読んでいますが、終了関数は次のようになります(gdbを使用)。

mov $0x0,%ebx
mov $0x1,%eax
80 int $0x80

私はこれがシャットダウンシステムコールであることを知っていますが、私のDebianでは:

jmp    *0x8049698
push   $0x8
jmp    0x80482c0

たぶん誰かがなぜ違うのか説明できますか? 0x80482c0でdisasを実行しようとすると、gdbは次のように出力します。

指定されたアドレスを含む関数はありません。

ありがとうございます!

答え1

コード呼び出しは、実際には実行できない可能性があるexit()Cライブラリ(libc)関数にリンクされています。exit()int $0x80

コードexit()の関数呼び出しは、実際には callプログラム接続テーブル(PLT)の命令にコンパイルされます。ランタイムダイナミックリンカは、ファイルを/usr/lib/libc.soメモリにマッピングする役割を果たします。それはCライブラリです。ランタイムダイナミックリンカはまた、PLTのエントリを修正して最終的にmapからコードを呼び出します/usr/lib/libc.so

私が知っている限り(私はArch Linuxを使用しています)、2番目の3つの命令はPLTエントリであり、gdbステップごとに入ると "exit @ plt"を呼び出します。jmp 0x80482c0別のアドレスにジャンプし、最終的にlibc.soコードにジャンプします。

かなり複雑な練習でこれを自分で証明することができます。まず、「exit @ plt」アドレスをgdb示すPLTテーブルエントリのアドレスを取得しました。jmp *0x8049698私のx86 Arch Linuxシステムでは:

(gdb) disassemble 0x8048310,+20
Dump of assembler code from 0x8048310 to 0x8048324:
   0x08048310 <exit@plt+0>:     jmp    *0x80496e8
   0x08048316 <exit@plt+6>:     push   $0x10
   0x0804831b <exit@plt+11>:    jmp    0x80482e0

それではreadelf -e _program_ > elf.headerself.headersファイルを表示する「セクションタイトル:」というテキスト行を見つけることができ、セクションタイトルのどこかに次の内容が表示されます。

  [ 9] .rel.dyn          REL             08048290 000290 000008 08   A  5   0  4
  [10] .rel.plt          REL             08048298 000298 000020 08  AI  5  12  4
  [11] .init             PROGBITS        080482b8 0002b8 000023 00  AX  0   0  4
  [12] .plt              PROGBITS        080482e0 0002e0 000050 04  AX  0   0 16

"exit@plt"はアドレス0x8048310にあります。 「.rel.plt」セクションにあります。 「.rel.plt」はおそらく「relocator link table」を意味します。

int $0x80今、私たちはおそらく存在しない部分に到達します。ldd _program_ない。同様に、Arch Linux x86は次のように言います。

linux-gate.so.1 (0xb77d9000)
libc.so.6 => /usr/lib/libc.so.6 (0xb7603000)
/lib/ld-linux.so.2 (0xb77da000)

「linux-gate.so.1」は見えますか?これには、システムコールを実行する実際のコードが含まれています。それであってもint $0x80、指示であったりsysenter、他のものであってもよい。 Linuxカーネルは、実際のコードと共にプロセスのアドレス空間に「小さな共有ライブラリ」を置き、小さな共有ライブラリのアドレスをELF「補助ベクトル」に渡すようになっています。詳細を確認してくださいman vdso。動的リンカーは/lib/ld-linux.so.2ELF補助ベクトルの詳細を知り、最終的にlinx-gate.so.1PLTのどこかにアドレスを配置するので、実際のC関数呼び出しは効率的なシステム呼び出しを生成します。

何度も電話をかけると、通話するたびにldd _program_表示されるアドレスがlinux-gate.so.1異なります。実際、カーネルは、独自のコードを実行するためにスタックの場所を知る必要があるマルウェアを混同するために、毎回同じアドレスにスタックの上部を配置しません。

関連情報