Исследовать малварь не только весело, но и крайне познавательно. Недавно в мои цепкие руки попал банковский троян LOKI-bot. Подобные вредоносы обычно пишут настоящие профессионалы, и потому банкеры зачастую содержат достаточно интересные хаки. Так случилось и в этот раз — трой сопротивляется отладке и пытается «спалить» нас довольно нетривиальными способами.
Для начала загрузим семпл в DiE и посмотрим, что он покажет.
Как видно на скриншоте, DiE отчего-то уверен, что наш семпл написан на Delphi, но это, разумеется, не так. Ты наверняка знаешь, что существуют специальные тулзы, которые умеют склеивать один файл с другим. Создатели LOKI-bot именно так и поступили (обрати внимание на размер секции ресурсов rsrc
в файле относительно его общего размера). Оригинальный LOKI запустится после того, как отработает его «обертка».
Все эксперименты с боевой малварью я настоятельно рекомендую проводить на изолированной от сети виртуальной машине, иначе есть риск получить заражение банкером LOKI-bot и лишиться своих данных!
Для того чтобы разобраться в механизме самозащиты этого бота, мы должны представлять себе, каким образом вообще малварь может сопротивляться отладке. Обычно так или иначе трой старается получить список процессов в системе, а после этого уже начинаются дальнейшие действия. Давай попробуем двигаться в эту сторону, чтобы изучить механизм самозащиты бота. Как известно, получить список процессов в Windows можно несколькими способами.
PSAPI EnumProcesses
.CreateToolhelp32Snapshot
.ZwQuerySystemInformation
.Безусловно, самый распространенный метод получения процессов — при помощи функции CreateToolhelp32Snapshot
, поэтому мы начнем с установки брейк-пойнта на эту функцию (используется отладчик x64dbg, версия для архитектуры x86).
Исследование малвари или решение крякмисов может растянуться надолго: не всегда с первого раза ты ставишь брейк-пойнты на нужные функции, не всегда все идет по плану. В любом случае это вереница проб и ошибок. Когда ты читаешь статью, у тебя на это уходит максимум 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]
и смотрим, что там есть.
Видим какой-то код, похожий на мусор, среди которого прослеживаются имена функций 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».
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее
1 год7690 р. |
1 месяц720 р. |
Я уже участник «Xakep.ru»
Читайте также
Последние новости