• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Статья Курим бамбук. Как работает легендарный шифровальщик Babuk.

logotype.png

Введение
Давай вспомним, сколько разных киберпреступлений было совершено с использованием вирусов шифровальщиков? В голове сразу всплывают мысли о великом PetyA или похождениях Revil. А теперь давай подумаем, почему в работе использовался именно такой тип малвари? Ответ крайне простой, ведь с помощью такой игрушки можно спокойно вытянуть огромные суммы из компании или человека. За счет блокировки ценных данных у людей не остается выбора, ведь если они не сделают то, что требуют хакеры, вся их личная жизнь окажется на виду у миллиона пользователей. Я думаю, ты понимаешь, о чем сегодня пойдет речь. Возьмем на прицел один из таких вирусов и попробуем разобраться в алгоритме его работы. А копаться мы будем в легендарном Babuk.

План работы
Думаю все наши планы я разобрал еще во введении, но для закрепления стоит расписать информацию более подробнее. Первым я расскажу тебе как исходники этого добра оказались у меня на руках. Немного заглянем в историю его создателя, а дальше нас ждет только практика. Попробуем понять принцип шифровки и дешифровки информации. Поищем интересные моменты в коде, а также соберем все это дело в один PE-файл.

Предыстория
Итак, перед тем как начать давай я верну тебя на год назад и расскажу с чего все началось. Сам топик со всеми сорсами лежит здесь, единственный минус ссылка больше не работает, а автор в неизвестном положении и не факт, что он дожил до наших дней. Но за старание и проделанный труд все же хочется сказать спасибо. Ну а как так получилось давай разбираться.

xss_ini.jpg


Начнем с того, что страница автора уже находится вне актива. Последние слова остались в поддержку состояния человека, ведь оставалось ему жить не так долго. О болезни говорить не будем, но именно он выложил исходный код своего проекта на форуме. Как ты понимаешь из диалога человеку 17 лет и за его творчество точно оставило след в истории. Ну а более подробнее о содержании архива можно вычитать из статьи на . Полистав топик можно выяснить, что сборка проекта проходит в папке Release и с форматом x86. А примерно так новость обо всем этом выкатили vx-underground в своем твиттере.

underground.jpg


С историей все печально, но наша задача разобраться в коде, поэтому воспоминания плавно перетекают в практику и разбор полета.

Разбираемся в коде
Любая работа шифровальщика завязана на методе запутывания данных. У каждого зловреда есть свой способ заблокировать информацию, чтобы пользователь не добрался до нее. Ну а перед работой предоставим доступ к локальной папке Visual Studio, чтобы было удобнее работать и ориентироваться в коде. Делается это на главной странице. Весь код ты сможешь над которым мы будем работать ты сможешь найти в разделе ресурсов.

Так как это все исходный код, который держится на C и C++, то тебе потребуются минимальные знания этих языков. Теперь, после импорта всех параметров можно начать работу. Первым делом я заглянул в файл Proj.sln. Он содержит всю необходимую основу для работы шифровальщика. Открываем этот файл и смотрим его содержимое. Здесь нас ждет еще 3 проекта с достаточно странными названиями d, e и test. Начнем по порядку и откроем самый первый файл. Мой взгляд тут же упал на название debug, в нем хранится обработчик ошибок, который в случаи некорректной работы создает файл и записывает в него все происходящие в программе процессы. Обрати внимание, что обращается программа к нашим ошибкам постоянно, поэтому в переменной h_log_file стоит параметр OPEN_ALWAYS. Это сделано с целью производительности, чтобы не открывать по десять раз один и тот же файл. Ну а в самом начале импортируется заголовок с названием debug.h. Открываем его во вкладке "Файлы заголовков" и смотрим, что там интересного есть. В этом месте инициализируется сама ошибка, которая включает в себя цель и сообщение при помощи функций. Ну а дальше все это дело фиксируется в переменной LogFile. Но это еще не самое интересное, что мне удалось найти. Загляни в файл another.cpp. Что ты видишь? Правильно, название процессов, которые подлежат остановки после запуска локера. Выглядит это как обычный массив с данными. Ну а дальше идет сам процесс в котором все это дело выключается. Помогает во всем этом деле эта строчка кода:

