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
CVE-2024-20698 — Análisis de la vulnerabilidad | Kitploit
Herramientas/GitHubGitHub/romanrybachek/cve-2024-20698
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónIngeniería InversaAnálisis de Binarios
GitHubromanrybachek/cve-2024-20698

CVE-2024-20698

Análisis de la vulnerabilidad

Ver Repositorio
5173hace 2 añosRevisado por Kitploit

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

CVE-2024-20698

Acerca de esta vulnerabilidad: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-20698

Análisis del parche

En ntoskrnl.exe tenemos dos funciones parcheadas: sub_1406AE224 y WbAddLookupEntryEx. La función vulnerable es WbAddLookupEntryEx. Rutas a esta función:

drawing

Para llamar a esta función necesitamos llamar a NtQuerySystemInformation con el primer argumento 0xb9. El primer byte en el búfer, que el usuario proporciona como segundo argumento, es la opción para este switch:

root@kitploit:~
switch ( first_byte_in_usermod_buf )
{
    case 1:
      status_1 = WbDecryptEncryptionSegment(item, copy_of_usermod_buf, NumberOfBytes_1);
      goto set_status_and_return;
    case 2:
      status_1 = WbReEncryptEncryptionSegment(item, copy_of_usermod_buf, NumberOfBytes_1);
      goto set_status_and_return;
    case 3:
      status_1 = WbHeapExecuteCall(item, copy_of_usermod_buf, usermod_buffer, NumberOfBytes_1);
      goto set_status_and_return;
    case 4:
      if ( !copy_of_usermod_buf )
      {
        status_1 = patched_case4_no_user_buffer(item, another_item);
set_status_and_return:
        status = status_1;
        goto return;
      }
      break;
    case 5:
    case 6:
      status = usermod_buffer != 0i64 ? STATUS_NOT_IMPLEMENTED : STATUS_INVALID_PARAMETER;
      goto return;
    case 7:
      status_1 = WbRemoveWarbirdProcess(item->proc_handle);
      goto set_status_and_return;
    case 8:
      status_1 = WbProcessStartup(item, copy_of_usermod_buf, NumberOfBytes_1);
      goto set_status_and_return;
    case 9:
      status_1 = WbProcessModuleUnload(item, copy_of_usermod_buf, NumberOfBytes_1);
      goto set_status_and_return;
}
Descargar herramienta

Para cada proceso que usa NtQuerySystemInformation con el argumento 0xb9, se creará una estructura que se almacenará en la memoria hasta que el proceso termine. Llamé a esta estructura item_instance. Primero, la función sub_1406AF294 intenta encontrar la estructura del proceso entre otras estructuras similares. Los punteros a estas estructuras se almacenan en la memoria en orden de ID de proceso. Si no se encuentra la estructura, se creará mediante WbCreateWarbirdProcess. A continuación, se añadirá un puntero a esta estructura al array usando WbAddLookupEntryEx, que es vulnerable.
El código de WbAddLookupEntryEx antes del parche:

root@kitploit:~
NTSTATUS WbAddLookupEntryEx(
        items_info *items_info,
        __int64 new_item_pointer,
        __int64 not_used,
        unsigned int new_item_index)
{
  unsigned int last_item_index;
  NTSTATUS status;
  unsigned int old_items_count;
  unsigned int size_of_item;

  last_item_index = items_info->last_item_index;
  status = 0;
  old_items_count = items_info->old_items_count;

  if ( last_item_index + 1 >= old_items_count )
  {
    status = WbReAlloc(
               items_info->vuln_buffer,
               old_items_count * items_info->size_of_item,
               items_info->size_of_item * (old_items_count + items_info->count_of_new_items),
               &items_info->vuln_buffer);

    if ( status < 0 )
      return status;

    items_info->old_items_count += items_info->count_of_new_items;
    old_items_count = items_info->old_items_count;
    last_item_index = items_info->last_item_index;
  }

  if ( new_item_index > last_item_index || !old_items_count )
    return STATUS_INVALID_PARAMETER;
  memmove(
    (char *)items_info->vuln_buffer + (new_item_index + 1) * items_info->size_of_item,
    (char *)items_info->vuln_buffer + new_item_index * items_info->size_of_item,
    items_info->size_of_item * (last_item_index - new_item_index));

  size_of_item = items_info->size_of_item;
  ++items_info->last_item_index;
  *(_QWORD *)((char *)items_info->vuln_buffer + new_item_index * size_of_item) = new_item_pointer;
  return status;
}

Reasigna el array de punteros e inserta un nuevo puntero.

El parche añade estas comprobaciones de seguridad:

root@kitploit:~
status = RtlULongMult(old_items_count, items_info->size_of_item, &size_of_old_items);
if ( status < 0 )
  return status;
status = RtlULongAdd(old_items_count, items_info->count_of_new_items, &sum_result);
if ( status < 0 )
  return status;
status = RtlULongMult(sum_result, mb_item_size, result_size_8byte);
if ( status < 0 )
  return status;

Esto hace que las operaciones de suma y multiplicación sean seguras contra desbordamiento. Por lo tanto, en la versión sin parche podemos obtener desbordamiento de enteros en estos casos:

  • old_items_count * size_of_item > 0xffffffff
  • old_items_count + count_of_new_items > 0xffffffff
  • (old_items_count + count_of_new_items) * size_of_item > 0xffffffff

Después del desbordamiento de enteros, el array de punteros se reasignará, pero con un tamaño menor. Y luego, memmove intentará desplazar elementos para hacer espacio para el nuevo elemento. Por lo tanto, corromperá los fragmentos que se encuentran después del nuevo fragmento asignado. Para desencadenar el desbordamiento de enteros necesitamos crear 0xffffffff / size_of_item + 1 estructuras. size_of_item siempre es 8. Por lo tanto, necesitamos crear 0x20000001 estructuras. Cada estructura representa un proceso. Así que necesitamos tener 0x20000001 (536870913) procesos concurrentes. En mi máquina virtual solo pude crear 12492 procesos concurrentes y 39652 en mi máquina anfitriona.