Tôi đã đề cập đến "tràn bộ đệm" trong một bình luận cho câu trả lời của Pythagras, tôi có lẽ nên làm rõ những gì tôi muốn nói một chút. Trong C, không đủ để biết rằng làm việc trực tiếp với bộ nhớ là nguy hiểm - bạn cũng nên hiểu những cách chính xác mà nó nguy hiểm. Tôi thực sự không thích phép ẩn dụ "tự bắn vào chân mình" cho tất cả các trường hợp này - rất nhiều lần, không phải bạn bóp cò, mà thường là một diễn viên có sở thích trái ngược với bạn và / hoặc người dùng của bạn ' .
Ví dụ: trong một kiến trúc có ngăn xếp giảm dần (hầu hết các kiến trúc phổ biến phù hợp với hóa đơn này - x86 và ARM thường bao gồm), khi bạn gọi một hàm, địa chỉ trả về của hàm sẽ được đặt trên ngăn xếp sau các biến cục bộ được xác định trong cơ thể của chức năng. Vì vậy, nếu bạn khai báo bộ đệm là biến cục bộ và để biến biến đó ra thế giới bên ngoài mà không kiểm tra lỗi tràn bộ đệm, như sau:
void myFn(void) {
char buf[256];
gets(buf);
}
một người dùng bên ngoài có thể gửi cho bạn một chuỗi ghi đè địa chỉ trả về từ ngăn xếp - về cơ bản, anh ta có thể thay đổi ý tưởng thời gian chạy chương trình của bạn về biểu đồ cuộc gọi dẫn đến hàm hiện tại. Vì vậy, người dùng cung cấp cho bạn một chuỗi đó là biểu diễn nhị phân của một số mã thực thi cho kiến trúc của bạn, đủ phần đệm để tràn vào ngăn xếp myFn
và một số dữ liệu bổ sung để ghi đè địa chỉ trả về myFn
để trỏ đến mã mà anh ta đã cung cấp cho bạn. Nếu điều này xảy ra, thì myFn
thông thường sẽ trả lại quyền kiểm soát cho người gọi của nó, thay vào đó, nó sẽ phân nhánh để mã mà người dùng độc hại cung cấp. Nếu bạn viết mã C (hoặc C ++) có khả năng tiếp xúc với người dùng không tin cậy, bạn cần hiểu vectơ tấn công này. Bạn nên hiểu tại sao một bộ đệm tràn vào ngăn xếp thường (nhưng không phải luôn luôn) dễ dàng khai thác hơn so với bộ đệm và bạn nên hiểu cách bộ nhớ trong heap được đặt ra (không nhất thiết là quá nhiều chi tiết, nhưng ý tưởng rằng một malloc()
khu vực có các cấu trúc điều khiển xung quanh nó có thể giúp hiểu lý do tại sao chương trình của bạn gặp sự cố ở một khu vực khác malloc()
hoặc trong free()
).
C cung cấp cho bạn các chi tiết cấp thấp về cách thức hoạt động của máy và nó cho phép bạn kiểm soát trực tiếp máy của mình nhiều hơn bất kỳ ngôn ngữ nào do người dùng chỉnh sửa khác sử dụng rộng rãi hiện nay. Với sức mạnh lớn đi kèm với trách nhiệm lớn - bạn thực sự cần phải hiểu những chi tiết cấp thấp đó để làm việc với C một cách an toàn và hiệu quả.