[Перевод] Детальный анализ вредоносного ПО, замаскированного под NOTEPAD++

3krhjzsu21e9pm5nd3menzbisas.jpeg


Lazarus привлекала своих жертв при помощи документов о вакансиях в таких компаниях, как LockHeed Martin, BAE Systems и Boeing. В данном конкретном случае злоумышленники привлекали жертв, ищущих работу в Boeing, при помощи документа Boeing BDS MSE.docx (твит ShadowChasing1). Вредоносное ПО извлекает имя хоста, имя пользователя, информацию о сети, список процессов и другую информацию, которая затем должна была передаваться на один из четырёх серверов C2. Предназначенные для передачи данные сжимались, шифровались XOR, кодировались Base64 и отправлялись на сервер C2. Троян реализует четыре действия, в том числе скачивает и исполняет файл .exe или .dll, загружает PE (Portable Executable) в память процессов и исполняет шелл-код.

▍ Технический анализ


SHA256: 803dda6c8dc426f1005acdf765d9ef897dd502cd8a80632eef4738d1d7947269

Файл является DLL, имеющим 7 экспортов. Лишь одна из этих функций выполняет зловредное действие (DllGetFirstChild):

lni02gi77xzwmcrmde_58l0qzt0.jpeg
Рисунок 1

Вредоносное ПО вызывает функцию ObtainUserAgentString для получения User Agent. Кроме того, в двоичном файле прописан User Agent «Mozilla / 5.0 (Windows NT 10.0; WOW64; Trident / 7.0; rv:11.0) li», то есть Internet Explorer в Windows 10:

locibppoz7zfoctenlt_cdzvwnm.jpeg
Рисунок 2

Двоичный файл извлекает текущие системные дату и время при помощи GetSystemTimeAsFileTime API:

lfvmojg9sic_ooljdbcasx4ufpa.jpeg
Рисунок 3

Для получения дескриптора модуля из ntdll.dll используется GetModuleHandleW:

sdqvqewrk6wbdwxorflkc-j5loo.jpeg
Рисунок 4

Процесс при помощи подпрограммы GetProcAddress получает адрес следующих функций экспорта:»RtlGetCompressionWorkSpaceSize»,»RtlCompressBuffer»,»RtlDecompressBuffer»,»RtlGetVersion». Пример вызова функции показан на рисунке 5:

x5rbe_ser7falqm-rzut9fzgguo.jpeg
Рисунок 5

При помощи вызова функции GetComputerNameW получается название локального компьютера в NetBIOS:

btsq34en6flgvjiqni66lj9tkoi.jpeg
Рисунок 6

GetAdaptersInfo API используется для получения информации об адаптере с локальной машины:

zxujrmw1bfxulnpqwemzauc0zyk.jpeg
Рисунок 7

Извлечённый ранее MAC-адрес записывается в буфер:

jfmqtkld9cv8b91wjxylhuex6bs.jpeg
Рисунок 8

Файл извлекает string командной строки текущего процесса:

9avpfmdieed3cyc9p3s0q9fnwew.jpeg
Рисунок 9

CommandLineToArgvW используется для извлечения массива указателей на аргументы командной строки и количества аргументов (аналогично argv и argc):

83gurkzaidm3xrzddfgy5kd8h7c.jpeg
Рисунок 10

Согласно статье, зловредное ПО должно было запускаться со следующими параметрами:

NTPR P6k+pR6iIKwJpU6oR6ZilgKPL7IxsitJAnpIYSx2KldSSRFFyUIzTBVFAwgzBkI2PS/+EgASBik/GgYBwBbRNy7pP+Xq4uTsxOXU6NPmudaEz7Xy5fLQica6yKHvtu2XkYmnhfeC/4ythf9I6UbAdvxvy1K2Um5ppVrEQY9WiHdxKbolqiKgLMElwSiKJrcWrQ+cMpYy5cnc+s/hufap15LJmsVFwr7MlMWwiLCGgLZPr4uSk5KIqZiadYGOlkS3cml1ZZdiZmyzZVpovmZiVlNPNXJsck4JXzpPIWw2YBcqCRMFCQJBDG4FfchmxkL2fO8V0jbSTeko2u/BI9YA9zGpM6UWoiGsdaVdqAmmIpYHjzWyM7IOSQR6SGE4dilXB0lfRXtCOEwkRTAIMgYWNnsvVRJSEvQp/xryAdsW1Df76fjl3eIb7M7lIujH5vbW7c/e8tTy2on1uuGh+rbml5GJp4X3gv+MrYXwSOFGzHbxb9BSwFLLaaJau0FNVoh3sim4JZYi1Cz1JZYohya0FpEP9TKZMpTJgvqn4e72sdefyZrF4sI=&


