2013-03-12 47 views
11

Tôi đang cố gắng kiểm soát tràn ngăn xếp. Thứ nhất, đây là một ví dụ về mã C tôi biên soạn trên x32 VM Linux (gcc -fno-stack-protector -ggdb -o first first.c),Lỗi tràn bộ đệm xuất hiện trước khi được mong đợi

#include "stdio.h" 

int CanNeverExecute() 
{ 
    printf("I can never execute\n"); 
    return(0); 
} 

void GetInput() 
{ 
    char buffer[8]; 

    gets(buffer); 
    puts(buffer); 
} 

int main() 
{ 
    GetInput(); 
    return(0); 
} 

Sau đó, gỡ lỗi (intel hương vị): bãi mã lắp ráp cho chức năng GetInput:

0x08048455 <+0>: push ebp 
0x08048456 <+1>: mov ebp,esp 
0x08048458 <+3>: sub esp,0x28 
0x0804845b <+6>: lea eax,[ebp-0x10] 

đây chúng ta có thể thấy rằng phụ đặc biệt, 0x28 dự trữ 40 byte cho một biến bộ đệm (phải không?). Chức năng CanNeverExecute được đặt tại địa chỉ 0x0804843c. Vì vậy, để chạy hàm CanNeverExecute, tôi cần đặt 40 byte vào biến bộ đệm, sau đó đi 8 byte cho con trỏ cơ sở được lưu trữ và sau đó 8 byte con trỏ trả về mà tôi muốn thay đổi.

Vì vậy, tôi cần một chuỗi 48 ký hiệu ASCII cộng với \x3c\x84\x04\x08 ở cuối (địa chỉ của hàm CanNeverExecute). Đó là về mặt lý thuyết. Nhưng Trong thực tế, tôi chỉ cần 20 byte trước địa chỉ của con trỏ trả về:

~/hacktest $ printf "123456789\x3c\x84\x04\x08" | ./first 
123456789.. 
I can never execute 
Illegal instruction (core dumped) 

Tại sao chỉ cần 20 byte thay vì 48? Sai lầm của tôi đâu rồi?

Trả lời

2

Nếu bạn tham gia lớn hơn của dissassembly Bạn sẽ thấy:

08048445 <GetInput>: 
8048445: 55      push %ebp 
8048446: 89 e5     mov %esp,%ebp 
8048448: 83 ec 28    sub $0x28,%esp 
804844b: 8d 45 f0    lea -0x10(%ebp),%eax 
804844e: 89 04 24    mov %eax,(%esp) 
8048451: e8 9a fe ff ff   call 80482f0 <[email protected]> 
8048456: 8d 45 f0    lea -0x10(%ebp),%eax 
8048459: 89 04 24    mov %eax,(%esp) 
804845c: e8 9f fe ff ff   call 8048300 <[email protected]> 
8048461: c9      leave 
8048462: c3      ret 

ebp được lưu, đặc biệt được chuyển đến ebp, sau đó 40 được trừ từ đặc biệt (stack khung, như bạn đã viết), nhưng con trỏ vào bộ đệm được truyền qua thanh ghi eax và eax được nạp với ebp-0x10!

lea -0x10(%ebp),%eax 

Vì vậy, bạn chỉ cần 20 byte làm tràn bộ đệm (16 Reserved + 4 cho lưu trữ con trỏ trên cơ sở hệ thống 32-bit)

9

Trước hết, lắp ráp của bạn là 32 bit. Lưu EBP và địa chỉ trả về là 4 byte mỗi.

Thứ hai, biến số buffer không bắt đầu ở đầu stack (ESP) - nó bắt đầu bằng ebp-0x10. Mà là 20 byte đi từ địa chỉ trở lại. 0x10 là 16 byte, sau đó 4 byte cho EBP đã lưu.