Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2024-20698 — 漏洞分析 | Kitploit
工具/GitHubGitHub/romanrybachek/cve-2024-20698
漏洞分析代码分析漏洞利用逆向工程二进制分析
GitHubromanrybachek/cve-2024-20698

CVE-2024-20698

漏洞分析

查看仓库
5172年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2024-20698

关于此漏洞:https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-20698

补丁分析

在 ntoskrnl.exe 中,有两个被修补的函数:sub_1406AE224 和 WbAddLookupEntryEx。存在漏洞的函数是 WbAddLookupEntryEx。该函数的调用路径如下:

示意图

要调用此函数,我们需要调用 NtQuerySystemInformation,第一个参数为 0xb9。用户提供的缓冲区中的第一个字节是此 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;
}

对于每个使用参数 0xb9 调用 NtQuerySystemInformation 的进程,都会创建一个结构体,该结构体将存储在内存中,直到进程终止。我将此结构体称为 item_instance。首先,函数 sub_1406AF294 试图在其他此类结构体中查找当前进程的结构体。这些结构体的指针按进程 ID 顺序存储在内存中。如果未找到该结构体,则会通过 WbCreateWarbirdProcess 创建。然后,该结构体的指针将通过存在漏洞的 WbAddLookupEntryEx 添加到数组中。
补丁前的 WbAddLookupEntryEx 代码:

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

它重新分配指针数组,并插入一个新指针。

补丁添加了以下安全检查:

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;

这使得加法和乘法运算在溢出时安全。因此,在未修补版本中,我们可以在以下情况下实现整数溢出:

  • 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

整数溢出发生后,指针数组将被重新分配,但大小更小。然后,memmove 将尝试移动元素以为新元素腾出空间。因此,它会破坏新分配块之后的内存块。 要触发整数溢出,我们需要创建 0xffffffff / size_of_item + 1 个结构体。size_of_item 始终为 8。因此,我们需要创建 0x20000001 个结构体。每个结构体代表一个进程。所以我们需要拥有 0x20000001 (536870913) 个并发进程。在我的虚拟机上,我只能创建 12492 个并发进程,而在我的主机上可以创建 39652 个。

下载工具