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

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

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

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

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

Категории

Все категории
Loading categories
Shelter — Обфускация сна на основе ROP для обхода сканеров памяти | Kitploit
Инструменты/GitHubGitHub/kudaes/shelter
Фреймворки для эксплойтовКриминалистика памятиRed Teaming
GitHubkudaes/shelter

Shelter

Обфускация сна на основе ROP для обхода сканеров памяти

Репозиторий
390481 год назадПроверено Kitploit

Популярное

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

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

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

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

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

Shelter

Shelter — это полностью вооруженная техника обфускации сна, которая позволяет полностью зашифровать вашу полезную нагрузку в памяти с широким использованием ROP.

Этот крейт обладает следующими характеристиками:

  • Шифрование AES-128.
  • Возможность шифрования всего PE.
  • Удаление прав на выполнение во время сна.
  • Отсутствие APC/HWBP/таймеров, исключительное использование ROP для достижения обфускации.
  • Использование Unwinder для подделки стека вызовов перед выполнением цепочки ROP.
  • Различные методы выполнения для адаптации к различным обстоятельствам.
  • Другие соображения OPSEC: DInvoke_rs, косвенные системные вызовы, шифрование строковых литералов и т.д.

Содержание

  • Использование
  • Примеры
    • fluctuate
    • fluctuate_from_address
    • fluctuate_from_pattern
  • Тестирование модуля
  • Планы

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

Импортируйте этот крейт в свой проект, добавив следующую строку в ваш cargo.toml:

root@kitploit:~
[dependencies]
shelter = "=0.1.2"

Затем скомпилируйте проект в режиме --release.

Основная функциональность этого крейта обернута в три функции:

  • fluctuate() позволяет зашифровать либо текущую область памяти, либо весь PE. Эта функция требует наличия байт MZ PE для динамического получения его базового адреса.
  • fluctuate_from_address() полностью шифрует PE. Эта функция принимает на вход базовый адрес PE.
  • fluctuate_from_pattern() также полностью шифрует PE. Эта функция принимает на вход пользовательский набор из двух байт для определения базового адреса PE. Эти пользовательские магические байты заменяют классический шаблон MZ.

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

Shelter использует NtWaitForSingleObject для сна. В дополнение к указанию количества секунд для сна, вы также можете передать дескриптор события и сигнализировать его в любое время, чтобы вернуться до истечения тайм-аута (например, используя SetEvent). Учтите, что если вся ваша полезная нагрузка зашифрована (в этом, я полагаю, и заключается суть), вам понадобится альтернативный способ сигнализировать событие, если вы уснули на неопределенный срок.

Примеры

fluctuate

Функция ожидает следующие параметры:

  • Логическое значение, указывающее, шифровать ли весь PE или только текущую область памяти. Передача true требует наличия байт MZ в памяти.
  • Количество секунд, на которое программа будет спать. Если оставить None, тайм-аут будет бесконечным, что означает, что выполнение не вернется, пока не будет сигнализировано событие, переданное в NtWaitForSingleObject.
  • Дескриптор события, передаваемый в NtWaitForSingleObject. Этот параметр может быть None. Программа зависнет, если вы установите этот параметр и тайм-аут оба в None.
root@kitploit:~
let time_to_sleep = Some(10); // Сон на 10 секунд
let _ = shelter::fluctuate(false, time_to_sleep, None); // Шифровать только текущую область памяти
root@kitploit:~
let time_to_sleep = Some(10); // Сон на 10 секунд
let _ = shelter::fluctuate(true, time_to_sleep, None); // Шифровать весь PE
root@kitploit:~
pub type CreateEventW = unsafe extern "system" fn (*const SECURITY_ATTRIBUTES, i32, i32, *const u16) -> HANDLE;

let k32 = dinvoke_rs::dinvoke::get_module_base_address("kernel32.dll"); 
let create_event: CreateEventW;
let event_handle: Option<HANDLE>;
dinvoke_rs::dinvoke::dynamic_invoke!(k32,"CreateEventW",create_event,event_handle,ptr::null_mut(),0,0,ptr::null());
let time_to_sleep = None; // Сон на неопределенный срок
let _ = shelter::fluctuate(true, time_to_sleep, event_handle); // Шифровать весь PE, пока не будет сигнализировано событие

fluctuate_from_address

Функция ожидает следующие параметры:

  • Количество секунд, на которое программа будет спать. Если оставить None, тайм-аут будет бесконечным, что означает, что выполнение не вернется, пока не будет сигнализировано событие, переданное в NtWaitForSingleObject.
  • Дескриптор события, передаваемый в NtWaitForSingleObject. Этот параметр может быть None. Программа зависнет, если вы установите этот параметр и тайм-аут оба в None.
  • Базовый адрес, по которому отображен PE.

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

Пример загрузчика:

root@kitploit:~
let payload: Vec<u8> = your_download_function();
let mut m = dinvoke_rs::manualmap::manually_map_module(payload.as_ptr(), true).unwrap();
println!("Библиотека загружена по базовому адресу 0x{:x}", m.1);
let dll_exported_function = dinvoke::get_function_address(m.1, "run");

let run: unsafe extern "Rust" fn (usize) = std::mem::transmute(dll_exported_function);
run(m.1 as usize);

Пример полезной нагрузки:

root@kitploit:~
#[no_mangle]
fn run(base_address: usize)
{
	...
	let time_to_sleep = Some(10); // Сон на 10 секунд
	let _ = shelter::fluctuate_from_address(time_to_sleep, None, base_address); // Шифровать весь PE от этого конкретного базового адреса
	...
}

fluctuate_from_pattern

Функция ожидает следующие параметры:

  • Количество секунд, на которое программа будет спать. Если оставить None, тайм-аут будет бесконечным, что означает, что выполнение не вернется, пока не будет сигнализировано событие, переданное в NtWaitForSingleObject.
  • Дескриптор события, передаваемый в NtWaitForSingleObject. Этот параметр может быть None. Программа зависнет, если вы установите этот параметр и тайм-аут оба в None.
  • Массив [u8;2], содержащий пользовательские магические байты для поиска с целью получения базового адреса PE.

Смысл создания этой функции в том, чтобы позволить загрузчику удалять заголовок PE и другие сигнатуры, включая классические байты MZ. Таким образом, эти байты могут быть заменены пользовательским шаблоном, который Shelter будет искать для получения базового адреса PE.

root@kitploit:~
let time_to_sleep = Some(10); // Сон на 10 секунд
let pattern = [0x29,0x07];
let _ = shelter::fluctuate_from_pattern(time_to_sleep, None, pattern); // Шифровать весь PE, используя пользовательский шаблон в качестве магических байт

Тестирование модуля

Для тестирования реализации техники в основном использовался PE-sieve. По умолчанию PE-sieve ищет импланты в исполняемых областях памяти, что означает, что даже обфускация исключительно текущей области памяти (.text) достаточна для предотвращения обнаружения:

Обфускация текущей области памяти. Обфускация текущей области памяти (Process Hacker).

Обратите внимание, что, поскольку мы используем Unwinder, стек вызовов подделывается, и поэтому флаг /threads также не обнаруживает отображенную библиотеку.

Теперь PE-sieve позволяет также проверять неисполняемые области памяти с помощью флага /data. Согласно официальной документации инструмента, этот флаг, установленный в always, может «выдать много шума/ложных срабатываний». Несмотря на это, мы решили использовать его для проверки эффективности возможности шифрования всего PE, поскольку он позволяет скрыть области данных PE, которые могут содержать индикаторы присутствия импланта в памяти.

Обфускация текущей области памяти обнаружена PE-sieve. Обфускация всего PE остается незамеченной.

Как видно, на первом рисунке показано, что обфускация только секции .text недостаточна, когда PE-sieve сканирует неисполняемые страницы памяти, поскольку некоторые области могут содержать строки, раскрывающие наличие DLL (MZ, DOS-заголовок, имена секций и т.д.). С другой стороны, второе изображение показывает, как эта проблема может быть решена с помощью механизма обфускации всего PE от Shelter. В любом случае, как указано в вики PE-sieve, эта опция приводит к огромному количеству ложных срабатываний, поскольку само присутствие в куче строк типа ".data" или "rdata" уже предупреждает о возможном внедренном PE, хотя он не может выгрузить что-либо из памяти (так как в этой области нет реального содержимого PE).

Наконец, в PE-sieve есть относительно новая опция для обнаружения присутствия обфусцированных имплантов путем поиска областей памяти с высокой энтропией. Эта опция (/obfusc) в сочетании с /data способна обнаружить присутствие полезной нагрузки из-за высокой энтропии области памяти, содержащей ее (хотя она не может извлечь PE, так как он полностью зашифрован):

Обнаружение обфускации всего PE. Обфускация всего PE (Process Hacker).

Планы

Хотя Shelter готов к использованию и разработан с учетом OPSEC, все еще есть некоторые улучшения, которые будут добавлены в ближайшем будущем:

  • Снижение энтропии при шифровании всего PE.
  • Замена BCryptEncrypt/BCryptDecrypt соответствующей функцией Nt.
  • Добавление некоторой случайности в процесс выбора гаджетов.

Предыдущие работы

  • Gargoyle
  • Ekko
  • Cronos
Скачать инструмент