Recently I met a problem in one of my TDI filters when filtering SMB traffic. The filter driver was able to see outgoing TDI_CONNECT requests to 139 and 445 ports, but during the heavy file upload there was no TDI_SEND requests issued.
Usually in such cases you start to googlize for a solution, and I found a few posts explaining the same problem, but they were actually dead – no reply since 2002
. I also asked for a question at popular DDK newsgroups assuming this was a well-known issue, and still got no answer.
Well, it started to be more and more interesting, especially taking into account that TDI lacks a lot of documentation and many things have to be resolved myself. I also used IrpTracker, TdiMon, TdiScoup utilities trying to see any missed IRPs but I was failed to see them. I need a point to start researches from. The best in this case is, I believe, a breakpoint to IoCallDriver. So, I opened share, started a file upload on a share, and put breakpoint in debugger:
0: kd> bp IofCallDriver
… and continue by pressing F5. Then break occures:
f62b281c f6e04139 nt!IofCallDriver
f62b2824 f6e03a47 rdbss!RxCeSubmitAsynchronousTdiRequest+0x28
f62b285c f6e0d0a0 rdbss!RxTdiSend+0x1ca
f62b28b8 f6d57609 rdbss!RxCeSend+0x74
f62b28e0 f6d35152 mrxsmb!VctTranceive+0x66
f62b2924 f6d597de mrxsmb!SmbCeTranceive+0x233
f62b2960 f6d5c350 mrxsmb!SmbPseOrdinaryExchange+0x18e
f62b29b0 f6d59668 mrxsmb!SmbPseExchangeStart_Write+0x1e3
f62b29c0 f6d57ab4 mrxsmb!SmbPseExchangeStart_default+0x12
f62b29e4 f6d5be6e mrxsmb!SmbCeInitiateExchange+0x287
f62b2a24 f6e0d49f mrxsmb!MRxSmbWrite+0x309
f62b2a4c f6e110e7 rdbss!RxLowIoSubmit+0x1c3
f62b2a6c f6e1183f rdbss!RxLowIoWriteShell+0x77
f62b2b90 f6e02d51 rdbss!RxCommonWrite+0x116f
f62b2c28 f6e0cbb0 rdbss!RxFsdCommonDispatch+0x353
f62b2c50 f6d57217 rdbss!RxFsdDispatch+0xda
f62b2c70 804ef095 mrxsmb!MRxSmbFsdDispatch+0x134
f62b2c80 8057e70a nt!IopfCallDriver+0x31
f62b2c94 8057c2cd nt!IopSynchronousServiceTail+0x60
f62b2d38 8054086c nt!NtWriteFile+0x5d7
As it seems from stack, the network file redirector is calling TDI (look at function name RxTdiSend) and this confuses me even more, as my filter has to receive IRP in this case. Continue more step by step debugging and I see actually that the request of file system redirector is sent to netbt.sys and not to TDI:
nt!IopfCallDriver:
804ef064 fe4a23 dec byte ptr [edx+23h]
804ef067 8a4223 mov al,byte ptr [edx+23h]
804ef06a 84c0 test al,al
804ef06c 7f0e jg nt!IopfCallDriver+0x18 (804ef07c)
804ef06e 6a00 push 0
804ef070 6a00 push 0
804ef072 6a00 push 0
804ef074 52 push edx
804ef075 6a35 push 35h
804ef077 e854ad0000 call nt!KeBugCheckEx (804f9dd0)
804ef07c 8b4260 mov eax,dword ptr [edx+60h]
804ef07f 83e824 sub eax,24h
804ef082 56 push esi
804ef083 894260 mov dword ptr [edx+60h],eax
804ef086 894814 mov dword ptr [eax+14h],ecx
804ef089 0fb600 movzx eax,byte ptr [eax]
804ef08c 8b7108 mov esi,dword ptr [ecx+8]
804ef08f 52 push edx
804ef090 51 push ecx
804ef091 ff548638 call dword ptr [esi+eax*4+38h] ds:0023:81f486e4={netbt!NbtDispatchInternalCtrl (f6da29ef)}
In dispatch function of netbt.sys I see the call to NtSend function: netbt!NbtDispatchInternalCtrl:
f6da29ef 8bff mov edi,edi
f6da29f1 55 push ebp
f6da29f2 8bec mov ebp,esp
f6da29f4 56 push esi
f6da29f5 8b750c mov esi,dword ptr [ebp+0Ch]
f6da29f8 57 push edi
f6da29f9 8b7e60 mov edi,dword ptr [esi+60h]
f6da29fc 807f0107 cmp byte ptr [edi+1],7
f6da2a00 897d0c mov dword ptr [ebp+0Ch],edi
f6da2a03 0f85b6120000 jne netbt!NbtDispatchInternalCtrl+0x24 (f6da3cbf)
f6da2a09 56 push esi
f6da2a0a ff7508 push dword ptr [ebp+8]
f6da2a0d e838060000 call netbt!NTSend (f6da304a)
In netbt.NtSend function I see a code which is preparing an IRP to be processed:
f6da310e 83ee24 sub esi,24h
f6da3111 83c004 add eax,4
f6da3114 894604 mov dword ptr [esi+4],eax
f6da3117 c7461c832fdaf6 mov dword ptr [esi+1Ch],offset netbt!SendCompletion (f6da2f83)
f6da311e 897e20 mov dword ptr [esi+20h],edi
f6da3121 c64603e0 mov byte ptr [esi+3],0E0h
f6da3125 c6060f mov byte ptr [esi],0Fh
f6da3128 c6460107 mov byte ptr [esi+1],7
f6da312c 8b0b mov ecx,dword ptr [ebx]
f6da312e 014f48 add dword ptr [edi+48h],ecx
f6da3131 8b4730 mov eax,dword ptr [edi+30h]
f6da3134 8b1d08d1dbf6 mov ebx,dword ptr [netbt!_imp__IoGetRelatedDeviceObject (f6dbd108)]
f6da313a 83574c00 adc dword ptr [edi+4Ch],0
f6da313e 50 push eax
f6da313f 8945f0 mov dword ptr [ebp-10h],eax
f6da3142 894618 mov dword ptr [esi+18h],eax
f6da3145 ffd3 call ebx {nt!IoGetRelatedDeviceObject (804ef658)}
And at the end of a function I see the code which is sending the IRP directly to tcpip.sys TcpSendData handler:
f6da3166 834060dc add dword ptr [eax+60h],0FFFFFFDCh
f6da316a 56 push esi
f6da316b 50 push eax
f6da316c ff5764 call dword ptr [edi+64h] ds:0023:8200c324={tcpip!TCPSendData (f6ea04f0)}
f6da316f 6a00 push 0
f6da3171 6a00 push 0
f6da3173 ff7508 push dword ptr [ebp+8]
f6da3176 8bf0 mov esi,eax
f6da3178 e81df8ffff call netbt!NBT_DEREFERENCE_DEVICE (f6da299a)
f6da317d 5f pop edi
f6da317e 8bc6 mov eax,esi
f6da3180 5e pop esi
f6da3181 5b pop ebx
f6da3182 c9 leave
f6da3183 c20800 ret 8
f6da3186 90 nop
Thats actually an answer to the question, why TDI filters are unable to filter SMB session traffic. Netbt.sys simply sends data directly to tcpip.sys via TCPSendData function and I believe, this is done for perfomance purposes.
[...] read the post http://www.shcherbyna.com/?p=121 Published Thu, Oct 9 2008 8:46 by V. S. Filed under: troubleshooting, [...]
Very nice analysis… Thanks for publishing this
Actually, I did not developed topic with “fast send handlers” – a special IOCTL sent by netbt in order to subscribe to fast send / recieve handlers …
I believe there is a way to intercept it as well. Just lazy to make research.