fs:[0x28](스택 카나리아)을 설정하는 것은 무엇입니까?

fs:[0x28](스택 카나리아)을 설정하는 것은 무엇입니까?

~에서이 게시물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-linuxFS 세그먼트 베이스의 일부입니다 glibc(프로그램이 정적으로 링크된 경우 이 코드는 바이너리에 포함됩니다). 이것이 모든 일이 일어나는 곳입니다.

시작하는 동안 프로그램이 로드됩니다.TLS 초기화. 여기에는 메모리 할당과 처음에 TLS를 가리키도록 FS 베이스를 설정하는 것이 포함됩니다. 이는 다음에 의해 수행됩니다.arch_prctl 시스템 호출. TLS 초기화 후security_init 기능fs:[0x28]호출되면 스택으로 보호되는 값을 생성하고 다음을 가리키는 메모리 위치에 씁니다 .

는 TLS의 시작 부분에 있는 구조의 필드 0x28오프셋 입니다.stack_guard

답변2

(GCC에서) 보이는 것을 이라고 합니다.스택 스매시 프로텍터(SSP), 이는 형식입니다.버퍼 오버플로 방지컴파일러에 의해 생성됩니다. 값은 시작 시 프로그램에 의해 생성된 난수이며 Wikipedia 기사에서 언급했듯이스레드 로컬 저장소(TLS). 다른 컴파일러는 이러한 유형의 보호를 구현하기 위해 다른 전략을 사용할 수 있습니다.

TLS에 값이 저장되는 이유는 무엇입니까? 여기에 값이 있기 때문에 CS, DS, SS 레지스터에서는 그 주소에 접근할 수 없기 때문에 악성코드를 통해 스택을 변경하려고 하면 저장된 값을 추측하기 어렵다.

관련 정보