Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #87, МАРТ 2006 г.

Системный шпионаж в *nix часть 1

Крис Касперски ака мыщъх

Хакер, номер #087, стр. 087-134-2


o контроль за динамически загружаемыми библиотеками осуществляется путем перехвата функций dlopen/dlsym, экспортируемыми libdl.so.x, но фактически реализованных в libc.so.x (там они называются _dl_open/_dl_sym);

o непубличные функции самой программы и статические библиотеки перехватываются путем внедрения команды jump thunk в их начало (естественно, оригинальное содержимое нужно где-то предварительно сохранить) с поиском по сигнатурам или с привязкой к фиксированным адресам;

* отсоединяемся от процесса через ptrace (PTRACE_DETACH/PT_DEATACH, pid, 0, 0), позволяя ему продолжить нормальное выполнение, но теперь уже с модифицированной GOT, вызывающей функции через наш хакерский thunk, который может протоколировать вызовы, "мухлевать" с аргументами или даже передавать управление подложным функциям;

Метод "модификации импорта" легко реализуется, надежен, но не освобожден от недостатков. В Windows функции ReadProcessMemory/WriteProcessMemory не требуют от процесса, чтобы он находился под отладкой, и подопытному приложению очень трудно им противостоять. Их Linux-аналоги являются частью библиотеки ptrace, обломать которую очень легко (см. мою статью "Методология защиты в мире UNIX", опубликованную в Хакере с год назад). К тому же подопытный процесс может вырваться из лап шпиона. Для этого ему достаточно породить дочерний процесс или сделать себе exec(), чтобы перезапуститься. В этом случае системный загрузчик перечитает исходный образ ELF-файла с диска, и все изменения в GOT'е будут потеряны. Чтобы этого не произошло, наш шпион должен следить за всеми потенциально опасными функциями, пускай и ценой усложнения реализации. И последнее (но самое главное) ограничение — шпионаж носит сугубо локальный характер и может контролировать только дочерние процессы или процессы, явно переданные ему на "съедение".

А вот другой популярный прием, называемый методом "подмены библиотеки", также позаимствованный из мира Windows:

* создаем "обертку" (wrapper) вокруг интересующей нас библиотеки, экспортирующей те же самые функции, что и она;

* оригинальную библиотеку переименовываем или размещаем в другом месте;

* функции-обертки определяют идентификатор вызывающего их процесса, и, если это действительно "их" процесс, совершают заранее запланированные действия (пишут вызов в log, подменяют аргументы или код возврата и т.д). Как определить id процесса? Это легко, ведь функции-обертки вызываются из контекста процесса, который их использует, и решение задачи сводится к выяснению идентификатора текущего процесса, возвращаемого функцией getpid();

* функция-обертка передает управление оригинальной функции основной библиотеки или своей собственной подложной функции;

За внешней простотой реализации такого подхода кроется целый ворох проблем. Создать обертки вокруг всех "системных" библиотек вручную практически нереально, и эту работу необходимо автоматизировать, написав несложный парсер so-файлов и кодогенератор. Необязательно генерировать готовый ELF-файл, проще создать Си-программу и откомпилировать ее с помощью gcc.

Назад на стр. 087-134-1  Содержание  Вперед на стр. 087-134-3