Finding Windows Filtering Platform (WFP) Callouts
WFP callouts are functions that are registered by kernel mode WFP filters with the networking stack (NETIO.sys). This document describes a technique to find a list of WFP callouts registered on the system.
The variable netio!gWfpGlobal is the starting point for most WFP data structures.
0: kd> dp netio!gWfpGlobal L1 fffff880`017536a0 fffffa80`03718000 ;pointer to the WFP global structure
The number of callouts and the pointer the array of callout structures is stored in this global table. To find the offset of these fields use the following technique:
0: kd> u netio!FeInitCalloutTable NETIO!FeInitCalloutTable: fffff880`01732a60 fff3 push rbx fffff880`01732a62 4883ec20 sub rsp,20h fffff880`01732a66 488b05330c0200 mov rax,qword ptr [NETIO!gWfpGlobal (fffff880`017536a0)] fffff880`01732a6d 33c9 xor ecx,ecx fffff880`01732a6f ba57667043 mov edx,43706657h fffff880`01732a74 48898848050000 mov qword ptr [rax+548h],rcx ;Offset of number of Entries fffff880`01732a7b 48898850050000 mov qword ptr [rax+550h],rcx ;Offset of pointer to array of callout structures fffff880`01732a82 4c8b05170c0200 mov r8,qword ptr [NETIO!gWfpGlobal (fffff880`017536a0)]
The find the number of built in layers and the pointer to the array of callout structures use the following technique:
0: kd> dq fffffa80`03718000 + 548 L1 fffffa80`03718548 00000000`0000011e ;number of entries 0: kd> dps fffffa80`03718000 + 550 L1 fffffa80`03718550 fffffa80`0509c000 ;Pointer to array of callout structures
To confirm that callout array pointer is correct, use the following technique:
0: kd> !pool fffffa80`0509c000
Pool page fffffa800509c000 region is Nonpaged pool
*fffffa800509c000 : large page allocation, Tag is WfpC, size is 0x4790 bytes
Pooltag WfpC : WFP callouts, Binary : netio.sys
To find the size of each structure in this array use the following technique :
0: kd> u NETIO!InitDefaultCallout NETIO!InitDefaultCallout: fffff880`01730230 fff3 push rbx fffff880`01730232 4883ec20 sub rsp,20h fffff880`01730236 4c8d05ab320200 lea r8,[NETIO!gFeCallout (fffff880`017534e8)] fffff880`0173023d ba57667043 mov edx,43706657h fffff880`01730242 b940000000 mov ecx,40h ;size of each entry in the array allocated from NPP fffff880`01730247 e8f4eefdff call NETIO!WfpPoolAllocNonPaged (fffff880`0170f140) fffff880`0173024c 488bd8 mov rbx,rax fffff880`0173024f 4885c0 test rax,rax
To display all the elements of the array use the following command template :
r $t0=array_base;.for ( r $t1=0; @$t1 < array_count; r $t1=@$t1+1 ) {dps @$t0+2*@$ptrsize L2; r $t0=@$t0+structure_size;}
0: kd> r $t0=fffffa80`0509c000;.for ( r $t1=0; @$t1 < 11e; r $t1=@$t1+1 ) {dps @$t0+2*@$ptrsize L2; r $t0=@$t0+40;}
fffffa80`0509c000 00000000`00000000
fffffa80`0509c008 00000000`00000000
fffffa80`0509c010 00000000`00000000
fffffa80`0509c018 00000000`00000000
fffffa80`0509c020 00000000`00000000
fffffa80`0509c028 00000000`00000000
fffffa80`0509c030 00000000`00000000
fffffa80`0509c038 00000000`00000000
fffffa80`0509c040 00000001`00000001
fffffa80`0509c048 00000000`00000000
fffffa80`0509c050 fffff880`019bf640 tcpip!IPSecInboundTransportFilterCalloutClassifyV4 ;WFP callouts
fffffa80`0509c058 fffff880`0180f2c0 tcpip!IPSecInboundTransportFilterCalloutNotifyV6+0x2 ;WFP callouts
fffffa80`0509c060 00000000`00000000
fffffa80`0509c068 00000000`00000000
fffffa80`0509c070 00000000`00000000
fffffa80`0509c078 00000000`00000000
fffffa80`0509c080 00000001`00000001
.
.
.