Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Исследовать малварь не только весело, но и крайне познавательно. Недавно в мои цепкие руки попал банковский троян LOKI-bot. Подобные вредоносы обычно пишут настоящие профессионалы, и потому банкеры зачастую содержат достаточно интересные хаки. Так случилось и в этот раз — трой сопротивляется отладке и пытается «спалить» нас довольно нетривиальными способами.
Для начала загрузим семпл в DiE и посмотрим, что он покажет.
LOKI в анализаторе DiE
Как видно на скриншоте, DiE отчего-то уверен, что наш семпл написан на Delphi, но это, разумеется, не так. Ты наверняка знаешь, что существуют специальные тулзы, которые умеют склеивать один файл с другим. Создатели LOKI-bot именно так и поступили (обрати внимание на размер секции ресурсов rsrc
в файле относительно его общего размера). Оригинальный LOKI запустится после того, как отработает его «обертка».
Для того чтобы разобраться в механизме самозащиты этого бота, мы должны представлять себе, каким образом вообще малварь может сопротивляться отладке. Обычно так или иначе трой старается получить список процессов в системе, а после этого уже начинаются дальнейшие действия. Давай попробуем двигаться в эту сторону, чтобы изучить механизм самозащиты бота. Как известно, получить список процессов в Windows можно несколькими способами.
PSAPI EnumProcesses
.CreateToolhelp32Snapshot
.ZwQuerySystemInformation
.Безусловно, самый распространенный метод получения процессов — при помощи функции CreateToolhelp32Snapshot
, поэтому мы начнем с установки брейк-пойнта на эту функцию (используется отладчик x64dbg, версия для архитектуры x86).
Итак, мы оказались в теле функции 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]
Видим какой-то код, похожий на мусор, среди которого прослеживаются имена функций WinAPI. Давай представим весь код в виде DWORD’ов.
Имена функций, получаемых динамически
Перед нами список функций, которые LOKI получает динамически. По этому списку мы можем судить о том, как работает банкер. В дальнейшем вызовы используемых WinAPI будут выполняться подобными call’ами. Итак, со списком WinAPI разобрались, теперь вернемся в код. Чтобы ты понимал его структуру, приведу листинг части функции поиска процессов (обрати внимание на адреса!):
01DC40DB | FF56 0C | call dword ptr ds:[esi+C] | CreateToolhelp32Snapshot
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 |
002238B2 | FF56 10 | call dword ptr ds:[esi+10] | Process32FirstW
002238B5 | E9 97EDFFFF | jmp 222651 |
Как видишь, код сильно фрагментирован и связан переходами (jmp
). Это нас не запугает: ставим точку останова на конец функции получения списка процессов и жмем на выполнение. Далее нас ждет такой код (некоторые не особо интересные функции я буду называть, но не стану в них заглядывать — по названию будет все понятно):
007C5D83 | 8D8D F8FDFFFF | lea ecx,dword ptr ss:[ebp-208] | Имя процесса
007C5D89 | E8 4AD8FFFF | call <str_len> | Считаем число символов имен процессов
007C5D8E | 83F8 40 | cmp eax,40 | Сравниваем размер имени процесса с числом 40h (64)
007C5D91 | 0F82 08000000 | jb 7C5D9F | Все хорошо, продолжаем корректное выполнение трояна
007C5D97 | 6A 00 | push 0 | Все плохо, завершаемся
007C5D99 | FF96 AC000000 | call dword ptr ds:[esi+AC] | ExitProcess
007C5D9F | E9 E1D1FFFF | jmp 7C2F85 |
Здесь считается размер имени каждого процесса и сравнивается с числом 40h
, или 64 в десятеричной системе. Если процесс с таким длинным именем найден, то выполняется выход. В чем тут был замысел?
Все дело в том, что обычно исследователи в вирусных лабораториях дают имена файлам семплов вредоносных программ в виде их хешей SHA-256, которые как раз имеют длину 64 символа. Если такой файл запустить, LOKI поймет это по числу символов процесса и выполнит выход. Или не поймет? Думаю, что внимательный читатель уже догадался: дело в том, что получаемое при помощи функции CreateToolhelp32Snapshot
имя процесса также содержит его расширение, которое добавляет еще четыре символа к имени — .exe
. Очевидно, разработчик забыл об этом, поэтому его замысел не сработает. Хотя идея достаточно оригинальна. Вывести из строя эту защиту банкера можно, проследив, чтобы в системе не было процессов с именами из 64 символов, включая расширение.
Источник: xakep.ru