Другое

DLL Injection в .NET: Руководство по замене DLL фреймворка

Исследуйте возможность DLL-инъекции в .NET через замену DLL фреймворка. Узнайте о порядке загрузки сборок, механизмах безопасности и более надежных методах перехвата.

Возможно ли выполнить инъекцию DLL в приложении .NET, размещая измененную версию DLL фреймворка (такую как System.Diagnostics.Process.dll) в рабочем каталоге для перехвата вызовов API? Конкретно говоря, если исполняемый файл .NET со своими зависимостями (dll, deps.json и runtimeconfig.json) запускает процесс с именем ‘alpha.exe’, может ли измененный System.Diagnostics.Process.dll в рабочем каталоге перенаправить его на ‘beta.exe’ вместо этого?

Да, внедрение DLL в .NET-приложение путем размещения измененной DLL фреймворка в рабочем каталоге технически возможно, но сталкивается со значительными трудностями из-за механизмов безопасности .NET и порядка загрузки сборок. Среда выполнения .NET обычно загружает сборки фреймворка из GAC (Global Assembly Cache) или каталогов фреймворка перед проверкой рабочего каталога, что делает этот подход ненадежным для перехвата основных API фреймворка, таких как System.Diagnostics.Process.

Понимание внедрения DLL в .NET

Внедрение DLL — это техника, используемая для запуска кода в адресном пространстве другого процесса путем принудительной загрузки динамически подключаемой библиотеки [источник]. В контексте .NET-приложений это становится более сложным из-за управляемой среды выполнения.

Для .NET-процессов существуют два основных типа подходов к внедрению DLL:

  1. Внедрение нативной DLL: внедрение нативной (неуправляемой) DLL, которая затем может взаимодействовать с средой выполнения .NET
  2. Внедрение управляемой DLL: прямое внедрение управляемой .NET-сборки

Рассматриваемая вами техника относится ко второй категории — попытка заменить DLL фреймворка вредоносной версией. Согласно исследованиям, этот подход включает в себя “простое внедрение нативной DLL, затем в DLLMain мы получаем дескриптор для .NET фреймворка и, наконец, выполняем фрагмент кода” [источник].

Порядок загрузки сборок в .NET

Среда выполнения .NET следует определенному порядку при поиске сборок, что важно для понимания, почему предложенный вами подход может работать не так, как ожидается.

Поведение по умолчанию при загрузке сборок заключается в следующем:

  1. Сначала поиск во всех системных расположениях (например, в GAC)
  2. Проверка текущего каталога (рабочего каталога)
  3. Наконец, поиск в любых определенных пользователем путях [источник]

Это означает, что для сборок фреймворка, таких как System.Diagnostics.Process, среда выполнения обычно найдет легитимную версию в каталоге .NET фреймворка или в GAC, прежде чем даже рассмотрит возможность поиска в рабочем каталоге приложения.

Важное замечание о безопасности: Такое поведение существует специально для предотвращения атак с захватом DLL. Как объясняет Microsoft, “фраза ‘Dll hijack’ означает поиск способа заставить целевое приложение загрузить вашу dll вместо правильного бинарного файла” [источник].

Проблемы замены DLL фреймворка

Замена основной DLL фреймворка, такой как System.Diagnostics.Process.dll, сталкивается с несколькими значительными техническими трудностями:

Сильное именование и Authenticode

Сборки фреймворка имеют сильные имена и цифровые подписи Microsoft. Среда выполнения .NET выполняет проверки целостности этих сборок, что затрудняет простую замену их вредоносными версиями.

Проблемы с блокировкой загрузчика

При попытке внедрить управляемый код необходимо быть “очень осторожным при выполнении кода в методе DLLMain из-за блокировки загрузчика” [источник]. Блокировка загрузчика — это критический примитив синхронизации в загрузчике Windows, и удержание ее во время инициализации DLL может вызвать взаимоблокировки.

Перенаправления привязки сборок

Современные .NET-приложения используют файлы конфигурации (app.config, web.config), которые могут содержать перенаправления привязки сборок. Эти перенаправления явно указывают среде выполнения, какую версию сборки загружать, потенциально обходя любую DLL в рабочем каталоге.

Зависимости и зависимости

DLL фреймворка имеют сложные зависимости. Например, System.Diagnostics.Process.dll зависит от других основных сборок. Заменяющая DLL должна правильно реализовывать или проксировать все эти зависимости.

