Software Security 101 - Đời anh Bug Thủ
"Viết code mà không có bug cũng giống như nấu mì Hảo Hảo mà không bỏ gói muối: Tồn tại nhưng vô hồn. Nhưng nếu bug của bạn lỏ đến mức dâng luôn cả cái server cho giang hồ mạng, thì chúc mừng, bạn vừa đẻ ra một lỗ hổng bảo mật đi vào lòng đất." 🍜💥
Dưới đây là phần mở bát cho chuyên mục Software Security - tập trung vào phần Buffer Overflow của mảng Pwnable: . Đọc kỹ để hiểu bộ nhớ máy tính nó vận hành thế nào, để sau này vác máy đi thực chiến không bị khè cho khóc thét nhé!
1.1 Khởi động: Lỗ hổng phần mềm và Sự thật cảm lạnh (The Reality Check)
Chúng ta thường hay tự ái cãi cùn với Tester rằng "trên máy em nó vẫn chạy bình thường", nhưng sự thật từ thống kê thì vả đôm đốp vào mặt:
-
Trung bình một developer "đẻ" ra tới 70 con bugs trên mỗi 1000 dòng code. Quá báo!
-
Và buồn thay, khoảng 15 bugs/1000 dòng code sẽ lọt qua mọi vòng test và đến thẳng tay khách hàng.
-
Thời gian để fix một con bug tốn gấp 30 lần thời gian bạn gõ ra dòng code lỏ đó.
Chưa hết, chi phí để sửa lỗi không hề đứng im, nó tăng theo cấp số nhân dọc theo từng giai đoạn của vòng đời phát triển phần mềm (SDLC). Tức là bug phát hiện lúc đang nháp thiết kế thì sửa tốn ly bạc xỉu, nhưng bug mà lòi ra lúc đã mang đi triển khai thì cái giá phải trả cực kỳ đắt.
Và trong thế giới của các lỗ hổng, một trong những ngôi sao sáng nhất, cái tên khiến bao hệ thống "đăng xuất" chính là Buffer Overflow. Nhìn vào biểu đồ các lỗ hổng phần mềm, nó chiếm trọn tận 37%.

