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?