Lỗi phát hiện 1 phần mềm debugger đang chạy ẩn năm 2024

Gỡ lỗi (debug) là một kỹ năng không thể thiếu đối với các lập trình viên và nhà nghiên cứu bảo mật. Nắm vững cách gỡ lỗi cho phép bạn hiểu tệp thực thi ở cấp độ thấp hơn và nắm bắt mọi lỗi tiềm ẩn.

GNU debugger hay GDB là một công cụ gỡ lỗi đã được các lập trình viên tin cậy trong nhiều năm nay. Đây là cách sử dụng GDB trên Linux.

Chuẩn bị chương trình mẫu

Để khám phá các tính năng của GDB, bạn sẽ cần một tệp thực thi để thử nghiệm. Để minh họa, bạn sẽ chạy GDB trên một chương trình kiểm tra khóa một lần với mã nguồn và biểu tượng gỡ lỗi có sẵn, một lần không có mã nguồn và trên một chương trình đa luồng đơn giản in các thông báo ra màn hình, cả được viết bằng C và được biên dịch bằng GCC (GNU C Compiler).

Lỗi phát hiện 1 phần mềm debugger đang chạy ẩn năm 2024

Rất có thể bạn sẽ chạy GDB trên các chương trình của riêng mình. Vì vậy, hãy đảm bảo biên dịch chúng bằng cờ -g với gcc để bật biểu tượng gỡ lỗi.

Chạy một chương trình trong GDB

Lỗi phát hiện 1 phần mềm debugger đang chạy ẩn năm 2024

Bạn chạy một chương trình trong GDB theo một số cách. Nhập gdb <program> và khi nó tải lên, hãy nhập run. Hoặc khởi động gdb rồi sử dụng lệnh <program> tệp, tải tệp nhị phân vào gdb, rồi thực thi nó bằng lệnh run.

Nếu chương trình của bạn yêu cầu các đối số dòng lệnh để hoạt động bình thường, hãy đảm bảo thêm các đối số sau tên chương trình. Đây là cú pháp để tải chương trình lên GDB và thực thi nó bằng các đối số:

gdb <program>  
run <args>

Hoặc:

gdb  
file <program>  
run <args>

Đặt điểm dừng với GDB

Lỗi phát hiện 1 phần mềm debugger đang chạy ẩn năm 2024

Điểm dừng (breakpoint) trong quá trình gỡ lỗi được đặt thủ công trong code để dừng luồng thực thi khi chương trình đạt đến điểm dừng. Việc đặt điểm dừng cho phép bạn xem qua code và kiểm tra xem từng giai đoạn thực thi ảnh hưởng đến dữ liệu và biến như thế nào.

Trong GDB, khi bạn gỡ lỗi một chương trình có ký hiệu gỡ lỗi, bạn có thể đặt điểm dừng theo tên của hàm hoặc đặt điểm dừng dựa trên số dòng. Đây là cú pháp:

break main  
break 47

Để xem tất cả các điểm dừng trong phiên gỡ lỗi hiện tại, hãy nhập:

info breakpoints

Để xóa một điểm dừng cụ thể hoặc nhiều điểm dừng, hãy nhập:

delete 2  
delete 3-5

GDB cũng cho phép bạn đặt các điểm dừng có điều kiện, nghĩa là chương trình sẽ chỉ dừng lại nếu một điều kiện cụ thể được thỏa mãn trong quá trình thực thi. Đó có thể là sự thay đổi giá trị của một biến hoặc lệnh gọi hàm không thành công hoặc bất cứ điều gì bạn muốn. Đây là cú pháp để đặt điểm dừng có điều kiện:

break <location> if n == 2

Nếu bạn muốn tiếp tục thực hiện chương trình sau khi gặp điểm ngắt, hãy nhập lệnh continue:

continue

Xem qua code

Việc xem qua code là rất quan trọng để hiểu cách chương trình xử lý dữ liệu. Bằng cách xem qua các chức năng khác nhau trong chương trình của bạn và kiểm tra trạng thái dữ liệu, bạn có thể hiểu rõ hơn về cách chương trình đang triển khai logic mà bạn đã viết bằng code.

Nó cũng giúp bạn phát hiện nguyên nhân gốc rễ của sự cố và nghiên cứu hoạt động của chương trình với độ chính xác cao vì bạn có thể duyệt qua từng dòng code theo ý muốn. Bạn có thể xem qua code theo ba cách chính trong GDB:

  1. step: Lệnh này yêu cầu GDB chuyển sang dòng tiếp theo của tệp nguồn. Điều này về cơ bản cho phép bạn duyệt qua độ dài của mã nguồn theo từng dòng.
  2. next: Lệnh này thực thi dòng mã nguồn tiếp theo bên trong hàm hiện tại rồi dừng lại. next coi hàm là một dòng duy nhất nên nếu bạn sử dụng next trước lệnh gọi hàm, nó sẽ coi hàm đó là một dòng duy nhất và bước qua nó, không giống như lệnh step.
  3. finish: Lệnh kết thúc thực thi tất cả các dòng còn lại bên trong hàm hiện tại rồi dừng lại.

Kiểm tra các biến

