2008-09-16 80 views
11

除了LD_PRELOAD技巧以及用你提供的替代特定系統調用的Linux內核模塊之外,還有可能攔截一個系統調用(例如打開),以便在它到達實際之前首先通過你的函數開放?我怎麼攔截linux系統調用?

+1

這個問題需要澄清 - 它太含糊。爲什麼LD_PRELOAD不夠? – Arafangion 2010-05-17 14:12:29

+7

@Arafangion - LD_PRELOAD可以攔截圖書館電話。但內核調用是不同的。 – 2010-07-08 13:31:40

回答

15

爲什麼不能使用LD_PRELOAD技巧?

示例代碼在這裏:

/* 
* File: soft_atimes.c 
* Author: D.J. Capelis 
* 
* Compile: 
* gcc -fPIC -c -o soft_atimes.o soft_atimes.c 
* gcc -shared -o soft_atimes.so soft_atimes.o -ldl 
* 
* Use: 
* LD_PRELOAD="./soft_atimes.so" command 
* 
* Copyright 2007 Regents of the University of California 
*/ 

#define _GNU_SOURCE 
#include <dlfcn.h> 
#define _FCNTL_H 
#include <bits/fcntl.h> 

extern int errorno; 

int (*_open)(const char * pathname, int flags, ...); 
int (*_open64)(const char * pathname, int flags, ...); 

int open(const char * pathname, int flags, mode_t mode) 
{ 
    _open = (int (*)(const char * pathname, int flags, ...)) dlsym(RTLD_NEXT, "open"); 
    if(flags & O_CREAT) 
     return _open(pathname, flags | O_NOATIME, mode); 
    else 
     return _open(pathname, flags | O_NOATIME, 0); 
} 

int open64(const char * pathname, int flags, mode_t mode) 
{ 
    _open64 = (int (*)(const char * pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64"); 
    if(flags & O_CREAT) 
     return _open64(pathname, flags | O_NOATIME, mode); 
    else 
     return _open64(pathname, flags | O_NOATIME, 0); 
} 

據我瞭解......這幾乎是LD_PRELOAD伎倆或內核模塊。除非你想在一個模擬器下運行它,而這個模擬器可能會陷入你的函數中,或者在實際的二進制代碼上重寫代碼以捕獲你的函數,否則沒有太多的中間立場。

假設你不能修改程序,也不能修改內核,LD_PRELOAD方法是最好的,假設你的應用程序是相當標準的,並且實際上並不是一個惡意程序試圖通過你的攔截。 (在這種情況下,你需要的其他技術之一。)

+5

程序確認LD_PRELOAD完全是可選的。並非每個程序都與libc鏈接。 – vipw 2012-12-12 20:33:07

+0

@vipw你能詳細說明一下嗎?程序如何繞過LD_PRELOAD?沒有與libc鏈接的每個程序都與鏈接器在加載可執行文件時(如果使用LD_PRELOAD指定)加載給定庫之前無關。如果該庫碰巧有可執行文件調用的函數,那麼該程序首先查找LD_PRELOAD加載的庫。後續庫也實現該功能並不重要。 – acib708 2015-03-11 19:29:02

2

我沒有語法可以正確使用LKM,但是本文提供了一個很好的總覽:http://www.linuxjournal.com/article/4378

您也可以修補sys_open函數。從linux-2.6.26開始,從file/open.c的第1084行開始。

如果您不需要構建新系統,您可能還會看到是否無法使用inotify,systemtap或SELinux爲您執行所有這些日誌記錄。

7

Valgrind可用於截取任何函數調用。如果你需要在你的成品中攔截系統調用,那麼這將是沒有用的。但是,如果您在開發過程中嘗試攔截,那麼它可能非常有用。我經常使用這種技術來攔截哈希函數,以便我可以控制返回的哈希以用於測試目的。

如果您不知道,Valgrind主要用於查找內存泄漏和其他內存相關的錯誤。但底層技術基本上是一個x86模擬器。它模擬你的程序並攔截對malloc/free等的調用。好的是,你不需要重新編譯來使用它。

Valgrind有一個功能,他們稱爲函數包裝,它用於控制功能的截取。詳情請參閱Valgrind manual的第3.2節。你可以爲你喜歡的任何功能設置功能包裝。一旦調用被攔截,您提供的替代功能就會被調用。

3

如果你只是想打開什麼,你想看看ptrace()函數,或命令行strace實用程序的源代碼。如果你真的想攔截這個調用,也許會讓它做別的事情,我想你列出的選項--LD_PRELOAD或者內核模塊 - 是你唯一的選擇。

2

如果您只是爲了調試目的而執行此操作,請查看strace,它是構建在ptrace(2)系統調用之上的,它允許您在系統調用完成時掛接代碼。請參閱手冊頁的PTRACE_SYSCALL部分。

4

某些應用程序可以欺騙strace的/ ptrace的不跑,所以唯一的選擇我已經使用了SystemTap

的SystemTap可以截獲一堆系統調用如果需要的話,由於其通配符匹配。 Systemtap不是C,而是一種單獨的語言。在基本模式下,systemtap應該可以防止你做出愚蠢的事情,但它也可以在「專家模式」下運行,如果需要的話,它可以讓開發人員使用C.

它並不要求你修補你的內核(或者至少不應該),並且一旦模塊被編譯完成,你可以從一個測試/開發框中複製它,並將其插入(通過insmod)到一個生產環境中系統。

我還沒有找到一個linux應用程序,找到了解決方法/避免被systemtap抓住。

1

聽起來像你需要auditd。

Auditd允許通過日誌記錄全局跟蹤所有系統調用或對文件的訪問。您可以爲您感興趣的特定活動設置按鍵。