目标
Radeon 软件修订号 Adrenalin Edition 18.12.1.1 可选
解释
总共有两个漏洞,发生在AMD Adrenalin Edition的atdcm64a.sys驱动程序中。
第一个漏洞
当通过Irp进入处理特定IOCTL代码的逻辑时,原样使用用户发送的数据。
systemBuffer_9 = Irp->AssociatedIrp.SystemBuffer;
v80 = __readmsr(*(_DWORD *)systemBuffer_9); // arbitrary read msr
*(QWORD *)((char *)systemBuffer_9 + 12) = v80;
*(QWORD *)((char *)systemBuffer_9 + 4) = v80;
第一个漏洞使用用户传递的系统缓冲区作为读取任意MSR的指针。
MSR(Model-Specific Register)是存在于CPU内部的特殊寄存器,用于控制处理器的特定硬件操作或读取状态信息。MSR是一组寄存器,根据CPU架构的不同而不同,控制特定的功能。主要是通过 MSR 使用低级软件(例如内核驱动程序)来处理处理器的高级功能或监视其状态。
MSR是CPU内部存储各种设置和状态的寄存器,因此读取或操作特定的MSR可能会影响系统的安全性和稳定性。以下是在 MSR 中阅读可能存在危险的重要信息。
-
时间戳计数器 (TSC) MSR
MSR地址:0x10
说明:该寄存器提供CPU时钟计数,可以让您获得高精度的时序信息。
风险:攻击者可以利用TSC信息进行旁路攻击。例如,通过精确测量特定代码的执行时间,可以间接提取敏感信息,例如推断CPU缓存状态或获取加密操作的时序信息。
-
IA32_SYSENTER_EIP、IA32_SYSENTER_CS、IA32_SYSENTER_ESP
MSR地址:0x176、0x174、0x175
说明:这些寄存器存储与处理系统调用的入口点地址相关的信息。
风险:由于有关内核入口点的信息有助于了解内核的控制流,因此攻击者很有可能利用它来执行诸如ROP(面向返回编程)之类的攻击。特别地,如果入口点地址被泄露,则可以利用它来绕过地址空间放置随机化(ASLR) 。
-
IA32_DEBUGCTL MSR
MSR地址:0x1D9
描述:存储调试相关设置并控制处理器调试功能的寄存器。
风险:调试信息提供有关系统操作的详细信息,允许攻击者跟踪内存访问模式或上下文切换。这可以用来间接找出内核中是否正在执行敏感操作。
-
IA32_MTRR(内存类型范围寄存器)
MSR地址:0x200~0x20F(范围)
描述:定义内存区域的缓存特性的寄存器。
风险:如果攻击者通过MTRR信息确定内存映射,并操纵特定内存区域的缓存特性,就可以控制内存访问速度,进行定时攻击或缓存冲突攻击。它还可以通过优化内存访问方法用于安全规避技术。
-
IA32_PERF_STATUS、IA32_PERF_CTL(性能监控)
MSR地址:0x198、0x199
说明:与CPU的性能状态和性能控制相关的寄存器。
风险:通过性能计数器信息,可以了解CPU的状态以及指令执行的频率。这允许您执行定时攻击或旁路攻击。例如,您可以跟踪执行某些函数时 CPU 使用率的变化,以分析何时发生敏感信息(例如加密操作)。
-
APIC MSR(高级可编程中断控制器)
MSR 地址:0x1B、0xFEE00000~0xFEEFFFFF(APIC MMIO 地址范围)
说明:APIC 用于控制处理器间中断,包含与本地 APIC 相关的设置。
风险:如果攻击者通过APIC操纵CPU之间的中断通信或更改APIC的设置,则可能会干扰系统的中断处理并导致拒绝服务(DoS)攻击。由于 APIC 设置不正确而导致的系统不稳定也是一个主要风险。
-
IA32_FEATURE_CONTROL MSR
MSR地址:0x3A
描述:用于启用或禁用 VT-x(虚拟化)等功能。
危险:可以通过该寄存器控制虚拟化功能。如果攻击者恶意操纵该值,他们就可以绕过基于硬件虚拟化的安全功能或配置异常的虚拟化环境。
-
固件控制 MSR(ACPI 相关 MSR)
描述:包含固件相关的设置信息,例如 ACPI。
风险:滥用与 ACPI 或电源管理相关的设置可以控制系统的电源管理策略,导致过热问题或操纵系统的运行状态。
第二个漏洞
驱动程序通过 InnerIrpIoCtlHandler() 和 InnerIrpIoCtlHandler() 将用户缓冲区按原样传递给名为 callDriver() 的函数。在callDriver()中,作为参数传递的用户缓冲区被传递给IoGetAttachedDeviceReference(),并且返回值被传递给IofCallDriver()。
int64 __fastcall callDriver(PDEVICE_OBJECT DeviceObject, int64 a2, int a3, UNICODE_STRING *a4, int a5, int a6)
{
_DEVICE_OBJECT *AttachedDeviceReference; // rdi
PIRP Irp; // rax
unsigned int Status; // ebx
struct _IO_STACK_LOCATION *CurrentStackLocation; // rcx
struct _IO_STATUS_BLOCK IoStatusBlock; // [rsp+40h] [rbp-38h] BYREF
struct _KEVENT event; // [rsp+50h] [rbp-28h] BYREF
KeInitializeEvent(&event, NotificationEvent, 0);
AttachedDeviceReference = IoGetAttachedDeviceReference(DeviceObject); [1]
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, AttachedDeviceReference, 0LL, 0, 0LL, &event, &IoStatusBlock);
if (Irp) {
CurrentStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
CurrentStackLocation[-1].Parameters.FileSystemControl.OutputBufferLength = 0;
CurrentStackLocation[-1].Parameters.FileSystemControl.InputBufferLength = a4;
*(_QWORD *)&CurrentStackLocation[-1].MinorFunction = (a3 != 0) + 15;
CurrentStackLocation[-1].Parameters.FileSystemControl.FsControlCode = a5;
CurrentStackLocation[-1].Parameters.FileSystemControl.Type3InputBuffer = a6;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Status = IofCallDriver(AttachedDeviceReference, Irp); [2]
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, 0, 0, 0LL);
Status = IoStatusBlock.Status;
}
}
else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
ObDereferenceObject(AttachedDeviceReference);
return Status;
}
调用 DeviceObject 的 DriverObject 部分的 MajorFunction 数组内的函数指针。由于我们可以控制 DeviceObject,因此我们可以控制 MajorFunction 数组内的函数指针。
{
_IO_STACK_LOCATION *v2; // rax
__int64 MajorFunction; // r8
if ( IopDispatchCallDriver )
{
if ( IopDispatchCallDriver == 3 )
return IopPerfCallDriver((PADAPTER_OBJECT)DeviceObject);
else
return IovCallDriver(DeviceObject);
}
else
{
if ( --Irp->CurrentLocation <= 0 )
KeBugCheckEx(0x35u, (ULONG_PTR)Irp, 0LL, 0LL, 0LL);
v2 = Irp->Tail.Overlay.CurrentStackLocation - 1;
Irp->Tail.Overlay.CurrentStackLocation = v2;
MajorFunction = v2->MajorFunction;
v2->DeviceObject = DeviceObject;
if ( (_BYTE)MajorFunction == 22 && (unsigned __int8)(v2->MinorFunction - 2) <= 1u )
return IopPoHandleIrp(Irp);
else
return ((__int64 (__fastcall *)(PDEVICE_OBJECT))DeviceObject->DriverObject->MajorFunction[MajorFunction])(DeviceObject); [3]
}
}
参考:
https://security.humanativaspa.it/exploiting-amd-atdcm64a-sys-arbitrary-pointer-dereference-part-1/
原文始发于微信公众号(Ots安全):AMD atdcm64a.sys 中任意指针取消引用导致的 LPE 漏洞
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论