Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用LD\U PRELOAD通过exec*包装调用拦截execve()?_C_Process_Posix_Instrumentation_Ld Preload - Fatal编程技术网

如何使用LD\U PRELOAD通过exec*包装调用拦截execve()?

如何使用LD\U PRELOAD通过exec*包装调用拦截execve()?,c,process,posix,instrumentation,ld-preload,C,Process,Posix,Instrumentation,Ld Preload,我正试图通过execl()截取execve()。这是我的包装器调用(构建为共享库-libexec.so) 定义GNU源 #包括 #包括 #包括 #包括 #包括 静态int(*real_exec)(常量char*,char*const[],char*const[])=0; 静态void _属性_((构造函数))init(void){ real_exec=(int(*)(const char*,char*const[],char*const[])dlsym(RTLD_NEXT,“execve”);

我正试图通过
execl()
截取
execve()
。这是我的包装器调用(构建为共享库-
libexec.so

定义GNU源
#包括
#包括
#包括
#包括
#包括
静态int(*real_exec)(常量char*,char*const[],char*const[])=0;
静态void _属性_((构造函数))init(void){
real_exec=(int(*)(const char*,char*const[],char*const[])dlsym(RTLD_NEXT,“execve”);
}
int execve(常量char*arg,char*const argv[],char*const envp[]){
printf(“包装中的execve\n”);
返回(*real_exec)(arg、argv、envp);
}
这是我的执行程序

//run.c
#包括
#包括
#包括
#包括
int main(){
int-pid;
pid=fork();
如果(pid==0){
execl(“/usr/bin/date”,“date”,空);
}否则{
等待(空);
}
返回0;
}
好的,所有其他的
exec*
调用都是在
execve()上包装的。我还通过运行strace验证了上面的程序

> strace -f -e execve ./run
execve("./run", ["./run"], 0x7ffcefad6a28 /* 61 vars */) = 0
strace: Process 1491914 attached
[pid 1491914] execve("/usr/bin/date", ["date"], 0x7fff28393cc8 /* 61 vars */) = 0
Tuesday 16 February 2021 12:52:16 PM UTC
[pid 1491914] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1491914, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

但当我以下面的方式运行程序时

> LD_PRELOAD=/home/user/libexec.so ./run
电话没有被截获。i、 e我看不到包装的execve中的
\n
正在打印。 我错过了什么?如果我改为直接在
run.c
中调用
execve()
,它会工作


其次,
LD_PRELOAD
是否也遵循子进程?子代和子代的调用是否也被拦截?

简短回答:问题是,在上述实现中,“libexec”将只拦截主程序到execve之间的execve调用。execl和execve之间的“libc”内部调用不会被libexec包装器截获

长答覆: 使用LD_LIBRARY_PATH=libexec.so,将建立以下调用树:“main”->“libexec.so”->“libc.so”。libexec将拦截来自“main”的调用,但“libc.so”内的调用(例如execl->execve)不会被拦截(默认情况下)


解决方案是在libexec.so中添加“execl”的包装,其结构与已经实现的execve包装相同。

AFAIK,所有其他exec*调用都是wrapper over execve()系统调用。我还通过使用strace运行验证了上述程序。
-不一定。库函数可以直接使用
syscall
调用系统调用,而无需从库中调用其包装函数。和
strace
显示实际的系统调用,而不是调用的库函数。您的意思是
execl()
->
syscall(,…)
而不是
execl()
->
execve()
->
系统调用(,…)
?没错,但为了确保您需要检查标准库的源代码谢谢。还有,有没有办法拦截来自分叉进程(子进程)的调用?当然,只需在调用
exec()
之前使用
putenv()
添加
LD\u PRELOAD=yourlib。谢谢,这是针对
libc.so
的吗?因为我还尝试了对
malloc()
(为
malloc
-
libmalloc.so
构建了一个包装器共享库,并将其与
LD\u PRELOAD
一起使用),其中我的程序正在调用一个真正共享库的函数(它是动态链接的)该函数调用了malloc()
(我检查了该函数的源代码),它工作了。这是不正确的。例如,如果您拦截
malloc
,并从自己的
malloc
实现调用
printf
,您的程序将因堆栈溢出而崩溃,因为
printf
在内部调用
malloc
,它将调用自定义版本的
malloc
,而不是库版本。是的,我明白了。但这不是重点。我的程序只调用共享库中的函数,在我的
malloc
包装中没有
printf
。它立即返回
NULL
,导致库函数在我的程序中失败。这是对@dash-o的注释,他的答案是incorrect@qrdl啊好的,如果你能加上你的评论作为回答,我会接受的。