修改strace以捕获并替换打开的系统调用中的文件名
我试图修改strace以捕获文件open syscall并更改实际打开的文件。例如,用户尝试: 打开(OUT,“>input.txt”),但真正要打开的文件是“input.txt.version1” 通过使用ptrace(ptrace_POKEDATA、pid、addr、laddr),当新名称的长度与旧名称的长度完全相同时,我取得了一些成功。我正在拦截open.c中的open调用,并将util.c中的umoven修改为poke而不是peek来替换字符 但是,当新文件名较长时,此操作将失败,因为它可能超出原始文件名数组的长度。我真正需要做的是用一个指向我自己字符串的新指针替换指向char数组的指针 文件名位于tcp->u_arg[0]中,这是x86系统上的rdi寄存器。我尝试过以下几种变体,但运气不佳:修改strace以捕获并替换打开的系统调用中的文件名,c,linux,strace,ptrace,C,Linux,Strace,Ptrace,我试图修改strace以捕获文件open syscall并更改实际打开的文件。例如,用户尝试: 打开(OUT,“>input.txt”),但真正要打开的文件是“input.txt.version1” 通过使用ptrace(ptrace_POKEDATA、pid、addr、laddr),当新名称的长度与旧名称的长度完全相同时,我取得了一些成功。我正在拦截open.c中的open调用,并将util.c中的umoven修改为poke而不是peek来替换字符 但是,当新文件名较长时,此操作将失败,因为它
struct user_regs_struct x86_64_r;
uint64_t *const x86_64_rdi_ptr = (uint64_t *) &x86_64_r.rdi;
ptrace(PTRACE_POKEDATA, tcp->pid, x86_64_rdi_ptr, &newPath);
如何用任意长度的新路径替换文件名?
只使用ptrace而不是strace的修改也可以。strace已经处理了很多其他问题。不是
ptrace
,也不是strace
,但是您可以通过LD\u PRELOAD
钩住open
功能来实现这一点
编辑:根据@JonathanLeffler的评论,我试图修复hook函数原型,以处理mode参数(如果给定的话),我不能100%确定这将始终有效,但它应该给出如何做到这一点的想法
胡克
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h> //mode_t
#include <stdarg.h> //va_arg
typedef int (*pfn_open_t)(const char *pathname, int flags, mode_t mode);
int open(const char *pathname, int flags, ...)
{
pfn_open_t o_open;
va_list val;
mode_t mode;
o_open = (pfn_open_t)dlsym(RTLD_NEXT,"open");
// Extract vararg (mode)
va_start(val, flags);
mode = va_arg(val, mode_t);
va_end(val);
if(strcmp(pathname, "origfile") == 0)
{
puts("opening otherfile\n");
return o_open("otherfile", flags, mode);
}
else
{
printf("opening %s\n", pathname);
return o_open(pathname,flags, mode);
}
}
使用钩子运行程序:
$ LD_PRELOAD=path/to/libhook.so myprogram
选民:请解释一下,为什么要这样做?听起来像是恶意软件。@Olaf它可能对调试有用……这样做有很多正当的理由。(不修改原始程序的测试和兼容性就是其中之一)@Olaf这是用于自动版本控制,而不需要像问题中所建议的那样修改原始程序。这是一种有趣的方法。我会回去做的。我假设这可以用于任何系统调用?挑剔:您的
pfn\u open\u t
类型与open()
的官方原型不匹配,后者有一个…
参数,您很清楚。如果标志包括O_CREAT,您需要传递第三个参数。@JonathanLeffler-谢谢您指出这一点。我在发布答案时忽略了这个问题,但这是一个需要解决的重要问题。我会试着把它修好。如果你有一个解决方案在手-请随时编辑我的答案,或张贴它单独。我很高兴看到:)你所拥有的和我所用的很接近。由于用户可能不会通过mode\u t
,除非flags
包含O\u CREAT,我可能会:mode\u t mode=0666;如果(flags&O_create){va_list args;va_start(args,flags);mode=va_arg(args,int);va_end(args);}
仅在(应该)提供时收集它。你所得到的通常会起作用,尽管模式值有时可能有点古怪——但这在形式上并不重要。“细化”(名义上的技巧——但实际上大部分都是繁忙的工作,其优势有限或没有优势)是根据O_CREAT进行函数调用。例如,此解决方案在某些情况下有效(“touch origfile”),但在其他情况下失败:perl-e“open(in,“>origfile”);”。在我接受这个答案之前,我需要这个方法在所有情况下都有效,或者至少理解其中的差异。
$ LD_PRELOAD=path/to/libhook.so myprogram