Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CLR-Unhook — Современные средства безопасности (CrowdStrike, Bitdefender, SentinelOne и т. д.) хукают функцию nLoadImage внутри clr.dll, чтобы перехватывать и сканировать загрузку .NET-сборок в памяти. Этот инструмент снимает хук с этой функции. | Kitploit
Инструменты/GitHubGitHub/hwbp/clr-unhook
Оборонительные ИнструментыЭксплуатацияПост-эксплуатацияТестирование на ПроникновениеRed TeamingРазработка Полезной Нагрузки
GitHubhwbp/clr-unhook

CLR-Unhook

Современные средства безопасности (CrowdStrike, Bitdefender, SentinelOne и т. д.) хукают функцию nLoadImage внутри clr.dll, чтобы перехватывать и сканировать загрузку .NET-сборок в памяти. Этот инструмент снимает хук с этой функции.

Репозиторий
217228 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Инструмент снятия хуков с CLR

  • Примечание: чтобы получить эффект чистого CLR, вам нужно вручную загружать DLL с диска в память (manual mapping). Вы не можете использовать LoadLibraryA/W, потому что антивирусные решения обнаружат событие загрузки DLL и могут сразу же установить на неё хук. Если вам нужно такое поведение, поищите существующие manual mappers на GitHub и интегрируйте один из них в свою кодовую базу. Я не включаю его сюда, так как вендоры антивирусов в целом этого не ценят.

Нативная утилита на C++, которая обходит хуки EDR/AV в среде .NET Common Language Runtime, восстанавливая исходную реализацию функции nLoadImage.

Краткое описание

Этот инструмент удаляет хуки продуктов безопасности из функции nLoadImage в CLR — критически важной нативной точки входа, которая обрабатывает все загрузки .NET-сборок в память. Читая чистый clr.dll с диска и перезаписывая в памяти байты захваченной функции, он восстанавливает исходное поведение CLR, позволяя Assembly.Load(byte[]) выполняться без проверки или сканирования со стороны EDR.

Что это делает?

Современные продукты безопасности (BitDefender, CrowdStrike, SentinelOne и т.д.) хукают функцию nLoadImage внутри clr.dll, чтобы перехватывать и сканировать загрузку .NET-сборок в память. Этот инструмент снимает хук с этой функции:

  1. Читая чистый clr.dll с диска
  2. Находя оригинальные байты nLoadImage
  3. Перезаписывая захваченную версию в памяти

После снятия хука Assembly.Load(byte[]) выполняется без проверки со стороны EDR.

Понимание nLoadImage

nLoadImage — это критически важная нативная функция, которая обрабатывает все загрузки сборок в память в .NET runtime. Она объявлена как InternalCall в управляемом коде, то есть у неё нет реализации на C# — вместо этого она является прямым мостом к нативному коду CLR.

Цепочка вызова:

