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

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

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

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

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

Категории

Все категории
Loading categories
Fiber — Rust-based PoC, использующий Windows fibers для скрытого выполнения кода в памяти, скрывая стеки полезной нагрузки от EDR путем переключения между управляющим и полезным волокнами без вызовов ядра. | Kitploit
Инструменты/GitHubGitHub/kudaes/fiber
Пост-эксплуатацияRed TeamingРазработка Полезной Нагрузки
GitHubkudaes/fiber

Fiber

Rust-based PoC, использующий Windows fibers для скрытого выполнения кода в памяти, скрывая стеки полезной нагрузки от EDR путем переключения между управляющим и полезным волокнами без вызовов ядра.

Репозиторий
245182 лет назадПроверено Kitploit

Популярное

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

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

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

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

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

Описание

Fiber (волокно) — это единица выполнения, которая должна планироваться вручную приложением, а не полагаться на механизм планирования на основе приоритетов, встроенный в Windows. Fibers часто называют легковесными потоками. Для получения более подробной информации о том, что такое fibers и как они работают, обратитесь к официальной документации. Fibers позволяют иметь несколько потоков выполнения в одном потоке, каждый со своим собственным состоянием регистров и стеком. С другой стороны, fibers невидимы для ядра, что делает их более скрытным (и более дешёвым) методом выполнения кода в памяти, чем создание новых потоков.

Один поток может создать несколько fibers и переключаться между ними по желанию, вызывая функцию SwitchToFiber. Перед этим текущий поток сам должен стать fiber, вызвав ConvertThreadToFiber, поскольку только fiber может создавать другие fibers. Наконец, чтобы создать fiber, который при планировании выполняет код в памяти (например, после отражённой загрузки PE или шеллкода), достаточно вызвать CreateFiber.

Функция SwitchToFiber является наиболее важной частью этого процесса, и именно в ней происходит вся магия. Эта функция позволяет запланировать один fiber или другой, причём всё происходит в пользовательском пространстве. Согласно официальной документации, «функция SwitchToFiber сохраняет информацию о состоянии текущего fiber и восстанавливает состояние указанного fiber». Это означает, что при вызове этой функции значения регистров и стек переключаются с состояния текущего fiber на состояние целевого fiber, позволяя «скрыть» стек текущего fiber после завершения процесса. Это также позволяет продолжить выполнение целевого fiber с той же точки, где выполнение было остановлено (так же, как это происходит, когда планировщик переключается между потоками в соответствии с собственной логикой приоритетов).

И именно это делает данная простая PoC:

  • Во-первых, у нас есть загрузчик, который использует DInvoke для ручного отображения DLL, содержащей нашу полезную нагрузку.
  • После этого загрузчик превращает текущий поток в fiber (далее известный как управляющий fiber). Управляющий fiber будет иметь «нормальный» стек, поскольку загрузчик выполняется из PE на диске.
  • Затем загрузчик создаёт новый fiber для выполнения функции run(), экспортируемой вручную отображённой DLL. Этот fiber будет далее известен как полезный fiber.
  • Управляющий fiber переключается на полезный fiber, который выполняет любой код, содержащийся в полезной нагрузке. Как только полезной нагрузке необходимо войти в состояние ожидания (например, при вызове Sleep), полезный fiber переключается обратно на управляющий fiber, скрывая свой стек (который может содержать несколько IOC вредоносной активности).
  • Управляющий fiber выполняет вызов Sleep. Когда вызов возвращается, он снова переключается на полезный fiber, чтобы тот мог продолжить выполнение.

Этот процесс повторяется бесконечно.

Преимущества

Использование fibers может быть выгодно для некоторых типов полезных нагрузок (например, для C2 beacon) по следующим причинам:

  • Fibers позволяют выполнять код в памяти без необходимости использования инструкций JMP или CALL от загрузчика, указывающих на неразмеченные области памяти.
  • Это выполнение происходит без создания новых потоков, что предотвращает генерацию обратных вызовов от ядра, которые могут быть собраны EDR.
  • Стек полезного fiber можно скрыть, когда полезная нагрузка входит в состояние ожидания или ей необходимо дождаться завершения операции ввода-вывода. Это делается с помощью управляющего fiber с нормальным стеком, который выполняет код с диска. Такое «сокрытие» дешевле и проще в реализации, чем обычный процесс подмены стека потока.
  • Fibers невидимы для ядра, и вся процедура переключения происходит в пользовательском пространстве, что упрощает скрытие от EDR.

Недостатки

  • В один момент времени в потоке может быть запланирован только один fiber, что означает, что для достижения реальной параллельности с помощью fibers необходимо создавать дополнительные потоки.
  • Хотя стек полезного fiber скрыт, когда управляющий fiber переключается обратно, он остаётся в памяти процесса и может быть обнаружен при проверке памяти.
  • Для скрытия импланта в памяти всё ещё требуется обфускация; это всего лишь способ скрыть стек и метод выполнения.

Компиляция

Поскольку мы используем плагин LITCRYPT для обфускации строковых литералов, перед компиляцией кода необходимо задать переменную окружения LITCRYPT_ENCRYPT_KEY:

root@kitploit:~
C:\Users\User\Desktop\Fiber> set LITCRYPT_ENCRYPT_KEY="yoursupersecretkey"

После этого просто скомпилируйте как полезную нагрузку, так и загрузчик, и запустите последний:

root@kitploit:~
C:\Users\User\Desktop\Fiber\payload> cargo build --release
C:\Users\User\Desktop\Fiber\loader> cargo build --release
C:\Users\User\Desktop\Fiber\loader\target\release> loader.exe

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

В выполнении этой PoC нет особой тайны. Всё, что нужно сделать, — запустить загрузчик и использовать любой инструмент, например ProcessHacker, для проверки стека потока. Поскольку полезная нагрузка переключается обратно на управляющий fiber перед сном, стек полезного fiber остаётся скрытым большую часть времени. Вы увидите в выводе, как два fibers последовательно планируются по уже описанной логике.

Код закомментирован, чтобы показать, как использовать, создавать и планировать fibers. Вы заметите, что и загрузчик, и полезная нагрузка, представленные в качестве примера, «застряли» в бесконечном цикле, что позволяет бесконечно переключаться между fibers и продолжать выполнение.

Если вы хотите протестировать другую полезную нагрузку, просто измените путь в строке 32 файла src::main.rs загрузчика. В этом случае новая DLL должна экспортировать функцию run(PVOID), которая будет получать в качестве входного параметра адрес управляющего fiber. Эта функция должна переключаться обратно на управляющий fiber для вызова функции Sleep, хотя вы можете изменить это поведение по своему усмотрению, чтобы соответствовать вашим требованиям.

Другой способ протестировать этот инструмент со случайной полезной нагрузкой — выполнить перехват IAT для перенаправления любого вызова функции Sleep (или любой другой импортированной функции), сделанного полезной нагрузкой, на функцию, расположенную в загрузчике, что позволит переключиться обратно на управляющий fiber при возникновении этого вызова. Решать вам.

На следующих скриншотах видно, как стек текущего потока перемещается из одной частной области памяти в другую при переключении fibers:

Стек в Process Hacker Стек в Process Hacker

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