我试图拦截所有的“syscall“为我的代码。我能够接收调用,但由于某种原因,我的实现的syscall是不等价的,因为在某些时候,程序崩溃,如果我激活的替代,而它的工作没有替代。
我这样做的原因是为了更好地理解我的程序中的哪些调用(及其依赖项)使用了哪些系统调用。我知道我可以使用诸如ptrace之类的东西,但现在对我来说,这真的是更多地理解为什么这不起作用。这是在arm64 Linux上运行的。
下面是我的系统调用替换实现:
long syscall(long number, ...){
printf("Intercepted syscall: %lu\n", number);
va_list original_args;
va_start(original_args, number);
long (*original_syscall)(long number, ...) = NULL;
original_syscall = (long (*)(long, ...))dlsym(RTLD_NEXT, "syscall");
long result = original_syscall(number, original_args);
va_end(original_args);
return result;
}
字符串
这里的日志:
Intercepted syscall: 178
Intercepted syscall: 178
Intercepted syscall: 178
Intercepted syscall: 178
Intercepted syscall: 178
Intercepted syscall: 57
Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 3606 (Thread-2)
型
1条答案
按热度按时间w1e3prcc1#
你想做的事情在C中并不容易做到,你必须手动解析参数列表(因为没有标准的方法将
va_list
重定向到可变参数函数)。使用汇编(未测试)可能更容易:
字符串
这个想法是你保持参数列表不变(保留所有可能的寄存器参数
x0
-x7
),并直接跳转到原始系统调用函数(通过br
)。由于返回地址已经在x30
中,因此函数将返回给我们的调用者而不是我们。这是一个优化,将already apply编译为 Package 器,但不幸的是,没有办法将varargs列表转发到C中的另一个可变参数函数。正如@stark提到的,
printf
可能会执行write
,这可能会导致无限递归(特别是因为stdout
是行缓冲的,\n
会刷新它)。唯一真实的“安全”的地方,你可以尝试记录你的数据是内存(并尝试稍后写入),但这本身会带来很多麻烦,所以我不推荐它。