C++:
ShellExecuteW(0, L"open", L"cmd.exe", L"/c vssadmin.exe delete shadows /all /quiet", 0, SW_HIDE);

Да, ты все правильно понял. Шифровальщик выполняет консольную команду, чтобы завершить все ненужные процессы. Далее идет обработка ошибок и больше ничего интересного в файле найти не удалось. А теперь к самому главному. Как же шифровальщик шифрует информацию? Давай посмотрим на это дело в файле entry.cpp. В этом месте и начинается веселье. Для начала переведу твой взгляд на одну из первых строчек кода, которая создает белый лист с папками/файлами не подлежащих шифрованию. Сделано это с одной целью - постараться не повредить операционную систему. Весь список ты можешь видеть ниже.

C++:
static const WCHAR* black[] = {
    0, L"AppData", L"Boot", L"Windows", L"Windows.old",
    L"Tor Browser", L"Internet Explorer", L"Google", L"Opera",
    L"Opera Software", L"Mozilla", L"Mozilla Firefox", L"$Recycle.Bin",
    L"ProgramData", L"All Users", L"autorun.inf", L"boot.ini", L"bootfont.bin",
    L"bootsect.bak", L"bootmgr", L"bootmgr.efi", L"bootmgfw.efi", L"desktop.ini",
    L"iconcache.db", L"ntldr", L"ntuser.dat", L"ntuser.dat.log", L"ntuser.ini", L"thumbs.db",
    L"Program Files", L"Program Files (x86)", L"#recycle", L"..", L"."
};

Удивительно то, что процессы он вырубает, а файлы не шифрует в этих папках. Также чуть выше находится переменная с названием "Как восстановить файлы.txt". Вероятнее всего этот текстовый документ создан специально для жертвы. Ну а теперь давай разберемся с тем, как шифруются файлы. Для начала в этом деле используются HC-256. Давай разберемся, что он их себя представляет.

HC-256 представляет собой потоковый шифр предназначен для обеспечения объемного шифрования в программном обеспечении на высоких скоростях, позволяя твердую уверенность в своей безопасности. 128-битный вариант был представлен как кандидат на шифрование eSTREAM и был выбран в качестве одного из четырех финальных участников в профиле программного обеспечения.

Работает он следующим образом. В наличии есть 256-битовый ключ и вектор инициализации (входной сигнал криптографического примитива) также состоящий из 256 бит. Если разглядывать все это дело изнутри, то все держится на двух секретных таблицах (P и Q). Каждая содержит 1024 слов формата 32-бит. Все это дело обновляется при помощи нелинейной функции. Спустя 2048 шагов таблицы с элементами полностью меняются.

Чтобы сгенерировать слово применяется функция линейного битового маскирования. Она состоит из двух параметров расписания сообщений в хэш-функции SHA256 внутри, но при этом задействуется таблица P и Q.

И на этой всей основе работает итоговое шифрование файлов в формат .babyk. Также в работе у нас без внимания остаются PE-файлы. Работу с ними можно увидеть в обычном условном цикле, где происходит посимвольное чтения названия файла, а после сравнение. Если конец файла равен .exe или .dll, то все это дело игнорируется. В принципе ты и сам можешь посмотреть на все это дело:

