GCC如何在程序中阻止系统调用?

Ha-*_*yen 5 c gcc system-calls

有人告诉我如何在程序中阻止某些特定的系统调用吗?我正在构建一个系统,它接受一段C源代码,用gcc编译并运行它.出于安全原因,我需要阻止已编译的程序调用某些系统调用.有没有办法做到这一点,从源代码级别(例如剥离gcc的头文件,检测恶意外部调用,......)到可执行级别?

编辑#1:添加有关恶意电话的详细信息.

编辑#2:我的系统是GNU/Linux系统.

编辑#3:

我在几天内尝试了一些方法,这是我到目前为止得出的结论:

  1. 扫描源代码并不能解决主要问题,因为人们总能很好地屏蔽他/她的C源文件.
  2. "覆盖C符号"适用于库,但对于系统调用,我没有达到我想要的效果.这个想法并没有死,但这样做肯定会让我花很多时间黑客攻击(gcc和/或ld).
  3. 许可减少就像魅力一样.我可以使用fakeroot或"访客"用户来执行此操作.这种方法也是最容易实现的.

另一个是本机客户,我还没有尝试,但由于项目和我的工作之间的共同点,我肯定会在不久的将来.

cra*_*cot 8

正如其他人所指出的那样,程序不可能避免进行系统调用,他们会在整个地方使用C库.

但是,如果你的平台支持(如Linux)的你也许能够取得一些进展与谨慎使用LD_PRELOAD机制,:你写的具有相同符号的名称作为那些在C库,这是所谓的共享库,而不是在预期的libc功能.(例如,电栅栏被构建为在基于Debian的系统和截距共享库调用malloc,free等人)中

我怀疑你可以使用这种机制来捕获或参数检查你不喜欢的任何libc函数的调用,也许还要注意那些你认为无条件安全的函数.因此,扫描已编译的可执行文件以获取对应的代码可能是合理的,INT 80以便捕获任何尝试进行原始系统调用(0xcd 0x80- 但要注意误报).但是我只是给了这个想法,我可能很容易错过一些东西,或者这可能会变得不切实际......

  • 可以在不使用任何库的情况下执行系统调用,因此如果您希望构建一个针对恶意用户的系统安全,则使用LD_PRELOAD是不够的. (3认同)

ot.*_*ot. 6

您可以通过从包装器分叉它来运行编译的程序,并使用 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 期刊文章及其后续文章中找到一个很好的介绍。


Jer*_*myP 5

你不能。

甚至这个程序:

#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 库包装器。

  • 既然您提到了文件系统权限,我通过以在该目录中没有写权限的自定义用户身份执行它来找到解决方案。我差点忘记了。谢谢:-D。 (2认同)