Метод перехвата активности файловой системы дочернего процесса

У меня есть небольшое приложение командной строки, написанное на C, которое действует как оболочка/пусковая установка для других программ (например, xargs). Приложение написано для компиляции на FreeBSD/Linux (через fork()/exec()) и Windows (CreateProcess()). В дополнение к возможности перехватывать, внедрять или иным образом манипулировать аргументами командной строки для дочернего приложения, мне было интересно, есть ли простой способ перехватить активность файловой системы дочерней программы (или ее дочерних элементов и т. д.). Меня в основном интересуют только имена файлов, доступные для чтения или записи, но не содержимое указанных файлов, и я хотел бы, чтобы перехват был как можно более легким.

При поиске в Google некоторых релевантных ключевых слов, приведенных выше, кажется, что в Win32 есть много способов сделать это. От драйверов фильтров файловой системы до подделки заголовков таблицы импорта PE. Ни один из них не кажется тривиальным или чем-то, что я мог бы содержать в исполняемом файле моей программы-оболочки (например, для большинства из них потребуются дополнительные библиотеки DLL или файлы драйверов вместе с основным исполняемым файлом). Кроме того, я хотел бы, чтобы это работало на Windows XP через 7, если это возможно , без необходимости обхода UAC или других дельт платформы. Это мой дочерний процесс, поэтому я полагаю, что смогу безопасно отслеживать его активность :)

В Linux есть функция inotify(), но она отслеживает общий доступ к файловой системе без учета ТОЛЬКО моих дочерних процессов. То же самое относится и к kqueue() FreeBSD. Они также не работают в случаях SMP, когда несколько экземпляров оболочки могут запускать разные программы, и каждый из них должен различать действия своей дочерней файловой системы друг от друга.

Я, безусловно, был бы признателен за любые предложения, которые может предложить сообщество SO.


person Optigrab    schedule 23.06.2009    source источник


Ответы (2)


Напишите библиотеку «interposer», которая перехватывает ваш fopen и устанавливает переменную среды LD_PRELOAD для всех дочерних процессов. Это работает с динамически подключаемыми библиотеками тыс.

Пример того, как это сделать, можно найти здесь: http://developers.sun.com/solaris/articles/lib_interposers.html и http://lists.debian.org/debian-powerpc/2004/11/msg00039.html показана частичная реализация интерпозера fopen().

person rasjani    schedule 23.06.2009
comment
Если вы хотите пойти по этому пути, вам, вероятно, лучше перехватывать системные вызовы, которые обращаются к файловой системе. open(), creat(), chmod(), exec*(). Могут быть и другие. - person Keith Smith; 23.06.2009
comment
^ правда, если вы напишете такую ​​оболочку с реализацией для open(), fopen(), fdopen(), freopen(), это должно охватывать довольно много случаев. - person rasjani; 23.06.2009
comment
Этот подход кажется самым простым, единственным недостатком которого является то, что мне нужно иметь отдельный файл общей библиотеки «перехватчик» в дополнение к моему исполняемому файлу. Есть ли механизм, эквивалентный LD_PRELOAD на платформах Win32? - person Optigrab; 24.06.2009
comment
Optigrab: я не знаком с разработкой Windows, но нашел эту статью в Википедии, в которой описываются 4 способа архивирования одного и того же: en. wikipedia.org/wiki/DLL_injection - person rasjani; 24.06.2009
comment
Спасибо всем за указатели. В *nix я успешно использую LD_PRELOAD, а в Win32 я нашел здесь отличную статью о внедрении DLL: codeproject.com/KB/threads/completeinject.aspx Единственным недостатком этого подхода является необходимость наличия дополнительного файла .so/.dll рядом с моим исполняемым файлом. Я полагаю, что мог бы автоматически извлечь его, использовать и удалить из моего исполняемого файла, но я оставлю это на другой день. - person Optigrab; 28.06.2009
comment
Я просто хочу добавить одну вещь. Этот подход не полностью защищен от несанкционированного доступа. Это означает, что если дочерний процесс активно пытается избежать вашего внимания/ограничений, он может это сделать. - person Stan; 30.06.2009

Единственное предложение, которое я бы сделал, это использовать strace (системные вызовы и сигналы трассировки), хотя это скорее инструмент отладки, и он влияет на производительность отслеживаемого процесса.

strace -f -e trace=file -o <output-file> <cmd-line>

-f - follow forks
-e trace=file - will output system calls related to the file-system
-o <output-file>

ИМХО - если вы познакомитесь с strace, это всегда полезный инструмент в арсенале.

person Beano    schedule 23.06.2009
comment
Спасибо, Беано. Я использовал strace, но не знал о ярлыке -e trace=file... очень удобно. К сожалению, потери производительности немного высоки, так как под капотом используется ptrace(2). - person Optigrab; 24.06.2009