🧠 1.2 Giải phẫu bộ nhớ (Process Memory Layout)
Để hack được một chương trình, bạn không thể cứ múa phím bừa như rắc muối trên terminal được. Bạn phải hiểu cách hệ điều hành phân lô bán nền cho cái chương trình đó trong RAM. Khi chương trình chạy, bộ nhớ của nó được quy hoạch làm 5 khu vực chính:
-
Stack (Ngăn xếp): Tầng cao thượng lưu (High address). Khu vực này chuyên dùng để lưu trữ các biến cục bộ bên trong hàm. Đặc tính của nó là vào sau ra trước (LIFO), lưu trữ các dữ liệu gọi hàm như địa chỉ trả về và tham số.
-
Heap (Đống): Khu vực cung cấp không gian cho việc cấp phát bộ nhớ động. Bạn gọi
mallochaycalloctrong C thì xin chúc mừng, bạn đang xin đất ở khu Heap này. -
BSS segment: Nơi lưu trữ các biến tĩnh/toàn cục chưa được khởi tạo và hệ thống sẽ nhân từ gán mặc định cho chúng giá trị zero.
-
Data segment: Chỗ này lưu các biến tĩnh/toàn cục đã được khởi tạo bởi lập trình viên.
-
Text segment: Nằm dưới đáy xã hội (Low address). Nó chứa mã máy thực thi của chương trình và bị khóa ở chế độ Read-only (chỉ đọc).
⚔️ 1.3 Cuộc chiến vô cực: Stack vs Heap
-
Stack: Quản lý data theo phương pháp LIFO. Ưu điểm là auto dọn dẹp, biến cục bộ dùng xong (khi return khỏi hàm) là tự động bị hủy. Yếu điểm là bộ nhớ vô cùng giới hạn. Tạo quá nhiều object trên đây là "Cook" ngay với rủi ro Stack overflow.
-
Heap: Bát ngát mênh mông, hệ điều hành cung cấp lượng memory tối đa có thể và hoàn toàn không có giới hạn kích thước. Nhưng bù lại, code chạy tốn thời gian thực thi hơn nhiều so với Stack. Quản lý bộ nhớ cũng phức tạp hơn vì nó được sử dụng toàn cục.
🏢 1.4 Stack Layout 101: Nghệ thuật xếp chồng
Trong bộ môn Pwnable, khu vực bạn cắm cọc nhiều nhất chính là Stack. Mỗi khi một hàm được gọi, một không gian bộ nhớ sẽ được cấp phát trên đỉnh của ngăn xếp, gọi chung là Stack Frame.
Một Stack Frame tiêu chuẩn cắm đầu về phía bộ nhớ thấp gồm 4 "ngăn" quan trọng:
-
Arguments (Tham số): Lưu trữ các giá trị tham số, chúng được đẩy vào ngăn xếp ở vị trí bắt đầu của stack frame.
-
Return Address (Địa chỉ trả về): Cột mốc sinh tử! Khi hàm chạy xong lệnh, nó cần biết địa chỉ bộ nhớ nào để quay lại chạy tiếp, và địa chỉ đó nằm ở đây. (Spoil: Bọn h@cker cực kỳ thèm khát chỗ này).
-
Previous Frame Pointer (Con trỏ khung cũ): Món đồ tiếp theo được đẩy vào stack frame là frame pointer của khung trước đó. Nó được dùng để thiết lập thanh ghi frame pointer.
-
Local Variables (Biến cục bộ): Nơi chứa các biến cục bộ của hàm.
🎯 1.5 Bộ 3 Thanh ghi "Trấn Phái" (Registers)
Để quản lý cái đống frame lộn xộn này trên máy tính xịn xò của bạn, CPU xài 3 thanh ghi cực uy tín:
-
esp(Extended Stack Pointer): Mũi giáo tiên phong. Nó lưu trữ địa chỉ bộ nhớ mà con trỏ stack đang trỏ tới, tức là đỉnh hiện tại của ngăn xếp (điểm cuối của bộ nhớ thấp). Thanh ghi này sẽ di chuyển động khi có thứ gì đó push hoặc pop khỏi stack frame. -
ebp(Extended Base Pointer): Cột mốc mỏ neo. Nó lưu trữ địa chỉ bộ nhớ mà frame pointer trỏ tới, tức là một vị trí cố định bên trong stack frame. Nhờebpđứng im phăng phắc, ta mới tính offset vị trí các biến dễ dàng. -
eip(Extended Instruction Pointer): Kẻ định đoạt số phận. Thanh ghi này là con trỏ lệnh (instruction pointer).
Vậy làm sao để "Đập nát" cái Stack này? Khúc này bắt đầu dùng não nhiều hơn dùng tay rồi.
2. Buffer Overflow: Khi Chiếc Cốc Chứa Không Đủ Nước
Về cơ bản, tràn bộ đệm (Buffer Overflow) là một lỗi rành rành do sự bất cẩn của lập trình viên (programming error). Lỗ hổng này kích hoạt khi chương trình cố gắng lưu trữ một lượng dữ liệu khổng lồ vượt quá giới hạn của một bộ đệm có kích thước cố định (attempts to store data beyond the limits of a fixed-sized buffer).
Chuyện gì đến cũng phải đến, lượng dữ liệu dư thừa đó sẽ tràn ra ngoài như vỡ đê và tàn nhẫn ghi đè lên các vị trí bộ nhớ kề cận (overwrites adjacent memory locations). Khốn nạn ở chỗ, những vị trí kề sát này có thể đang chứa các biến khác của chương trình, các tham số, hoặc chí mạng nhất là chứa dữ liệu điều khiển luồng (program control flow data) như địa chỉ trả về (return addresses) và con trỏ trỏ đến khung stack trước đó (pointers to previous stack frames).
Hậu quả của trò "tham thực cực thân" này là gì? Dữ liệu bị hỏng (corruption of data), luồng điều khiển của chương trình bị chuyển hướng một cách vô lý (unexpected transfer of control), vi phạm quyền truy cập bộ nhớ, và cái kết quen thuộc nhất là chương trình tự hủy, lăn quay ra chết (eventual program termination) .

