~에서이 게시물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-linux
FS 세그먼트 베이스의 일부입니다 glibc
(프로그램이 정적으로 링크된 경우 이 코드는 바이너리에 포함됩니다). 이것이 모든 일이 일어나는 곳입니다.
시작하는 동안 프로그램이 로드됩니다.TLS 초기화. 여기에는 메모리 할당과 처음에 TLS를 가리키도록 FS 베이스를 설정하는 것이 포함됩니다. 이는 다음에 의해 수행됩니다.arch_prctl
시스템 호출. TLS 초기화 후security_init
기능fs:[0x28]
호출되면 스택으로 보호되는 값을 생성하고 다음을 가리키는 메모리 위치에 씁니다 .
는 TLS의 시작 부분에 있는 구조의 필드 0x28
오프셋 입니다.stack_guard
답변2
(GCC에서) 보이는 것을 이라고 합니다.스택 스매시 프로텍터(SSP), 이는 형식입니다.버퍼 오버플로 방지컴파일러에 의해 생성됩니다. 값은 시작 시 프로그램에 의해 생성된 난수이며 Wikipedia 기사에서 언급했듯이스레드 로컬 저장소(TLS). 다른 컴파일러는 이러한 유형의 보호를 구현하기 위해 다른 전략을 사용할 수 있습니다.
TLS에 값이 저장되는 이유는 무엇입니까? 여기에 값이 있기 때문에 CS, DS, SS 레지스터에서는 그 주소에 접근할 수 없기 때문에 악성코드를 통해 스택을 변경하려고 하면 저장된 값을 추측하기 어렵다.