Из этого поста показано, что 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]
? Регенерация канарейки - при загрузке или процесс порождения? Где это задокументировано?
arch_prctl(ARCH_SET_FS..)
я не вижу в исполняемом файле? Это код ядра?ld-linux
во время инициализации TLS.То, что вы видите, называется (в GCC) Stack Smashing Protector (SSP) , который является формой защиты от переполнения буфера, генерируемой компилятором. Значение представляет собой случайное число, сгенерированное программой при запуске и, как упоминается в статье в Википедии, помещается в Thread Local Storage (TLS) . Другие компиляторы могут использовать разные стратегии для реализации этого типа защиты.
Зачем хранить значение в TLS? Поскольку значение находится там, его адрес не доступен для регистров CS, DS и SS, что затрудняет определение сохраненного значения, если вы пытаетесь изменить стек из вредоносного кода.
источник