Câu trả lời:
Bảo vệ ngăn xếp được thực hiện bởi trình biên dịch (thêm một số dữ liệu bổ sung vào ngăn xếp và bỏ đi một số cuộc gọi, kiểm tra sự tỉnh táo khi trở về). Không thể vô hiệu hóa mà không biên dịch lại. Đó là một phần của vấn đề, thực sự ...
Để mở rộng những gì vonbrand có (chính xác, +1) đã nói, có hai phần để bảo vệ ngăn xếp của Linux.
Stack canaries là tính năng mà trình biên dịch thực thi mà vonbrand đề cập đến. Chúng không thể bị vô hiệu hóa mà không cần biên dịch lại.
Để chứng minh điều này với chính mình và xem cách họ làm việc, hãy lấy đoạn mã sau:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
int mybadfunction(char* a_bad_idea)
{
char what[100];
strcpy(what, a_bad_idea);
printf("You passed %s\n", what);
}
int main(int argc, char** argv)
{
printf("Tralalalaala\n");
mybadfunction(argv[1]);
}
Bây giờ biên dịch rằng ( gcc -fstack-protector -masm=intel -S test.c
) thành một cái gì đó gnu như sẽ rất vui khi lắp ráp và đọc đầu ra. Điểm quan trọng là khi thoát khỏi mybadfunction
hàm, có đoạn mã nhỏ này:
mov edx, DWORD PTR [ebp-12]
xor edx, DWORD PTR gs:20
je .L2
call __stack_chk_fail
Như bạn có thể đoán, đó là lấy một ngăn xếp cookie [ebp-12]
và so sánh nó với giá trị tại gs:20
. Không phù hợp? Sau đó, nó gọi một hàm __stack_chk_fail
trong glibc sẽ giết chương trình của bạn ngay tại đó.
Có nhiều cách để giải quyết vấn đề này bằng cách viết khai thác, nhưng cách dễ dàng trong việc xây dựng trường hợp kiểm thử shellcode là biên dịch chương trình của bạn -fno-stack-protector
.
Có một số cân nhắc khác trên các hệ thống Linux hiện đại. Nếu bạn lấy sơ đồ kiểm tra shellcode thông thường:
char buffer[] = {...};
typedef void (* func)(void);
int main(int argc, char** argv)
{
func f = (func) buffer;
f();
return 0;
}
GCC / Linux hiện đại sẽ ánh xạ .rodata
phần của tệp PE chỉ đọc mà không có quyền thực thi. Bạn cần tắt nó đi, có thể được thực hiện bằng cách sử dụng mẫu mã từ bài đăng trên blog này . Ý tưởng cơ bản: bạn sử dụng mprotect
để thêm các quyền bạn muốn vào các trang chứa dữ liệu shellcode.
Nếu bạn định kiểm tra một kịch bản khai thác truyền thống, ví dụ mã xấu của tôi ở trên, với shellcode của bạn thì bạn cũng cần đảm bảo ngăn xếp có thể thực thi được cho các trường hợp đơn giản. Định dạng tệp PE chứa một trường để xác định xem ngăn xếp có thể thực thi được hay không - bạn có thể truy vấn và kiểm soát điều này với execstack . Để kích hoạt ngăn xếp thực thi, hãy chạy
execstack -s /path/to/myprog
Điều này có thể được thực hiện trên các chương trình tùy ý mà không cần biên dịch lại, nhưng sẽ không tự động vô hiệu hóa các canaries ngăn xếp vì chúng được đưa vào biên dịch.
Để tắt nó , echo 0 > /proc/sys/kernel/randomize_va_space
.
Số Bất kỳ khai thác phải làm việc xung quanh đống chim hoàng yến (rất nhiều không tầm thường) và một trong hai tìm thấy một chương trình với execstack
bộ, hoặc thiết lập nó (có nghĩa là nó đã có thể thực hiện các lệnh tùy ý anyway) hoặc sử dụng khác kỹ thuật khó khăn hơn, chẳng hạn như quay trở lại libc / khứ hồi định hướng lập trình.