SMB traffic not captured in TDI filter driver
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, [...]