Потрошим Carbanak. Как изнутри устроен известный банковский троян

Банковские трояны, ворующие деньги со счетов компаний и простых пользователей, ежегодно наносят ущерб на миллионы долларов. Естественно, вирмейкеры стараются держать все, что связано с внутренней кухней банкеров, в глубочайшей тайне. Именно поэтому мы никак не могли упустить уникальное событие — попадание исходников банковского троя Carbanak в паблик — и принялись исследовать его устройство изнутри. Результатами этих изысканий мы сегодня щедро поделимся с тобой.

Хакер уже писал об утечке в публичный доступ исходных кодов банковской малвари Carbanak. Надо сказать, что эта малварь сейчас все еще активна и развивается, несмотря на аресты, а украденные суммы давно перевалили за миллиард долларов. Все любопытствующие могут ознакомиться с исходным кодом этого творения на GitHub. Лично я рекомендую сохранить этот код (для академических исследований, естественно), а то всякое может случиться. Итак, давай заглянем внутрь Carbanak.

Структура проекта Carbanak

Первое, что меня обычно привлекает в профессионально написанной малвари, — это способы, с помощью которых эта самая малварь противодействует антивирусам и скрывает свою активность. В Carbanak используется несколько приемов борьбы с антивирусными программами. Их мы сейчас и рассмотрим.

Для начала мне стало интересно, как Carbanak общается с WinAPI и каким образом вызывает нужные ему функции. Чтобы увидеть этот механизм, необходимо заглянуть в следующие файлы:

coresourcewinapi.cpp
coreincludecorewinapi.h
coreincludecoreapi_funcs_type.h
coreincludecoreapi_funcs_hash.h

Бросается в глаза код получения структуры процессов PEB, настроенный на условную компиляцию в зависимости от архитектуры системы:

PPEB GetPEB()
{
#ifdef _WIN64
    return  (PPEB)__readgsqword(0x60);
#else
    PPEB PEB;
    __asm
    {
        mov eax, FS:[0x30]
        mov [PEB], eax
    }
    return PEB;
#endif
}

Там же представлен список нужных DLL, где хранятся WinAPI (это только часть используемых трояном библиотек):

const char* namesDll[] = 
{
    _CT_("kernel32.dll"), // KERNEL32 = 0
    _CT_("user32.dll"), // USER32 = 1
    _CT_("ntdll.dll"), // NTDLL = 2
    _CT_("shlwapi.dll"), // SHLWAPI = 3
    _CT_("iphlpapi.dll"), // IPHLPAPI = 4
    _CT_("urlmon.dll"), // URLMON = 5

.....

Обрати внимание на макросы _CT_ — они шифруют строки. Ты ведь не думал, что в малвари подобного уровня текстовые строки будут храниться в открытом виде? Кроме того, в блоке инициализации этого модуля мы видим код, динамически получающий функции GetProcAddress и LoadLibraryA по их хешу:

    HMODULE kernel32;
    if ( (kernel32 = GetDllBase(hashKernel32)) == NULL )
        return false;
    _GetProcAddress = (typeGetProcAddress)GetApiAddr( kernel32, hashGetProcAddress );
    _LoadLibraryA = (typeLoadLibraryA)GetApiAddr( kernel32, hashLoadLibraryA );
    if ( (_GetProcAddress == NULL) || (_LoadLibraryA == NULL) )

Далее троян выполняет поиск и сравнение с таблицей хешей искомых функций. Вот, например, часть кода, с помощью которой Carbanak определяет, найдена нужная функция или нет:

for( uint i = 0; i < exportDir->NumberOfNames; i++)
    {
        char* name = (char*)RVATOVA( module, *namesTable );
        if( Str::Hash(name) == hashFunc )
        {
            ordinal = *ordinalTable;
            break;
    }
        // Следующая функция
        namesTable++;
        ordinalTable++;
    }

На самом деле перед нами классический движок для поиска WinAPI по их хешу, о котором мы уже говорили в отдельной статье.

Кроме всего прочего, меня привлек кусок кода, в комментариях к которому было написано «антиэмуляционная защита от КАВа». Такой код встречается в нескольких местах этого проекта:

// Антиэмуляционная защита от КАВа

char path2[MAX_PATH];       // Символьный массив
API(KERNEL32, GetTempPathA)( MAX_PATH, path2 );     // Получаем в него путь до папки временных файлов
API(KERNEL32, CreateFileA)( path2, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 );   // OPEN_EXISTING — открыть файл
if( API(KERNEL32, GetLastError)() == 3 )        // ERROR_PATH_NOT_FOUND

Суть этого приема заключается в том, что эмуляторы антивирусных решений не всегда могут корректно воспроизвести поведение окружения, в котором выполняется приложение. В данном случае троян сначала вызывает функцию GetTempPathA, позволяющую получить путь до папки временных файлов (temp), а затем пытается запустить несуществующий файл из нее. Если после этих действий ОС вернет ошибку ERROR_PATH_NOT_FOUND (обычная ошибка при выполнении приложения в реальной системе), малварь приходит к выводу, что исполнение кода не эмулируется средствами антивируса, и управление передается дальше.

Источник: xakep.ru

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *