Finding AFD Endpoints
AFD.sys maintains a list of endpoint structures in the global variable afd!AfdEndpointListHead, each one of which represents a socket. This document describes how to walk this list to obtain all the AFD endpoints on the system.
0: kd> dt nt!_LIST_ENTRY @@masm(afd!AfdEndpointListHead)
[ 0xfffffa80`05b95900 - 0xfffffa80`04c0f770 ]
+0x000 Flink : 0xfffffa80`05b95900 _LIST_ENTRY [ 0xfffffa80`0377f8d0 - 0xfffff880`0310fd30 ]
+0x008 Blink : 0xfffffa80`04c0f770 _LIST_ENTRY [ 0xfffff880`0310fd30 - 0xfffffa80`04d11d30 ]
To find the offset of the link field in the AFD endpoint structure, disassemble the function afd!AfdIsAddressInUse() and look for an instruction that uses a negative offset which would represent the macro CONTAINING_RECORD.
0: kd> uf afd!AfdIsAddressInUse
afd!AfdIsAddressInUse:
fffff880`03120ab0 48895c2408 mov qword ptr [rsp+8],rbx
fffff880`03120ab5 48896c2410 mov qword ptr [rsp+10h],rbp
fffff880`03120aba 4889742418 mov qword ptr [rsp+18h],rsi
fffff880`03120abf 57 push rdi
fffff880`03120ac0 4883ec30 sub rsp,30h
fffff880`03120ac4 488bf1 mov rsi,rcx
fffff880`03120ac7 488b0d7af2feff mov rcx,qword ptr [afd!AfdGlobalData (fffff880`0310fd48)]
fffff880`03120ace 33db xor ebx,ebx
fffff880`03120ad0 ff158ae5fdff call qword ptr [afd!_imp_ExEnterCriticalRegionAndAcquireResourceShared (fffff880`030ff060)]
fffff880`03120ad6 488b3d53f2feff mov rdi,qword ptr [afd!AfdEndpointListHead (fffff880`0310fd30)]
fffff880`03120add 488d2d4cf2feff lea rbp,[afd!AfdEndpointListHead (fffff880`0310fd30)]
fffff880`03120ae4 eb7f jmp afd!AfdIsAddressInUse+0xb5 (fffff880`03120b65)
afd!AfdIsAddressInUse+0x36:
fffff880`03120ae6 488d97f0feffff lea rdx,[rdi-110h] ; Offset of the LIST_ENTRY field
fffff880`03120aed 483bd6 cmp rdx,rsi
fffff880`03120af0 7470 je afd!AfdIsAddressInUse+0xb2 (fffff880`03120b62)
.
.
.
To display the entries in the list use the following command :
0: kd> r $t0 = 0xfffffa80`05b95900; .for( r $t1 = poi(@$t0) ; (@$t1 != @$t0) ; r $t1 = poi(@$t1) ) { dw @$t1-110 L1}
fffffa80`0377f7c0 afd0
fffffa80`05aa7340 afd0
fffffa80`039023a0 afd0
fffffa80`03a3e770 afd0
fffffa80`0541e330 afd0
fffffa80`039cec40 afd0
fffffa80`048621f0 afd0
fffffa80`038f62f0 afd0
fffffa80`062b8e50 afd0
fffffa80`04f753f0 afd0
fffffa80`04e82530 afd0
fffffa80`038e85d0 afd0
fffffa80`03a48740 afd0
fffffa80`05ef3010 afd0
fffffa80`05657e50 afd2
fffffa80`059f2300 afd2
.
.
.
The numbers displayed in the second column in the above output indicate the type of endpoint.
The number 0xafd1 indicates an endpoint representing a datagram socket.
The numbers 0xafd0, 0xafd2, 0xafd4, 0xafd6 indicate endpoints representing TCP sockets in various states.
All AFD endpoints have the pool tag AfdE, this can be used to find/verify AFD endpoints.
0: kd> !pool 0xfffffa80`05b95900 2 Pool page fffffa8005b95900 region is Nonpaged pool *fffffa8005b957e0 size: 1c0 previous size: 90 (Allocated) *AfdE (Protected) Pooltag AfdE : Afd endpoint structure, Binary : afd.sys