Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng

Tiến trình là gì?

• Là chương trình đang được thực hiện

• Các tài nguyên tối thiểu của tiến trình:

Vùng nhớ được cấp phát

Con trỏ lệnh(Program Counter)

Các thanh ghi của CPU

• Khối điều khiển tiến trình(Process Control Block-PCB):

Cấu trúc chứa thông tin của tiến trình

Khái niệm

• Bộ đệm (Buffer): tập hợp liên tiếp các phần tử có kiểu dữ

liệu xác định

Ví dụ: Trong ngôn ngữ C/C++, xâu là bộ đệm của các ký tự

Có thể hiểu theo nghĩa rộng: bộ đệm = vùng nhớ chứa dữ liệu

• Tràn bộ đệm (Buffer Overflow): Đưa dữ liệu vào bộ đệm

nhiều hơn khả năng chứa của nó

• Lỗ hổng tràn bộ đệm: Không kiểm soát kích thước dữ liệu

đầu vào.

• Tấn công tràn bộ đệm: Phần dữ liệu tràn ra khỏi bộ đệm

làm thay đổi luồng thực thi của tiến trình.

Dẫn tới một kết quả ngoài mong đợi

• Ngôn ngữ bị ảnh hưởng: C/C++

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 1

Trang 1

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 2

Trang 2

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 3

Trang 3

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 4

Trang 4

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 5

Trang 5

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 6

Trang 6

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 7

Trang 7

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 8

Trang 8

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 9

Trang 9

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng trang 10

Trang 10

Tải về để xem bản đầy đủ

pdf 29 trang duykhanh 6340
Bạn đang xem 10 trang mẫu của tài liệu "Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng

Bài giảng An toàn an ninh thông tin - Chương 10: An toàn vùng nhớ tiến trình - Bùi Trọng Tùng
[4];
 int loc2;
 }
 0xffffffff
 loc2 loc1 ??? ??? arg1 arg2 caller’s data
 Stack frame: Một phần của vùng nhớ stack 
 tương ứng với lời gọi của một hàm
 10
 5
10
 Stack frame
 void main(){ countUp(3);}
 void countUp(int n)
 {
 if(n > 1)
 countUp(n-1);
 printf(“%d\n”, n);
 }
 0xffffffff
 countUp(1) countUp(2) countUp(3) main()
 Con trỏ 
 stack
 11
11
 Stack frame
 void func(char *arg1, int arg2)
 {
 char loc1[4];
 int loc2;
 loc2++; Q: loc2 nằm ở đâu?
 } A: -8(%ebp)
 • %ebp: con trỏ frame.
 • (%ebp): nội dung vùng nhớ trỏ bởi %ebp
 0xffffffff
 loc2 loc1 ??? arg1 arg2 caller’s data
 ??? %ebp
 Không thể đoán 
 được ở thời 
 điểm dịch
 12
 6
12
 Stack – Trả về từ hàm
 int main()
 {
 ...
 func(“Hey”, 10);
 ... Q: Làm cách nào để khôi 
 } phục %ebp của hàm gọi
 0xffffffff
 loc2 loc1 ??? ??? arg1 arg2 caller’s data
 %ebp %ebp
 ?
 13
13
 Stack – Trả về từ hàm
 int main()
 {
 ...
 func(“Hey”, 10);
 ... Q: Làm cách nào để khôi 
 } phục %ebp của hàm gọi
 %esp
 ??? arg1 arg2 caller’s data
 %ebp
 14
 7
14
 Stack – Trả về từ hàm
 int main()
 {
 ...
 func(“Hey”, 10);
 ... Q: Làm cách nào để khôi 
 } phục %ebp của hàm gọi
 %esp
 0xffffffff
 %ebp ??? arg1 arg2 caller’s data
 %ebp
 1. Đưa %ebp vào stack trước biến cục bộ (pushl %ebp)
 15
15
 Stack – Trả về từ hàm
 int main()
 {
 ...
 func(“Hey”, 10);
 ... Q: Làm cách nào để khôi 
 } phục %ebp của hàm gọi
 0xffffffff
 loc2 loc1 %ebp ??? arg1 arg2 caller’s data
 %ebp
 1. Đưa %ebp vào stack trước biến cục bộ (pushl %ebp)
 2. Thiết lập %ebp bằng với %esp (movl %esp %ebp)
 16
 8
