GCC, how to block system calls within the program?

Will someone tell me how to block some specific system calls within the program, please? I create a system that takes a piece of C source code, compiles it with gcc, and runs it. For security reasons, I need to prevent the compiled program from invoking some system calls. Is there a way to do this, starting from the source code level (for example, deleting gcc header files, detecting malicious external calls, ...) to the executable level?

Edited # 1: add details about malicious calls.

Edited # 2: My system is GNU / Linux.

Edited # 3:

I tried several methods for several days, and here are the conclusions that I have so far:

  • Scanning the source code does not solve the main problem, since you can always quite often dispute its source file.
  • "Overriding the C character" works well for libraries, but for system calls, I did not achieve what I wanted. This idea is not dead, however it makes a definite reason for me a lot of hacking time (gcc and / or ld).
  • De-escalation resolution works like a charm. I could use fakeroot or "guest" for this. This method is also the easiest to implement.

Another native client that I have not tried yet, but I will definitely be in the near future due to the common between the project and my work.

+5
source share
6 answers

, , , C .

, , LD_PRELOAD, (, Linux): , C, libc. (, " " Debian malloc, free .)

, libc, , , , , . , INT 80, raw syscalls (0xcd 0x80 - ). , -, ...

+8

, 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 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 .

+4

.

:

#include <stdio.h>

int main()
{
    printf("Hello, World\n");
    return 0;
}

( "Hello, World\n" ). - . .

:

, , . execv() BASH script, .

, . , , BASH script , . , root. - .

, execv . Linux C (execve).

+3

, , :

int main() {
    return 0;
}

20 , strace. open (), , .

+1

, , grep , ? , .

+1

All Articles