WFP Filter
Geblockte Pakete ohne Windows Firewall Regel
Es gab den Fall, dass zwei Programme keine Daten an deren Cloud Server senden konnten. Obwohl in der Windows Firewall und Windows Defender nichts geblockt wurde, kam keine Verbindung zustande. Auch in Wireshark hat man keine Verbindungsversuche gesehen.
Ursache waren mehrere WFP Filter
WFP (Windows Filter Platform) Filter sind Netzwerkfilter, die übergeordnet zur Windows Firewall existieren. Windows Firewall Regeln und andere Security Programme (z.B. Windows Defender EDR) bilden ihre Regeln als WFP Filter ab.
Filter, die direkt als WFP Filter erstellt werden, können auch nicht in der Windows Firewall gesehen werden.
Generell ist es auch so, dass diese Filter (und auch Windows Firewall Regeln) greifen, bevor Netzwerkpakete von Tools wie Wireshark gesehen werden können.
WFP Filter können mit folgendem Befehl angezeigt werden:
"netsh wfp show filter" oder "netsh wfp show state"
Alternativ bietet sich die Software WFP Explorer an.
Mit dem WFP Explorer können Filter auch gelöscht werden (die FilterID wird hier in HEX dargestellt. Die ID in der XML ist Dezimal).
Es gibt meines Wissens kein Bordmittel, mit dem Regeln erstellt und gelöscht werden können. Auch mit nativer PowerShell kommt man nicht weiter, da es nur eine C/C++ API gibt und PowerShell das wohl nicht nativ beherrscht.
Es gibt zwar diverse PowerShell-Module, die man herunterladen kann, aber WFP Explorer ist einfacher.
Geblockte Pakete werden zwar im Windows Firewall Log protokolliert, aber man sieht da keine Details, weswegen diese geblockt werden.
Dafür kann man:
netsh wfp capture start cab=off
netsh wfp capture stop
verwenden.
Das erzeugt eine .ETL und .XML Datei mit den geblockten Paketen.
Mit der ETL Datei kann man nicht viel anfangen, aber die XML Datei enthält die relevanten Informationen.
Die XML Datei enthält Details wie WFP FilterID und wenn man in der XML nach der FilterID weiter sucht, findet man auch die entsprechende Regel.
Alternativ zum netsh wfp capture kann man auch einen Audit Filter über GPO aktivieren:
Computer > Windows > Security > Advanced Audit > Object Access > Audit Filtering Platform Connection
Dort entweder "Audit Filtering Platform Connection" oder "Audit Filtering Platform Packet Drop" aktivieren.
Idealerweise mit "Failure", sonst würden wohl zu viele Events generiert.
"Platform Connection" liefert noch ein paar Daten mehr als "Packet Drop", die scheinen auf den ersten Blick aber nicht relevant.
Beispiel: Geblocktes Event und dessen WFP Filter Regel
Geblocktes Paket:
<netEvent>
<header>
<timeStamp>2025-09-15T10:55:03.145Z</timeStamp>
<flags numItems="9">
<item>FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET</item>
<item>FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET</item>
<item>FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET</item>
<item>FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET</item>
<item>FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET</item>
<item>FWPM_NET_EVENT_FLAG_APP_ID_SET</item>
<item>FWPM_NET_EVENT_FLAG_USER_ID_SET</item>
<item>FWPM_NET_EVENT_FLAG_IP_VERSION_SET</item>
<item>FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET</item>
</flags>
<ipVersion>FWP_IP_VERSION_V4</ipVersion>
<ipProtocol>6</ipProtocol>
<localAddrV4>192.168.0.1</localAddrV4>
<remoteAddrV4>192.168.0.2</remoteAddrV4>
<localPort>49911</localPort>
<remotePort>8080</remotePort>
<scopeId>0</scopeId>
<appId>
irgendein binärer Blob - nicht relevant
<asString>\.d.e.v.i.c.e.\.h.a.r.d.d.i.s.k.v.o.l.u.m.e.3.\.p.r.o.g.r.a.m. .f.i.l.e.s.\.m.e.i.n.\.p.r.o.g.r.a.m.m.\.p.r.o.g.r.a.m.m.e...e.x.e...</asString>
</appId>
<userId>S-1-5-21-xxxx</userId>
<addressFamily>FWP_AF_INET</addressFamily>
<packageSid>S-1-0-0</packageSid>
<enterpriseId/>
<policyFlags>0</policyFlags>
<effectiveName/>
</header>
<type>FWPM_NET_EVENT_TYPE_PUBLIC_CLASSIFY_DROP</type>
<classifyDrop>
<filterId>76580</filterId>
<layerId>48</layerId>
<reauthReason>0</reauthReason>
<originalProfile>3</originalProfile>
<currentProfile>3</currentProfile>
<msFwpDirection>MS_FWP_DIRECTION_OUT</msFwpDirection>
<isLoopback>false</isLoopback>
<vSwitchId/>
<vSwitchSourcePort>0</vSwitchSourcePort>
<vSwitchDestinationPort>0</vSwitchDestinationPort>
</classifyDrop>
<internalFields>
<internalFlags numItems="1">
<item>FWPM_NET_EVENT_INTERNAL_FLAG_FILTER_ORIGIN_SET</item>
</internalFlags>
capabilities/>
<fqbnVersion>0</fqbnVersion>
<fqbnName/>
<terminatingFiltersInfo numItems="2">
<item>
<filterId>76580</filterId>
<subLayer>32768</subLayer>
<actionType>FWP_ACTION_BLOCK</actionType>
</item>
<item>
<filterId>78029</filterId>
<subLayer>FWPP_SUBLAYER_INTERNAL_FIREWALL_WF</subLayer>
<actionType>FWP_ACTION_PERMIT</actionType>
</item>
</terminatingFiltersInfo>
<filterOrigin>Unknown</filterOrigin>
<policyAppId/>
<compartmentId>1</compartmentId>
</internalFields>
</netEvent>
WFP Regel zum geblockten Paket:
<layers numItems="97">
<item>
<layer>
...
</layer>
<callouts numItems="8">
...
</callouts>
<filters numItems="63">
...
<item>
<filterKey>{9a657e8b-04c2-46c7-8321-e5a3955c08fc}</filterKey>
<displayData>
<name>Custom Outbound Filter</name>
<description/>
</displayData>
<flags numItems="2">
<item>FWPM_FILTER_FLAG_PERSISTENT</item>
<item>FWPM_FILTER_FLAG_INDEXED</item>
</flags>
<providerKey>{608f5011-fb72-4986-a003-8fa1d9a00640}</providerKey>
<providerData/>
<layerKey>FWPM_LAYER_ALE_AUTH_CONNECT_V4</layerKey>
<subLayerKey>FWPM_SUBLAYER_UNIVERSAL</subLayerKey>
<weight>
<type>FWP_EMPTY</type>
</weight>
<filterCondition numItems="1">
<item>
<fieldKey>FWPM_CONDITION_ALE_APP_ID</fieldKey>
<matchType>FWP_MATCH_EQUAL</matchType>
<conditionValue>
<type>FWP_BYTE_BLOB_TYPE</type>
<byteBlob>
irgendein binärer Blob -- nicht relevant
<asString>\device\harddiskvolume3\program files\mein\programm\programm.exe</asString>
</byteBlob>
</conditionValue>
</item>
</filterCondition>
<action>
<type>FWP_ACTION_BLOCK</type>
<filterType/>
</action>
<rawContext>0</rawContext>
<reserved/>
<filterId>76580</filterId>
<effectiveWeight>
<type>FWP_UINT64</type>
<uint64>137438953472</uint64>
</effectiveWeight>
</item>
</filters>
</item>
</layers>
PowerShell Code zum Auslesen der geblockten Events:
$filterEvents =@()
$wfpXML = [System.Xml.XmlDocument](Get-Content C:\temp\wfpdiag.xml)
foreach ($event in $wfpXML.wfpdiag.events.netEvent) {
$filterEvents += [pscustomobject]@{
filterID = $event.classifyDrop.filterId
localIP = $event.Header.localAddrV4
localPort = $event.Header.localPort
remoteIP = $event.Header.remoteAddrV4
remotePort = $event.Header.remotePort
direction = $event.classifyDrop.msFwpDirection
}
}
$filterEvents |ft
Neben Anmerkungen
Wireshark kann diese Events nicht filtern. (Der Begriff ist glaube ich ETW Events).
Möchte man nicht nur die geblockten WFP-Pakete sehen, sondern auch sonstigen Netzwerkverkehr, muss man netsh trace verwenden.
netsh trace start capture=yes persistent=no tracefile=c:\temp\trace.etl scenario=netconnection
netsh trace stop
Damit kann man zusätzlich zum Netzwerktraffic auch die ETW/WFP-Events sehen.
Dafür muss man das erzeugte ETL-File aber in Windows Netmon oder Message Analyzer öffnen.
Wireshark kann mit ETL nicht umgehen und auch die Umwandlung mit ETL2PCAPNG hilft nicht.
Netmon und Message Analyzer sind EOL, aber Netmon wird noch offiziell von Microsoft als Download angegeben.
In Netmon und Message Analyzer kann man nach WFP-gebockten Paketen filtern:
Netmon:
- NetEvent.MicrosoftWindowsWFP.WFP_CLASSIFY_DROP_EVENT
- NetEvent.MicrosoftWindowsWFP.WFP_CLASSIFY_DROP_EVENT.RemoteAddress.IPv4.Address == 192.168.0.2
Message Analyzer:
- (Microsoft_Windows_WFP)
- (Microsoft_Windows_WFP.RemoteAddress.FlatAddress == 192.168.0.2)
Im Event sieht man dann auch wieder die FilterID (in HEX).
Powershell:
$wfpXML = [System.Xml.XmlDocument](Get-Content "C:\temp\wfpcapture1.xml")
$filterRules = @{}
foreach ($item in $wfpXML.wfpdiag.initialState.layers.item) {
if ($item.filters -ne "") {
foreach ($filterItem in $item.filters.item) {
$conditions = @()
foreach ($condition in $filterItem.filterCondition.Item) {
$value = ""
switch ($condition.fieldKey) {
"FWPM_CONDITION_ALE_APP_ID" {$value = $condition.conditionValue.byteBlob.asString}
"FWPM_CONDITION_ALE_USER_ID" {$value = $condition.conditionValue.sd}
"FWPM_CONDITION_IP_REMOTE_ADDRESS" {
if ($condition.matchType -eq "FWP_MATCH_RANGE") {
$value = "$($condition.conditionValue.rangeValue.valueLow.uint32) - $($condition.conditionValue.rangeValue.valueHigh.uint32)"
} else {
$value = $condition.conditionValue.uint32
}
}
"FWPM_CONDITION_IP_LOCAL_PORT" {
if ($condition.matchType -eq "FWP_MATCH_RANGE") {
$value = "$($condition.conditionValue.rangeValue.valueLow.uint16) - $($condition.conditionValue.rangeValue.valueHigh.uint16)"
} else {
$value = $condition.conditionValue.uint16
}
}
"FWPM_CONDITION_IP_REMOTE_PORT" {
if ($condition.matchType -eq "FWP_MATCH_RANGE") {
$value = "$($condition.conditionValue.rangeValue.valueLow.uint16) - $($condition.conditionValue.rangeValue.valueHigh.uint16)"
} else {
$value = $condition.conditionValue.uint16
}
}
}
$conditions += [pscustomobject]@{
fieldKey = $condition.fieldKey
match = $value
}
}
$ruleobject = [pscustomobject]@{
filterkey = $filterItem.filterKey
filtername = $filterItem.displayData.name
layer = $filterItem.layerKey
conditions = $conditions
}
$filterRules[$filterItem.filterId] = $ruleobject
}
}
}
$filterEvents =@()
$wfpXML = [System.Xml.XmlDocument](Get-Content C:\temp\wfpdiag4\wfpdiag4.xml)
foreach ($event in $wfpXML.wfpdiag.events.netEvent) {
$filterEvents += [pscustomobject]@{
filterID = $event.classifyDrop.filterId
localIP = $event.Header.localAddrV4
localPort = $event.Header.localPort
remoteIP = $event.Header.remoteAddrV4
remotePort = $event.Header.remotePort
direction = $event.classifyDrop.msFwpDirection
}
}
$filterEvents |ft