C++:
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && lstrcmpW(fd.cFileName, NOTE_FILE_NAME) != 0)
{
    for (int i = lstrlenW(fd.cFileName) - 1; i >= 0; i--) {
        if (fd.cFileName[i] == L'.') {
            if (
                lstrcmpiW(fd.cFileName + i, L".exe") == 0
                    ||
                lstrcmpiW(fd.cFileName + i, L".dll") == 0
                    ||
                lstrcmpiW(fd.cFileName + i, L".babyk") == 0
                ) {
                goto skip;
            }
            else break;
        }
}

Больше в проекте ловить нам нечего. Но раз эта часть отвечает за шифрование, то другая должна все это дело расшифровывать. Поэтому переходим на проект ниже и открываем файл entry.cpp. Здесь как раз и содержится вся необходимая информация для расшифровки. Изрядно поломав себе мозги я так и не понял в чем подвох и почему метод дешифровки выглядит значительнее проще чем шифровка. Но давай пройдемся по коду. На первых строчках нас опять встречает белый список исключений. Файлы и папки которые ни в коем случаи нельзя трогать. Далее к этому делу добавляется уже известный файл для жертвы. Проходит инициализация ключа на валидность и дальше все становится значительно интереснее. Сам процесс проверки ты можешь посмотреть в коде. Он находится в условном цикле с переменной INVALID_HANDLE_VALUE.

Возвращаемся к дешифровки. Она находится чуть ниже проверки и работает следующим образом. Если файл имеет окончание babyk, то он устанавливает его местоположение. Также устанавливается положение конфигураций сети, которые к сожалению для жертвы шифруются тоже. Кстати все конфиги с шифрованием HP-256 ты можешь найти в папке eSTREAM. Алгоритм дешифрации файлов первым делом проходит по дискам начиная с буквы A и заканчивая Z. То есть в теории если мы вставим флешку в ПК и запустим шифровальщик, то под раздачу попадут абсолютно любые диски. Все продумано до мелочей. Далее у нас идет замена символов с использованием сдвига в пять знаков. Ну и с помощью рекурсивного подхода происходит поиск нужных данных. Также это все дело проверяется на наличие ошибок, что дает гарантию на расшифровку файлов. На коде все выглядит следующим образом.

C++:
if (dwDrives & 1)
                {
                    if (WCHAR* driveBuffer = (WCHAR*)_halloc(7 * sizeof(WCHAR))) {
                        lstrcpyW(driveBuffer, L"\\\\?\\");
                        lstrcpyW(driveBuffer + 5, L":");
                        driveBuffer[4] = disk;

                        if (DWORD driveType = GetDriveTypeW(driveBuffer)) {
                            if (driveType != DRIVE_CDROM) {
                                if (driveType != DRIVE_REMOTE) {
                                    find_files_recursive(driveBuffer);
                                }
                                else {
                                    DWORD remoteDrvSize = 260;
                                    if (WCHAR* remoteDrv = (WCHAR*)_halloc(remoteDrvSize * sizeof(WCHAR)))
                                    {
                                        if (WNetGetConnectionW(&driveBuffer[4], remoteDrv, &remoteDrvSize) == NO_ERROR) {
                                            find_files_recursive(remoteDrv);
                                            _hfree(remoteDrv);
                                        }
                                    }
                                }
                            }
                        }
                        _hfree(driveBuffer);
                    }

Если немного полистать и погулять по файлам малвари, то ты скорее всего заметишь, что многие файлы идентичные друг другу. Поэтому на этом все самое интересное заканчивается. Также хочу сказать, что весь проект ты можешь собрать наведя курсор на файл Proj.sln и нажав по нему правой кнопкой мыши. Далее выбирай пункт собрать и жди готового результата. Папка test отвечает за работу шифра и ты его можешь спокойно протестить на работоспособность. По мимо этого в архиве расположен генератор ключей с определенной последовательностью байтов, которая требуется для разблокировки системы. Как ты понимаешь теперь, чтобы все это дело завершить нам нужно подвести итог.

Подводим итог
На первый взгляд сложно сказать, что весь этот код написал и опубликовал 17-ти летний парень, но с другой стороны мало, кто рискнул бы на такой шаг. Ведь после выпуска Babuk в свет на его основе составляли другие шифровальщики. Тот же Rook стоит на всем этом коде, а что уже говорить про другие. Поэтому не заметить такой зловред крайне сложно. По результатам статьи мы достигли цели и разобрали, все, что нам нужно.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!