Z tego postu pokazano, że FS:[0x28]
jest kanarek-stos. Generuję ten sam kod za pomocą GCC w tej funkcji,
void foo () {
char a[500] = {};
printf("%s", a);
}
W szczególności otrzymuję ten zestaw ..
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
Co to jest ustawienie wartości fs:[0x28]
? Jądro, czy GCC wrzuca kod? Czy potrafisz pokazać kod w jądrze lub skompilować do pliku binarnego, który ustawia fs:[0x28]
? Czy kanarek jest regenerowany - przy starcie, czy proces spawnowania? Gdzie to jest udokumentowane?
arch_prctl(ARCH_SET_FS..)
którego nie widzę w pliku wykonywalnym? Czy to jest kod jądra?ld-linux
podczas inicjowania TLS.To, co widzisz, nazywa się (w GCC) Stack Smashing Protector (SSP) , który jest formą ochrony przed przepełnieniem bufora generowanej przez kompilator. Wartość jest liczbą losową generowaną przez program podczas uruchamiania i, jak wspomniano w artykule w Wikipedii, jest umieszczana w wątku Local Storage (TLS) . Inne kompilatory mogą stosować różne strategie do implementacji tego rodzaju ochrony.
Po co przechowywać wartość w TLS? Ponieważ wartość znajduje się tam, jej adres nie jest dostępny dla rejestrów CS, DS i SS, co utrudnia odgadnięcie przechowywanej wartości, jeśli próbujesz zmienić stos ze złośliwego kodu.
źródło