Самостоятельное распространение программ‑вымогателей в локальной сети в качестве сетевого червя давно уже не является чем‑то уникальным и новым. Программа‑вымогатель WannaCry в 2017 году распространялась в локальной сети, используя уязвимость SMBv1 MS17–010. Для этого создатели WannaCry использовали эксплойт EternalBlue и бэкдор DoublePulsar из публикации хакерской группировки The Shadow Brokers «Lost in Translation». Но стоит отметить, это всё же немного другая история, отличная от современных RaaS.

В настоящее время уязвимости такого плана и масштаба в арсенале вымогателей появляются не часто, но всегда есть возможность распространения с помощью доступных легитимных механизмов. Для реализации таких способов необходимо наличие корректных учетных данных, которые партнеры RaaS в большинстве случаев и так похищают на этапе постэксплуатации. Программы‑вымогатели LockBit используют групповые политики для своего распространения в локальной сети, а в образцах BlackCat (APLHV) для самораспространения используется содержащаяся в них в зашифрованном и сжатом виде утилита Sysinternals PsExec.

По‑видимому, авторы LockBit для совершенствования своего продукта, а также чтобы не отставать от конкурента, добавили опцию распространения “psexec_netspread”. Но сразу оговоримся, сама утилита PsExec в данном случае не применяется. Интересное мнение о неработоспособности данной функции высказали коллеги. Давайте разберемся в новом механизме распространения в локальной сети, реализованном в LockBit 3.0.

В сентябре 2022 года в публичный доступ «утек» билдер LockBit 3.0, используемый RaaS LockBit. Конечно, эта утечка неплохо помогла ресерчерам в их исследовании LockBit 3.0, но при этом и нельзя умолчать о громадном вреде, которые несут такие общедоступные публикации. По сути, это «оружие», которое получают все без разбора киберхулиганы и хактивисты различной политической окраски. Для атак на российские компании были использованы программы‑вымогатели, созданные в том числе и с помощью данного билдера.

Для анализа сэмплов LockBit 3.0 использовались разработанные скрипты, позволяющие значительно облегчить их анализ. Также среди этих скриптов вы можете найти и реализацию криптографических алгоритмов шифрования файлов в LockBit на Python.

Рис. 1. Фрагмент конфигурации LockBit 3.0 в формате JSON из утекшего в публичный доступ билдера
Рис. 1. Фрагмент конфигурации LockBit 3.0 в формате JSON из утекшего в публичный доступ билдера

Этап 1. Проверка указанных учетных данных

Распространение в локальной сети осуществляется при включенной в конфигурации LockBit опции «psexec_netspread» при запуске программы‑вымогателя в режиме полного шифрования системы или шифрования в безопасном режиме (safe mode). Но при этом, как видим (рис. 2), для самораспространения необходим еще и некоторый токен пользователя (g_hUserToken).

Рис. 2. Фрагмент функции полного шифрования системы EncryptEverything
Рис. 2. Фрагмент функции полного шифрования системы EncryptEverything

Токен пользователя (g_hUserToken) программа‑вымогатель получает ранее в функции, которую мы назвали Prepare, при этом, разумеется, для этого должна быть включена опция конфигурации имперсонификации “impersonation” (рис. 3), а также указаны корректные администраторские учетные данные в поле “impers_accounts”.

Рис. 3. Имперсонификация. Фрагмент функции Prepare
Рис. 3. Имперсонификация. Фрагмент функции Prepare

В функции LogonAccounts (рис. 4) определяется имя домена, а далее осуществляется последовательный перебор учетных записей, указанных в поле конфигурации “impers_accounts” и попытка аутентификации для каждой записи с помощью функции API LogonUserW. В случае успешной аутентификации перебор учетных записей прекращается, из функции возвращается токен пользователя, а использованные для входа имя домена, имя пользователя и пароль шифруются и сохраняются в глобальные переменные g_pEncDomain, g_pEncUser и g_pEncPassword соответственно. Впоследствии эти данные, как это показано на рис. 2, используются в качестве параметров функции RunNetSpread.

Функции с именами IsRunningAsSvcи RunAsSvc рассмотрим позже, они будут использоваться на последнем этапе.

Рис. 4. Фрагмент функции LogonAccounts
Рис. 4. Фрагмент функции LogonAccounts

Для взаимодействия между процессами LockBit в функции RunNetSpread создается канал IPC (Inter‑Process Communication) в виде именованного пайпа (PIPE1) (рис. 5)

\\.\pipe\<PIPE1_NAME>

