Vha*_*run 14 c linux hook redirect system-calls
除了LD_PRELOAD技巧,以及用你提供的系统调用取代某个系统调用的Linux内核模块之外,是否有可能拦截一个系统调用(例如打开),以便在它到达实际打开之前首先通过你的函数?
DJ *_*lis 18
为什么不能/不想使用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 <sys/types.h>
#include <bits/fcntl.h>
#include <stddef.h>
extern int errorno;
int __thread (*_open)(const char * pathname, int flags, ...) = NULL;
int __thread (*_open64)(const char * pathname, int flags, ...) = NULL;
int open(const char * pathname, int flags, mode_t mode)
{
if (NULL == _open) {
_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)
{
if (NULL == _open64) {
_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);
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解......它几乎是LD_PRELOAD技巧或内核模块.除非你想在一个模拟器下运行它,它可能会陷入你的函数或者在实际的二进制文件上重写代码来捕获你的函数,所以没有很多中间结构.
假设你不能修改程序而不能(或者不想)修改内核,LD_PRELOAD方法是最好的方法,假设你的应用程序是相当标准的,并且实际上并不是那个恶意试图过去的方法你的拦截.(在这种情况下,您将需要其他技术之一.)
Tim*_*mmm 13
首先让我们消除一些其他人给出的非答案:
LD_PRELOAD
。是的,你LD_PRELOAD
在问题中说了“此外......”,但显然这对某些人来说还不够。这不是一个好的选择,因为它仅在程序使用 libc 时才有效,但情况不一定如此。然而,这里还没有提到其他可能性。请注意,我对所有这些东西都很陌生,还没有尝试过任何东西,所以我可能对某些事情是错误的。
理论上,您可以使用某种自定义加载程序来重写系统调用指令以跳转到自定义处理程序。但我认为实施起来绝对是一场噩梦。
kprobes是某种内核检测系统。它们只有对任何内容的只读访问权限,因此您不能使用它们来拦截系统调用,而只能记录它们。
ptrace是 GDB 等调试器用来进行调试的 API。有一个PTRACE_SYSCALL
选项可以在系统调用之前/之后暂停执行。从那里您可以像 GDB 一样做几乎任何您喜欢的事情。这是一篇有关如何使用 ptrace 修改系统调用参数的文章。然而它显然有很高的开销。
Seccomp是一个旨在允许您过滤系统调用的系统。您无法修改参数,但可以阻止它们或返回自定义错误。Seccomp 过滤器是 BPF 程序。如果您不熟悉,它们基本上是用户可以在内核空间虚拟机中运行的任意程序。这避免了用户/内核上下文切换,这使得它们比 ptrace 更快。
虽然您无法直接从 BPF 程序修改参数,但您可以返回SECCOMP_RET_TRACE
,这将触发ptrace
ing 父级中断。因此,它基本上是相同的,PTRACE_SYSCALL
只是您需要在内核空间中运行一个程序来决定是否要根据其参数实际拦截系统调用。因此,如果您只想拦截一些系统调用(例如open()
使用特定路径),它应该会更快。
我认为这可能是最好的选择。这是与上述同一作者撰写的一篇关于它的文章。请注意,他们使用经典的 BPF 而不是 eBPF,但我想您也可以使用 eBPF。
编辑:实际上你只能使用经典的BPF,而不能使用eBPF。LWN有一篇关于它的文章。
以下是一些相关问题。第一篇绝对值得一读。
这里还有一篇关于通过 ptrace 操作系统调用的好文章。
小智 7
Valgrind可用于拦截任何函数调用.如果您需要拦截成品中的系统调用,那么这将是没有用的.但是,如果您在开发期间尝试拦截,那么它可能非常有用.我经常使用这种技术来拦截散列函数,以便我可以控制返回的散列以进行测试.
如果您不知道,Valgrind主要用于查找内存泄漏和其他与内存相关的错误.但底层技术基本上是一个x86模拟器.它模拟你的程序并拦截对malloc/free等的调用.好的是,你不需要重新编译就可以使用它.
Valgrind有一个功能,他们称之为功能包装,用于控制功能的拦截.有关详细信息,请参见Valgrind手册的第3.2节.您可以为任何您喜欢的功能设置功能包装.拦截调用后,将调用您提供的替代函数.
小智 5
有些应用程序可以欺骗strace/ptrace不运行,所以我唯一真正的选择就是使用systemtap
如果需要由于其通配符匹配,Systemtap可以拦截一堆系统调用.Systemtap不是C,而是一种单独的语言.在基本模式下,systemtap应该阻止你做愚蠢的事情,但它也可以在"专家模式"下运行,如果需要,可以回退到允许开发人员使用C.
它不需要你修补你的内核(或者至少不应该),并且一旦编译了一个模块,你就可以从测试/开发盒中复制它并在生产系统上插入它(通过insmod).
我还没有找到一个已经找到解决方法的linux应用程序/避免被systemtap捕获.
如果您确实需要一个解决方案,您可能会对实现此目的的 DR rootkit 感兴趣,http://www.immunityinc.com/downloads/linux_rootkit_source.tbz2有关它的文章位于http://www.theregister.co。英国/2008/09/04/linux_rootkit_released/
归档时间: |
|
查看次数: |
17497 次 |
最近记录: |