16
 Stack – Trả về từ hàm
 int main()
 {
 ...
 func(“Hey”, 10);
 ... Q: Làm cách nào để thực thi 
 } tiếp lệnh sau khi hàm trả về
 0xffffffff
 loc2 loc1 %ebp ??? arg1 arg2 caller’s data
 %ebp
 1. Đưa %ebp vào stack trước biến cục bộ (pushl %ebp)
 2. Thiết lập %ebp bằng với %esp (movl %esp %ebp)
 3. Khi hàm trả về, thiết lập %ebp bằng (%ebp) (movl (%ebp) %ebp)
 17
17
 Con trỏ lệnh - %eip
 ...
 0x5bf mov %esp,%ebp
 0x5be push %ebp
 ...
 ...
 0x4a7 mov $0x0,%eax
 0x4a2 call 
 0x49b movl $0x804..,(%esp)
 0x493 movl $0xa,0x4(%esp) %eip
 ...
 Text
 18
 9
18
 Stack – Trả về từ hàm
 int main()
 {
 ...
 func(“Hey”, 10);
 ... Q: Làm cách nào để khôi 
 } phục %ebp của hàm gọi
 0xffffffff
 loc2 loc1 %ebp %eip arg1 arg2 caller’s data
 %ebp Đưa %eip của 
 lệnh tiếp theo 
 vào stack trước 
 khi gọi hàm
 19
19
 Stack – Trả về từ hàm
 int main()
 {
 ...
 func(“Hey”, 10);
 ... Q: Làm cách nào để khôi 
 } phục %ebp của hàm gọi
 0xffffffff
 loc2 loc1 %ebp %eip arg1 arg2 caller’s data
 Thiết lập %eip bằng %ebp Đưa %eip của 
 4(%ebp) khi trả về lệnh tiếp theo 
 vào stack trước 
 khi gọi hàm
 20
 10
20
 Stack – Trả về từ hàm
 Trong C Mã assembly sau khi dịch
 return; leave: mov %ebp %esp
 pop %ebp
 ret: pop %eip
 Caller’s Callee’s Caller’s 
 code stack frame stack frame
 text loc2 loc1 %ebp %eip arg1 arg2
 %eip %esp %ebp Con trỏ frame cũ
 21
21
 Stack – Trả về từ hàm
 Trong C Mã assembly sau khi dịch
 return; leave: mov %ebp %esp
 pop %ebp
 ret: pop %eip
 Caller’s Callee’s Caller’s 
 code stack frame stack frame
 text loc2 loc1 %ebp %eip arg1 arg2
 %eip %ebp Con trỏ frame cũ
 %esp
 22
 11
22
 Stack – Trả về từ hàm
 Trong C Mã assembly sau khi dịch
 return; leave: mov %ebp %esp
 pop %ebp
 ret: pop %eip
 Caller’s Callee’s Caller’s 
 code stack frame stack frame
 text loc2 loc1 %ebp %eip arg1 arg2
 %eip %esp %ebp
 23
23
 Stack – Trả về từ hàm
 Trong C Mã assembly sau khi dịch
 return; leave: mov %ebp %esp
 pop %ebp
 ret: pop %eip
 Caller’s Callee’s Caller’s 
 code stack frame stack frame
 text loc2 loc1 %ebp %eip arg1 arg2
 %eip %esp %ebp
 24
 12
24
 Stack – Trả về từ hàm
 Trong C Mã assembly sau khi dịch
 return; leave: mov %ebp %esp
 pop %ebp
 ret: pop %eip
 Caller’s Callee’s Caller’s 
 code stack frame stack frame
 text loc2 loc1 %ebp %eip arg1 arg2
 %eip %ebp
 %esp
 Các lệnh tiếp theo xóa tham số khỏi stack
 25
