KASLR泄露限制
近年来,微软一直致力于缓解漏洞类别和利用技术。在最新的Windows版本中,新增了一项变化,为针对Windows内核的攻击者带来了重大挑战——限制内核地址向用户模式的泄露。几乎任何内存漏洞都需要攻击者获取某些内核地址泄露,以了解将要读取/写入/溢出/破坏的地址。这些地址可能是ntoskrnl.exe或其他内核驱动程序的地址,也可能是攻击者目标的某些对象的地址。直到最近,获取这些地址都非常容易(对于任何以中等完整性级别或更高权限运行的用户而言)。只需调用几个已知的Windows API之一即可。
但从Windows 11/Windows Server 2022 24H2版本开始,这些API将不再泄露任何内核地址,除非请求进程已启用SeDebugPrivilege——这是一种强大的特权,仅适用于管理员进程且默认未启用。此检查通过传递给ExIsRestrictedCaller的新标志实现:
ExIsRestrictedCaller在内核中的多个位置被调用,以检查进程是否应获得对资源的访问权限或被允许执行操作。例如,这用于限制以低或不受信任完整性级别运行的进程调用返回内核地址的API。现在,此API还会检查进程是否启用了SeDebugPrivilege,并使用结果设置RestrictKernelAddressLeaks参数(名称由我选择,因为参数名称未公开)并将其返回给调用者。然后,调用者使用此参数决定哪些内核数据可以返回给用户模式调用者。
例如,当使用SystemModuleInformation类调用NtQuerySystemInformation(调用内部的ExpQuerySystemInformation)时,会调用ExIsRestrictedCaller来确定调用者可以接收哪些数据。输出参数随后传递给ExpQueryModuleInformation:
在ExpQueryModuleInformation内部,使用RestrictKernelAddressLeaks参数决定函数是否为系统中加载的每个内核模块填充DllBase字段:
如果参数被设置,意味着进程未启用SeDebugPrivilege,进程仍能接收有关已加载内核模块的信息。但该信息将不包含这些模块的基地址——该字段将被设置为0。
此检查在所有其他已知向用户模式调用者泄露内核地址的API中执行。在所有情况下,查询对于以中等IL或更高权限运行的调用者都会成功,但通常包含内核地址的字段将留空。现在限制内核地址泄露的API完整列表为: [表 id=1 /]
这些API是泄露内核地址的唯一方式吗?KASLR泄露终于消失了吗?当然不是。但更多内容将在另一篇博客文章中讨论。