где PIPE1_NAME — UUID‑подобная строка {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}, полученная с помощью хеша MD5 от Unicode‑строки <DECRYPTION_ID>_IPC$, где DECRYPTION_ID — строка с первыми 8 байтами в шестнадцатеричном представлении модуля (n) публичного ключа RSA‑1024.

Пример:

DECRYPTION_ID: 4D30CBF764117970

PIPE1_NAME: {1B7F1036-41FE-3F89-169A-86DB06D0C609}

Рис. 5. Фрагмент функции RunNetSpread
Рис. 5. Фрагмент функции RunNetSpread

Далее программа‑вымогатель запускает себя в контексте безопасности учетной записи, полученной в LogonAccounts, при запуске также добавляет параметр командной строки "‑psex". Если текущая учетная запись — LocalSystem, для запуска нового процесса программы используется функция API CreateProcessAsUserW(g_hUserToken, …), в ином случае — CreateProcessWithLogonW с именем пользователя, именем домена и паролем, расшифрованных из g_pEncDomain, g_pEncUser, g_pEncPassword.

После этого в канал IPC PIPE1 записываются строка с аргументами командной строки, использованными при первоначальном запуске программы‑вымогателя (рис. 6). Затем программа‑вымогатель продолжает обычное функционирование, в том числе и шифрование данных на хосте.

Рис. 6. Фрагмент функции RunNetSpread
Рис. 6. Фрагмент функции RunNetSpread

Функция RunNetSpread возвращает дескриптор запущенного процесса, и вызывающая функция ожидает его завершения (рис. 2).

При самораспространении же с помощью групповых политик программа‑вымогатель запускается с параметром “‑gspd”, в остальном же все действия программы‑вымогателя идентичны на данном этапе.

Этап 2. Выполнение программы-вымогателя с аргументом "-psex"

На предыдущем этапе программа-вымогатель была запущена в контексте безопасности учетной записи, указанной в конфигурации, с добавлением аргумента командной строки "‑psex". Проверка аргументов командной строки в LockBit 3.0 осуществляется по контрольным суммам так же, как и в BlackMatter, впрочем, и как многое другое (рис. 7-8).

Рис. 7. Фрагмент функции Payload
Рис. 7. Фрагмент функции Payload
Рис. 8. Фрагмент функции Payload
Рис. 8. Фрагмент функции Payload

В функции PsexHandler программа открывает ранее созданный основным процессом LockBit канал IPC \\.\pipe\<PIPE1_NAME>, из которого получает строку с первоначальными аргументами командной строки, и затем в случае успеха вызывает функцию NetSpread (рис. 9).

Рис. 9. Функция PsexHandler
Рис. 9. Функция PsexHandler

В функции NetSpread (рис. 10) создается еще один канал IPC PIPE2 (функция CreateAndReadPipe2)

\\.\pipe\<PIPE2_NAME>

где PIPE2_NAME – UUID-подобная строка, полученная с помощью хеша MD5 от Unicode-строки в нижнем регистре

\\<COMP_NAME>.<DOMAIN_NAME>\_IPC$

COMP_NAMEимя компьютера, DOMAIN_NAME – имя домена.

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

Пример:

DOMAIN_NAME: rootdomain.net

COMP_NAME: MYDC1

PIPE2_NAME: {ABCA3D07-9E6B-A1F0-443E-768D0BF31AE5}

COMP_NAME: MYPC1

PIPE2_NAME:  {8A2A1C43-2D7E-ACCC-BD0E-98F7911AE5B7}

Дескриптор именованного канала PIPE2дублируется с помощью NtDuplicateObjectдля уже существующего процесса explorer.exe или lsass.exe, в результате чего будет закрыт впоследствии данным процессом.

Программа получает список компьютеров домена (функция GetADCompList).

Рис. 10. Начальный фрагмент функции NetSpread
Рис. 10. Начальный фрагмент функции NetSpread

Получение списка компьютеров в GetADCompList осуществляется двумя способами. Первый способ — перечисление контроллеров домена с помощью функций API DsGetDcOpenW / DsGetDcNextW. Второй способ — перечисление собственно компьютеров Active Directory с помощью запросов LDAP, для перечисления используются функции API ADsOpenObject, ADsBuildEnumerator, ADsEnumerateNext и интерфейсы IADs, IADsContainer.

Далее для каждого хоста из указанного списка создается поток (рис. 11), но одновременно может выполняться не более 64 потока. В функцию потока передается имя хоста в виде

\\<COMP_NAME>.<DOMAIN_NAME>\

где COMP_NAMEимя компьютера, DOMAIN_NAME – имя домена.

