当前位置:首页> 正文

关于C#:我如何截获linux sys调用?

关于C#:我如何截获linux sys调用?

how could I intercept linux sys calls?

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


您为什么/不想使用LD_PRELOAD技巧?

此处的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
 * 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方法是最好的方法,假设您的应用程序是相当标准的,并且实际上并不是恶意地试图通过的方法您的拦截。 (在这种情况下,您将需要其他技术之一。)


Valgrind可用于拦截任何函数调用。如果您需要在最终产品中拦截系统调用,则将无济于事。但是,如果您尝试在开发过程中进行拦截,那么它将非常有用。我经常使用此技术来拦截哈希函数,以便可以出于测试目的控制返回的哈希。

如果您不知道,Valgrind主要用于查找内存泄漏和其他与内存相关的错误。但是底层技术基本上是x86仿真器。它模拟您的程序并拦截对malloc / free等的调用。好处是,您无需重新编译即可使用它。

Valgrind具有一个称为功能包装的功能,该功能用于控制功能的拦截。有关详细信息,请参见Valgrind手册的3.2节。您可以为任何喜欢的功能设置功能包装。呼叫被拦截后,便会调用您提供的替代功能。


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

如果需要,由于其通配符匹配,Systemtap可以拦截大量系统调用。 Systemtap不是C,而是一种独立的语言。在基本模式下,systemtap应该阻止您执行愚蠢的事情,但是它也可以在"专家模式"下运行,如果需要的话,它可以退回到允许开发人员使用C的位置。

它不需要修补内核(至少不需要修补),并且一旦编译了模块,就可以从测试/开发盒中复制它,并将其插入(通过insmod)在生产系统上。

我还没有找到一个Linux应用程序,该应用程序已经找到解决/避免被systemtap捕获的方法。


如果您只想查看打开的内容,则需要查看ptrace()函数或命令行strace实用程序的源代码。如果您实际上是想拦截该调用,也许想让它执行其他操作,那么我认为您列出的选项-LD_PRELOAD或内核模块-是您唯一的选择。


听起来您需要审核。

审计允许通过日志全局跟踪所有系统调用或对文件的访问。您可以为您感兴趣的特定事件设置键。


如果仅出于调试目的而做,请查看strace,它位于ptrace(2)系统调用的顶部,可让您在完成系统调用后连接代码。请参见手册页的PTRACE_SYSCALL部分。


我没有语法可以通过LKM轻松地做到这一点,但是本文提供了您需要做的很好的概述:http://www.linuxjournal.com/article/4378

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

您可能还会看到,如果不需要构建新系统,是否可以使用inotify,systemtap或SELinux为您完成所有这些日志记录。


如果您确实需要解决方案,那么您可能会对可以完成此操作的DR rootkit感兴趣,请访问http://www.immunityinc.com/downloads/linux_rootkit_source.tbz2,有关该文章的文章位于http://www.theregister.co。 uk / 2008/09/04 / linux_rootkit_released /


可以选择使用SystemTap。

对于Ubuntu,请按照https://wiki.ubuntu.com/Kernel/Systemtap中的指示进行安装。

然后只需执行以下命令,您将监听所有openat syscall:

1
2
3
4
5
6
# stap -e 'probe syscall.openat { printf("%s(%s)
", name, argstr) }'
openat(AT_FDCWD,"
/dev/fb0", O_RDWR)
openat(AT_FDCWD,"
/sys/devices/virtual/tty/tty0/active", O_RDONLY)
openat(AT_FDCWD,"
/sys/devices/virtual/tty/tty0/active", O_RDONLY)
openat(AT_FDCWD,"
/dev/tty1", O_RDONLY)

展开全文阅读

相关内容