の設定は何ですか?](https://linux33.com/image/136463/fs%3A%5B0x28%5D(%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%E3%82%AB%E3%83%8A%E3%83%AA%E3%82%A2)%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%81%AF%E4%BD%95%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F.png)
~からこの投稿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-linux
FSセグメントベースの一部ですglibc
(プログラムが静的にリンクされている場合、このコードはバイナリに含まれます)。これがすべてのことが起こるところです。
起動中にプログラムがロードされます。TLS初期化。これには、メモリ割り当てと最初にTLSを指すようにFSベースを設定することが含まれます。これは以下によって行われる。arch_prctl
システムコール。 TLS初期化後security_init
機能fs:[0x28]
呼び出されると、スタックで保護された値を生成し、次を指すメモリ位置に書き込みます。
はTLSの先頭にある構造体のフィールド0x28
オフセットです。stack_guard
答え2
(GCCで)見えるものといいます。スタックスマッシュプロテクター(SSP)、これは形式です。バッファオーバーフロー防止コンパイラによって生成されます。値は起動時にプログラムによって生成された乱数であり、Wikipediaの記事で述べたようにスレッドローカルストレージ(TLS)。他のコンパイラは、このタイプの保護を実装するために異なる戦略を使用することができます。
TLSに値が格納されるのはなぜですか?ここに値があるため、CS、DS、SSレジスタではそのアドレスにアクセスできないため、マルウェアを介してスタックを変更しようとすると、保存された値を推測することは困難です。