看板 C_and_CPP 關於我們 聯絡資訊
和大家分享, 若有什麼問題也麻煩幫忙指證。 我一直很好奇 check stack 有沒爆掉是怎麼做的, 一位朋友為我解惑, 就在 stack 底端 塞個值, 檢查他就好了, 我頓時茅塞頓開, 原來如此。 不過本著求證的心態, 來看看是 不是真的。 stack_pro.c 1 2 #include <stdio.h> 3 #include <string.h> 4 5 int main() 6 { 7 8 char string[10]; 9 10 strcpy(string, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); 11 12 } gcc -m32 -g -static -fno-stack-protector stack_pro.c -o stack_pro.nosp gcc -m32 -g -static -fstack-protector stack_pro.c -o stack_pro.sp objdump -d stack_pro.sp 1 080482d0 <main>: 2 80482d0: 55 push %ebp 3 80482d1: 89 e5 mov %esp,%ebp 4 80482d3: 83 e4 f0 and $0xfffffff0,%esp 5 80482d6: 83 ec 20 sub $0x20,%esp 6 80482d9: 65 a1 14 00 00 00 mov %gs:0x14,%eax 7 80482df: 89 44 24 1c mov %eax,0x1c(%esp) 8 80482e3: 31 c0 xor %eax,%eax 9 80482e5: b8 dc 02 0b 08 mov $0x80b02dc,%eax 10 80482ea: c7 44 24 08 23 00 00 movl $0x23,0x8(%esp) 11 80482f1: 00 12 80482f2: 89 44 24 04 mov %eax,0x4(%esp) 13 80482f6: 8d 44 24 12 lea 0x12(%esp),%eax 14 80482fa: 89 04 24 mov %eax,(%esp) 15 80482fd: e8 ee 74 00 00 call 804f7f0 <memcpy> 16 8048302: 8b 54 24 1c mov 0x1c(%esp),%edx 17 8048306: 65 33 15 14 00 00 00 xor %gs:0x14,%edx 18 804830d: 74 05 je 8048314 <main+0x44> 19 804830f: e8 2c be 00 00 call 8054140 <__stack_chk_fail> 20 8048314: c9 leave 21 8048315: c3 ret L6, 7, 16, 17 就是這些魔法施行的地方。string[10] 從 0x12(%esp) 開始, 長度 10, 所以這個魔法標記紀錄在 0x1c(%esp), 0x1c-0x12 = 0xa, 在做完 memcpy (為什麼 strcpy 變成 memcpy 就不用管他了) 之後, 再來檢查 0x1c(%esp) 值是不是之前保存 (從 %gs:0x14 得來的) 的即可, 如果不一樣, 就去執行 __stack_chk_fail。 在我測試時, 這個值是: %gs:0x14: 0x944bc400 不過似乎會一直變化, 每次執行都不一樣, 不是固定值。 這是把 0x1c(%esp) dump 出來, 本來應該要是 0x00 0xc4 0x4b 0x94 (little endian), 可是因為我們把 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 覆蓋超過了 string[10], 所以就變成 0x41 0x41 0x41 0x41 ... (gdb) x/32xb 0xffffd39c 0xffffd39c: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0xffffd3a4: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41 這是執行結果, 沒有 -fstack-protector 的版本, 自然是發出 Segmentation fault。 stack protector 執行結果 1 *** stack smashing detected ***: ./stack_pro.sp terminated 2 ======= Backtrace: ========= 3 [0x8054189] 4 [0x805414d] 5 [0x8048314] 6 [0x41414141] 7 ======= Memory map: ======== 8 08048000-080cf000 r-xp 00000000 08:05 18620900 /home/descent/my-git/progs/stack_pro.sp 9 080cf000-080d1000 rw-p 00086000 08:05 18620900 /home/descent/my-git/progs/stack_pro.sp 10 080d1000-080d3000 rw-p 00000000 00:00 0 11 08f7b000-08f9d000 rw-p 00000000 00:00 0 [heap] 12 f77c9000-f77ca000 r-xp 00000000 00:00 0 [vdso] 13 ffdc2000-ffdd7000 rw-p 00000000 00:00 0 [stack] 14 Aborted Emit extra code to check for buffer overflows, such as stack smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. This includes functions that call alloca, and functions with buffers larger than 8 bytes. The guards are initialized when a function is entered and then checked when the function exits. If a guard check fails, an error message is printed and the program exits. NOTE: In Ubuntu 6.10 and later versions this option is enabled by default for C, C++, ObjC, ObjC++, if neither -fno-stack-protector nor -nostdlib are found. 至於 man page 的 8 byte 我怎麼試都觀察不到, 就沒辦法分享這段的意思了。 stack overflow 有篇類似的, 可惜我找不到了。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.125.239.46
scwg:有個至少 8 byte 的字元陣列 (buffer) 是加入 stack protecto 05/06 11:35
scwg:r 的條件. 把 string 改成 [4] 就不會加了. 05/06 11:36
IdFormat:可以參考 #1HT7LCg0 這篇 05/06 13:07