25
 Tổng kết
 Hàm gọi(trước khi gọi):
 1. Đẩy các tham số vào stack theo thứ tự ngược
 2. Đẩy địa chỉ trả về vào stack, ví dụ %eip + 2
 3. Nhảy tới địa chỉ của hàm được gọi
 Hàm được gọi:
 4. Đẩy %ebp cũ vào stack
 5. Thiết lập %ebp tới đỉnh của stack
 6. Đẩy các biến cục bộ vào stack truy cập theo độ lệch từ %ebp
 Hàm được gọi trả về:
 7. Thiết lập lại %ebp cũ
 8. Nhảy tới địa chỉ trả về
 Hàm gọi:
 9. Xóa các tham số khỏi stack
 26
 13
26
 2. TẤN CÔNG TRÀN BỘ ĐỆM
 Bùi Trọng Tùng,
 Viện Công nghệ thông tin và Truyền thông,
 Đại học Bách khoa Hà Nội
 27
27
 Khái niệm
 • Bộ đệm (Buffer): tập hợp liên tiếp các phần tử có kiểu dữ 
 liệu xác định
 Ví dụ: Trong ngôn ngữ C/C++, xâu là bộ đệm của các ký tự
 Có thể hiểu theo nghĩa rộng: bộ đệm = vùng nhớ chứa dữ liệu
 • Tràn bộ đệm (Buffer Overflow): Đưa dữ liệu vào bộ đệm 
 nhiều hơn khả năng chứa của nó
 • Lỗ hổng tràn bộ đệm: Không kiểm soát kích thước dữ liệu 
 đầu vào.
 • Tấn công tràn bộ đệm: Phần dữ liệu tràn ra khỏi bộ đệm 
 làm thay đổi luồng thực thi của tiến trình.
 Dẫn tới một kết quả ngoài mong đợi
 • Ngôn ngữ bị ảnh hưởng: C/C++
 28
 14
28
 C/C++ vẫn rất phổ biến(2020)
 29
29
 Sự phổ biến của lỗ hổng BoF
 Sự phổ biến của lỗ hổng Buffer Overflow
 1000 7
 910
 880
 900 6.21
 841 6
 800
 5.33 704 5.25
 700 5
 4.58
 600
 4.07 4
 500
 3
 Số lỗ Số lỗ hổng 400
 287
 300 2
 200
 1
 100
 0 0
 2017 2018 2019 2020 2021
 Số lỗ hổng Tỉ lệ (%)
 30
 15
30
 Ví dụ về tràn bộ đệm
 void func(char *arg1)
 {
 char buffer[4];
 strcpy(buffer, arg1);
 return;
 }
 int main()
 {
 char *mystr = “AuthMe!”;
 func(mystr);
 ...
 }
 00 00 00 00 %ebp %eip &arg1
 buffer
 31
31
 Ví dụ về tràn bộ đệm
 void func(char *arg1)
 {
 char buffer[4];
 strcpy(buffer, arg1);
 return;
 }
 int main()
 {
 char *mystr = “AuthMe!”;
 func(mystr);
 ...
 }
 M e ! \0
 A u t h 4d 65 21 00 %eip &arg1
 buffer
 32
 16
32
 Ví dụ về tràn bộ đệm
 void func(char *arg1)
 {
 char buffer[4];
 strcpy(buffer, arg1);
 return; pop %ebp %ebp = 0x0021654d
 } SEGMENTATION FAULT
 int main()
 {
 char *mystr = “AuthMe!”;
 func(mystr);
 ...
 }
 M e ! \0
 A u t h 4d 65 21 00 %eip &arg1
 buffer
 33
