Classic TDI fillter, attached to TCP and UDP using IoAttachDevice(). Receives TCP connect ,send and receive as expected, UDP TDI_SEND_DATAGRAM, but never TDI_RECEIVE_DATAGRAM. This should be present at least for DNS responses that is most interesting for me. Tested on Win7 x32 and 64, WinXP - same problem. FastIoDispatch is NULL for target driver, so this should be not a point.Here list of all the IRPs that it receives on UDP device, looks also weird : hex MajorFunction, MinorFunction:
UDP 0 0
UDP 12 0
UDP 2 0
UDP E 0
UDP F 3
UDP F 7
UDP F 9
UDP F B
UDP F C
UDP F 50
P.S. I know that TDI is declared obsolete, but need support for NT.
The socket layer (AFD.SYS) does not use TDI_RECEIVE_DATAGRAM often or even ever. Your filter should expect that almost all RX dataflow will be via callbacks on the Address Object.
Good Luck,
Dave Cattley
Sent from Mail for Windows 10
>via callbacks on the Address Object.
How to hook it? Possible to attach to \device\afd\endpoint , is there sample code somewhere?
>>via callbacks on the Address Object.
How to hook it? Possible to attach to \device\afd\endpoint , is there sample code somewhere?
To intercept TDI callbacks from an AddressObject to a TDI Client your filter must process TDI_SET_EVENT_HANDLER requests from the TDI client and interpose your own proxy callback and context.
See this for more information on TDI Client Callbacks.
https://msdn.microsoft.com/en-us/library/windows/hardware/ff565081(v=vs.85).aspx
At one time there was a third-party sample TDI firewall filter driver in source available for download. IIRC it was not what one might consider “production quality” but it was illustrative in some sense.
TDI filters are very challenging to implement correctly. There are many ‘under documented’ aspects of TDI and some outright undocumented corners.
What problem are you trying to solve on platforms earlier than Vista that has you thinking you need a TDI filter?
Perhaps there is a less difficult approach to solving your root problem.
Good Luck,
Dave Cattley
I am malware researcher, run malware on XP platform too, so need to monitor it. I get tcp_connect and tcp_send/receive per PID, not system wide that pcap/tcpdump gives. A challenge is to get URL from IP that could be obtained from previous DNS response. It could be obtained using getaddressinfo(0) in ring 3, but it asks DNS and sometimes is very slow. Looked also at WFD code samples, they look horrible , I believe it is simpler to fix issue in TDI filter.
If all you want to do is monitor UDP DNS requests to ‘capture’ what has been resolved then you have multiple choices:
- As you have intended – capture UDP datagrams filtering TDI. Hard.
- Capture link-level frames via NDIS Protocol like WinPCAP. This would be pretty easy.
- On NT5 use the Firewall Hook. Obscure, but effective.
- On NT6+ use WFP “monitoring” filter. Very easy to build.
By watching (filtering) TDI you can create a correlation table of flow (5-tuple) to PID. You can look at the packets of the flow(s) via any convenient mechanism. Observing data from TDI is not terribly convenient.
And if I were a malware writer I would infiltrate KM and talk directly to NDIS to get by your entire rig. ???
Good Luck,
Dave Cattley
Sent from Mail for Windows 10
Found code sample, installing events handlers solves the problem. I get DNS packets, then TCP connections, names are resolved such way in most of cases.
Cannot solve problem of callbacks detach. If I stop driver using SC manager API and detach in unload event, I get bluescreen with if any callbacks are active. Run driver, then Iexplore, see that any callbacks installed - attempt to stop driver causes bluescreen in any combination. Probably the client is inside of callback and returns “not finished”, so stopping driver prohibited.
Code fragment:
query_irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, devobj, fileobj, NULL, NULL);
if (query_irp)
{
TdiBuildSetEventHandler(query_irp, devobj, fileobj, NULL, NULL, event_type,
ctx->old_handler, ctx->old_context);
status = IoCallDriver(devobj, query_irp);
if (status == STATUS_SUCCESS)
IoFreeIrp(query_irp);
}
TDI filter drivers cannot unload dynamically.
It is not possible to force the close of all handles, detach of all other
Device Objects that have attached to your filter, etc.
Dave Cattley
Taras,
>
Cannot solve problem of callbacks detach. If I stop driver using SC manager API
and detach in unload event, I get bluescreen with if any callbacks are active.
Run driver, then Iexplore, see that any callbacks installed - attempt to stop
driver causes bluescreen in any combination. Probably the client is inside of
callback and returns “not finished”, so stopping driver prohibited.
<<
As others have mentioned, since TDI filters do not support unloading the best you can do is to set your driver into pass-though mode. The problem you are trying to solve has been actively discussed more or less ten years ago when XP was popular. I now experience a deja vu. Most of us solved this problem using the following approach:
-
in the early 2000s some engineers simply hook the dispatch routine of \Device\UDP or \Device\TCP: this is bad practice as hooking is unreliable. Also, it would solve the problem of unloading the driver (technically you will be able to unload), however you need to replace the callbacks you have changed when handling TDI_SET_EVENT_HANDLER and this is not an easy task because the callback may be currently active. Most of the antiviruses started to detect the dispatch routine hooking as well.
-
later on most of the community started to simply attach to the \Device\UDP or \Device\TCP using IoAttachDevice(…) and similar and once you need to uninstall the driver you simply put it into pass-through mode and wait until the reboot. This is what most of the antiviruses were (and some are still) doing for XP. I am aware of a few products which do this even in Vista and 7.
That is the best you can do for XP. In Vista you can start using WFP callouts which will allow you to unload your driver even if you have any custom data associated with the wfp contexts. It will take some time to make it work, but it is possible.