Как я могу перехватить вызовы Linux Linux? - PullRequest
13 голосов
/ 16 сентября 2008

Помимо трюка LD_PRELOAD и модулей ядра Linux, которые заменяют определенный системный вызов на предоставленный вами, есть ли возможность перехватить системный вызов (открытый, например), чтобы он сначала прошел через вашу функцию, прежде чем достигнет фактическое открытие?

Ответы [ 8 ]

17 голосов
/ 16 сентября 2008

Почему вы не можете / не хотите использовать трюк LD_PRELOAD ?

Пример кода здесь:

/*
 * File: soft_atimes.c
 * Author: D.J. Capelis
 *
 * Compile:
 * gcc -fPIC -c -o soft_atimes.o soft_atimes.c
 * gcc -shared -o soft_atimes.so soft_atimes.o -ldl
 *
 * Use:
 * LD_PRELOAD="./soft_atimes.so" command
 *
 * Copyright 2007 Regents of the University of California
 */

#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <bits/fcntl.h>

extern int errorno;

int (*_open)(const char * pathname, int flags, ...);
int (*_open64)(const char * pathname, int flags, ...);

int open(const char * pathname, int flags, mode_t mode)
{
    _open = (int (*)(const char * pathname, int flags, ...)) dlsym(RTLD_NEXT, "open");
    if(flags & O_CREAT)
        return _open(pathname, flags | O_NOATIME, mode);
    else
        return _open(pathname, flags | O_NOATIME, 0);
}

int open64(const char * pathname, int flags, mode_t mode)
{
    _open64 = (int (*)(const char * pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64");
    if(flags & O_CREAT)
        return _open64(pathname, flags | O_NOATIME, mode);
    else
        return _open64(pathname, flags | O_NOATIME, 0);
}

Из того, что я понимаю ... это в значительной степени трюк LD_PRELOAD или модуль ядра. Существует не так много промежуточного положения, если вы не хотите запустить его под эмулятором, который может перехватить вашу функцию или переписать код в самом двоичном файле, чтобы перехватить вашу функцию.

Предполагая, что вы не можете модифицировать программу и не можете (или не хотите) изменять ядро, подход LD_PRELOAD является лучшим, предполагая, что ваше приложение довольно стандартное и на самом деле не является тем, которое злонамеренно пытается чтобы пройти ваш перехват. (В этом случае вам понадобится один из других методов.)

7 голосов
/ 16 сентября 2008

Valgrind может использоваться для перехвата любого вызова функции. Если вам нужно перехватить системный вызов в вашем готовом продукте, то это будет бесполезно. Однако, если вы пытаетесь перехватить во время разработки, это может быть очень полезно. Я часто использовал эту технику для перехвата хеш-функций, чтобы я мог контролировать возвращаемый хеш для тестирования.

Если вы не знаете, Valgrind в основном используется для обнаружения утечек памяти и других ошибок, связанных с памятью. Но основная технология - это эмулятор x86. Он эмулирует вашу программу и перехватывает вызовы malloc / free и т. Д. Хорошо, что вам не нужно перекомпилировать его для использования.

В Valgrind есть функция, которую они называют Функция-оболочка , которая используется для управления перехватом функций. Подробнее см. Раздел 3.2 руководства *1019* Valgrind . Вы можете настроить перенос функций для любой функции, которая вам нравится. Как только вызов перехвачен, вызывается альтернативная функция, которую вы предоставляете.

5 голосов
/ 17 сентября 2008

Некоторые приложения могут обмануть strace / ptrace, чтобы они не запускались, поэтому единственный реальный вариант, который у меня был, - это использование systemtap

Systemtap может перехватывать кучу системных вызовов, если это необходимо из-за совпадения его подстановочного знака. Systemtap - это не C, а отдельный язык. В базовом режиме системная карта должна не позволять вам делать глупости, но она также может работать в «экспертном режиме», который позволяет разработчику использовать C, если это требуется.

Это не требует, чтобы вы исправляли ядро ​​(или, по крайней мере, не должны), и после компиляции модуля вы можете скопировать его из коробки тестирования / разработки и вставить (через insmod) в производственную систему .

Мне еще предстоит найти приложение linux, которое нашло способ обойти / избежать попадания в systemtap.

3 голосов
/ 16 сентября 2008

Если вы просто хотите посмотреть , что открыто, вам нужно взглянуть на функцию ptrace () или исходный код утилиты командной строки strace. Если вы действительно хотите перехватить вызов, чтобы, возможно, заставить его сделать что-то еще, я думаю, что перечисленные вами опции - LD_PRELOAD или модуль ядра - ваши единственные варианты.

2 голосов
/ 20 января 2011

Звучит так, как будто тебе нужен audd.

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

2 голосов
/ 17 сентября 2008

Если вы просто хотите сделать это для целей отладки, посмотрите на strace, который встроен в системный вызов ptrace (2), который позволяет подключать код после завершения системного вызова. См. Часть страницы руководства PTRACE_SYSCALL.

2 голосов
/ 16 сентября 2008

У меня нет синтаксиса, чтобы сделать это изящно с LKM, но в этой статье представлен хороший обзор того, что вам нужно сделать: http://www.linuxjournal.com/article/4378

Вы также можете просто пропатчить функцию sys_open. Начиная с строки 1084 файла / open.c, начиная с linux-2.6.26.

Вы также можете увидеть, если вы не можете использовать inotify, systemtap или SELinux, чтобы делать все это для вас без необходимости создавать новую систему.

1 голос
/ 16 сентября 2008

если вам действительно нужно решение, которое вас может заинтересовать в рутките DR, который выполняет именно это, http://www.immunityinc.com/downloads/linux_rootkit_source.tbz2 статья о нем находится здесь http://www.theregister.co.uk/2008/09/04/linux_rootkit_released/

...