有人告诉我如何阻止程序中的某些特定系统调用吗?我正在构建一个系统,它接受一段C源代码,用gcc编译并运行它。出于安全原因,我需要阻止已编译的程序调用某些系统调用。有没有办法做到这一点,从源代码级别(例如剥离gcc的头文件,检测恶意外部调用,......)到可执行级别?
已编辑#1:添加有关恶意电话的详细信息。
编辑#2:我的系统是GNU / Linux系统。
编辑#3:
我已经在几天内尝试了一些方法,这是我到目前为止得出的结论:
另一个是native client,我还没有尝试过,但由于项目和我的工作之间的共同点,我肯定会在不久的将来。
答案 0 :(得分:8)
正如其他人所指出的那样,程序不可能避免进行系统调用,他们会在整个地方使用C库。
但是,如果您的平台支持LD_PRELOAD机制(例如Linux),您可能会小心翼翼地使用LD_PRELOAD机制:您编写的共享库具有与C库中相同的符号名称,这些名称被称为而不是预期的libc函数。 (例如,Electric Fence在基于Debian的系统上构建为共享库,并拦截对malloc
,free
等的调用。)
我怀疑你可以使用这种机制来捕获或参数检查你不喜欢的任何libc函数的调用,也许还要注意那些你认为无条件安全的函数。然后,扫描已编译的可执行文件以查找与INT 80
对应的代码以捕获任何尝试进行原始系统调用(0xcd 0x80
- 尽管要注意误报)可能是合理的。但是我只是想了几分钟,我可能很容易错过一些东西,或者这可能会变得不切实际......
答案 1 :(得分:4)
您可以通过从包装器中分叉来运行已编译的程序,并使用Linux ptrace(2)工具拦截并检查程序调用的所有系统调用。
以下示例代码显示了运行/ usr / bin / w命令的包装器,打印了该命令调用的每个系统调用,并在尝试调用write(2)系统调用时终止该命令。
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <sys/syscall.h> #include <sys/reg.h> #define BAD_SYSCALL __NR_write int main(int argc, char *argv) { pid_t child; int status, syscall_nr; child = fork(); if (child == 0) { /* In child. */ ptrace(PTRACE_TRACEME, 0, NULL, NULL); execl("/usr/bin/w", NULL, NULL); // not reached } /* In parent. */ while (1) { wait(&status); /* Abort loop if child has exited. */ if (WIFEXITED(status) || WIFSIGNALED(status)) break; /* Obtain syscall number from the child's process context. */ syscall_nr = ptrace(PTRACE_PEEKUSER, child, 4 * ORIG_EAX, NULL); printf("Child wants to execute system call %d: ", syscall_nr); if (syscall_nr != BAD_SYSCALL) { /* Allow system call. */ printf("allowed.\n"); ptrace(PTRACE_SYSCALL, child, NULL, NULL); } else { /* Terminate child. */ printf("not allowed. Terminating child.\n"); ptrace(PTRACE_KILL, child, NULL, NULL); } } exit(EXIT_SUCCESS); }
您可以使用ptrace执行更强大的功能,例如检查和更改进程的地址空间(例如,获取和修改传递给系统调用的参数)。
可以在此Linux Journal Article及其follow-up中找到一个很好的介绍。
答案 2 :(得分:3)
你做不到。
即使是这个程序:
#include <stdio.h>
int main()
{
printf("Hello, World\n");
return 0;
}
进行至少一次系统调用(将字符串“Hello,World \ n”发送到标准输出)。系统调用是程序与外部世界交互的唯一方式。使用操作系统的安全模型来确保安全。
编辑此评论:
我的意思不是所有系统调用,而是恶意系统调用,例如execv()可用于执行擦除磁盘上数据的BASH脚本。
您的操作系统已经包含了阻止此类事件发生的机制。例如,为了使bash脚本消除您的数据,该进程必须已具有对该数据的写访问权。这意味着它必须由您或root启动。您唯一真正的选择是不要安装不值得信任的软件。
顺便说一句,根据您的平台,execv不一定是系统调用。在Linux上,它是真实系统调用的一个C库包装器(execve)。
答案 3 :(得分:1)
为了说明这是不可能的,以下程序:
int main() {
return 0;
}
使用strace
报告超过20次系统调用。调用包括open
(两次),这是您似乎想要阻止的一个调用。
答案 4 :(得分:1)
好吧,如果您只想阻止特定的调用,为什么不在编译之前只通过源代码执行grep?并拒绝使用不安全系统调用的程序。
答案 5 :(得分:1)
有些项目有类似的想法,你可以看看nacl:http://code.google.com/p/nativeclient/