Исследовать малварь не только весело, но и крайне познавательно. Недавно в мои цепкие руки попал банковский троян LOKI-bot. Подобные вредоносы обычно пишут настоящие профессионалы, и потому банкеры зачастую содержат достаточно интересные хаки. Так случилось и в этот раз — трой сопротивляется отладке и пытается «спалить» нас довольно нетривиальными способами.

Для начала загрузим семпл в DiE и посмотрим, что он покажет.

LOKI в анализаторе DiE
LOKI в анализаторе DiE

Как видно на скриншоте, DiE отчего-то уверен, что наш семпл написан на Delphi, но это, разумеется, не так. Ты наверняка знаешь, что существуют специальные тулзы, которые умеют склеивать один файл с другим. Создатели LOKI-bot именно так и поступили (обрати внимание на размер секции ресурсов rsrc в файле относительно его общего размера). Оригинальный LOKI запустится после того, как отработает его «обертка».

INFO

Все эксперименты с боевой малварью я настоятельно рекомендую проводить на изолированной от сети виртуальной машине, иначе есть риск получить заражение банкером LOKI-bot и лишиться своих данных!

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

  1. Перечислить процессы при помощи функции PSAPI EnumProcesses.
  2. Создать снимок процессов при помощи функции CreateToolhelp32Snapshot.
  3. Перечислить процессы при помощи ZwQuerySystemInformation.
  4. Применить трюки со счетчиками производительности.
  5. Использовать Windows Management Instrumentation (WMI).

Безусловно, самый распространенный метод получения процессов — при помощи функции CreateToolhelp32Snapshot, поэтому мы начнем с установки брейк-пойнта на эту функцию (используется отладчик x64dbg, версия для архитектуры x86).

INFO

Исследование малвари или решение крякмисов может растянуться надолго: не всегда с первого раза ты ставишь брейк-пойнты на нужные функции, не всегда все идет по плану. В любом случае это вереница проб и ошибок. Когда ты читаешь статью, у тебя на это уходит максимум 10–15 минут, но это не значит, что любой взлом или снятие упаковки с файла будет занимать столько же времени. Просто есть «рабочие» моменты, рутина, которой не стоит утомлять читателя и которую автор пропускает. Поэтому создается впечатление, будто любой взлом быстр и элементарен, а автор с первого раза «угадывает», на какие функции WinAPI установить бряки, чтобы победить защиту. Но в жизни это не всегда так! 🙂

 

Начинаем погружение

Итак, мы оказались в теле функции CreateToolhelp32Snapshot. Давай выполним ее и сделаем еще один шаг, чтобы вернуться по ret. В итоге мы попадаем в такой код:

01DC40D8 | 53                       | push ebx
01DC40D9 | 6A 02                    | push 2
01DC40DB | FF56 0C                  | call dword ptr ds:[esi+C]
01DC40DE | 8BD8                     | mov ebx,eax   <----- мы здесь
01DC40E0 | 83FB FF                  | cmp ebx,FFFFFFFF
01DC40E3 | 0F85 634C0000            | jne 1DC8D4C
01DC40E9 | 33C0                     | xor eax,eax
01DC40EB | E9 6AE5FFFF              | jmp 1DC265A

Мы стоим на 01DC40DE, но ты ведь помнишь, что мы только что вернулись из CreateToolhelp32Snapshot? Стало быть, call, который выше по коду, и есть вызов CreateToolhelp32Snapshot. Вспоминаем прототип CreateToolhelp32Snapshot:

HANDLE CreateToolhelp32Snapshot(
    DWORD dwFlags,
    DWORD th32ProcessID
);

Как видим, передаются два аргумента, один из которых — push 2, что говорит о передаче параметра TH32CS_SNAPPROCESS. Он заставляет CreateToolhelp32Snapshot сделать снимок всех процессов. Все указывает на вызов CreateToolhelp32Snapshot, но этот call не похож на стандартный вызов WinAPI в коде. Идем в ds:[esi+C] и смотрим, что там есть.

Вид «сырой» памяти в ds:[esi+C]
Вид «сырой» памяти в ds:[esi+C]

Видим какой-то код, похожий на мусор, среди которого прослеживаются имена функций WinAPI. Давай представим весь код в виде DWORD’ов.

Имена функций, получаемых динамически
Имена функций, получаемых динамически

Перед нами список функций, которые LOKI получает динамически. По этому списку мы можем судить о том, как работает банкер. В дальнейшем вызовы используемых WinAPI будут выполняться подобными call’ами. Итак, со списком WinAPI разобрались, теперь вернемся в код. Чтобы ты понимал его структуру, приведу листинг части функции поиска процессов (обрати внимание на адреса!):

; CreateToolhelp32Snapshot
01DC40DB | FF56 0C        | call dword ptr ds:[esi+C]
01DC40DE | 8BD8           | mov ebx,eax
01DC40E0 | 83FB FF        | cmp ebx,FFFFFFFF
01DC40E3 | 0F85 634C0000  | jne 1DC8D4C
01DC40E9 | 33C0           | xor eax,eax
01DC40EB | E9 6AE5FFFF    | jmp 1DC265A

00228D4C | 8D85 D4FDFFFF  | lea eax,dword ptr ss:[ebp-22C]
00228D52 | 50             | push eax
00228D53 | E9 53ABFFFF    | jmp 2238AB

002238AB | 53             | push ebx
002238AC | 89BD D4FDFFFF  | mov dword ptr ss:[ebp-22C],edi
; Process32FirstW
002238B2 | FF56 10        | call dword ptr ds:[esi+10]
002238B5 | E9 97EDFFFF    | jmp 222651

Как видишь, код сильно фрагментирован и связан переходами (jmp). Это нас не запугает: ставим точку останова на конец функции получения списка процессов и жмем на выполнение. Далее нас ждет такой код (некоторые не особо интересные функции я буду называть, но не стану в них заглядывать — по названию будет все понятно):

; Имя процесса
007C5D83 | 8D8D F8FDFFFF  | lea ecx,dword ptr ss:[ebp-208]
; Считаем число символов имен процессов
007C5D89 | E8 4AD8FFFF    | call <str_len>
; Сравниваем размер имени процесса с числом 40h (64)
007C5D8E | 83F8 40        | cmp eax,40
; Все хорошо, продолжаем корректное выполнение трояна
007C5D91 | 0F82 08000000  | jb 7C5D9F
; Все плохо, завершаемся
007C5D97 | 6A 00          | push 0
; ExitProcess
007C5D99 | FF96 AC000000  | call dword ptr ds:[esi+AC]
007C5D9F | E9 E1D1FFFF    | jmp 7C2F85

Здесь считается размер имени каждого процесса и сравнивается с числом 40h, или 64 в десятеричной системе. Если процесс с таким длинным именем найден, то выполняется выход. В чем тут был замысел?

 

Замысел создателя

Все дело в том, что обычно исследователи в вирусных лабораториях дают имена файлам семплов вредоносных программ в виде их хешей SHA-256, которые как раз имеют длину 64 символа. Если такой файл запустить, LOKI поймет это по числу символов процесса и выполнит выход. Или не поймет? Думаю, что внимательный читатель уже догадался: дело в том, что получаемое при помощи функции CreateToolhelp32Snapshot имя процесса также содержит его расширение, которое добавляет еще четыре символа к имени — .exe. Очевидно, разработчик забыл об этом, поэтому его замысел не сработает. Хотя идея достаточно оригинальна. Вывести из строя эту защиту банкера можно, проследив, чтобы в системе не было процессов с именами из 64 символов, включая расширение.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    3 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии