Điều gì đặt fs: [0x28] (stack canary)?


11

Từ bài đăng này, nó được hiển thị FS:[0x28]là một canary stack. Tôi đang tạo cùng một mã bằng GCC trên chức năng này,

void foo () {
    char a[500] = {};
    printf("%s", a);
}

Cụ thể, tôi đang nhận lắp ráp này ..

    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

Đặt giá trị là fs:[0x28]gì? Hạt nhân, hoặc là GCC ném trong mã? Bạn có thể hiển thị mã trong kernel hoặc được biên dịch thành tệp nhị phân fs:[0x28]không? Là chim hoàng yến được tái sinh - khi khởi động, hoặc quá trình sinh sản? Tài liệu này ở đâu?

Câu trả lời:


17

Thật dễ dàng để theo dõi quá trình khởi tạo này, vì (hầu như) mọi quy trình đều stracehiển thị một tòa nhà rất đáng ngờ trong thời gian đầu của quá trình chạy:

arch_prctl(ARCH_SET_FS, 0x7fc189ed0740) = 0

Đó là những gì man 2 arch_prctlnói:

   ARCH_SET_FS
          Set the 64-bit base for the FS register to addr.

Yay, có vẻ như đó là những gì chúng ta cần. Để tìm, ai gọi arch_prctl, chúng ta hãy tìm một backtrace:

(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 ?? ()

Vì vậy, cơ sở phân đoạn FS được đặt bởi ld-linux, là một phần của glibcquá trình tải chương trình (nếu chương trình được liên kết tĩnh, mã này được nhúng vào nhị phân). Đây là nơi tất cả xảy ra.

Trong quá trình khởi động, trình nạp khởi tạo TLS . Điều này bao gồm cấp phát bộ nhớ và đặt giá trị cơ sở FS để trỏ đến TLS bắt đầu. Điều này được thực hiện thông qua arch_prctl tòa nhà chọc trời . Sau khi security_init hàm khởi tạo TLS được gọi, hàm này sẽ tạo ra giá trị của bộ bảo vệ ngăn xếp và ghi nó vào vị trí bộ nhớ, fs:[0x28]trỏ đến:

0x28là phần bù của stack_guardtrường trong cấu trúc được đặt tại điểm bắt đầu TLS.


zomfg, câu trả lời thực sự tuyệt vời. Tôi đã cố gắng để tháo rời một nhị phân với radare. Điều này có hình thức và nội dung mà tôi đang tìm kiếm. Cảm ơn rất nhiều.
Evan Carroll

Điều gì khởi tạo một quá trình với arch_prctl(ARCH_SET_FS..)tôi không thấy điều đó trong thực thi? Đó có phải là mã hạt nhân không?
Evan Carroll

Xem liên kết "tòa nhà" trong bài. Nó dẫn đến trang web cuộc gọi thực tế ( git.launchpad.net/glibc/tree/sysdeps/x86_64/nptl/tls.h#n153 ) nơi tòa nhà được thực thi. Nó được thực hiện bởi ld-linuxtrong quá trình khởi tạo TLS.
Danila Kiver

6

Những gì bạn đang thấy được gọi là (trong GCC) Bộ bảo vệ Đập ngăn xếp (SSP) , là một hình thức bảo vệ chống tràn bộ đệm được tạo bởi trình biên dịch. Giá trị là một số ngẫu nhiên được tạo bởi chương trình khi khởi động và như bài viết trên Wikipedia đề cập, được đặt trong Lưu trữ cục bộ luồng (TLS) . Các trình biên dịch khác có thể sử dụng các chiến lược khác nhau để thực hiện loại bảo vệ này.

Tại sao lưu trữ giá trị trong TLS? Vì giá trị được đặt ở đó, các thanh ghi CS, DS và SS không thể truy cập địa chỉ của nó, khiến cho việc đoán giá trị được lưu trữ rất khó khăn nếu bạn đang cố gắng thay đổi ngăn xếp từ mã độc.


Đây không phải là những gì tôi đang tìm kiếm, vì vậy tôi đã làm rõ một chút trong một nỗ lực để được rõ ràng. "số ngẫu nhiên được tạo bởi chương trình khi khởi động" bạn có thể chỉ ra nơi mà nó có thể thực thi được không, và điều gì đặt mã để tạo ra nó?
Evan Carroll
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.