root@kitploit:~
Managed Code (C#)
    ↓
Assembly.Load(byte[])
    ↓
RuntimeAssembly.nLoadImage(...) [InternalCall - no managed body]
    ↓
clr.dll!AssemblyNative::LoadImage (Native C++ implementation)
    ↓
Assembly loaded into AppDomain

Почему это критично:

Почти каждая загрузка сборки в память проходит через nLoadImage. Метод Assembly.Load(byte[]) и его перегрузки (включая загрузку с байтами символов) внутри вызывают nLoadImage. Когда вы вызываете Assembly.Load(byte[]), управляемый код в mscorlib.dll передаёт ваш массив байтов через RuntimeAssembly.nLoadImage(), который помечен атрибутом [MethodImpl(MethodImplOptions.InternalCall)] — то есть его тело пусто в C#, и выполнение немедленно переходит к нативному коду CLR.

Даже сценарии динамической генерации кода — фреймворки сериализации, генерирующие сборки во время выполнения, генерация XML-сериализаторов и red team-инструменты, такие как execute-assembly от Cobalt Strike, — все проходят через эту единственную функцию.

Нативная реализация:

Заглушка InternalCall nLoadImage в mscorlib.dll указывает на нативную функцию C++ AssemblyNative::LoadImage внутри clr.dll. Эта функция:

  • Разбирает PE-заголовки из массива байтов
  • Проверяет метаданные и IL-код
  • Выделяет память для сборки
  • Регистрирует сборку в AppDomain
  • Инициирует события после загрузки (ETW, сканирование AMSI в .NET 4.8+)
  • Обрабатывает сборки смешанного режима (нативные + управляемые)
  • Обеспечивает проверку строгих имён (strong-name verification)

В .NET Framework 4.8+ каждый вызов nLoadImage автоматически передаёт байты сборки в AMSI Защитника Windows (AmsiScanBuffer) для сканирования перед выполнением, что делает эту функцию критической точкой для продуктов безопасности.

Сигнатура функции (.NET Framework 4.7+):

root@kitploit:~
[MethodImpl(MethodImplOptions.InternalCall)]
static internal extern Assembly nLoadImage(
    byte[] rawAssembly,              // PE bytes
    byte[] rawSymbolStore,           // Optional PDB bytes
    Evidence evidence,               // CAS evidence (obsolete)
    ref StackCrawlMark stackMark,    // Security stack marker
    bool fIntrospection,             // Reflection-only flag
    bool fSkipIntegrityCheck,        // Skip integrity validation
    SecurityContextSource securityContextSource  // Security context
);

Когда вы вызываете Assembly.Load(byte[]), nLoadImage вызывается с этими типичными параметрами:

root@kitploit:~
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return RuntimeAssembly.nLoadImage(
    rawAssembly,                            // Your byte array
    null,                                   // rawSymbolStore
    null,                                   // evidence
    ref stackMark,                          // LookForMyCaller
    false,                                  // fIntrospection
    SecurityContextSource.CurrentAssembly   // securityContextSource
);

Параметр fIntrospection управляет тем, загружается ли сборка для выполнения (false) или только для проверки через рефлексию (true). Метод Assembly.ReflectionOnlyLoad(byte[]) вызывает nLoadImage с fIntrospection=true, что позволяет изучать метаданные без выполнения кода.

Почему EDR хукает её:

Поскольку nLoadImage — это единственная точка входа для всех загрузок сборок в память, продукты EDR хукают её на нативном уровне в clr.dll. Это позволяет им:

  • Проверять каждую сборку до её загрузки
  • Сканировать массивы байтов на вредоносные паттерны
  • Блокировать выполнение до того, как .NET вообще обработает сборку
  • Обходить техники уклонения от AMSI/ETW (так как хук находится ниже этих уровней)

Традиционные обходы (патчинг AMSI, отключение ETW) не влияют на хуки уровня CLR, поскольку они работают на более высоком уровне стека. Хук происходит внутри самого CLR, ещё до вызова AMSI.

Использование

Локальный процесс (текущий процесс)

root@kitploit:~
CLRUnhook.exe

Снимает хуки с CLR в текущем процессе. Примечание: это работает только если CLR уже загружена (т.е. вы запущены из .NET-приложения или после ручной загрузки CLR).

Удалённый процесс (нацеливание на другой процесс)

root@kitploit:~
CLRUnhook.exe powershell.exe

CLRUnhook.exe 1234

Снимает хуки с CLR в удалённом процессе.

Пример вывода

Успешное снятие хуков в удалённом процессе

root@kitploit:~
=== CLR Unhooking Tool ===

[*] Mode -> Remote Process Unhooking
[*] Target -> PID 21436
[+] Found PID -> 21436
[*] Unhooking CLR->nLoadImage in remote process...
[DEBUG] Remote mode enabled
[DEBUG] Found clr.dll at 0x00007FFD38CB0000
[DEBUG] CLR path -> C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
[DEBUG] CLR module size -> 10108928 bytes
[DEBUG] Read 10108928 bytes from remote process
[DEBUG] Searching for 'nLoadImage' in module (size: 10108928)
[DEBUG] Remote base address: 0x00007FFD38CB0000
[DEBUG] Scanning for string 'nLoadImage' (11 bytes)...
[DEBUG] Found string at RVA 0x7c12b8
[DEBUG] Searching for remote pointer: 0x7ffd394712b8
[DEBUG] Found pointer at offset 0x7a4340
[DEBUG] Valid function pointer found at RVA 0x5e4f30
[DEBUG] Found nLoadImage at RVA 0x00000000005E4F30
[DEBUG] Hooked function address -> 0x00007FFD39294F30
[DEBUG] Clean function at offset 0x00000000005E4F30 in disk file
[DEBUG] Reading hooked bytes before patch...
[DEBUG] First 16 bytes BEFORE unhook:
       4C 8B DC 49 89 5B 08 49 89 73 10 4D 89 4B 20 57
[DEBUG] Clean bytes from disk:
       8B 4B 78 E8 88 A9 EA FF C6 44 24 28 00 80 3D A4
[DEBUG] Wrote 30 bytes successfully
[DEBUG] First 16 bytes AFTER unhook:
       8B 4B 78 E8 88 A9 EA FF C6 44 24 28 00 80 3D A4
[DEBUG] VERIFICATION SUCCESS: Patched bytes match clean bytes!
[+] SUCCESS -> CLR nLoadImage unhooked in remote process!
[+] EDR/AV hooks bypassed

[*] Press Enter to exit...

Цепочка хука

root@kitploit:~
Managed Code (C#)
    ↓
Assembly.Load(byte[])
    ↓
RuntimeAssembly.nLoadImage(...) [InternalCall]
    ↓
clr.dll!AssemblyNative::LoadImage
    ↓
[EDR HOOK] ← We bypass this
    ↓
Original CLR Code

Процесс снятия хуков

  1. Найти захваченную функцию — находит nLoadImage в загруженном clr.dll (в данный момент захвачена хуком)
  2. Загрузить чистую копию — читает оригинальный clr.dll из C:\Windows\Microsoft.NET\Framework64\v4.0.30319\
  3. Извлечь чистые байты — получает первые 30 байт исходной функции; .NET использует JIT, и мы не хотим проблем
  4. Перезаписать хук — патчит захваченную версию чистыми байтами

Обнаружение функции

Использует паттерн-сканирование для поиска nLoadImage:

  1. Поиск строки "nLoadImage" в памяти модуля
  2. Поиск указателя на эту строку
  3. Определение указателя на функцию рядом с указателем на строку
  4. Проверка, что адрес находится в границах модуля

Благодарности

Исследование техники:

  • Matthew Graeber (@mattifestation) — реверс-инжиниринг методов InternalCall и внутренностей CLR

Реализация:

  • HWBP — снятие хуков с CLR через восстановление памяти
  • @Evilbytecode — помог мне с расхукингом, у меня были проблемы из-за того, что .NET использует JIT

Отказ от ответственности

ТОЛЬКО ДЛЯ ОБРАЗОВАТЕЛЬНЫХ И АВТОРИЗОВАННЫХ ИССЛЕДОВАНИЙ БЕЗОПАСНОСТИ.

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

Ссылки

  • Reverse Engineering InternalCall Methods — Matthew Graeber
  • Эталонный исходный код Microsoft .NET
  • Документация по конвейеру загрузки сборок CLR

Скачать инструмент