Lỗi phát hiện 1 phần mềm debugger đang chạy ẩn năm 2024

Khi bạn duyệt qua mã, bạn sẽ muốn kiểm tra giá trị của các biến để xem logic chương trình đang thay đổi chúng như thế nào. Đây là cú pháp để xem giá trị của các biến trong GDB:

print <variable>

Trong trường hợp bạn muốn in những thay đổi về giá trị của một biến mỗi khi nó được cập nhật, bạn nên sử dụng lệnh display. Điều này đặc biệt hữu ích khi bạn muốn theo dõi và in giá trị của một biến trong vòng lặp:

display <variable>

Đặt điểm quan sát

Điểm quan sát (watchpoints) và điểm dừng có điều kiện có liên quan chặt chẽ với nhau vì cả hai đều phản ứng với những thay đổi trong chương trình. Điểm quan sát được sử dụng để theo dõi những thay đổi về dữ liệu trong code. Ví dụ: bạn có thể muốn chương trình bị ngắt bất cứ khi nào giá trị của một biến thay đổi. Đây là cách thực hiện điều đó với GDB:

watch <variable_name>

Gỡ lỗi theo chủ đề cụ thể

Lỗi phát hiện 1 phần mềm debugger đang chạy ẩn năm 2024

GDB cho phép bạn thực hiện gỡ lỗi theo từng luồng cụ thể khi làm việc với các chương trình đa luồng. Để minh họa, chúng ta sẽ làm việc với một Chương trình C đơn giản sử dụng bốn luồng để in thông báo với mỗi luồng.

Để xem các chủ đề hiện được sinh ra trong chương trình của bạn, hãy sử dụng lệnh info:

gdb  
file <program>  
run <args>

0

Để làm việc với một luồng cụ thể, bạn có thể chọn nó từ danh sách bằng số chỉ mục của nó. Ví dụ:

gdb  
file <program>  
run <args>

1

Sau khi chọn luồng, bạn có thể duyệt qua luồng thực thi của nó bằng cách sử dụng các lệnh step, next và finish như minh họa ở trên.

Gỡ lỗi từ xa

Lỗi phát hiện 1 phần mềm debugger đang chạy ẩn năm 2024

Bạn cũng có thể gỡ lỗi từ xa các chương trình nằm trên một hệ thống khác. Để làm như vậy, bạn cần thiết lập gdbserver trên máy đích. Bạn có thể dễ dàng cài đặt nó bằng trình quản lý gói mặc định của bản phân phối hoặc các trình quản lý gói khác mà bạn đã cài đặt trên hệ thống của mình.

Ví dụ: để cài đặt gdbserver trên hệ thống dựa trên Ubuntu hoặc Debian của bạn, hãy sử dụng APT:

gdb  
file <program>  
run <args>

2

Sau khi cài đặt, hãy di chuyển vào thư mục của tệp nhị phân và chạy lệnh này để khởi động gdbserver:

gdb  
file <program>  
run <args>

3

gdbserver sẽ trả về kết quả đầu ra và lắng nghe trên cổng bạn đã xác định. Bây giờ trên máy khách, khởi động GDB và sau đó kết nối với máy chủ từ xa bằng lệnh target:

gdb  
file <program>  
run <args>

4

Viết tập lệnh GDB để tự động gỡ lỗi

Lỗi phát hiện 1 phần mềm debugger đang chạy ẩn năm 2024

GDB cho phép các lập trình viên viết các tập lệnh GDB sẽ tự động thực thi các lệnh GDB. Điều này giúp ích rất nhiều khi bạn đang cố gắng gỡ lỗi cùng một phần mã nhiều lần. Thay vì phải đặt điểm ngắt, duyệt từng bước mã và in các giá trị biến mỗi khi bạn tải tệp nhị phân, bạn có thể sử dụng tập lệnh GDB để tự động hóa toàn bộ quy trình.

Đây là một ví dụ:

gdb  
file <program>  
run <args>

5

Trong tập lệnh ở trên, bạn đang yêu cầu GDB kích hoạt tính năng ghi nhật ký và lưu nhật ký vào một tệp có tên sample.out, sau đó đặt điểm dừng ở hàm main.

Đối với điểm dừng số 1, trong trường hợp này là điểm dừng tại hàm main, hãy chạy các lệnh sau: backtrace, print, continue. Về cơ bản, GDB trước tiên sẽ chạy backtrace, sau đó in giá trị của biến “N”, tiếp tục thực thi và cuối cùng thoát.

Để thực thi tập lệnh này, hãy sử dụng:

gdb  
file <program>  
run <args>

6

Bây giờ bạn đã biết cách gỡ lỗi chương trình bằng GDB!

Gỡ lỗi là một kỹ năng thiết yếu và gỡ lỗi bằng GDB là một kỹ năng tuyệt vời cần có trong vốn kiến ​​thức của bạn. Các tính năng khác nhau của GDB như duyệt qua code, đặt điểm dừng, gỡ lỗi luồng có chọn lọc, v.v. làm cho GDB trở thành một công cụ mạnh mẽ khi gỡ lỗi các tệp nhị phân trên Linux.