代码之家  ›  专栏  ›  技术社区  ›  Vhaerun

如何拦截Linux系统调用?

  •  13
  • Vhaerun  · 技术社区  · 16 年前

    除了ldu preload技巧,以及用您提供的系统调用替换某个系统调用的Linux内核模块之外,是否有可能截获一个系统调用(例如open),以便它在实际打开之前首先通过您的函数?

    8 回复  |  直到 6 年前
        1
  •  1
  •   sztanpet    16 年前

    如果你真的需要一个解决方案,你可能会对rootkit博士感兴趣,因为他能做到这一点, http://www.immunityinc.com/downloads/linux_rootkit_source.tbz2 关于它的文章在这里 http://www.theregister.co.uk/2008/09/04/linux_rootkit_released/

        2
  •  17
  •   Matheus Santana Joan Esteban    6 年前

    为什么你不能/不想使用 LD_PRELOAD trick ?

    示例代码如下:

    /*
     * 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 u预加载技巧或内核模块。除非您想在一个模拟器下运行它,该模拟器可以捕获到您的函数,或者在实际二进制文件上重新编写代码,以捕获到您的函数,否则中间不会有太多内容。

    假设您不能修改程序,也不能(或不想)修改内核,那么ld_preload方法是最好的方法,假设您的应用程序相当标准,实际上并不是恶意试图通过拦截的方法。(在这种情况下,您将需要其他技术之一。)

        3
  •  7
  •   Andrew Langrick    16 年前

    Valgrind 可用于截获任何函数调用。如果您需要截获成品中的系统调用,那么这将没有用处。但是,如果您试图在开发期间拦截,那么它可能非常有用。我经常使用这种技术来截取散列函数,这样我就可以控制返回的散列来进行测试。

    如果您不知道,valgrind主要用于查找内存泄漏和其他与内存相关的错误。但基础技术基本上是一个x86模拟器。它模拟您的程序,拦截对malloc/free等的调用。好的是,您不需要重新编译来使用它。

    Valgrind有一个他们称之为 函数包装 用于控制函数的截取。见第3.2节 Valgrind manual 详情。您可以为您喜欢的任何函数设置函数包装。一旦调用被截获,您提供的备用函数就会被调用。

        4
  •  5
  •   user75240    16 年前

    有些应用程序可以欺骗strace/ptrace不运行,所以我唯一的选择是使用systemtap

    如果需要的话,SystemTap可以拦截大量系统调用,因为它的通配符匹配。SystemTap不是C,而是一种独立的语言。在基本模式下,SystemTap应该可以防止你做一些愚蠢的事情,但是它也可以在“专家模式”下运行,如果需要的话,可以让开发人员使用C。

    它不需要您对内核进行修补(或者至少不应该这样做),一旦编译了一个模块,您就可以从一个测试/开发框中复制它,并将它(通过insmod)插入到生产系统中。

    我还没有找到一个Linux应用程序,它找到了解决/避免被SystemTap捕获的方法。

        5
  •  3
  •   pjz    16 年前

    如果你只是想 打开后,您需要查看ptrace()函数或命令行strace实用程序的源代码。如果你真的想 拦截 这个调用,为了让它做些别的事情,我认为您列出的选项——ld_preload或内核模块——是您唯一的选项。

        6
  •  2
  •   DJ Capelis    16 年前

    我没有现成的LKM来优雅地完成这项工作的语法,但是本文提供了您需要做什么的一个很好的概述: http://www.linuxjournal.com/article/4378

    您也可以只修补sys_open函数。从Linux-2.6.26起,它从file/open.c的第1084行开始。

    您还可以看到,如果不必构建一个新的系统,就不能使用inotify、systemtap或selinux来为您完成所有这些日志记录。

        7
  •  2
  •   Johan Dahlin Idelic    16 年前

    如果您只是为了调试的目的而这样做,请查看Strace,它内置于ptrace(2)系统调用之上,它允许您在系统调用完成时挂接代码。请参见手册页的ptrace_Syscall部分。

        8
  •  2
  •   Troy Rose    13 年前

    听起来你需要试镜。

    auditd允许全局跟踪所有系统调用或对文件的访问,并进行日志记录。您可以为感兴趣的特定事件设置键。