Двоичный файл расшифровывает этот параметр при помощи алгоритма, показанного на рисунке 11. Список получившихся строк содержит несколько серверов C2:

dqbo5n4gf2qywajwn3tjqvttquy.jpeg
Рисунок 11

oilwppskzpfbs-fzrc49v513tuc.jpeg
Рисунок 12

В процессе реверс-инжиниринга расшифрованы следующие URL:

  • https[:]//mante.li/images/draw.php


  • https[:]//bmanal.com/images/draw.php


  • https[:]//shopandtravelusa.com/vendor/monolog/monolog/src/Monolog/monolog.php
  • https[:]//industryinfostructure.com/templates/worldgroup/view.php


Подпрограмма GetNetworkParams используется для получения сетевых параметров локального компьютера:

5k8s5mjolnjxxrrcydctrzslcl8.jpeg
Рисунок 13

Зловредный процесс извлекает имя DNS-домена, назначенного локальному хосту (0×2 = ComputerNameDnsDomain:

gmulogdhlqpzihwgf3f5wc6mts0.jpeg
Рисунок 14

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

bn_8u8vead1olt9xbuxipmdjrxk.jpeg
Рисунок 15

eqgvon_uuoxyrqnssjbq3sunbmy.jpeg
Рисунок 16

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

fgg-uj59-cy_i0gjovtd8i6qkkk.jpeg
Рисунок 17

Двоичный файл делает снэпшот всех процессов в системе при помощи CreateToolhelp32Snapshot API (0×2 = TH32CS_SNAPPROCESS):

mjsd0ilo4jjzkoiniip1va6278m.jpeg
Рисунок 18

Файл извлекает информацию о первом процессе из снэпшота при помощи вызова Process32FirstW:

fn4qdjjjy2vqoyngm_ialfmecle.jpeg
Рисунок 19

Затем двоичный файл открывает объект процесса при помощи подпрограммы OpenProcess (0×410 = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ):

rpxhvsexbzbdt-tlewvnn8uudfy.jpeg
Рисунок 20

Если у файла не хватает прав для открытия процесса, он копирует во временный буфер «Unknown» с именем процесса.

Далее он при помощи CreateToolhelp32Snapshot API (0×8 = TH32CS_SNAPMODULE) делает снэпшот текущего процесса со всеми его модулями:

qbbjeg7mxgnupk-amgchqlhimt4.jpeg
Рисунок 21

Для получения информации о первом модуле, связанном с текущим процессом, используется Module32FirstW:

iduft9frmqmjihzzuvvkcwip-yo.jpeg
Рисунок 22

Зловредный DLL получает информацию о следующем процессе, записанном в снэпшот:

jmicfhux3qab_mypx4k0lgd1hw0.jpeg
Рисунок 23

Для открытия связанного с процессом токена доступа используется подпрограмма OpenProcessToken (0×8 = TOKEN_QUERY):

p-0qqvd76tejdwpmfq2yiqgmdq8.jpeg
Рисунок 24

Для извлечения аккаунта пользователя токена используется GetTokenInformation (0×1 = TokenUser):

n8oxelxab0fz7tskyhnwkr5mqlw.jpeg
Рисунок 25

При помощи вызова функции LookupAccountSidW процесс получает имя аккаунта для SID и имя первого домена, в котором найден SID:

l-my6qva90wzg9gvpwti5csvpak.jpeg
Рисунок 26

Для извлечения идентификатора связанной с токеном сессии Terminal Services используется GetTokenInformation (0xC = TokenSessionId):

7wyb6uroka82fuqpy1sgg8ecmy4.jpeg
Рисунок 27

Чтобы определить нужный размер буфера WorkSpace для функции RtlCompressBuffer используется RtlGetCompressionWorkSpaceSize API (0×102 = COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM):

v2axfv6gcip8w7rjjxswkq9waie.jpeg
Рисунок 28

При помощи функции RtlCompressBuffer процесс сжимает буферы, показанные на рисунках 15 и 16 (0×102 = COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM):

ikpdxmylsz4zicpl-74phyxbkf4.jpeg
Рисунок 29

DLL случайным образом выбирает один из четырёх серверов C2 в списке, а потом при помощи вызова InternetOpenW инициализирует использование приложением функций WinINet:

expto8nodxyol6dzg7ayz8pzqqo.jpeg
Рисунок 30

Для приведения URL в каноничный вид используется InternetCanonicalizeUrlW:

vjmkhfqe-qqihaosrbliy5vruq8.jpeg
Рисунок 31

При помощи вызова InternetCrackUrlW API зловред разбивает URL на компоненты:

dfhd1wftgitqjfw3b7usecirmbc.jpeg
Рисунок 32

При помощи подпрограммы InternetSetOptionW устанавливаются таймауты подключения, отправки и получения на 150 с (0×2 = INTERNET_OPTION_CONNECT_TIMEOUT, 0×5 = INTERNET_OPTION_SEND_TIMEOUT, 0×6 = INTERNET_OPTION_RECEIVE_TIMEOUT):

y0rcjwdcxu9hureecy_bzlqvxyu.jpeg
Рисунок 33

q2j4kw9fixajads2b3xyc5tj8ke.jpeg
Рисунок 34

kazy4g-40-zu1wlm-egcap3noco.jpeg
Рисунок 35

DLL открывает HTTP-сессию с сервером C2 через порт 443 (0×3 = INTERNET_SERVICE_HTTP):

vicote3ufn2r_aggzbv8ddoc_ao.jpeg
Рисунок 36

Двоичный файл создаёт дескриптор POST-запроса к URI, извлечённому из указанного URL:

ud_tsxzswizpsxcinbqgwtw-7my.jpeg
Рисунок 37

Флаги безопасности для дескриптора задаются при помощи InternetSetOptionW API (0×1F = INTERNET_OPTION_SECURITY_FLAGS, 0xF180 = SECURITY_FLAG_IGNORE_REVOCATION | SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP | SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS):

weazec00y4tvbegtpnmoqnhmkeu.jpeg
Рисунок 38

Ранее сжатый буфер (конкатенация двух буферов) шифруется при помощи XOR (ключ = 32-байтный массив):

rqzdzaxjqmkpved_y3fzcza2-mc.jpeg
Рисунок 39

z4fxevkezrbeoqrifoxnrqhxlgo.jpeg
Рисунок 40

Далее зашифрованный буфер кодируется при помощи Base64:

havs0oau18hmqcox-kfkvbvfr08.jpeg
Рисунок 41

bp98vj-4v17md73keni9v3pokpm.jpeg
Рисунок 42

Двоичный файл создаёт следующие параметры: «search=YOIPOUP&ei=6128&oq=»:

vep-quternrosazbqr-dzllpvpm.jpeg
Рисунок 43

Извлечённый ранее User Agent добавляется к дескриптору HTTP-запроса при помощи подпрограммы HttpAddRequestHeadersW (0xA0000000 = HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD):

zrv7ukd_wldnydux5qm0wvawrps.jpeg
Рисунок 44

Для передачи данных на сервер C2 используется HttpSendRequestW:

aanu93ad_7pnecw2kbzritotbda.jpeg
Рисунок 45

Стоит отметить, что на момент выполнения нашего анализа все серверы C2 уже были отключены. Мы эмулировали сетевые соединения при помощи FakeNet.

Размер ответа C2 получается при помощи вызова подпрограммы HttpQueryInfoW (0×5 = HTTP_QUERY_CONTENT_LENGTH):

ddbhvdy-devxnuq6ggxtcgznazo.jpeg
Рисунок 46

Двоичный файл копирует ответ C2 в буфер при помощи вызова функции InternetReadFile:

kc19j6rqaoickcbbfpf9mo913fk.jpeg
Рисунок 47

Зловредный процес парсит данные между тэгами и 

:

92nhixajf94b92qqk-m6-nzo3vc.jpeg
Рисунок 48

Зловредное ПО выполняет похожий POST-запрос с другими значениями параметров: «search=DOWPANY&ei=6128»:

g60gyerq6xzwnfsf39rnymxblau.jpeg
Рисунок 49

Ответ C2 декодируется при помощи Base64, а затем расшифровывается XOR. Зловредный код реализует четыре разных действия на основании значения регистра EAX:

ta8qsqkducxwuwn6bjser4-pk6e.jpeg
Рисунок 50

EAX = 0 — загрузка PE в память текущего процесса

Для получения информации о текущей системе используется GetNativeSystemInfo:

zaxua5zpvqosea3_r3anq5jz0w8.jpeg
Рисунок 51

DLL выполняет несколько вызовов функции VirtualAlloc, выделяющих память под новый исполняемый файл (0×3000 = MEM_COMMIT | MEM_RESERVE, 0×4 = PAGE_READWRITE):

dvsh9hzv8ypcdc_dri3khmyicwa.jpeg
Рисунок 52

Зловредный код в зависимости от сегмента меняет защиту памяти (например, защита памяти для сегмента кода установлена на 0×20 = PAGE_EXECUTE_READ):

fizojx-_xubaboargfrmaszyncy.jpeg
Рисунок 53

Спустя ещё несколько операций процесс передаёт поток управления новому PE.

EAX = 1 — скачать и исполнить файл .exe

Двоичный файл получает путь к папке AppData, вызывая подпрограмму SHGetFolderPathW (0×1c = CSIDL_LOCAL_APPDATA):

kfv9x1hz1ydsud8wjgymedskvzg.jpeg
Рисунок 54

Для получения количества секунд после запуска системы используется GetTickCount:

ctgt-hj7cs1lvqyszavxzvtkgx8.jpeg
Рисунок 55

Зловредный код создаёт файл на основании указанного выше значения (0×40000000 = GENERIC_WRITE, 0×1 = FILE_SHARE_READ, 0×2 = CREATE_ALWAYS, 0×80 = FILE_ATTRIBUTE_NORMAL):

pgogiazz5tvjfacam1qiqdew-mm.jpeg
Рисунок 56

Созданный файл заполняется содержимым, который должен быть передан на сервер C2:

8y2t9lndrhra1evearpeytbv8dk.jpeg
Рисунок 57

Зловредный двоичный код исполняет файл, вызывая CreateProcessW API:

ordsx-nxc2tqh302sfsgqzchh-u.jpeg
Рисунок 58

EAX = 2 — скачать и исполнить файл .dll

Поток исполнения схож с показанным выше, поэтому мы покажем только различия. Для исполнения файла DLL используется Rundll32.exe (также в командной строке может быть задана функция экспорта):

barxfdhd8vajut4vrwc7owonk7o.jpeg
Рисунок 59

EAX = 3 — копировать и исполнить шелл-код

Процесс выделяет память при помощи подпрограммы VirtualAlloc (0×1000 = MEM_COMMIT, 0×40 = PAGE_EXECUTE_READWRITE):

inhpkuv7uptyancaitwexbx__9y.jpeg
Рисунок 60

DLL реализует проверку на антианализ. Она вызывает isProcessorFeaturePresent API, чтобы определить, доступен ли _fastfail (). Если эта функция не поддерживается, текущий процесс прекращается вызовом функций GetCurrentProcess и TerminateProcess (0×17 = PF_FASTFAIL_AVAILABLE):

zou9tsppepi3g1_vvgkrak0k0ec.jpeg
Рисунок 61

Зловредный код переходит к шелл-коду, а затем освобождает выделенную ранее область памяти:

ux_mypawcaftqouxdugv29jyaji.jpeg
Рисунок 62

Как говорилось в начале нашего анализа, злоумышленник добавил рассмотренную выше функцию экспорта, а все остальные вполне безобидны.

Мы изучили подлинное расширение оболочки Notepad++ (SHA256: f3e2e6f9e7aa065e89040a0c16d1f948489b3751e5eb5efac8106d5f7d65d98d 64-bit) и сравнили функции экспорта двух файлов. Как видно ниже, функции очень схожи:

3krhjzsu21e9pm5nd3menzbisas.jpeg
Рисунок 63

wtko1rv2urpb4p06nslsw4a3phy.jpeg
Рисунок 64

Справочные материалы


  1. MSDN
  2. Fakenet
  3. VirusTotal
  4. MalwareBazaar


Признаки компрометации

Домены C2:
  • mante.li
  • bmanal.com
  • shopandtravelusa.com
  • industryinfostructure.com

SHA256: 803dda6c8dc426f1005acdf765d9ef897dd502cd8a80632eef4738d1d7947269

URL:
  • https[:]//mante.li/images/draw.php
  • https[:]//bmanal.com/images/draw.php
  • https[:]//shopandtravelusa.com/vendor/monolog/monolog/src/Monolog/monolog.php
  • https[:]//industryinfostructure.com/templates/worldgroup/view.php

xbo4gmrlicdllfwrmtuypqrlcgg.jpeg

Habrahabr.ru прочитано 34502 раза