Ne fs ayarlar: [0x28] (yığın kanarya)?


13

Kaynaktan bu yazı gösterilmiştir FS:[0x28]bir yığın kanaryadır. Ben bu işlevi GCC kullanarak aynı kodu üretiyorum,

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

Özellikle, bu montajı alıyorum ..

    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

Değerini ayarlamak nedir fs:[0x28]? Çekirdek mi, yoksa GCC kodda mı atıyor? Kodu çekirdekte gösterebilir veya ayarlanan ikili dosyaya derleyebilir fs:[0x28]misiniz? Kanarya yeniden başlatılıyor mu? Bu nerede belgeleniyor?

Yanıtlar:


18

Bu başlatmayı izlemek kolaydır, çünkü (neredeyse) her işlem strace, işlem çalışmasının başlangıcında çok şüpheli bir sistem çağrısı gösterir:

arch_prctl(ARCH_SET_FS, 0x7fc189ed0740) = 0

Ne budur man 2 arch_prctldiyor ki:

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

Yay, ihtiyacımız olan şey bu. Kimin aradığını bulmak arch_prctliçin bir geri izleyelim:

(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 ?? ()

Bu nedenle, FS segment tabanı, programın yüklenmesi sırasında ld-linuxbir parçası olan tarafından ayarlanır glibc(program statik olarak bağlıysa, bu kod ikiliye gömülür). Her şey burada gerçekleşiyor.

Başlatma sırasında yükleyici TLS'yi başlatır . Bu, bellek ayırmayı ve FS taban değerini TLS başlangıcını gösterecek şekilde ayarlamayı içerir. Bu arch_prctl sistem çağrısı ile yapılır . Yığın koruyucusunun değerini üreten ve bunu bellek konumuna yazan TLS başlatma security_init işlevi çağrıldıktan sonra fs:[0x28]:

Ve 0x28ofset edilir stack_guardTLS başlangıcında yer almaktadır yapısında alanında.


zomfg, gerçekten harika bir cevap. Radare ile bir ikili sökmeye çalışıyordum. bu aradığım biçim ve içeriğe sahip. Bir ton teşekkürler.
Evan Carroll

arch_prctl(ARCH_SET_FS..)Yürütülebilir dosyada görmediğim bir işlemi başlatan nedir? Bu çekirdek kodu mu?
Evan Carroll

Yayındaki "syscall" bağlantısına bakın. Sistem çağrısının yürütüldüğü gerçek çağrı sitesine ( git.launchpad.net/glibc/tree/sysdeps/x86_64/nptl/tls.h#n153 ) yönlendirir. ld-linuxTLS başlatma sırasında tarafından yürütülür .
Danila Kiver

6

Gördüğünüz şeye (GCC'de) derleyici tarafından üretilen bir arabellek taşması koruması biçimi olan Stack Smashing Protector (SSP) denir . Değer, başlangıçta program tarafından oluşturulan rastgele bir sayıdır ve Wikipedia makalesinde bahsedildiği gibi, Yerel İş Parçacığına (TLS) yerleştirilir . Diğer derleyiciler bu tür korumayı uygulamak için farklı stratejiler kullanabilir.

Değeri neden TLS'de saklamalıyım? Değer orada bulunduğundan, adres CS, DS ve SS kayıtları tarafından erişilemez, bu da yığını kötü amaçlı koddan değiştirmeye çalışıyorsanız depolanan değeri tahmin etmeyi çok zorlaştırır.


Aradığım şey bu değil, bu yüzden net olmak için biraz açıkladım. "Başlangıçta program tarafından oluşturulan rasgele sayı" çalıştırılabilir bir dosyada nerede üretildiğini ve kodu oluşturmak için ne koyduğunu gösterebilir misiniz?
Evan Carroll
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.