
Linux eBPF руткит с бэкдором, C2, внедрением библиотек, перехватом выполнения, возможностями персистентности и скрытности.
TripleCross — это руткит для Linux на основе eBPF, демонстрирующий наступательные возможности технологии eBPF.
TripleCross вдохновлён предыдущими разработками в этой области, в частности работами Джеффа Дилео на DEFCON 271, Пэта Хогана на DEFCON 292, Гийома Фурнье и Сильвена Афшена также на DEFCON 293, а также Boopkit Крис Нова4. Мы повторно используем и расширяем некоторые методы, впервые разработанные в этих предыдущих исследованиях наступательных возможностей технологии eBPF.
Этот руткит был создан для моей дипломной работы в UC3M. Более подробная информация о его конструкции представлена в документе диссертации.
Этот руткит предназначен исключительно для образовательных и академических целей. Программное обеспечение предоставляется «как есть», и авторы не несут ответственности за любой ущерб или проблемы, которые могут возникнуть при его использовании.
Не пытайтесь использовать TripleCross для нарушения закона. Неправильное использование предоставленного программного обеспечения и информации может привести к уголовной ответственности.
На следующем рисунке показана архитектура TripleCross и его модулей.
Библиотека сырых сокетов RawTCP_Lib, используемая для передачи данных руткита, является моей авторской разработкой и имеет собственный репозиторий.
В следующей таблице описаны основные файлы и каталоги исходного кода для упрощения навигации:
Данный исследовательский проект был протестирован в следующих средах:
| ДИСТРИБУТИВ | ЯДРО | GCC | CLANG | GLIBC | |
|---|---|---|---|---|---|
| ВЕРСИЯ | Ubuntu 21.04 | 5.11.0 | 10.3.0 | 12.0.0 | 2.33 |
Рекомендуем использовать Ubuntu 21.04, которая по умолчанию включает указанные версии программного обеспечения. В противном случае некоторые из возможных проблем описаны здесь.
Исходный код руткита компилируется с помощью двух Makefile.```
cd src make all
cd client make
Следующая таблица подробно описывает назначение каждого Makefile:
| MAKEFILE | КОМАНДА | ОПИСАНИЕ | РЕЗУЛЬТИРУЮЩИЕ ФАЙЛЫ |
| ------------- | ------------- | ------------- | ------------- |
| src/client/Makefile | make | Компиляция клиента руткита | src/client/injector |
| src/Makefile | make help | Компиляция программ для тестирования возможностей руткита, а также вредоносной программы и библиотеки модулей перехвата выполнения и внедрения библиотек соответственно | src/helpers/simple_timer, src/helpers/simple_open, src/helpers/simple_execve, src/helpers/lib_injection.so, src/helpers/execve_hijack |
| src/Makefile | make kit | Компиляция руткита с использованием библиотеки libbpf | src/bin/kit |
| src/Makefile | make tckit | Компиляция TC egress программы руткита | src/bin/tc.o |
### Установка
После того как файлы руткита созданы в каталоге src/bin/, необходимо последовательно загрузить программы *tc.o* и *kit*. В следующем примере бэкдор руткита будет работать в сетевом интерфейсе *enp0s3*:```
// TC egress program
sudo tc qdisc add dev enp0s3 clsact
sudo tc filter add dev enp0s3 egress bpf direct-action obj bin/tc.o sec classifier/egress
// Libbpf-powered rootkit
sudo ./bin/kit -t enp0s3
Существует два скрипта, packager.sh и deployer.sh, которые компилируют и устанавливают руткит автоматически, как это сделал бы злоумышленник в реальном сценарии атаки.
Выполнение packager.sh сгенерирует все файлы руткита в каталоге apps/.
Выполнение deployer.sh установит руткит и создаст файлы персистентности.
Эти скрипты сначала должны быть настроены со следующими параметрами для правильной работы модуля персистентности:
| SCRIPT | CONSTANT | DESCRIPTION |
|---|---|---|
| src/helpers/deployer.sh | CRON_PERSIST | Задание cron для выполнения после перезагрузки |
| src/helpers/deployer.sh | SUDO_PERSIST | Запись sudo для предоставления привилегий без пароля |
Руткит может перехватывать выполнение процессов, вызывающих системные вызовы sys_timerfd_settime или sys_openat. Это достигается перезаписью раздела глобальной таблицы смещений (GOT) в виртуальной памяти вызывающего процесса. Это приводит к выполнению вредоносной библиотеки (src/helpers/injection_lib.c). Библиотека запускает обратную оболочку (reverse shell) на машине злоумышленника, а затем возвращает поток выполнения исходной функции без сбоя процесса.
TripleCross готов обходить распространённые методы защиты ELF, включая:
Он также готов работать с кодом, совместимым с Intel CET.
Функциональность модуля можно проверить с помощью двух тестовых программ src/helpers/simple_timer.c и src/helpers/simple_open.c. В качестве альтернативы можно попытаться перехватить любой системный процесс (проверено и работает с systemd).
Конфигурация модуля задаётся с помощью следующих констант:
Принять обратную оболочку от машины злоумышленника можно с помощью netcat:``` nc -nlvp <ATTACKER_PORT>
### Внедрение библиотеки через перехват GOT
Техника, реализованная в TripleCross, состоит из 5 этапов:
#### Локализация GOT и адреса возврата
Руткит перехватывает системный вызов с помощью программы-трассировщика (tracepoint). Оттуда он находит адрес в секции GOT, который заглушка PLT использовала для вызова функции glibc, отвечающей за системный вызов.
Чтобы добраться до секции GOT, программа eBPF использует адрес возврата, сохраненный в стеке. Обратите внимание:
* .text выполняет *call* к .plt, поэтому *rip* сохраняется как *ret* в стеке.
* .plt выполняет *jump* к glibc через .got, поэтому дополнительный *rip* не сохраняется. Также он не изменяет и не сохраняет значение *rbp*.
* Glibc выполняет *syscall*, который не сохраняет *rip* в стеке, а сохраняет его в *rcx*.
<img src="https://assets.kitploit.com/production/public/readmes/5614/d216fa5b7b656bb52587027db28f3e3902fa8389d0b2944a1f7e870d6d2e6bee.jpg" float="left">
Поэтому, чтобы проверить из eBPF, является ли адрес в стеке адресом возврата, который приведет нас к нужному GOT, мы должны убедиться, что это адрес возврата заглушки PLT, использующей адрес GOT, по которому происходит переход к функции glibc, выполняющей системный вызов, который мы перехватили из eBPF.
Были реализованы два метода поиска адреса возврата:
* С помощью sys_timerfd_settime программа eBPF сканирует вперед, используя аргументы системного вызова.
* С помощью sys_openat программа eBPF сканирует, используя данные из структуры *pt_regs* точек трассировки для поиска адреса возврата.
<img src="https://assets.kitploit.com/production/public/readmes/5614/61217fb3fd84bec65cbbee906dd27860e5e1c211912cfe450ea4cf9051fa480b.png" float="left">
#### Локализация ключевых функций для шелл-кода
Шелл-код должен генерироваться динамически, чтобы обойти ASLR и PIE, которые изменяют адреса таких функций, как dlopen(), при каждом запуске программы.
<img src="https://assets.kitploit.com/production/public/readmes/5614/6cbb620495d8cb9711e499fd5b1ae9ea845c03d0c33019cf008b456a95d5ddd6.png" float="left">
#### Внедрение шелл-кода в кодовую пещеру
Кодовую пещеру можно найти с помощью реверс-инжиниринга ELF, если ASLR и PIE отключены, но обычно это не так. Программа eBPF отправляет запрос пользовательской программе руткита, которая использует файловую систему /proc, чтобы найти и записать в кодовую пещеру в секции .text (исполняемой).
<img src="https://assets.kitploit.com/production/public/readmes/5614/c7daea0eed684437b5c7d971d0f69f5aac9138861d44da36c5368be9f97666d1.png" float="left">
#### Перезапись секции GOT
В зависимости от того, активен ли Partial или Full RELRO в исполняемом файле, программа eBPF перезаписывает секцию GOT напрямую или с помощью файловой системы /proc.
<img src="https://assets.kitploit.com/production/public/readmes/5614/7e69ec2982ee8c77c39b42f364ab25e52c40d96890f7413b3afe04dde1b825c3.png" float="left">
#### Ожидание следующего системного вызова
Когда в перехваченной программе выполняется следующий системный вызов, секция PLT использует измененную секцию GOT, перехватывая поток выполнения, который перенаправляется на шелл-код в кодовой пещере. Шелл-код подготовлен так, чтобы программа не падала, и вызывает вредоносную библиотеку (*src/helpers/lib_injection.so*). Эта библиотека выполняет fork() и порождает обратный шелл на машине атакующего. После этого поток выполнения восстанавливается.
<img src="https://assets.kitploit.com/production/public/readmes/5614/4e780cbcba855fe11a55f6a34709d83d855a4235960b15b69470233147f04318.png" float="left">
## Бэкдор и C2
Бэкдор работает "из коробки" без необходимости какой-либо настройки. Бэкдором можно управлять удаленно с помощью клиентской программы руткита:
| АРГУМЕНТЫ КЛИЕНТА | ОПИСАНИЕ ДЕЙСТВИЯ |
| ------------- | ------------- |
| ./injector -c \<IP жертвы\> | Запускает псевдо-шелл в открытом виде, используя модуль перехвата выполнения |
| ./injector -e \<IP жертвы\> | Запускает зашифрованный псевдо-шелл, управляя бэкдором с помощью триггера на основе шаблона |
| ./injector -s \<IP жертвы\> | Запускает зашифрованный псевдо-шелл, управляя бэкдором с помощью многопакетного триггера (обоих типов) |
| ./injector -p \<IP жертвы\> | Запускает фантомный шелл, управляя бэкдором с помощью триггера на основе шаблона |
| ./injector -a \<IP жертвы\> | Дает команду руткиту активировать все программы eBPF |
| ./injector -u \<IP жертвы\> | Дает команду руткиту отключить все свои программы eBPF |
| ./injector -S \<IP жертвы\> | Демонстрирует, как бэкдор может скрыть сообщение от ядра (простой PoC) |
| ./injector -h | Отображает справку |
### Триггеры бэкдора
Действия отправляются бэкдору с помощью триггеров бэкдора, которые указывают бэкдору, какое действие выполнить, в зависимости от значения атрибута **K3**:
| ЗНАЧЕНИЕ K3 | ДЕЙСТВИЕ |
| ------------- | ------------- |
| 0x1F29 | Запрос на запуск зашифрованного соединения псевдо-шелла |
| 0x4E14 | Запрос на запуск соединения фантомного шелла |
| 0x1D25 | Запрос на загрузку и подключение всех программ eBPF руткита |
| 0x1D24 | Запрос на отключение всех программ eBPF руткита (кроме бэкдора) |
#### Триггер на основе шаблона
Этот триггер скрывает команду и информацию о клиенте, чтобы они были распознаны бэкдором, но в то же время выглядят достаточно случайными для внешнего сетевого наблюдателя. Он основан на триггере, использованном в недавно обнаруженном рутките АНБ [Bvp47](https://www.pangulab.cn/files/The_Bvp47_a_top-tier_backdoor_of_us_nsa_equation_group.en.pdf).
<img src="https://assets.kitploit.com/production/public/readmes/5614/58cec7ee2dbd89b6c7d71d60c006a1a98d7b9165b20bdbe006467a82d5dc30ab.png" float="left">
#### Многопакетный триггер
Этот триггер состоит из нескольких TCP-пакетов, в которых полезная нагрузка бэкдора скрыта в заголовках пакетов. Данная конструкция основана на имплантате ЦРУ [Hive](https://wikileaks.org/vault7/document/hive-DevelopersGuide/hive-DevelopersGuide.pdf), описанном в утечке Vault 7. Используется следующая полезная нагрузка:
<img src="https://assets.kitploit.com/production/public/readmes/5614/45a8348c3d366af4941d9cca845c281fc8c5a565353fc8fe3fb91350f39dd5f8.png" float="left">
Затем над указанной полезной нагрузкой вычисляется циклический XOR, и она делится на несколько частей в зависимости от режима, выбранного клиентом руткита. TripleCross поддерживает полезные нагрузки, скрытые в порядковом номере TCP:
<img src="https://assets.kitploit.com/production/public/readmes/5614/2b9d7fd46f7133e3eeda694e0b4791fbed2a51616b7d2f14e989a9e0e56af9e2.png" float="left">
И в порту источника TCP:
<img src="https://assets.kitploit.com/production/public/readmes/5614/1a6ea6da628a9902eaf55cc3c1549a2ecf26cba211275acdce6bc5491b34140c.png" float="left">
### Псевдо-шеллы бэкдора
Клиент может устанавливать псевдо-шеллы руткита — специальное соединение между руткитами «руткит-клиент», которое имитирует работу оболочки, позволяя атакующему удаленно выполнять команды Linux и получать результаты так, как если бы он выполнял их непосредственно на зараженной машине. В наш руткит встроено несколько псевдо-шеллов:
#### Псевдо-шелл в открытом виде
Эта оболочка создается после успешного выполнения модуля перехвата выполнения, который запускает вредоносный файл, устанавливающий соединение с клиентом руткита следующим образом:
<img src="https://assets.kitploit.com/production/public/readmes/5614/6495b5b62c33ae136b8c965658d9c5f501e609029bde7fcefe7266966f8effbb.png" float="left">
<img src="https://assets.kitploit.com/production/public/readmes/5614/5301e208d9853760eabdc14772c57a3639f28d71d050ee82d151bff93a76cedf.png" float="right">
#### Зашифрованный псевдо-шелл
Зашифрованный псевдо-шелл может быть запрошен клиентом руткита в любое время; он представляет собой TLS-соединение между руткитом и клиентом руткита. Внутри зашифрованного соединения используется протокол передачи для обмена командами и информацией, аналогичный тому, что используется в псевдо-шеллах в открытом виде.
Для запуска зашифрованного псевдо-шелла требуется, чтобы бэкдор прослушивал триггеры, которые могут быть как триггерами на основе шаблона, так и обоими типами многопакетных триггеров:
<img src="https://assets.kitploit.com/production/public/readmes/5614/d4929247af8895f78522f28c4ac8087e74d76b91320c67e0b37ea841cd8869d0.png" float="left">
<img src="https://assets.kitploit.com/production/public/readmes/5614/6e2a72d04028212a4917397b75b052a4bdf3c0529fb6c5e336b7fc0a06571728.png" float="right">
#### Фантомный шелл
Фантомный шелл использует комбинацию программ XDP и TC для преодоления ограничений eBPF в сети, в частности невозможности генерировать новые пакеты. Для этого бэкдор модифицирует существующий трафик, перезаписывая полезную нагрузку данными передачи C2. Исходные пакеты не теряются, поскольку TCP-ретрансляции через короткое время снова отправляют исходный пакет (без изменений).
Следующий протокол иллюстрирует трафик во время выполнения команды с использованием фантомного шелла:
<img src="https://assets.kitploit.com/production/public/readmes/5614/0aafe6b672757e4e9d37402c72ce14893a8a7f198030b2f2386df631c345d16b.png" float="left">
Фантомный шелл запрашивается клиентом руткита, который отправляет команду для выполнения бэкдором:
<img src="https://assets.kitploit.com/production/public/readmes/5614/e07dec48ff6a22e708b6d4b0d762473cc6483f065011cd6cdccdac49f12f916b.png" float="left">
После того как зараженная машина отправляет любой TCP-пакет, бэкдор перезаписывает его, и клиент отображает ответ:
<img src="https://assets.kitploit.com/production/public/readmes/5614/19bea585b78a0bb1d52aa7c63ff05a0111551a0cc767732775491641e1dec021.png" float="left">
## Модуль перехвата выполнения
В принципе, программа eBPF не может сама по себе запустить выполнение программы. Этот модуль показывает, как вредоносный руткит может использовать легитимные программы для выполнения вредоносного кода в пользовательском пространстве. Этот модуль достигает двух целей:
* Выполнение вредоносной пользовательской программы с использованием выполнения другой программы.
* Быть прозрачным для пользовательского пространства, то есть, если мы перехватываем выполнение программы так, чтобы запускалась другая, исходная программа также должна выполняться с минимальной задержкой.
Этот модуль работает путем перехвата системного вызова sys_execve(), изменяя его аргументы так, чтобы вместо него запускалась вредоносная программа (*src/helpers/execve_hijack.c*). Изменение выполняется таким образом, что вредоносная программа может затем выполнить исходную программу с исходными аргументами, чтобы не вызывать подозрений в пользовательском пространстве. Следующая диаграмма обобщает общую функциональность:
<img src="https://assets.kitploit.com/production/public/readmes/5614/601610696506e303f91a7957ec2a3d61f73f7d0e036430a9f67bd80a6f19b2d3.png" float="left">
Аргументы исходного вызова sys_execve() изменяются таким образом, чтобы исходные аргументы не терялись (с использованием argv[0]), и исходная программа могла быть выполнена после вредоносной:
<img src="https://assets.kitploit.com/production/public/readmes/5614/e483317a3bdac422cdfc49ca92acdcefe624ddceb5b2ed036ccec141c8d1e5e6.png" float="left">
Мы добавили пример тестовой программы (*src/helpers/simple_execve.c*) для тестирования модуля перехвата выполнения. Модуль также может перехватывать любой вызов в системе в зависимости от конфигурации:
| ИМЯ ФАЙЛА | КОНСТАНТА | ОПИСАНИЕ |
| ------------- | ------------- | ------------- |
| src/common/constants.h | PATH_EXECUTION_HIJACK_PROGRAM | Расположение вредоносной программы, которая будет запущена после успешного выполнения вызова sys_execve |
| src/common/constants.h | EXEC_HIJACK_ACTIVE | Деактивировать (0) или активировать (1) модуль перехвата выполнения |
| src/common/constants.h | TASK_COMM_RESTRICT_HIJACK_ACTIVE | Перехватывать любой вызов sys_execve (0) или только те, которые указаны в TASK_COMM_NAME_RESTRICT_HIJACK (1) |
| src/common/constants.h | TASK_COMM_NAME_RESTRICT_HIJACK | Имя программы, для которой перехватываются вызовы sys_execve |
После успешного перехвата модуль останавливается. Вредоносная программа *execve_hijack* будет ожидать запросов на открытый псевдо-шелл от клиента руткита.
## Персистентность руткита
После перезагрузки зараженной машины все программы eBPF будут выгружены из ядра, а пользовательская программа руткита будет завершена. Более того, даже если руткит сможет запуститься снова автоматически, он больше не будет иметь привилегий root, необходимых для повторного подключения программ eBPF. Модуль персистентности руткита направлен на решение двух задач:
* Автоматический запуск руткита без участия пользователя после перезагрузки машины.
* После того как руткит получил привилегии root при первом запуске на машине, он должен сохранить их даже после перезагрузки.
TripleCross использует два секретных файла, создаваемых в *cron.d* и *sudoers.d*, для реализации этой функциональности. Эти записи гарантируют, что руткит загружается автоматически и с полными привилегиями после перезагрузки. Эти файлы создаются и управляются сценарием *deployer.sh*:
<img src="https://assets.kitploit.com/production/public/readmes/5614/88500b779b9ad5ba771803900a8abfffd08f3a6be59518e690534779a4134cf8.png" float="left">
<img src="https://assets.kitploit.com/production/public/readmes/5614/5ae61ed98af6d7c8aa9448fed3de553712ffb5c63e95d98a6f4300ff407bce23.png" float="right">
Сценарий содержит две константы, которые необходимо настроить для пользователя, подлежащего заражению в целевой системе:
| СЦЕНАРИЙ | КОНСТАНТА | ОПИСАНИЕ |
| ------------- | ------------- | ------------- |
| src/helpers/deployer.sh | CRON_PERSIST | Задание cron, выполняемое после перезагрузки |
| src/helpers/deployer.sh | SUDO_PERSIST | Запись в sudo для предоставления привилегий без пароля |
## Стелс-режим руткита
Модуль персистентности основан на создании дополнительных файлов, но они могут быть со временем обнаружены владельцем системы или каким-либо программным обеспечением, поэтому существует риск их оставить в системе. Кроме того, файлы руткита необходимо хранить в каком-то месте, где они могут быть обнаружены.
Учитывая вышесказанное, модуль стелс-режима предоставляет следующие возможности:
* Полностью скрыть каталог от пользователя (чтобы мы могли спрятать внутри все файлы руткита).
* Скрыть определенные файлы в каталоге (нам нужно скрыть файлы персистентности, но мы не можем полностью скрыть каталоги *sudoers.d* или *cron.d*, так как они принадлежат нормальному функционированию системы).
Файлы и каталоги, скрываемые руткитом, могут быть настроены с помощью следующих констант конфигурации:
| ИМЯ ФАЙЛА | КОНСТАНТА | ОПИСАНИЕ |
| ------------- | ------------- | ------------- |
| src/common/constants.h | SECRET_DIRECTORY_NAME_HIDE | Имя скрываемого каталога |
| src/common/constants.h | SECRET_FILE_PERSISTENCE_NAME | Имя скрываемого файла |
По умолчанию TripleCross скрывает любые файлы с именем "*ebpfbackdoor*" и каталог с именем "*SECRETDIR*". Этот модуль активируется автоматически после установки руткита.
Техника, используемая для достижения этой функциональности, заключается во вмешательстве в аргументы системного вызова sys_getdents():
<img src="https://assets.kitploit.com/production/public/readmes/5614/7f928351c1c07e7b6a534846c5374788449e03455191cddf8c7f02af2c885852.png" float="left">
## Лицензия
Руткит TripleCross и клиент руткита распространяются под лицензией GPLv3. См. [LICENSE](https://github.com/h3xduck/TripleCross/blob/master/LICENSE).
Библиотека [RawTCP_Lib](https://github.com/h3xduck/RawTCP_Lib) распространяется под лицензией MIT.
Оригинальный текст диссертации и включенные в нее рисунки опубликованы под лицензией [Creative Commons BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/).
J. Dileo. Evil eBPF: Практическое злоупотребление внутриядерной средой выполнения байт-кода. DEFCON 27. слайды ↩
P. Hogan. Искажение реальности: создание и противодействие следующему поколению руткитов Linux с помощью eBPF. DEFCON 27. презентация ↩
G. Fournier and S. Afchain. eBPF, я думал, мы друзья! DEFCON 29. слайды ↩
| КАТАЛОГ | НАЗНАЧЕНИЕ |
|---|
| docs | Оригинальный документ диссертации |
| src/client | Исходный код клиента руткита |
| src/client/lib | Разделяемая библиотека RawTCP_Lib |
| src/common | Константы и конфигурация руткита. Также включает реализацию общих элементов для eBPF и пользовательской части руткита, таких как кольцевой буфер |
| src/ebpf | Исходный код eBPF-программ, используемых руткитом |
| src/helpers | Включает программы для тестирования функциональности нескольких модулей руткита, а также вредоносную программу и библиотеку, используемые в модулях перехвата выполнения и внедрения библиотек соответственно |
| src/libbpf | Содержит библиотеку libbpf, интегрированную с руткитом |
| src/user | Исходный код пользовательских программ, используемых руткитом |
| src/vmlinux | Заголовочные файлы с определением структур данных ядра (это рекомендуемый метод при использовании libbpf) |
| FILENAME |
|---|
| CONSTANT |
|---|
| DESCRIPTION |
|---|
| src/common/constants.h | TASK_COMM_NAME_INJECTION_ TARGET_TIMERFD_SETTIME | Имя процесса для перехвата при системном вызове sys_timerfd_settime |
| src/common/constants.h | TASK_COMM_NAME_INJECTION_ TARGET_OPEN | Имя процесса для перехвата при системном вызове sys_openat |
| src/helpers/injection_lib.c | ATTACKER_IP & ATTACKER_PORT | IP-адрес и порт машины злоумышленника |