- 自己在编写驱动程序的时候 遇到一些疑问: IoBuildSynchronousFsdRequest 和IoBuildAsynchronousFsdRequest之间创建的同步异步IRP有什么区别?
- 为什么这两个函数只能创建几种IRP?调用IoAllocateIrp后 初始化IRP时哪些域是要填充的 哪些是不要填充的?
- 偏偏书上讲的都很模糊 驱动新手 一切只能自己动手。
- 先来看下 IoBuildSynchronousFsdRequest
- .text:004191D6 _IoBuildSynchronousFsdRequest@28 proc near
- .text:004191D6 ; CODE XREF: HalExamineMBR(x,x,x,x)+70p
- .text:004191D6 ; IopShutdownBaseFileSystems(x)+7Ap ...
- .text:004191D6
- .text:004191D6 MajorFunction = dword ptr 8
- .text:004191D6 DeviceObject = dword ptr 0Ch
- .text:004191D6 Buffer = dword ptr 10h
- .text:004191D6 Length = dword ptr 14h
- .text:004191D6 StartingOffset = dword ptr 18h
- .text:004191D6 Event = dword ptr 1Ch
- .text:004191D6 IoStatusBlock = dword ptr 20h
- .text:004191D6
- .text:004191D6 mov edi, edi
- .text:004191D8 push ebp
- .text:004191D9 mov ebp, esp
- .text:004191DB push edi
- .text:004191DC push [ebp+IoStatusBlock] ; IoStatusBlock
- .text:004191DF push [ebp+StartingOffset] ; StartingOffset
- .text:004191E2 push [ebp+Length] ; Length
- .text:004191E5 push [ebp+Buffer] ; Buffer
- .text:004191E8 push [ebp+DeviceObject] ; DeviceObject
- .text:004191EB push [ebp+MajorFunction] ; MajorFunction
- .text:004191EE call _IoBuildAsynchronousFsdRequest@24 ; 创建同步IRP 实质上还是创建异步IRP
- .text:004191F3 mov edi, eax ; pIrp送EDI 检验IRP是否创建成功
- .text:004191F5 test edi, edi ; pIrp
- .text:004191F7 jz short loc_41922D
- .text:004191F9 mov eax, [ebp+Event] ; event
- .text:004191FC push ebx
- .text:004191FD push esi
- .text:004191FE mov cl, 1
- .text:00419200 mov [edi+2Ch], eax ; pIrp->UserEvent = event
- .text:00419203 call ds:__imp_@KfRaiseIrql@4 ; movzx edx,cl
- .text:00419203 ; movzx ecx,byte ptr [edx-7F92EDA8h]
- .text:00419203 ; mov eax,dword ptr ds:[FFFE0080h];TPR寄存器中当前任务优先级送eax
- .text:00419203 ; mov dword ptr ds:[0FFFE0080h],ecx;装入新的任务优先级
- .text:00419203 ; shr eax,4;任务优先级/16
- .text:00419203 ; movzx eax,byte ptr [eax-7F923F78h]返回优先级
- .text:00419203 ; ret 中断级和任务优先级的换算 还要依靠806D1258和806DC088这两个地方的表或者结构
- .text:00419203 ; 对任务优先级不甚明白 以后有时间再仔细看看
- .text:00419203 ;
- .text:00419209 mov edx, [edi+50h] ; pIrp->Tail.overlay.Thread
- .text:00419209 ; edx值为ETHREAD的指针
- .text:0041920C add edx, 210h ; ÐREAD.IrpList
- .text:0041920C ; edx值为ETHREAD.IrpList的指针
- .text:00419212 mov ebx, [edx] ; ETHREAD.IrpList.flink
- .text:00419214 lea esi, [edi+10h] ; &pIrp->ThreadFlink
- .text:00419217 mov [esi], ebx ; pIrp->ThreadListEntry.flink = ETHREAD.IrpList.flink
- .text:00419219 mov [esi+4], edx ; pIrp->ThreadListEntry.blink = ÐREAD.IrpList
- .text:0041921C mov [ebx+4], esi ; ETHREAD.IrpList.flink = &pIrp->ThreadListEntry.flink
- ;IRP与线程关联
- .text:0041921F mov cl, al
- .text:00419221 mov [edx], esi
- .text:00419223 call ds:__imp_@KfLowerIrql@4 ; 恢复原IRQL
- .text:00419229 pop esi
- .text:0041922A mov eax, edi
- .text:0041922C pop ebx
- .text:0041922D
- .text:0041922D loc_41922D: ; CODE XREF: IoBuildSynchronousFsdRequest(x,x,x,x,x,x,x)+21j
- .text:0041922D pop edi
- .text:0041922E pop ebp
- .text:0041922F retn 1Ch
- .text:0041922F _IoBuildSynchronousFsdRequest@28 endp
- 从上面可以看出同步IRP和异步IRP 区别不是很大 IoBuildSynchronousFsdRequest内部调用了IoBuildAsynchronousFsdRequest 虽然同步IRP填充了IRP.UserEvent
- 但是 在编写驱动时 为了知道异步IRP操作什么时候真正完成 有时候同样要手动填充irp.UserEvent域。真正有点区别的估计就是同步IRP与线程关联了
- 而异步IRP没有。
- 再来看下IoBuildAsynchronousFsdRequest
- .text:00418E96 _IoBuildAsynchronousFsdRequest@24 proc near
- .text:00418E96 ; CODE XREF: IoBuildSynchronousFsdRequest(x,x,x,x,x,x,x)+18p
- .text:00418E96 ; IovBuildAsynchronousFsdRequest(x,x,x,x,x,x)+22p
- .text:00418E96
- .text:00418E96 var_20 = dword ptr -20h
- .text:00418E96 Irp = dword ptr -1Ch
- .text:00418E96 ms_exc = CPPEH_RECORD ptr -18h
- .text:00418E96 MajorFunction = dword ptr 8
- .text:00418E96 DeviceObject = dword ptr 0Ch
- .text:00418E96 VirtualAddress = dword ptr 10h
- .text:00418E96 Length = dword ptr 14h
- .text:00418E96 StartingOffset = dword ptr 18h
- .text:00418E96 IoStatusBlock = dword ptr 1Ch
- .text:00418E96
- .text:00418E96 push 10h
- .text:00418E98 push offset stru_401748
- .text:00418E9D call __SEH_prolog
- .text:00418EA2 mov edi, [ebp+DeviceObject]
- .text:00418EA5 mov al, [edi+30h] ; pDeviceObject->StackSize 送al
- .text:00418EA8 mov byte ptr [ebp+var_20], al
- .text:00418EAB push 0 ; FALSE
- .text:00418EAD push [ebp+var_20]
- .text:00418EB0 call _pIoAllocateIrp ; 分配IRP 通过调用IopAllocateIrpPrivate
- .text:00418EB6 mov esi, eax ; pIrp送esi
- .text:00418EB8 mov [ebp+Irp], esi
- .text:00418EBB test esi, esi
- .text:00418EBD jz loc_418FCC
- .text:00418EC3 mov eax, large fs:124h ; &_KPCR.KPRCB.CurrentThread
- .text:00418EC9 mov [esi+50h], eax ; pIrp->Thread = &KTHREAD KTHREAD 的地址就是ETHREAD地址
- .text:00418ECC mov ebx, [esi+60h] ; pIrp->IoStackLocation
- .text:00418ECF sub ebx, 24h ; IoStackLocation指向一个IO_STACK_LOCATION数组
- .text:00418ECF ; -24h 就是当前IO_STACK_LOCATION[i-1] 这里开始初始
- .text:00418ECF ; 下一层驱动的IO_STACK_LOCATION
- .text:00418ED2 mov eax, [ebp+MajorFunction]
- .text:00418ED5 mov [ebx], al ; IO_STACK_LOCATION.MajorFunction
- .text:00418ED7 cmp eax, 9 ; IRP_MJ_FLUSH_BUFFERS
- .text:00418EDA jz loc_418F62
- .text:00418EE0 cmp eax, 10h ; IRP_MJ_SHUTDOWN
- .text:00418EE3 jz short loc_418F62
- .text:00418EE5 cmp eax, 1Bh ; IRP_MJ_PNP
- .text:00418EE8 jz short loc_418F62
- .text:00418EEA cmp eax, 16h ; IRP_MJ_POWER
- .text:00418EED jz short loc_418F62
- .text:00418EEF mov eax, [edi+1Ch] ; pDeviceObject->flag 初始flag是C8H
- .text:00418EF2 test al, 4 ; DO_BUFFER_IO置位 是CCH
- .text:00418EF4 jz short loc_418F72
- .text:00418EF6 push 20206F49h ; Tag
- .text:00418EFB push [ebp+Length] ; NumberOfBytes
- .text:00418EFE push 4 ; PoolType
- .text:00418F00 call _ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
- .text:00418F05 mov [esi+0Ch], eax ; pIrp->AssociatedIrp.SystemBuffer
- .text:00418F08 test eax, eax
- .text:00418F0A jnz short loc_418F17
- .text:00418F0C
- .text:00418F0C loc_418F0C: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+F5j
- .text:00418F0C push esi ; Irp
- .text:00418F0D call _IoFreeIrp@4 ; IoFreeIrp(x)
- .text:00418F12 jmp loc_418FCC
- .text:00418F17 ; ---------------------------------------------------------------------------
- .text:00418F17
- .text:00418F17 loc_418F17: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+74j
- .text:00418F17 cmp [ebp+MajorFunction], 4 ; IRP_MJ_WRITE
- .text:00418F1B jnz short loc_418F41
- .text:00418F1D mov ecx, [ebp+Length] ; 如果是写请求的话
- .text:00418F20 mov esi, [ebp+VirtualAddress]
- .text:00418F23 mov edi, eax ; 把 参数中PVOID提供的内存 复制到 分配出来的内存中的内容 中去
- .text:00418F25 mov eax, ecx
- .text:00418F27 shr ecx, 2
- .text:00418F2A rep movsd
- .text:00418F2C mov ecx, eax
- .text:00418F2E and ecx, 3
- .text:00418F31 rep movsb
- .text:00418F33 mov eax, [ebp+Irp]
- .text:00418F36 mov dword ptr [eax+8], 30h ; pIrp->Flags
- .text:00418F3D mov esi, eax
- .text:00418F3F jmp short loc_418F4E
- .text:00418F41 ; ---------------------------------------------------------------------------
- .text:00418F41
- .text:00418F41 loc_418F41: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+85j
- .text:00418F41 mov dword ptr [esi+8], 70h
- .text:00418F48
- .text:00418F48 loc_418F48: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+DEj
- .text:00418F48 mov eax, [ebp+VirtualAddress]
- .text:00418F4B mov [esi+3Ch], eax
- .text:00418F4E
- .text:00418F4E loc_418F4E: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+A9j
- .text:00418F4E ; IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+113j
- .text:00418F4E mov eax, [ebp+Length]
- .text:00418F4B mov [esi+3Ch], eax ; pIrp->UserBuffer IRP_MJ_READ 时 DO_BUFFERED_IO模式下保存参数中的内存首地址
- .text:00418F4B ; 看了下整个函数只有这里 和IRP_MJ_READ提供的内存有关 猜测驱动在完成IRP后
- .text:00418F4B ; 系统会寻找UserBuffer域然后 复制systembuffer里的东西
- .text:00418F4E
- .text:00418F4E loc_418F4E: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+A9j
- .text:00418F4E ; IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+113j
- .text:00418F4E mov eax, [ebp+Length]
- .text:00418F51 mov [ebx+4], eax ; IO_STACK_LOCATION.Write.Length
- .text:00418F51 mov [ebx+4], eax ; IO_STACK_LOCATION.Write.Length
- .text:00418F54 mov eax, [ebp+StartingOffset]
- .text:00418F57 mov ecx, [eax]
- .text:00418F59 mov [ebx+0Ch], ecx ; IO_STACK_LOCATION.Write.ByteOffset.u.LowPart
- .text:00418F5C mov eax, [eax+4]
- .text:00418F5F mov [ebx+10h], eax ; IO_STACK_LOCATION.Write.ByteOffset.u.HighPart
- .text:00418F62
- .text:00418F62 loc_418F62: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+44j
- .text:00418F62 ; IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+4Dj ...
- .text:00418F62 mov eax, [ebp+IoStatusBlock]
- .text:00418F65 mov [esi+28h], eax ; pIrp->UserIosb
- .text:00418F68 mov eax, esi
- .text:00418F6A
- .text:00418F6A loc_418F6A: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+138j
- .text:00418F6A call __SEH_epilog
- .text:00418F6F retn 18h
- .text:00418F72 ; ---------------------------------------------------------------------------
- .text:00418F72
- .text:00418F72 loc_418F72: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+5Ej
- .text:00418F72 test al, 10h ; DO_DIRECT_IO
- .text:00418F74 jz short loc_418F48
- .text:00418F76 xor edi, edi
- .text:00418F78 push edi ; Irp
- .text:00418F79 push edi ; ChargeQuota
- .text:00418F7A push edi ; SecondaryBuffer
- .text:00418F7B push [ebp+Length] ; Length
- .text:00418F7E push [ebp+VirtualAddress] ; VirtualAddress
- .text:00418F81 call _IoAllocateMdl@20 ; 分配一个MDL
- .text:00418F86 mov [esi+4], eax ; pIrp->MdlAddress
- .text:00418F89 cmp eax, edi
- .text:00418F8B jz loc_418F0C
- .text:00418F91 mov [ebp+ms_exc.disabled], edi
- .text:00418F94 xor ecx, ecx
- .text:00418F96 cmp [ebp+MajorFunction], 3 ; IRP_MJ_READ
- .text:00418F9A setz cl ; 如果是IRP_MJ_READ cl置位
- .text:00418F9D push ecx ; Operation
- .text:00418F9E push edi ; AccessMode
- .text:00418F9F push eax ; MemoryDescriptorList
- .text:00418FA0 call _MmProbeAndLockPages@12 ; 锁定MDL
- .text:00418FA5 or [ebp+ms_exc.disabled], 0FFFFFFFFh
- .text:00418FA9 jmp short loc_418F4E
- .text:00418FAB ; ---------------------------------------------------------------------------
- .text:00418FAB
- .text:00418FAB loc_418FAB: ; DATA XREF: .text:stru_401748o
- .text:00418FAB xor eax, eax
- .text:00418FAD inc eax
- .text:00418FAE retn
- .text:00418FAF ; ---------------------------------------------------------------------------
- .text:00418FAF
- .text:00418FAF loc_418FAF: ; DATA XREF: .text:stru_401748o
- .text:00418FAF mov esp, [ebp+ms_exc.old_esp]
- .text:00418FB2 mov esi, [ebp+Irp]
- .text:00418FB5 mov eax, [esi+4]
- .text:00418FB8 test eax, eax
- .text:00418FBA jz short loc_418FC2
- .text:00418FBC push eax ; Mdl
- .text:00418FBD call _IoFreeMdl@4 ; IoFreeMdl(x)
- .text:00418FC2
- .text:00418FC2 loc_418FC2: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+124j
- .text:00418FC2 push esi ; Irp
- .text:00418FC3 call _IoFreeIrp@4 ; IoFreeIrp(x)
- .text:00418FC8 or [ebp+ms_exc.disabled], 0FFFFFFFFh
- .text:00418FCC
- .text:00418FCC loc_418FCC: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+27j
- .text:00418FCC ; IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+7Cj
- .text:00418FCC xor eax, eax
- .text:00418FCE jmp short loc_418F6A
- .text:00418FCE _IoBuildAsynchronousFsdRequest@24 endp
- IoBuildAsynchronousFsdRequest内部不算很复杂 通过调用IoAllocateIrp来分配IRP
- 对于IRP_MJ_SHUTDOWN,IRP_MJ_PNP,IRP_MJ_POWER,IRP_MJ_FLUSH_BUFFERS 这样的不对设备读写的请求
- MajorFunction送入IO_STACK_LOCATION后就直接返回了。。。
- 而对于IRP_MJ_READ或者IRP_MJ_WRITE还要对缓冲区进行处理
- 对于缓冲区读写的设备 MajorFunction为IRP_MJ_WRITE时IoBuildAsynchronousFsdRequest调用ExAllocatePoolWithTag分配内存 填充到
- pIrp->AssociatedIrp.SystemBuffer域中 同时复制要写入的数据到SystemBuffer中去(看到这里 估计就明白IO管理器是怎么管理SystemBuffer
- 的) MajorFunction为IRP_MJ_READ时 只分配好内存,最后IO_STACK_LOCATION域填充好 返回
- 对于直接读写的设备 为参数中提供的内存创建一个MDL MmProbeAndLockPages函数校验那个数据缓冲区是否有效,是否可以按适当模式访问。
- 如果我们向设备写数据,我们必须能读缓冲区。如果我们从设备读数据,我们必须能写缓冲区。
- 分析到这里其实已经差不多了 IoBuildAsynchronousFsdRequest和IoBuildSynchronousFsdRequest之所以只能分配少数几种IRP 只是因为内部
- 只对这几种IRP进行了 封装(废话啊)至于调用IoAllocateIrp后应该填充的域显然 应该和IoBuildAsynchronousFsdRequest中做的差不多(当然根据
- 具体的MajorFunction具体填充) 比如:IoStackLocation,UserIosb
IRP的创建
最新推荐文章于 2023-09-19 16:21:31 发布