Практические соображения по реализации

Если вы пытаетесь реализовать эту технику, вот практические соображения:

Управление текущим рабочим каталогом

Рабочий каталог обычно устанавливается в расположение исполняемого файла или может быть изменен программно. Атакующему необходимо убедиться, что его вредоносная DLL находится в правильном каталоге перед запуском целевого приложения.

Перехват создания процесса

Для перехвата вызовов Process.Start() ваша вредоносная DLL должна:

  1. Перехватить метод Process.Start
  2. Определить, когда запускается ‘alpha.exe’
  3. Перенаправить вызов для запуска ‘beta.exe’ вместо этого
  4. Возможно, проксировать исходную функциональность

Нативный против управляемого подхода

Некоторые исследования показывают, что “LoadLibrary и т.д. загружают только нативные библиотеки” [источник], что означает, что вам может потребоваться создать нативную DLL, которая загружает .NET фреймворк и затем выполняет ваш управляемый код.

csharp
// Пример того, что может содержать вредоносная Process.dll
public static class Process
{
    public static Process Start(ProcessStartInfo startInfo)
    {
        if (startInfo.FileName == "alpha.exe")
        {
            startInfo.FileName = "beta.exe";
        }
        return System.Diagnostics.Process.Start(startInfo);
    }
}

Безопасностные последствия

Этот тип атаки относится к нескольким категориям безопасности:

CWE-427: Неконтролируемый элемент пути поиска

Уязвимость, которую вы описываете, соответствует CWE-427 от MITRE: “Плохо загружать сборки из каталогов, которые атакующий может контролировать” [источник]. Это хорошо известная слабость безопасности, с которой Microsoft боролась в последних версиях .NET.

Атаки предварительной загрузки DLL

Microsoft предоставляет конкретные рекомендации по “безопасной загрузке библиотек для предотвращения атак предварительной загрузки DLL” [источник]. Современные версии .NET улучшили безопасность, чтобы сделать эти атаки более сложными.

Стратегии смягчения рисков

Приложения могут предотвратить этот тип атаки путем:

  • Использования явной загрузки сборок с полными путями
  • Реализации изоляции AppDomain
  • Использования сильных перенаправлений привязки сборок
  • Следования лучшим практикам Microsoft для загрузки сборок [источник]

Альтернативные подходы

Если ваша цель — перехват создания процесса в .NET-приложении, существуют более надежные подходы:

Перехват нативных API

Вместо замены управляемых сборок вы можете перехватывать нативные API Windows, такие как CreateProcess или ShellExecute, которые используются Process.Start().

Использование API профилирования

.NET предоставляет API профилирования, которые позволяют отслеживать и изменять вызовы методов во время выполнения.

ETW (Event Tracing for Windows)

ETW можно использовать для мониторинга событий создания процесса и потенциального их перехвата или изменения.

Переменные окружения

Вы можете изменить PATH или другие переменные окружения для контроля, какой исполняемый файл находится.


Источники

  1. DLL injection - Wikipedia
  2. DLL Injection Part 4 — Injecting managed DLL – Random IT Utensils
  3. DLL injection - Microsoft Q&A
  4. .NET - In what order are locations searched to load referenced DLLs? - Stack Overflow
  5. Prevent .Net Framework from Loading Assemblies from Current Working Directory - Stack Overflow
  6. Secure loading of libraries to prevent DLL preloading attacks - Microsoft Support
  7. Dll Injection in C# not working - Stack Overflow
  8. DLL Hijacking - HackTricks

Заключение

Хотя технически возможно попытаться внедрить DLL в .NET путем размещения измененной DLL фреймворка в рабочем каталоге, этот подход сталкивается со значительными трудностями из-за механизмов безопасности .NET и порядка загрузки сборок. Среда выполнения .NET разработана так, чтобы отдавать приоритет сборкам фреймворка перед DLL из рабочего каталога, что делает надежный перехват основных API, таких как System.Diagnostics.Process, затруднительным.

Для практических целей существуют более надежные альтернативные подходы для перехвата создания процесса, включая перехват нативных API, API профилирования .NET и мониторинг ETW. Современные версии .NET реализовали дополнительные меры безопасности для предотвращения атак предварительной загрузки DLL, что делает эту технику все менее надежной.

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

Авторы
Проверено модерацией
Модерация