33
 Tràn bộ đệm – Ví dụ khác
 void func(char *arg1)
 {
 int authenticated = 0
 char buffer[4];
 strcpy(buffer, arg1);
 if(authenticated){//privileged execution}
 }
 int main()
 { Hàm được thực 
 char *mystr = “AuthMe!”;
 func(mystr); thi như thế nào?
 ...
 }
 M e ! \0
 A u t h 4d 65 21 00 %ebp %eip &arg1
 buffer authenticated
 34
 17
34
 Tràn bộ đệm – Ví dụ khác
 void func(char *arg1)
 {
 int authenticated = 0
 char buffer[4];
 strcpy(buffer, arg1);
 if(authenticated){//privileged execution}
 }
 int main()
 {
 char *mystr = “AuthMe!”;
 func(mystr);
 ...
 }
 Người dùng có thể ghi đè dữ liệu tùy ý tới các vùng nhớ khác
 35
35
 Khai thác lỗ hổng tràn bộ đệm
 • Lỗ hổng tràn bộ đệm cho phép kẻ tấn công truy cập 
 (read/write/execute) tùy ý vào vùng nhớ khác
 • Phương thức khai thác phổ biến nhất: chèn mã nguồn 
 thực thi (code injection)
 • Ý tưởng
 %eipX %eip
 text 00 00 00 00 %ebp %eip &arg1  Malcode
 buffer
 36
 18
36
 Code Injection
 • Vấn đề 1: Nạp mã độc(malcode) vào stack
 Phải là mã máy
 Không chứa byte có giá trị 0
 Không sử dụng bộ nạp (loader)
 Không sử dụng vùng nhớ stack
 • Vấn đề 2: Nạp đúng các địa chỉ lệnh thực thi sau khi kết 
 thúc lời gọi hàm Xác định đúng %eip
 Mức độ khó khi xác định giá trị %eip phụ thuộc vị trí của malcode 
 • Vấn đề 3: Nạp đúng địa chỉ trả về Xác định đúng %ebp
 37
37
 Buffer Overflow – Phòng chống
 • Secure Coding: sử dụng các hàm an toàn có kiểm soát 
 kích thước dữ liệu đầu vào.
 fgets(), strlcpy(), strlcat()
 • Stack Shield:
 Lưu trữ địa chỉ trả về vào vùng nhớ bảo vệ không thể bị ghi đè
 Sao chép địa chỉ trả về từ vùng nhớ bảo vệ
 • Stack Guard: sử dụng các giá trị canh giữ (canary) để 
 phát hiện mã nguồn bị chèn
 • Non-executable stack: Không cho phép thực thi mã 
 nguồn trong stack
 Linux: sysctl -w kernel.exec-shield=0
 Vẫn bị khai thác bởi kỹ thuật return-to-libc
 38
 19
38
 Sử dụng giá trị canh giữ - Ví dụ 
 callee() static int random;
 { caller()
 int canary = random; {
 char buffer[]; random = rand();
 ... callee();
 if(canary!=random) }
 //detect attack
 else return;
 }
 00 00 00 00 4d 65 21 00 %eip &arg1
 buffer canary
 Buffer4d 65 Overflow 21 00 attack %eip &arg1
 buffer canary 39
39
 Buffer Overflow – Phòng chống
 • Address Space Layout Randomization
 0xffffffff
 Kernel 0xc0000000
 Thiết lập khi tiến trình cmdline & env
 bắt đầu
 Stack
 Thay đổi khi thực Nạp vào với địa chỉ 
 thi bắt đầu của mỗi 
 Heap vùng là ngẫu nhiên
 Xác định ở thời BSS
 điểm biên dịch Data
 Text
 Không gian địa chỉ 
 0x08048000
 của thiết bị vào-ra Unused
 0x00000000 40
 20
40
 3. MỘT SỐ LỖ HỔNG TRUY CẬP BỘ NHỚ KHÁC
 Bùi Trọng Tùng,
 Viện Công nghệ thông tin và Truyền thông,
 Đại học Bách khoa Hà Nội
 41
41
 Lỗ hổng xâu định dạng
 • Format String: Xâu định dạng vào ra dữ liệu
 • Lỗ hổng Format String: xâu định dạng không phù hợp với 
 danh sách tham số
 • Ví dụ void func()
 {
 char buf[32];
 if(fgets(buf, sizeof(buf),stdin) == NULL)
 return;
 printf(buf);
 }
 %ebp %eip &fmt
 printf’s stack frame Caller’s stack 
 frame 42
 21
42
 Lỗ hổng xâu định dạng
 • printf(“%d”);
 Hiển thị 4 byte phía trước địa chỉ đầu tiên của stack frame của hàm 
 printf
 • printf(“%s”);
 Hiển thị các byte cho tới khi gặp ký tự kết thúc xâu
 • printf(“%d%d%d”)
 Hiển thị chuỗi byte dưới dạng số nguyên
 • printf(“%x%x%x”)
 Hiển thị chuỗi byte dưới dạng hexa
 • printf(“%n”):
 Ghi số byte đã hiển thị vào vùng nhớ
 43
43
 Lỗ hổng tràn số nguyên
 • Trong máy tính, số nguyên được biểu diễn bằng trục số 
 tròn. Dải biểu diễn:
 Số nguyên có dấu: [–2n – 1, 2n–1 – 1]
 Số nguyên không dấu: [0, 2n – 1]
 • Integer Overflow: Biến số nguyên của chương trình nhận 
 một giá trị nằm ngoài dải biểu diễn. Ví dụ
 Số nguyên có dấu: 0x7ff..f + 1 = 0x80..0, 0xff..f + 1 = 0x0
 Số nguyên không dấu: 0xff..f + 1 = 0x0, 0x0 – 1 = 0xff...f
 • Ngôn ngữ bị ảnh hưởng: Tất cả
 • Việc không kiểm soát hiện tượng tràn số nguyên có thể 
 dẫn đến các truy cập các vùng nhớ mà không thể kiểm 
 soát.
 44
 22
44
 Lỗ hổng tràn số nguyên – Ví dụ 1
 • Lỗ hổng nằm ở đâu?
 #define MAX 1024
 void vul_func1()
 {
 char buff[1024];
 int len = recv_len_from_client();
 char *mess = recv_mess_from_client();
 if (len > 1024)
 printf (“Too large”);
 else
 memcpy(buf, mess, len);
 }
 45
45
 Lỗ hổng tràn số nguyên – Ví dụ 2
 • Lỗ hổng nằm ở đâu?
 int main()
 {
 int *arr;
 int len;
 printf(“Number of items: ”); scanf(“%d”, &len);
 arr = malloc(len * sizeof(int));
 for(int i = 0; i < len; i++)
 scanf(“%d”, arr[i]);
 return 0;
 }
 46
 23
46
 4. LẬP TRÌNH AN TOÀN
 Bùi Trọng Tùng,
 Viện Công nghệ thông tin và Truyền thông,
 Đại học Bách khoa Hà Nội
 47
47
 Lập trình an toàn
 • Yêu cầu: Viết mã nguồn chương trình để đạt được các 
 mục tiêu an toàn bảo mật
 • Bao gồm nhiều kỹ thuật khác nhau:
 Kiểm soát giá trị đầu vào
 Kiểm soát truy cập bộ nhớ chính
 Che giấu mã nguồn
 Chống dịch ngược
 Kiểm soát kết quả đầu ra
 Kiểm soát quyền truy cập
 
 • Bài này chỉ đề cập đến một số quy tắc và nhấn mạnh vào 
 vấn đề truy cập bộ nhớ một cách an toàn
 48
 24
48
 An toàn truy cập bộ nhớ
 • An toàn không gian(Spatial safety): thao tác chỉ nên truy 
 cập vào đúng vùng nhớ đã xác định
 • Nếu gọi:
 b: địa chỉ ô nhớ đầu tiên của vùng nhớ được chỉ ra
 p: địa chỉ cần truy cập tới
 e: địa chỉ ô nhớ cuối cùng của vùng nhớ được chỉ ra
 s: kích thước vùng nhớ cần truy cập
 • Thao tác truy cập bộ nhớ chỉ an toàn khi và chỉ khi:
 b ≤ p ≤ e – s
 • Lưu ý: Các toán tử tác động trên p không làm thay đổi b
 và e.
 49
49
 An toàn không gian – Ví dụ
 int x = 0;
 int *y = &x; // b = &x, e = &x + 4, s = 4
 int *z = y + 1; // b = &x, e = &x + 4, s = 4
 *y = 10; //OK: &x ≤ p = &x ≤ (&x + 4) - 4
 *z = 10; //Fail: &x ≤ p = &x + 4 ≤/ (&x + 4) - 4
 char str[10]; //b = &str, e = &str + 10
 str[5] = 'A'; //OK: &str ≤ p = &str + 5 ≤ (&str + 10) - 1
 str[10] = 'F'; //Fail: &str ≤ p = &str + 10 ≤/ (&str + 10) - 1
 • Lỗi truy cập không an toàn về không gian gây ra các lỗ 
 hổng như đã biết
 50
 25
50
 An toàn truy cập bộ nhớ
 • An toàn thời gian(): thao tác chỉ truy cập vào vùng nhớ 
 mà đã được khởi tạo:
 Đã cấp phát bộ nhớ
 Đã được khởi tạo giá trị
 • Ví dụ: Vi phạm an toàn về thời gian
 int n;
 printf("%d", n); // Fail
 int *p;
 *p = 0; // Fail
 p = (int *) malloc(sizeof(int));
 *P = 0; // OK
 free(p);
 *p = 10; // Fail
 51
51
 Điều kiện truy cập bộ nhớ
 • Tiền điều kiện(precondition): điều kiện để câu lệnh/hàm 
 được thực thi đúng đắn
 • Hậu điều kiện(postcondition): khẳng định trạng thái đúng 
 đắn của các đối tượng khi lệnh/hàm kết thúc
 • Ví dụ: Xác định các điều kiện truy cập bộ nhớ
 void displayArr(int a[], size_t n)
 {
 for(size_t i = 0; i < n, i++)
 printf(“%d”, a[i]);
 }
 52
 26
52
 Các nguyên tắc lập trình an toàn
 • Không tin cậy những thứ mà không do bạn tạo ra
 • Người dùng chỉ là những kẻ ngốc nghếch
 Hàm gọi (Caller) = Người dùng
 • Hạn chế cho kẻ khác tiếp cận những gì quan trọng. Ví dụ: 
 thành phần bên trong của một cấu trúc/đối tượng
 Ngôn ngữ OOP: nguyên lý đóng gói
 Ngôn ngữ non-OOP: sử dụng token
 • Không bao giờ nói “không bao giờ”
 • Sau đây sẽ đề cập đến một số quy tắc trong C/C++
 • Về chủ đề lập trình an toàn, tham khảo tại đây:
 https://security.berkeley.edu/secure-coding-practice-
 guidelines
 53
53
 Kiểm tra mọi dữ liệu đầu vào
 • Các giá trị do người dùng nhập
 • File được mở
 • Các gói tin nhận được từ mạng
 • Các dữ liệu thu nhận từ thiết bị cảm biến (Ví dụ: 
 QR code, âm thanh, hình ảnh,)
 • Thư viện của bên thứ 3
 • Mã nguồn được cập nhật
 • Khác
 54
 27
54
 Sử dụng các hàm xử lý xâu an toàn
 • Sử dụng các hàm xử lý xâu an toàn thay cho các 
 hàm thông dụng
 strcat, strncat strlcat
 strcpy, strncpy strlcpy
 gets fgets, fprintf
 • Luôn đảm bảo xâu được kết thúc bằng ‘\0’
 • Nếu có thể, hãy sử dụng các thư viện an toàn 
 hơn
 Ví dụ: std::string trong C++
 55
55
 Sử dụng con trỏ một cách an toàn
 • Hiểu biết về các toán tử con trỏ: +, -, sizeof
 • Cần xóa con trỏ về NULL sau khi giải phóng bộ nhớ
 int x = 5;
 int *p = (int *)malloc(sizeof(int));
 free(p);
 p = NULL;
 int **q = (int **)malloc(sizeof(int*));
 *q = &x;
 *p = 5; //Crash OK
 **q = 3;
 56
 28
56
 Cẩn trọng khi sử dụng lệnh goto
 • Ví dụ:
 57
57
 Sử dụng các thư viện an toàn hơn
 • Nên sử dụng chuẩn C/C++11 thay cho các chuẩn cũ
 • Sử dụng std::string trong C++ để xử lý xâu
 • Truyền dữ liệu: sử dụng Goolge Protocol Buffers hoặc 
 Apache Thrift
 58
 29
58

File đính kèm:

  • pdfbai_giang_an_toan_an_ninh_thong_tin_chuong_10_an_toan_vung_n.pdf