2012-05-21 36 views
11

Tôi đang viết một công cụ. Một phần của công cụ đó sẽ là khả năng ghi lại các tham số của các cuộc gọi hệ thống. Được rồi tôi có thể sử dụng ptrace cho mục đích đó, nhưng ptrace thì khá chậm. Một phương pháp nhanh hơn mà tôi nghĩ đến là sửa đổi glibc. Nhưng điều này là khó khăn, như gcc kỳ diệu chèn của riêng mình được xây dựng trong các chức năng như hệ thống gọi wrappers hơn bằng cách sử dụng mã được xác định trong glibc. Sử dụng -fno-builtin cũng không giúp ích ở đó. Vì vậy, tôi đã nghĩ ra ý tưởng viết một thư viện được chia sẻ, bao gồm mọi trình bao bọc cuộc gọi hệ thống, chẳng hạn như mmap và sau đó thực hiện ghi nhật ký trước khi gọi hàm bao bọc cuộc gọi hệ thống thực tế. Ví dụ mã giả của những gì tôi mmap sẽ giống như được đưa ra dưới đây.Đây có phải là cách hay để chặn cuộc gọi hệ thống không?

int mmap(...) 
{ 
log_parameters(...); 
call_original_mmap(...); 
... 
} 

Sau đó, tôi có thể sử dụng LD_PRELOAD để tải lên thư viện này. Bạn có nghĩ ý tưởng này sẽ hoạt động không, hoặc tôi đang thiếu một cái gì đó?

+7

Nó có thể sẽ không hoạt động đối với các tệp thực thi được liên kết tĩnh. Và nó sẽ không làm việc cho các tập tin thực thi làm syscalls mà không đi qua libc. –

+0

Bạn có muốn chặn mỗi khi một cuộc gọi sys thực tế được thực hiện (tại mỗi 'int 0x80'), hoặc tại mỗi cuộc gọi đến một hàm xử lý thư viện? – Chris

+0

Tôi nghĩ rằng nó có thể sẽ chậm. Đó là cơ bản chính xác những gì valgrind làm cho thiết bị của nó, và mặc dù là một công cụ rất nổi tiếng và phát triển, nó vẫn giết chết hiệu suất. Tôi nghĩ rằng nếu có một cách nhanh hơn, nó sẽ được sử dụng đã có. Tôi đoán là bạn đánh giá thấp chức năng khai thác gỗ sẽ tốn bao nhiêu, và không có cách nào xung quanh đó. – zebediah49

Trả lời

0

Tất cả các cuộc gọi hệ thống từ không gian người dùng đi qua trình xử lý ngắt để chuyển sang chế độ hạt nhân, nếu bạn tìm trình xử lý này, bạn có thể thêm nội dung nào đó vào đó.

EDIT Tôi tìm thấy điều này http://cateee.net/lkddb/web-lkddb/AUDITSYSCALL.html. Nhân Linux: 2.6.6–2.6.39, 3.0–3.4 có hỗ trợ kiểm tra cuộc gọi hệ thống. Đây là mô-đun hạt nhân phải được bật. Có lẽ bạn có thể xem mã nguồn của mô-đun này nếu nó không gây nhầm lẫn.

+2

LSM có thể được sử dụng để kiểm soát syscalls quá. http://en.wikipedia.org/wiki/Linux_Security_Modules – osgx

+0

Tôi muốn nghe lý do tại sao tôi có một downvote về điều này – Joelmob

+0

Điều này không phải là phổ quát đúng - nó có thể đúng cho x86 trên một số phiên bản của hệ điều hành nhất định, nhưng có rất nhiều các nền tảng và/hoặc các hệ điều hành không sử dụng ngắt làm cơ chế chuyển đổi hạt nhân sang chế độ người dùng. – twalberg

0

Như những người khác đã đề cập, nếu nhị phân được liên kết tĩnh, trình liên kết động sẽ bỏ qua bất kỳ nỗ lực nào để chặn các hàm bằng cách sử dụng libdl. Thay vào đó, bạn nên cân nhắc việc tự khởi chạy quy trình và làm tròn điểm nhập vào hàm mà bạn muốn chặn.

Điều này có nghĩa là tự khởi chạy quy trình, ngăn chặn việc thực hiện và ghi lại bộ nhớ của nó để đặt lệnh nhảy ở đầu định nghĩa của hàm trong bộ nhớ cho hàm mới mà bạn kiểm soát.

Nếu bạn muốn chặn cuộc gọi hệ thống thực sự và không thể sử dụng ptrace, bạn sẽ phải tìm trang web thực thi cho từng cuộc gọi hệ thống và viết lại hoặc bạn có thể cần ghi đè lên bảng gọi hệ thống trong bộ nhớ và lọc ra tất cả mọi thứ ngoại trừ quá trình bạn muốn kiểm soát.

2

Không có phương pháp nào bạn có thể mơ ước trong không gian người dùng sẽ hoạt động liền mạch với bất kỳ ứng dụng nào. May mắn thay cho bạn, đã có hỗ trợ để thực hiện chính xác những gì bạn muốn làm trong kernel. Kprobes và Kretprobes cho phép bạn kiểm tra trạng thái của máy ngay trước và sau khi thực hiện cuộc gọi hệ thống.

Tài liệu ở đây: https://www.kernel.org/doc/Documentation/kprobes.txt

0

Nếu mã bạn đang phát triển là quá trình liên quan đến, đôi khi bạn có thể phát triển triển khai thay thế mà không vi phạm các mã hiện. Điều này rất hữu ích nếu bạn đang viết lại một cuộc gọi hệ thống quan trọng và muốn có một hệ thống đầy đủ chức năng để gỡ lỗi nó.

Đối với trường hợp của bạn, bạn đang viết lại thuật toán mmap() để tận dụng lợi thế của một tính năng mới thú vị (hoặc nâng cao tính năng mới). Trừ khi bạn nhận được mọi thứ ngay trong lần thử đầu tiên, nó sẽ không dễ dàng để gỡ lỗi hệ thống: Một cuộc gọi hệ thống mmap() không chắc chắn nhất định dẫn đến một hệ thống không hoạt động. Như mọi khi, có hy vọng.

Thông thường, giữ an toàn cho thuật toán còn lại và xây dựng thay thế của bạn ở bên cạnh.Bạn có thể đạt được điều này bằng cách sử dụng id người dùng (UID) làm điều kiện để quyết định thuật toán nào sẽ sử dụng:

if (current->uid != 7777) { 
/* old algorithm .. */ 
} else { 
/* new algorithm .. */ 
} 

Tất cả người dùng ngoại trừ UID 7777 sẽ sử dụng thuật toán cũ. Bạn có thể tạo một người dùng đặc biệt, với UID 7777, để kiểm tra thuật toán mới. Điều này làm cho việc kiểm tra mã có liên quan đến quy trình quan trọng trở nên dễ dàng hơn nhiều.

Các vấn đề liên quan