Ha-*_*yen 5 c gcc system-calls
有人告诉我如何在程序中阻止某些特定的系统调用吗?我正在构建一个系统,它接受一段C源代码,用gcc编译并运行它.出于安全原因,我需要阻止已编译的程序调用某些系统调用.有没有办法做到这一点,从源代码级别(例如剥离gcc的头文件,检测恶意外部调用,......)到可执行级别?
编辑#1:添加有关恶意电话的详细信息.
编辑#2:我的系统是GNU/Linux系统.
编辑#3:
我在几天内尝试了一些方法,这是我到目前为止得出的结论:
另一个是本机客户,我还没有尝试,但由于项目和我的工作之间的共同点,我肯定会在不久的将来.
正如其他人所指出的那样,程序不可能避免进行系统调用,他们会在整个地方使用C库.
但是,如果你的平台支持(如Linux)的你也许能够取得一些进展与谨慎使用LD_PRELOAD机制,:你写的具有相同符号的名称作为那些在C库,这是所谓的共享库,而不是在预期的libc功能.(例如,电栅栏被构建为在基于Debian的系统和截距共享库调用malloc,free等人)中
我怀疑你可以使用这种机制来捕获或参数检查你不喜欢的任何libc函数的调用,也许还要注意那些你认为无条件安全的函数.因此,扫描已编译的可执行文件以获取对应的代码可能是合理的,INT 80以便捕获任何尝试进行原始系统调用(0xcd 0x80- 但要注意误报).但是我只是给了这个想法,我可能很容易错过一些东西,或者这可能会变得不切实际......
您可以通过从包装器分叉它来运行编译的程序,并使用 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 孩子;
int 状态,syscall_nr;
孩子=叉();
如果(孩子== 0){
/* 在孩子。*/
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/usr/bin/w", NULL, NULL);
// 还没到
}
/* 在父级。*/
而 (1) {
等待(&状态);
/* 如果孩子已经退出,则中止循环。*/
if (WIFEXITED(status) || WIFSIGNALED(status))
休息;
/* 从子进程上下文中获取系统调用号。*/
syscall_nr = ptrace(PTRACE_PEEKUSER, child, 4 * ORIG_EAX, NULL);
printf("孩子想要执行系统调用 %d:", syscall_nr);
如果(syscall_nr != BAD_SYSCALL){
/* 允许系统调用。*/
printf("允许。\n");
ptrace(PTRACE_SYSCALL, child, NULL, NULL);
} 别的 {
/* 终止子进程。*/
printf("不允许。终止子进程。\n");
ptrace(PTRACE_KILL, child, NULL, NULL);
}
}
退出(退出成功);
}
您可以使用 ptrace 做更强大的事情,例如检查和更改进程的地址空间(例如,获取和修改传递给系统调用的参数)。
可以在这篇Linux 期刊文章及其后续文章中找到一个很好的介绍。
你不能。
甚至这个程序:
#include <stdio.h>
int main()
{
printf("Hello, World\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
至少进行一次系统调用(将字符串“Hello, World\n”发送到标准输出)。系统调用是程序与外界交互的唯一途径。使用操作系统的安全模型来确保安全。
为此评论编辑:
我的意思不是所有的系统调用,而是恶意的系统调用,例如 execv() 可用于执行 BASH 脚本,该脚本会清除磁盘上的数据。
您的操作系统已经包含阻止此类事情发生的机制。例如,为了让 bash 脚本清除您的数据,该进程必须已经对该数据具有写访问权限。这意味着它必须由您或 root 启动。您唯一真正的选择是不要安装不可信的软件。
顺便说一句,根据您的平台, execv 不一定是系统调用。在 Linux 上,它是真实系统调用 (execve) 的 C 库包装器。