Overview: GEAR Software's GEAR CDRom Filter device driver for Windows contains a vulnerability in its handling of a certain IOCTL, allowing an attacker to overwrite arbitrary memory in kernel mode. The attacker can use this to run arbitrary code as SYSTEM to ie. gain administrative credentials from a limited-access account. Vulnerable software: GEAR Software's GEAR CDrom Filter gearaspiwdm.sys, MD5 5AE3A887ECE5BBB72CFAB273C2FD1CFA Available from: http://www.gearsoftware.com/support/drivers.php (tested version: 4.019.1 / Oct. 18, 2011) Downstream affected software: iTunes for Windows (tested version: 10.5) Multiple Symantec backup programs, see ie. http://www.kb.cert.org/vuls/id/146896 for a list Vulnerability: The driver's 0x222000 IOCTL (FILE_DEVICE_UNKNOWN, function 0, FILE_ANY_ACCESS, METHOD_BUFFERED) allows a user to send a pass-through direct SCSI request to a given SCSI-addressable device. The driver checks to ensure that the IO buffer (DataBuffer) given in the request is aligned to a 32KB cache boundary. If it is not, it duplicates the contents of the buffer into a newly allocated properly-aligned buffer before passing the request to the underlying device, after which it copies the results back into the unaligned user buffer. The issue is that the driver does not check that this user-provided IO buffer location actually lies within user-addressable memory, and hence the driver can be lead into writing the SCSI results into arbitrary kernel memory. This IOCTL is accessible from a limited-access Windows account; even though the device is created using IoCreateDeviceSecure, the provided SDDL allows full access to all users on the machine ("D:P(A;;GA;;;BU)(A;;GA;;;SY)(A;;GA;;;BA)"). Attached is a POC exploit, which attempts to use several SCSI commands' results to overwrite a function pointer in Windows' HAL dispatch table to a user-specified payload (here, a simple bug-check is executed). Notable locations in the device driver file: 0x1210: IRP_MJ_DEVICE_CONTROL / IRP_MJ_INTERNAL_DEVICE_CONTROL handler 0xC5E: 0x222000 IOCTL handler 0xD86: Call to memcpy() which can be exploited Relevant portion of 0x222000 IOCTL handler, decompiled: dataBuffer = userScsiReq->DataBuffer; userScsiReq->TargetId = 0; *(_DWORD *)(stateBufElem + 272) = IoGetCurrentProcess(); dataTransferLength = userScsiReq->DataTransferLength; notAligned = ((_WORD)dataBuffer & 0x7FFF) != 0; if ( dataTransferLength ) { if ( notAligned ) { newPool = ExAllocatePoolWithTag( NonPagedPoolCacheAligned, ((dataTransferLength >> 11) + ((dataTransferLength & 0x7FF) != 0)) << 11, 'IOeG'); userScsiReq->DataBuffer = newPool; if ( !newPool ) { userScsiReq->ScsiStatus = 8; return STATUS_NO_MEMORY; } memcpy(newPool, dataBuffer, userScsiReq->DataTransferLength); } } else { userScsiReq->DataBuffer = 0; } result = DoIofCallDriver( 0x4D014u, // IOCTL_SCSI_PASS_THROUGH_DIRECT *(PDEVICE_OBJECT *)(stateBufElem + 8), userScsiReq, 0x9Cu, userScsiReq, 0x9Cu); if ( userScsiReq->DataBuffer ) { if ( notAligned ) { memcpy(dataBuffer, userScsiReq->DataBuffer, userScsiReq->DataTransferLength); ExFreePool(userScsiReq->DataBuffer); } } Additional info: There is another closely-related vulnerability, albeit of a lesser severity: If the user-supplied SCSI IO buffer (DataBuffer) is unaligned, and its user-supplied length (DataTransferLength) is at least 0xFFFFF800, the calculation for the size of the aligned SCSI IO buffer will overflow, leading to kernel heap overflow when the data is copied from the unaligned buffer to the aligned one. This leads to local DOS, as the size is overlarge.