GCC, как к блокировке звонит в рамках программы?

Кто-либо говорит мне, как заблокировать некоторые определенные системные вызовы в рамках программы? Я создаю систему, которая берет часть исходного кода C, компилирует его с gcc и выполняет его. Из соображений безопасности я должен препятствовать тому, чтобы скомпилированная программа назвала некоторые системные вызовы. Там какой-либо путь состоит в том, чтобы сделать это, от уровня исходного кода (например, лишение заголовочных файлов gcc, обнаружив злонамеренные внешние вызовы...) к исполняемому уровню?

Отредактированный № 1: Добавьте детали о злонамеренных вызовах.

Отредактированный № 2: Моей системой является GNU/Linux один.

Отредактированный № 3:

Я попробовал некоторые методы в течение нескольких дней и здесь являюсь заключениями, которые я имею до сих пор:

  1. Сканирование исходного кода не решает основную проблему, так как каждый всегда может obsfucate его исходный файл C вполне хорошо.
  2. "Переопределение C символ" работает хорошо на библиотеки, но на системные вызовы я не достиг того, что я хотел. Эта идея не мертва, однако, делание этого определенно вызвало бы меня много времени, взломав (gcc и/или ld).
  3. Уменьшение разрешения работает как очарование. Я мог использовать fakeroot или "гостевого" пользователя, чтобы сделать это. Этот метод является также самым легким реализовать.

Другой является собственным клиентом, который я еще не судил, но я определенно был бы в ближайшем будущем из-за общего между проектом и моей работой.

5
задан Ha-Duong Nguyen 3 June 2010 в 13:28
поделиться

6 ответов

Как отмечали другие, программа не может избежать выполнения системных вызовов, они повсюду размещают библиотеку C.

Однако вы можете добиться некоторого прогресса при осторожном использовании механизма LD_PRELOAD, если ваша платформа поддерживает его (например, Linux): вы пишете общую библиотеку с теми же именами символов, что и в библиотеке C, которые называются вместо предполагаемых функций libc. (Например, Electric Fence построен как разделяемая библиотека в системах на основе Debian и перехватывает вызовы malloc , free и др.)

Я подозреваю, что вы могли бы использовать этот механизм для перехвата или проверки аргументов любых функций libc, которые вам не нравятся, и, возможно, для отметки тех, которые вы считаете безусловно безопасными. Тогда было бы разумно просканировать скомпилированный исполняемый файл на предмет кода, соответствующего INT 80 , чтобы уловить любые попытки сделать необработанные системные вызовы ( 0xcd 0x80 - хотя остерегайтесь ложных срабатываний). Однако я подумал только несколько минут, я легко мог что-то пропустить, или это могло оказаться непрактичным ...

8
ответ дан 18 December 2019 в 09:05
поделиться

Что ж, если вы просто хотите заблокировать определенные вызовы, почему бы просто не выполнить команду grep через исходный код, прежде чем пытаться его скомпилировать? И отклоняйте программы, использующие небезопасные системные вызовы.

1
ответ дан 18 December 2019 в 09:05
поделиться

В некоторых проектах есть похожая идея, вы можете взглянуть на nacl: http://code.google.com/p/nativeclient/

1
ответ дан 18 December 2019 в 09:05
поделиться

Нельзя.

Даже эта программа:

#include <stdio.h>

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

делает по крайней мере один системный вызов (чтобы послать строку "Hello, World\n" в стандартный аут). Системные вызовы - это единственный способ взаимодействия программы с внешним миром. Используйте модель безопасности операционной системы для обеспечения безопасности.

Отредактировано для этого комментария:

Я имел в виду не все системные вызовы, а вредоносные системные вызовы, например, execv() может быть использован для выполнения BASH-скрипта, который сотрет мои данные на диске.

Ваша операционная система уже содержит механизмы, предотвращающие подобные вещи. Например, чтобы сценарий bash мог стереть ваши данные, процесс уже должен иметь доступ на запись к этим данным. Это означает, что он должен быть запущен вами или root. Ваш единственный реальный выход - не устанавливать ненадежное программное обеспечение.

Кстати, в зависимости от вашей платформы, execv не обязательно является системным вызовом. В Linux это обертка библиотеки C для настоящего системного вызова (execve).

3
ответ дан 18 December 2019 в 09:05
поделиться

Вы можете запустить скомпилированную программу, разветвив ее из оболочки и используя средство 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 и в ее продолжении .

4
ответ дан 18 December 2019 в 09:05
поделиться

Чтобы проиллюстрировать, что это невозможно, следующая программа:

int main() {
    return 0;
}

выполняет более 20 системных вызовов, как сообщается с использованием strace . Вызовы включают open (дважды), что является одним из вызовов, которые вы, кажется, хотите заблокировать.

1
ответ дан 18 December 2019 в 09:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: