Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
iqvw64e-privilege-escalation — CVE-2015-2291 Escalada de privilegios local PoC | Kitploit
Herramientas/GitHubGitHub/ethanedits/iqvw64e-privilege-escalation
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónIngeniería InversaAprendizaje y EducaciónExplotación de Binarios
GitHubethanedits/iqvw64e-privilege-escalation

iqvw64e-privilege-escalation

CVE-2015-2291 Escalada de privilegios local PoC

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Ver Repositorio
2hace 6 mesesAún no revisado

iqvw64e-privilege-escalation

CVE-2015-2291 PoC de escalada de privilegios local

PoC

Resumen

Este proyecto es una prueba de concepto educativa para una vulnerabilidad de Escalada de Privilegios Local (LPE) en el driver iqvw64e.sys (SHA256: 37c637a74bf20d7630281581a8fae124200920df11ad7cd68c14c26cc12c5ec9) — el controlador de diagnóstico de Ethernet de Intel asociado con CVE-2015-2291.

Después de ver el driver explotado en cargadores de modo kernel como KDMapper, quise realizar ingeniería inversa por mi cuenta para entender cómo funciona el despacho de IOCTL, qué tipo de funciones expone al modo usuario y cómo un atacante podría descubrirlas o aprovecharlas. Este análisis recorre el proceso desde el análisis estático hasta la construcción de primitivas de memoria usando DeviceIoControl, y finalmente la creación de un exploit que abusa de esas primitivas para reemplazar el token de acceso del proceso actual con el token del proceso SYSTEM, elevando efectivamente el proceso a privilegios SYSTEM.

En Windows, cada proceso está asociado con un token de acceso que define su identidad y privilegios. Al obtener lectura/escritura arbitraria del kernel, se vuelve posible modificar el puntero al token almacenado en la estructura de proceso del kernel. Reemplazar este puntero con el del proceso SYSTEM hace que el SO asocie el proceso actual con el contexto de seguridad de SYSTEM, otorgándole efectivamente privilegios completos. Obtenga más información aquí.

Del Manejador de IOCTL a la Tabla de Saltos

El driver registra una rutina de despacho para IRP_MJ_DEVICE_CONTROL, que maneja llamadas DeviceIoControl desde el modo usuario. Como se muestra a continuación, conduce a sub_11150 que dirige el flujo de código según el Código de Control de IO de entrada. En este caso, estamos interesados en 0x80862007, que nos lleva a loc_111C2.

IRP_MJ_DEVICE_CONTROL

Siguiendo el flujo de control a través de loc_111C2, llegamos a sub_113C0. Recibe un búfer de entrada (a1) y usa el primer QWORD de ese búfer como índice en una tabla de saltos de funciones manejadoras internas. Aquí, el driver realiza lo siguiente:

  • Lee a1 → primer QWORD (0x0) → jump_table_index

  • Realiza un switch basado en este índice

  • Despacha a la función interna correspondiente

  • Usa los campos restantes de a1 como argumentos

Ahora sabemos que el búfer de entrada controla tanto el objetivo de despacho como sus parámetros. Definiremos más a fondo la estructura del búfer de entrada a medida que continuamos el análisis.

root@kitploit:~
typedef struct _MEMMOVE_INPUT_BUFFER
{
uint64_t jump_table_index; // 0x00 — used as the dispatch selector
} MEMMOVE_INPUT_BUFFER, *PMEMMOVE_INPUT_BUFFER;

loc_111C2

sub_113C0

Identificación de la Primitiva memmove

Mientras analizaba los casos de la tabla de saltos, busqué manejadores que se asemejaran a memmove o memcpy. En el caso 0x33, el driver llama a sub_11EA0, pasando tres campos del búfer de entrada. Esto se asemeja fuertemente a una copia de memoria:

case_0x33

Al abrir sub_11EA0, encontramos la firma esperada:

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

El desensamblado confirma que:

  • Argumento a1 = destination
  • Argumento a2 = source
  • Argumento a3 = length

sub_11EA0

Con esta información, ahora podemos reconstruir completamente el diseño del búfer de entrada esperado para la llamada 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;

Logrando Lectura/Escritura Arbitraria de Memoria

Ahora entendemos que al enviar un MEMMOVE_INPUT_BUFFER válido al driver, con:

  • jump_table_index = 0x33
  • source, destination y length configurados según sea necesario

Podemos instruir al driver para que llame a memmove en direcciones arbitrarias, lo que nos otorga capacidades completas de lectura/escritura de memoria del kernel desde el modo usuario.

Aquí están los wrappers de modo usuario construidos alrededor de esta primitiva:

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));
}

Estos ayudantes permiten lecturas y escrituras arbitrarias de 64 bits en memoria virtual del kernel. A partir de este punto, varios ataques se vuelven posibles (como robo de token de EPROCESS), pero este análisis se centra en reconstrucción y análisis. Encontrará que main.cpp contiene un exploit PoC de robo de token de EPROCESS, cortesía de Eap2468 en CVE-2021-2155

Notas

  • Versión de Windows: 10 x64 22H2 (19045.6466)

  • Desplazamientos de EPROCESS:

    • UniqueProcessId: 0x440
    • ActiveProcessLinks: 0x448
    • Token: 0x4b8
  • Driver: iqvw64e.sys (El binario del driver ha sido incluido en el repositorio para su conveniencia)

  • SHA256: 37c637a74bf20d7630281581a8fae124200920df11ad7cd68c14c26cc12c5ec9

Referencias y Créditos

  • CVE-2015-2291 (iqvw64e.sys)
  • KDMapper
  • CVE-2021-21551 / Token Stealing Exploit
  • Proyecto Vergilius por las Definiciones de Estructuras de Windows

Showcase

PoC

Descargar herramienta