Writeup - Honeykeeper
Рабочий компьютер сотрудника был скомпрометирован в результате фишинговой атаки. По легенде задания злоумышленники использовали Linux-руткит eBee, распространяемый на подпольных «пчелиных» форумах.
Для анализа был предоставлен сжатый дамп оперативной памяти:
honeykeeper_dump.img.xz
Цель задания — исследовать дамп, обнаружить следы руткита и восстановить флаг.
Проверка и распаковка дампа
Сначала проверим целостность XZ-архива:
xz -t honeykeeper_dump.img.xz
Ошибок обнаружено не было.
Распаковываем дамп:
xz -dk honeykeeper_dump.img.xz
Определяем формат полученного файла:
file honeykeeper_dump.img
Результат показал, что перед нами не образ диска, а ELF core dump Linux x86-64 размером около 1,6 ГБ:
ELF 64-bit LSB core file, x86-64
Это полноценный снимок оперативной памяти виртуальной машины.
Первичный анализ строк
Для первоначального поиска индикаторов компрометации используем strings:
strings -a honeykeeper_dump.img | less
Также выполним поиск по названию предполагаемого руткита:
strings -a honeykeeper_dump.img | grep -i -E 'ebee|rootkit|bpf'
В памяти были обнаружены следующие строки:
bpf_prog_166a5b3876fbe624_eBeeKeys bpf_prog_a0c6dd9bd609151f_eBeeIngress bpf_prog_7c18515a1e8909af_eBeeEgress
Таким образом, в системе были загружены три подозрительные eBPF-программы:
По названиям можно предположить следующее назначение компонентовeBeeKeys - перехват нажатий клавиатурыeBeeIngress - обработка входящего сетевого трафикаeBeeEgress - перехват исходящего сетевого трафика
Следовательно, компрометация системы подтверждается.
Информация об исследуемой системе
В дампе удалось найти информацию об операционной системе и ядре:
Linux 6.17.0-35-generic Ubuntu 6.17.0-35.35-generic x86-64
Также были обнаружены имя пользователя и hostname:
USER=honeykeeper HOSTNAME=honeykeeper-pc
Для полноценного анализа Linux-дампа через Volatility требуется таблица символов, соответствующая конкретной версии ядра.
При попытке запуска стандартных Linux-плагинов Volatility без символов возникала ошибка:
Unsatisfied requirement: kernel.layer_name kernel.symbol_table_name
В дампе присутствовала подсказка:
rootkit or ebee lets go: https://ebee-deps-imqs01in.avitoctf.ru/
Вероятно, по этому адресу ранее располагались необходимые символы ядра или дополнительные материалы для анализа. Однако для нахождения флага оказалось достаточно ручного исследования памяти и структур eBPF.
Анализ функциональности eBee
В памяти были обнаружены названия структур и полей, относящихся к C2-каналу руткита:
c2_details enabled c2_key_logging crypto_key key_logging
Также присутствовали структуры пакетов:
c2_datapacket source data C2_NONE C2_KEYLOGGING keylog symbol salt
Из этого следует, что руткит реализует отдельный механизм передачи перехваченных нажатий клавиатуры.
Каждая запись кейлоггера содержит как минимум:
- зашифрованный символ
symbol; - значение
salt; - источник данных;
- идентификатор типа C2-пакета.
- При этом для шифрования используется поле
crypto_key.
Поиск флага в открытом виде
Первым делом проверим распространённые форматы флагов:
strings -a honeykeeper_dump.img | grep -Eio \
'avito\{[^}]+\}|flag\{[^}]+\}|ctf\{[^}]+\}'Результатов получено не было.
Это означало, что флаг:
- не хранится в памяти открытым текстом;
- либо находится в бинарной структуре;
- либо был зашифрован руткитом перед сохранением в eBPF-карте.
Основным объектом дальнейшего анализа стала программа eBeeKeys.
Поиск eBPF-карты кейлоггера
Рядом со структурами eBPF-программ были обнаружены ссылки на используемые карты.
Особый интерес представляла карта:
c2_databus
Она использовалась как буфер для передачи данных между компонентами руткита и содержала записи типа c2_datapacket.
Внутри записей находились значения:
symbol salt
Также в конфигурационной структуре руткита было найдено значение криптографического ключа:
crypto_key = 0x31
После сопоставления нескольких записей стало понятно, что каждый символ зашифрован операцией XOR.
Формула расшифровки:
plain_symbol = encrypted_symbol ^ salt ^ crypto_key
Для найденного экземпляра руткита:
plain_symbol = encrypted_symbol ^ salt ^ 0x31
Расшифровка кейлогов
Для автоматической расшифровки записей можно использовать следующий Python-код:
CRYPTO_KEY = 0x31
def decrypt_symbol(encrypted_symbol: int, salt: int) -> int:
return encrypted_symbol ^ salt ^ CRYPTO_KEY
records = [
# (encrypted_symbol, salt)
# Значения извлекаются из записей c2_datapacket карты c2_databus.
]
result = bytearray()
for encrypted_symbol, salt in records:
symbol = decrypt_symbol(encrypted_symbol, salt)
result.append(symbol)
print(result.decode("utf-8", errors="replace"))После расшифровки и восстановления правильного порядка элементов очереди была получена следующая последовательность пользовательского ввода:
keeper<TAB>avito{eBeepf_is_awes8me_4_ev3ryth1ng}<ENTER>Вероятно, пользователь вводил логин keeper, нажимал Tab, после чего вводил пароль или секретное значение.
Этим секретным значением и являлся флаг.
Дополнительные индикаторы компрометации
В дампе также были найдены сетевые индикаторы:
https://ebee-deps-imqs01in.avitoctf.ru/ http://honey-crm:8000/alert.html 192.168.122.1
В журнале ядра присутствовала запись:
apparmor="WARN" dest="https://ebee-deps-imqs01in.avitoctf.ru/" comm="firefox" scope="network" tracer="bpftaint"
Для страницы honey-crm:8000/alert.html был обнаружен заголовок:
Security Alert
Вероятно, данная страница использовалась как часть фишингового сценария. Пользователь перешёл на неё и ввёл учётные данные, которые были перехвачены компонентом eBeeKeys.