Рис. 11. Фрагмент функции NetSpread
Рис. 11. Фрагмент функции NetSpread

В функции NetConnAddOrCancel с помощью функции API WNetAddConnection2W осуществляется подключение к административным сетевым ресурсам компьютера (Admin Shares) ADMIN$ и IPC$ (рис. 12). Подключение к ресурсу IPC$ позволяет осуществлять удаленное взаимодействие между процессами LockBit.

Программа проверяет наличие канала IPC PIPE2 на хосте

\\<COMP_NAME>.<DOMAIN_NAME>\pipe\<PIPE2_NAME>

Если именованный пайп PIPE2 на хосте уже существует, дальнейших действий по распространению для данного компьютера не осуществляется.

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

Рис. 12. Фрагмент функции потока CompSpreadThreadProc
Рис. 12. Фрагмент функции потока CompSpreadThreadProc

Программа-вымогатель создает на другом компьютере каталог

\\<COMP_NAME>.<DOMAIN_NAME>\ADMIN$\Temp

и копирует в него свой исполняемый файл под именем <PIPE2_NAME>.exe (рис. 13).

Рис. 13. Фрагмент функции потока CompSpreadThreadProc
Рис. 13. Фрагмент функции потока CompSpreadThreadProc

На компьютере удаленно создается и запускается служба с именем PIPE2_NAME, для которой используется скопированный на компьютер исполняемый файл программы-вымогателя со следующими аргументами командной строки (рис. 14):

%%SystemRoot%%\Temp\<PIPE2_NAME>.exe -k LocalServiceNetworkRestricted

Рис. 14. Фрагмент функции потока CompSpreadThreadProc
Рис. 14. Фрагмент функции потока CompSpreadThreadProc

После успешного запуска в канал IPC PIPE2 записываются ранее полученные через канал IPC PIPE1 данные – строка с первоначальными аргументами командной строки. Далее служба удаляется и происходит отключение от административных сетевых ресурсов компьютера (Admin Shares) ADMIN$ и IPC$ (рис. 15).

Рис. 15. Фрагмент функции потока NetConnAddThreadProc
Рис. 15. Фрагмент функции потока NetConnAddThreadProc

Этап 3. Выполнение службы на компьютере

Ранее на 1 этапе мы упоминали функции с именами IsRunningAsSvcи RunAsSvc, которые вызывались в Prepare (рис. 3). В функции IsRunningAsSvc осуществляется проверка наличия аргумента командной строки "LocalServiceNetworkRestricted" с помощью контрольной суммы строки (рис. 16). Эта проверка осуществляется заранее, до проверки аргументов в функции Payload (рис. 7).

Рис. 16. Фрагмент функции IsRunningAsSvc
Рис. 16. Фрагмент функции IsRunningAsSvc

Таким образом, если программа-вымогатель запущена с аргументом командной строки "LocalServiceNetworkRestricted", запускается функция RunAsSvc, которая осуществляет запуск программы как системной службы (рис. 17).

Рис. 17. Фрагмент функции RunAsSvc
Рис. 17. Фрагмент функции RunAsSvc

В функции SvcMain программа создает IPC канал с именем PIPE2_NAME и читает из него данные в буфер (рис. 18). После этого служба завершает свою работу.

Рис. 18. Функция SvcMain
Рис. 18. Функция SvcMain

Далее после завершения службы выполняется следующий за StartServiceCtrlDispatcherW код, а именно запускается функция RunMe, которой в качестве параметра передаются данные, полученные из IPC канала PIPE2. Функция RunMeзапускает исполняемый файл программы-вымогателя с аргументами командной строки, переданными первоначально программе на 1-м этапе. RunMe определяет идентификатор сеанса физической консоли (GetActiveConsoleSessionID) и устанавливает его для токена текущего процесса (процесса службы) (NtSetInformationToken) и запускает процесс шифрования компьютера в контексте безопасности текущего процесса (CreateProcessAsUserW).

Таким образом, запуск программы-вымогателя на одном из компьютеров домена при наличии корректных учетных данных администратора домена в конфигурационных данных программы-вымогателя приводит к шифрованию компьютеров (рис. 19) и контроллера домена (рис. 20).

Рис. 19. Выполнение программы-вымогателя на компьютере домена MYPC1
Рис. 19. Выполнение программы-вымогателя на компьютере домена MYPC1
Рис. 20. Выполнение программы-вымогателя на контроллере домена MYDC1
Рис. 20. Выполнение программы-вымогателя на контроллере домена MYDC1

Как видим, все работает...

Комментарии (0)