fs:[0x28](スタックカナリア)の設定は何ですか?

fs:[0x28](スタックカナリア)の設定は何ですか?

~からこの投稿FS:[0x28]これがスタックカナリアであることがわかります。この関数でGCCを使用して同じコードを生成しました。

void foo () {
    char a[500] = {};
    printf("%s", a);
}

特にこのアセンブリを組み立てています。

    0x000006b5      64488b042528.  mov rax, qword fs:[0x28]                ; [0x28:8]=0x1978 ; '(' ; "x\x19"
    0x000006be      488945f8       mov qword [local_8h], rax
...stuff...
    0x00000700      488b45f8       mov rax, qword [local_8h]
    0x00000704      644833042528.  xor rax, qword fs:[0x28]
    0x0000070d      7405           je 0x714
    0x0000070f      e85cfeffff     call sym.imp.__stack_chk_fail           ; void __stack_chk_fail(void)
    ; CODE XREF from 0x0000070d (sym.foo)
    0x00000714      c9             leave
    0x00000715      c3             ret

設定された値は何ですかfs:[0x28]?カーネルですか、それともGCCが投げたコードですか?カーネルにコードを表示したり、設定バイナリにコンパイルできますかfs:[0x28]?起動時にカナリアが再生成されるか、プロセスが生成されますか?これはどこで録音されましたか?

ベストアンサー1

strace(ほとんど)すべてのプロセスがプロセス実行の初期に非常に疑わしいシステムコールを表示するため、この初期化を追跡するのは簡単です。

arch_prctl(ARCH_SET_FS, 0x7fc189ed0740) = 0

これman 2 arch_prctlが言う内容です:

   ARCH_SET_FS
          Set the 64-bit base for the FS register to addr.

はい、それは私たちに必要なようです。誰が電話をかけたのかを調べるarch_prctlために、逆追跡を探しましょう。

(gdb) catch syscall arch_prctl
Catchpoint 1 (syscall 'arch_prctl' [158])
(gdb) r
Starting program: <program path>

Catchpoint 1 (call to syscall arch_prctl), 0x00007ffff7dd9cad in init_tls () from /lib64/ld-linux-x86-64.so.2
(gdb) bt
#0  0x00007ffff7dd9cad in init_tls () from /lib64/ld-linux-x86-64.so.2
#1  0x00007ffff7ddd3e3 in dl_main () from /lib64/ld-linux-x86-64.so.2
#2  0x00007ffff7df04c0 in _dl_sysdep_start () from /lib64/ld-linux-x86-64.so.2
#3  0x00007ffff7dda028 in _dl_start () from /lib64/ld-linux-x86-64.so.2
#4  0x00007ffff7dd8fb8 in _start () from /lib64/ld-linux-x86-64.so.2
#5  0x0000000000000001 in ?? ()
#6  0x00007fffffffecef in ?? ()
#7  0x0000000000000000 in ?? ()

したがって、FSセグメントベースはプログラムのロード中に設定され、ld-linuxFSセグメントベースの一部ですglibc(プログラムが静的にリンクされている場合、このコードはバイナリに含まれます)。これがすべてのことが起こるところです。

起動中にプログラムがロードされます。TLS初期化。これには、メモリ割り当てと最初にTLSを指すようにFSベースを設定することが含まれます。これは以下によって行われる。arch_prctl システムコール。 TLS初期化後security_init 機能fs:[0x28]呼び出されると、スタックで保護された値を生成し、次を指すメモリ位置に書き込みます。

はTLSの先頭にある構造体のフィールド0x28オフセットです。stack_guard

おすすめ記事