2.1 Tà Đạo Khai Thác 1: Stack Smashing (Đập nát EIP)
Đây là đòn đánh kinh điển nhất trong bộ môn Pwnable. Khi code lỏ không thèm kiểm tra độ dài của dữ liệu đầu vào (doesn't check the length of the data provided) mà cứ thế tống một cục bự vào cái buffer có kích thước cố định, ta có đòn tấn công Stack Smash. Mục tiêu tối thượng của đòn này là ghi đè thành công con trỏ lệnh đã lưu (overwriting the saved instruction pointer - eip).
Quy trình nổ não xảy ra như sau:
-
Khi hàm (ví dụ như hàm
main()) chuẩn bị trả về, nó sẽ thực hiện lệnhpopcái giá trị vừa bị ghi đè (ví dụ0x44434241hay chuỗi "DCBA" mã hex) ra khỏi stack . -
Tiếp theo, CPU vô cùng ngây thơ cố gắng tìm nạp (fetch), giải mã (decode) và thực thi (execute) các lệnh tại cái địa chỉ
0x44434241dỏm đó. -
Vì địa chỉ đó không chứa các lệnh hợp lệ của chương trình gốc, mà có thể đang chứa mã độc (malicious code) do h@cker khéo léo tuồn vào, hệ thống đã chính thức bị dắt mũi. Chúc mừng, bạn đã dâng server cho giang hồ mạng!
2.2 Tà Đạo Khai Thác 2: Stack Off-by-one (Trượt tay 1 byte, đi luôn cái EBP)
Không ồn ào và bạo lực như Stack Smashing, Stack off-by-one tinh tế và thâm độc hơn nhiều. Lỗ hổng này xảy ra khi lập trình viên nhầm lẫn tính toán một chút xíu về độ dài của chuỗi (a programmer makes a small calculation mistake relating to lengths of strings).
Chỉ một byte thừa mứa bị tràn, nhưng nó đủ sức ghi đè lên byte ít quan trọng nhất của con trỏ khung đã lưu (overwriting the saved frame pointer - ebp).
-
Khi byte này bị đổi (ví dụ đổi từ
0xbffff81cthành0xbffff800), toàn bộ cáiebpsẽ bị trượt xuống một địa chỉ thấp hơn (The ebp has been slid down to a lower address). -
Sự xê dịch lươn lẹo này đánh lừa hàm, khiến nó
popnhầm một địa chỉ trả về mới (popping the new saved eip) do h@cker dựng sẵn từ trước. Thế là "bùm", luồng thực thi lại bị bẻ cong hoàn hảo.
2.3 Ngoại Truyện: Tràn Đống (Heap Overflow)
Nếu Stack bị hệ thống giám sát quá gắt, giang hồ mạng sẽ rủ nhau chuyển kênh xuống khu Heap để quậy. Tràn bộ đệm hoàn toàn có thể xảy ra ở vùng dữ liệu Heap (occur in the heap data area).
Khu vực này là nơi chứa các bộ đệm được cấp phát động với vô số kích thước khác nhau (dynamically allocate buffers of varying sizes) thông qua các hàm thao tác tiêu biểu như malloc() và free(). Lỗi ở đây cực kỳ nguy hiểm vì các pháp sư có thể:
-
Ghi đè lên các dữ liệu nhạy cảm (sensitive data), ví dụ như đổi tên file hoặc phá hoại các biến quan trọng khác.
-
Thay đổi luồng logic của chương trình (logical program flow) bằng cách thọc tay vào cấu trúc điều khiển heap hoặc sửa đổi trực tiếp các con trỏ hàm (function pointer modification) . Nhảy vào hàm khác chạy như chốn không người!
3. Thực Chiến Pwnable - Nghệ Thuật "Trượt Cỏ" NOP Sled & Bơm Shellcode
"Phá vỡ một hệ thống đôi khi không cần búa tạ. Bạn chỉ cần mớm cho nó một đoạn text dài hơn mức nó có thể nhai, chèn thêm một xíu 'gia vị ma thuật' mang tên Shellcode, và cầu nguyện. Boom! Quyền root bay thẳng vào tay bạn." 🪄💥
Sau khi đã nắm rõ lý thuyết Stack và những cú Crash chí mạng ở chương trước, phần này chúng ta sẽ xắn tay áo lên để đi vào tà đạo thực chiến. Làm thế nào để từ một cái lỗi "lỏ" của dev mà cướp được cả một cái server? Lấy giấy bút ra ghi chép ngay!
🗺️ 3.1 Quy Trình 4 Bước "Lên Đồ" (General Exploitation Steps)
Hack một chương trình không phải cứ bật terminal lên gõ lạch cạch vài dòng xanh lá cây là xong như trên phim Hollywood. Nó là cả một nghệ thuật tinh tế gồm 4 bước cơ bản:
-
Bước 1: Khảo sát địa hình (Discovery): Các pháp sư mạng phải đi lùng sục lỗ hổng tràn bộ đệm (buffer overflow vulnerability) bằng cách soi mã nguồn chạy bằng cơm (manual code review). Nếu lười, họ dùng tool tự động (fuzzing) để ném hàng tá dữ liệu ngoại cỡ vào xem chương trình có lăn ra chết không.
-
Bước 2: Nặn đồ chơi (Craft the payload): Đây là lúc nhào nặn ra "Shellcode". Shellcode thực chất là một chuỗi instruction mã máy siêu nhỏ gọn. Mục tiêu phổ biến nhất là chế ra một đoạn mã gọi system call
execveđể triệu hồi cái terminal thần thánh/bin/sh. -
Bước 3: Bơm hàng (Injection & Triggering): Ném cái payload vừa nặn vào bộ đệm (thường qua network packet hoặc web request) . Kích hoạt lỗ hổng để chương trình bê nguyên cái payload đó đè bẹp các vị trí nhớ kề bên (overwrite adjacent memory locations).
-
Bước 4: Hái quả (Execution): Mã độc của bạn được thực thi, cho phép bạn thao túng chương trình và múa phím tùy thích.
🎯 3.2 Múa GDB Săn Offset (Tìm Tọa Độ)
Thử thách đau não nhất của bộ môn này là: Làm sao biết phải nhét cái Shellcode vào đúng địa chỉ nào, và làm sao ép con CPU ngây thơ nhảy chính xác vào đó? Vì vị trí bộ đệm phụ thuộc vào cách chương trình sử dụng stack nên ta không thể "nhắm mắt đưa chân" đoán mò được.
Bạn không biết địa chỉ trả về (Return address) nằm ở đâu, nhưng bạn biết chắc chắn nó nấp đâu đó trên Stack . Lúc này ta lôi gdb (GNU Debugger) ra làm thước đo:
-
Ném chương trình vào
gdb, đặt breakpoint và cho chương trình chạy đến đúng cái hàm đang bị lỗi. -
Bắt đầu soi: Tìm địa chỉ của thanh ghi
$ebp(cái cột mốc không bao giờ suy chuyển) và địa chỉ bắt đầu của biếnbuffer. -
Toán học lớp 1: Lấy địa chỉ của
$ebptrừ đi địa chỉ củabufferlà ta lòi ra được khoảng cách (offset). Tuy nhiên, để chạm trúng tử huyệt Return Address, bạn phải cộng thêm 4 byte nữa (với hệ điều hành 32-bit).
🛝 3.3 Nghệ Thuật NOP Sled (Cầu Trượt Vạn Năng)
Đời không như là mơ! Dù bạn có tính toán offset kỹ như kỹ sư NASA, việc đoán trúng phóc địa chỉ bắt đầu của mã độc (chính xác đến từng byte) vẫn vô cùng rủi ro. Đoán hụt 1 byte thôi là chương trình sập luôn (Failed Attack).
Giải pháp của các hệ tư tưởng lớn: Dùng đòn NOP (No-Operation). Trên kiến trúc x86 (cả 32-bit lẫn 64-bit), lệnh NOP được đại diện bằng mã hex 0x90. Lệnh này sinh ra chỉ để tốn chỗ, chả có tác dụng tính toán gì cả. Khi CPU đọc trúng nó, nó sẽ ngoan ngoãn lướt qua lệnh tiếp theo.
-
Cách chơi: H@cker sẽ tạo ra một dải NOP (NOP Sled) dài thò lò ngay trước cái Shellcode của mình.
-
Độ uy tín: Thay vì phải ném Return Address trúng phóc vào đầu Shellcode, giờ đây hacker chỉ cần ném đại Return Address vào bất kỳ đâu trên dải NOP này. CPU sẽ đáp xuống dải NOP, êm ái trượt một lèo xuống dưới và đâm sầm vào cái Shellcode đang há miệng chờ sẵn (Successful Attack). Tỷ lệ thành công cứ phải gọi là kịch trần!

Tưởng chừng như mớm được Shellcode vào Stack là xong game, nhưng không! Các OS Developers không hề rảnh rỗi để bạn thao túng server dễ thế. Họ đã giăng ra vô vàn cạm bẫy. Chuẩn bị tinh thần đi, phần 4 này chúng ta sẽ đối đầu với các cơ chế phòng vệ của hệ thống và ngó qua một tà đạo khác mang tên: Tràn Đống (Heap Overflow).
4.1 "Lưới Trời" OS & Các Tuyệt Kỹ "Né Chiêu" (Defensive Mechanisms)
Nếu bạn mang nguyên cái file badfile lỏ từ đời tống đi quật các hệ thống Linux hiện đại, 99% bạn sẽ bị cho ra đảo ngay. Dưới đây là 3 lớp khiên chân ái của hệ thống và cách giang hồ mạng "lươn lẹo":
🐦 1. Nghệ Thuật Nuôi Chim Trên Stack (Stack Canaries / StackGuard)
Giống như thợ mỏ ngày xưa hay mang theo một con chim hoàng yến xuống hầm để test khí độc, hệ thống cũng xài trò này.
-
Cơ chế: Trình biên dịch sẽ cấy một giá trị ngẫu nhiên (random canary value) nằm ngáng đường ngay trước Return Address trên Stack . Khi bạn vã data tràn buffer hòng đè lên Return Address, bạn buộc phải "đè bẹp" luôn con chim hoàng yến này. Trước khi hàm
return, hệ thống sẽ bắt mạch xem con chim còn sống không (giá trị có bị đổi không). Nếu phát hiện sai lệch, nó la làngstack smashing detectedvà cho chương trình tự hủy ngay lập tức. -
Cách lách (Bypass): Dân chơi hệ não to có thể dùng các lỗ hổng rò rỉ thông tin (information leak) để đọc lén giá trị canary, sau đó khi ghi đè thì "chép phạt" lại y nguyên giá trị đúng đó vào vị trí cũ (overwriting the canary with the correct value). Hoặc tinh tế hơn, làm hỏng một con trỏ khác để nó trỏ thẳng tới Return Address mà không thèm đạp trúng chim.
🎲 2. Hỗn Loạn Không Gian (ASLR - Address Space Layout Randomization)
-
Cơ chế: Kỹ thuật thao túng tâm lý đỉnh cao của OS. Mỗi lần bạn chạy chương trình, ASLR sẽ xáo trộn ngẫu nhiên địa chỉ bắt đầu của Stack và Heap. Việc bạn hì hục cắm GDB tính toán offset thủ công coi như vứt ra chuồng gà, vì địa chỉ sẽ chớp nhoáng thay đổi liên tục.
-
Chế độ Easy Mode (Tắt trong Lab): Đi làm bài tập mà bật cái này thì trầm cảm mất. Anh em thường hóa chaos bằng quyền root để tắt nó đi qua lệnh:
sudo sysctl -w kernel.randomize_va_space=0. Thế là stack lại đứng im ngoan ngoãn chờ bạn hack.
🛡️ 3. Lệnh Cấm Thi Triển Võ Công (Non-Executable Stack)
-
Cơ chế: Ngày xưa giang hồ tự do, Stack cho phép thực thi mã máy thoải mái. Ngày nay, Kernel (hạt nhân) quy hoạch lại, đánh dấu Stack là khu vực chỉ chứa Data, CẤM thực thi code (non-executable) . Bạn có bơm Shellcode thành công, ép CPU nhảy tới đúng chỗ, nhưng đụng ngay cái biển "Cấm cản" thì CPU cũng chê không thèm chạy.
-
Chế độ Easy Mode (Tắt trong Lab): Lúc bạn dùng
gccbiên dịch file C, hãy kẹp thêm cái cờ-z execstackđể nài nỉ OS mở lại quyền thực thi trên Stack . Tiện tay thì táng luôn cờ-fno-stack-protectorđể lột luôn cả lớp giáp StackGuard đi cho dễ thở.
4.2 Ngoại Truyện: Tràn Đống (Heap Overflow)
Khi Stack bị bảo vệ tầng tầng lớp lớp, các dân chơi hệ Pwnable rủ nhau chuyển kênh sang đấm nhau ở khu Heap. Đây là các lỗi tràn bộ đệm xảy ra ở vùng lưu trữ cấp phát động (dynamically allocate buffers) – những chỗ xài malloc() hay free() .
Khác với Stack, vùng Heap bát ngát mênh mông nhưng hoàn toàn không có cái return address nào để bạn nhắm tới cả. Tuy nhiên, sự thâm độc nằm ở chỗ khác:
-
Mượn dao giết người: H@cker có thể cho data tràn ra, ghi đè lên các vùng dữ liệu cực kỳ nhạy cảm (sensitive data) nằm liền kề, ví dụ như biến lưu tên file hoặc quyền user.
-
Bẻ cong không gian: Khét lẹt hơn, chúng có thể ghi đè trực tiếp lên các Con trỏ hàm (Function Pointer) nằm ngay ở block bộ nhớ sát bên. Lúc này, thay vì chạy hàm hợp lệ, chương trình sẽ bị bẻ luồng logic (logical program flow) và nhảy thẳng vào đoạn shellcode của attacker. Khó nhai hơn Stack nhiều, nhưng độ tàn phá thì vẫn cứ là "đăng xuất" khỏi trái đất!

"Bạn không thể ngăn h@cker tấn công hệ thống, giống như bạn không thể cản crush seen tin nhắn của mình vậy. Nhưng bạn hoàn toàn có thể tự bảo vệ bản thân bằng cách đừng tự tay bóp dais, đừng xài
gets()và hãy đa nghi với mọi thứ người dùng nhập vào!" 🛑🛡️
5.1 Quay Xe Sang Hệ "Ngôn Ngữ An Toàn" (Safe Languages)
Tại sao phải khổ sở chống tràn bộ đệm bằng tay khi mà có những ngôn ngữ lập trình sinh ra đã miễn nhiễm với trò đùa này? .
Sự thật là trong các ngôn ngữ an toàn, việc bị dính Buffer Overflow là gần như bất khả thi nhờ vào các hàng rào kiểm tra tự động của hệ thống ngay trong lúc chạy (runtime system checks). Để được đứng vào hàng ngũ "Safe", một ngôn ngữ phải đáp ứng đủ 3 tiêu chuẩn vàng:
-
Định kiểu mạnh mẽ (Strongly typed): Ép kiểu gắt gao, không có chuyện "râu ông nọ cắm cằm bà kia".
-
Auto soi biên (Automatic bounds checks): Tự động kiểm tra ranh giới của mảng, bạn mà cố nhét data lố qua hàng rào là nó báo lỗi ném thẳng vào mặt chứ không cho ghi đè bậy bạ.
-
Quản lý bộ nhớ tự động (Automatic memory management): Tự cấp phát, tự dọn rác (Garbage Collection), dev không cần phải lo rò rỉ bộ nhớ.
Các gương mặt vàng trong làng "Safe" được xướng tên là: Java, Python và... C++ (có vẻ các bô lão viết giáo trình khá ưu ái cho C++, dù giang hồ vẫn cãi nhau to về độ an toàn của nó).
Cái giá phải trả: Mọi thứ đều có trade-off! Đánh đổi lấy sự an toàn tuyệt đối đó là hiệu năng của chương trình có thể bị giảm sút (Possible performance degradation) vì hệ thống phải liên tục "chạy bằng cơm" để kiểm tra lỗi ngầm . Chậm một chút nhưng chắc, còn hơn bay mất cái server!
5.2 Khẩu Quyết "Đa Nghi Như Tào Tháo" (Defensive Programming)
Nếu dự án bắt ép bạn phải code bằng C/C++ hay những ngôn ngữ Unsafe, thì xin chúc mừng, mạng sống của server lúc này hoàn toàn phụ thuộc vào nhân phẩm và trình độ gõ phím của bạn. Hãy niệm 3 câu thần chú sau:
💀 1. Tất Cả Input Đều Là Ác Quỷ (ALL input is EVIL)
Đừng bao giờ tin tưởng người dùng! Bất kể đó là dữ liệu nhập từ bàn phím, file tải lên, hay thông số truyền qua mạng . Hãy luôn kiểm tra, xác thực (validate) mọi thứ trước khi cho nó đi sâu vào hệ thống. Lươn lẹo một nhịp là hệ thống cook ngay.
🚫 2. Tẩy Chay Hàm gets()
Lịch sử ngành IT đã chứng minh: gets() là một cái red flag siêu to khổng lồ.
-
Bản chất của hàm
gets()là nó không thèm kiểm tra lượng dữ liệu đang được nhồi vào cái buffer của bạn . -
Cứ có data là nó hút, hút cho đến khi bộ nhớ tràn trề, làm bục cả Stack, tạo cơ hội vàng cho h@cker bơm shellcode.
-
Các cụ đã gào thét cảnh báo: Hàm
gets()là cực kỳ nguy hiểm và TUYỆT ĐỐI KHÔNG ĐƯỢC SỬ DỤNG dưới bất kỳ hình thức nào (dangerous and should not be used) . -
Giải pháp: Chuyển sang chơi với các hàm an toàn hơn, những hàm có tích hợp tính năng kiểm tra độ dài biên (safer functions that do bounds checking) như
fgets()haystrncpy().
🛠️ 3. Chơi đồ để tăng sức đề kháng (Analysis Tools)
Sức người có hạn, check bug bằng mắt thì 10 năm nữa cũng chưa xong. Hãy sắm cho mình các công cụ phân tích tự động để soi mã nguồn (automatic tools to analyze code).
-
Các tool này có "mắt cú vọ", sẽ giúp gắn cờ báo động (flag) ngay lập tức khi phát hiện bạn lỡ tay gõ các hàm hoặc cấu trúc tiềm ẩn rủi ro thiếu an toàn .
-
Dù các tool này không thể nào diệt cỏ tận gốc 100% các lỗi buffer overflows, nhưng có còn hơn không. Nó sẽ gánh bớt cho bạn một đống lỗi sơ đẳng để giảm thiểu tối đa lỗ hổng bảo mật (mitigate security lapses). Bạn có thể lùng sục các tool này trên trang của OWASP .

🏁 Tóm cái váy lại:
-
Luật giang hồ của hệ điều hành: OS không rảnh phân lô bán nền cho vui. Stack để chứa đồ lặt vặt của hàm, Heap để vứt data động, Text để chạy code. Ranh giới đã định, bước hụt một nhịp hay cố tình vượt biên là ăn ngay nghiệp quật Segmentation fault (core dumped) liền!
-
Buffer Overflow - Lỗi do lòng tham: Bắt nguồn từ sự lười biếng của dev. Cái chén dung tích 32 bytes nhưng cố nhồi nguyên bộ bách khoa toàn thư vào. Nước tràn ly, data tràn khuôn, đè bẹp mỏ neo ebp, tiện tay bẻ lái luôn cái vô lăng eip.
-
Bộ 3 thanh ghi là sinh mệnh: esp múa lân trên đỉnh ngăn xếp, ebp đứng yên làm cột mốc đo tọa độ, eip là ông hoàng định đoạt số phận CPU. H@cker mà thao túng được eip thì server của bạn chính thức treo bảng "Đã đổi chủ".
-
Đạo cao một thước, ma cao một trượng: OS tung đủ mọi khiên chắn: thả Chim hoàng yến (Canaries) để bẫy, múa tung chảo địa chỉ (ASLR) để lừa mắt, rút luôn giấy phép hành nghề (NX bit) trên Stack. Nhưng vỏ quýt dày thì có móng tay nhọn, các pháp sư luồng lách được nếu dev tiếp tục để bug.
-
Chân lý sinh tồn: Xóa ngay hàm gets() ra khỏi trí nhớ. Tâm bất biến giữa dòng đời vạn biến, nhưng input của user thì TUYỆT ĐỐI LÀ ÁC QUỶ, không bao giờ được tin!
END BLOG
Baobei à, tới đây hiểu được bao nhiêu rồi… hay vẫn đang loading vậy? 🤡
Không sao, tôi cũng không hiểu hết — chỉ là giả vờ bình tĩnh thôi.
Bảo bối đừng vác ba cái tool lỏ đi chọc ngoáy server thật. Lên phường uống trà như chơi đấy eiu
Anyways, cya in the next chaos 💀