Що встановлює fs: [0x28] (стек канарів)?


13

З цієї публікації видно, що 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]? Чи регенерується канарка - під час завантаження чи нерестовина для процесу? Де це документально зафіксовано?

Відповіді:


18

Це легко відстежити цю ініціалізацію, оскільки (майже) кожен процес straceдемонструє дуже підозрілий syscall на самому початку запуску процесу:

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, який є частиною glibc, під час завантаження програми (якщо програма статично пов'язана, цей код вбудовується у двійковий). Тут все відбувається.

Під час запуску завантажувач ініціалізує TLS . Сюди входить розподіл пам'яті та встановлення базового значення FS для вказівки на початок TLS. Це робиться через arch_prctl syscall . Після ініціалізації TLS викликається security_init функція , яка генерує значення захисту стека і записує його в місце пам'яті, яке fs:[0x28]вказує на:

І 0x28це зсув stack_guardполя в структурі, яка знаходиться на старті TLS.


zomfg, дійсно чудова відповідь. Я намагався розібрати бінарне з радаре. це має форму та зміст, які я шукав. Дякую тонну.
Еван Керролл

Що ініціалізує процес, коли arch_prctl(ARCH_SET_FS..)я не бачу цього у виконаному файлі? Це код ядра?
Еван Керролл

Дивіться посилання "syscall" у публікації. Він призводить до фактичного сайту виклику ( git.launchpad.net/glibc/tree/sysdeps/x86_64/nptl/tls.h#n153 ), де виконується системний виклик. Він виконується ld-linuxпід час ініціалізації TLS.
Даніла Ківер

6

Те, що ви бачите, називається (в GCC) захистом стека Smashing (SSP) , що є формою захисту від переповнення буфера, що генерується компілятором. Значення є випадковим числом, згенерованим програмою при запуску, і, як згадується у статті Вікіпедії, розміщується в локальному сховищі теми (TLS) . Інші компілятори можуть використовувати різні стратегії для реалізації цього типу захисту.

Навіщо зберігати значення в TLS? Оскільки значення знаходиться там, його адреса недоступна регістрами CS, DS та SS, що робить здогадування збереженого значення дуже складним, якщо ви намагаєтесь змінити стек від шкідливого коду.


Це не те, що я шукаю, тому я трохи уточнив, намагаючись бути зрозумілим. "випадкове число, згенероване програмою при запуску", чи можете ви показати, де у виконаному файлі воно генерується, і що ставить код для його створення?
Еван Керролл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.