cmp r15d, 17h ; check
PnPControlClass
jnb loc_1405C73D5 ; return STATUS_INVALID_PARAMETER_1
mov r14, r15
lea rcx, PlugPlayHandlerTable ; located in writable PAGEDATA section
shl r14, 4 ; PnPControlClass << 4
add r14, rcx ; get record describing this
PnPControlClass
cmp [r14], r15d ; field at offset 0 -
PnPControlClass
jnz loc_1405C73CB ; return STATUS_INTERNAL_ERROR
test r14, r14 ; I don`t know for what this paranoid check
jz loc_1405C73D5 ; return STATUS_INVALID_PARAMETER_1
cmp qword ptr [r14+8], 0 ; Gotcha ! This is pointer to function
jz loc_1405C7304 ; return STATUS_NOT_IMPLEMENTED
cmp [r14+4], ebp ; field at offset 4 - PnPControlDataLength
jnz loc_1405C730E ; return STATUS_INVALID_PARAMETER_MIX
...
mov r8d, ebp ; PnPControlDataLength
mov rdx, rbx ; PnPControlData
mov ecx, r15d ; PnPControlClass
call qword ptr [r14+8] ; call handler by pointer
The main problem with this code is that it calls function by pointer which located in writable PAGEDATA section. Also this section is not checking by PatchGuard. So you can rewrite some unused handler (and perhaps length of PnPControlDataLength) and call PnPControlClass with patched PnPControlClass to pass some data to code in KM.
Actually there is a lot of unused entries in PlugPlayHandlerTable - on w8 dev preview it contains only 8 handlers:
- PiControlStartDevice for code 4
- PiControlQueryAndRemoveDevice for code 6
- PiControlGetPropertyData for code 0xA
- PiControlGetRelatedDevice for code 0xC
- PiControlGetSetDeviceStatus for code 0xE
- PiControlGetDeviceDepth for code 0xF
- PiControlQueryDeviceRelations for code 0x10
- PiControlQueryConflictList for code 0x12