I create my sublayer and assign zero weight to it. Then I create filters with callouts on following layers: FWPM_LAYER_IPFORWARD_V4_DISCARD, FWPM_LAYER_INBOUND_IPPACKET_V4_DISCARD, FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD, FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD, FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD, FWPM_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD, FWPM_LAYER_STREAM_V4_DISCARD, FWPM_LAYER_DATAGRAM_DATA_V4_DISCARD and DISCARDS on ALE layers. All these filters assigned at my sublayer. I don’t assign any conditions to filters, because I want to catch all discarded packets.
To test project I use “Program” that blocks all outgoing traffic and works only on following layers: FWPM_LAYER_INBOUND_IPPACKET_V4, FWPM_LAYER_OUTBOUND_IPPACKET_V4, FWPM_LAYER_IPFORWARD_V4 and on corresponding discards.
In my mind it must work so: “Program” blocks packet, packet goes to some other sublayers and finally packet goes to my sublayer with inspection filters. I use DbgPrint() function in classify function to identify if callout is invoked. When I send some packet, “Program” drops it, but my classify functions don’t start.
Also I have some questions:
- Is my thought is clear that all dropped packets wil go to discard layers on all sublayers?
- If no, how can I inspect if packet was dropped by another filter on another sublayer?
- Can I attach my own filter on another’s sublayer?
This my functions for adding and registering callouts:
NTSTATUS AddDefault(
LPCWSTR calloutName,
LPCWSTR calloutDescription,
const GUID calloutKey,
const GUID layerKey,
LPCWSTR filterName,
LPCWSTR filterDescription,
const GUID filterKey
)
{
NTSTATUS status;
FWPM_CALLOUT0 callout = { 0 };
FWPM_FILTER0 filter;
RtlZeroMemory(&filter, sizeof(FWPM_FILTER0));
callout.calloutKey = GUIDcallout;
callout.displayData.name = wstrName;
callout.displayData.description = wstrDescription;
callout.applicableLayer = GUIDlayer;
callout.providerKey = (GUID *)&GUIDprovider;
status = FwpmCalloutAdd0(g_hEngine, &callout, NULL, NULL);
if (!NT_SUCCESS(status))
{
PRINT_ERR("FwpmCalloutAdd0 failed", status);
goto Exit;
}
filter.providerKey = (GUID *)&GUIDprovider;
filter.displayData.name = wstrName;
filter.displayData.description = wstrDescription;
filter.layerKey = GUIDlayer;
filter.subLayerKey = GUIDsublayer;
filter.numFilterConditions = 0;
filter.filterCondition = NULL;
filter.action.type = FWP_ACTION_CALLOUT_INSPECTION;\
filter.action.calloutKey = GUIDcallout;
filter.filterKey = GUIDfilter;
filter.weight.type = FWP_EMPTY;
filter.flags = FWPM_FILTER_FLAG_NONE;
status = FwpmFilterAdd0(g_hEngine, &filter, NULL, NULL);
if (!NT_SUCCESS(status))
{
PRINT_ERR("FwpmFilterAdd0 failed", status);
goto Exit;
}
Exit:
return status;
}
NTSTATUS RegisterDefault(
PDEVICE_OBJECT pDevice,
const GUID calloutKey,
FWPS_CALLOUT_CLASSIFY_FN0 classifyFn,
FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN0 flowDeleteFn,
FWPS_CALLOUT_NOTIFY_FN0 notifyFn
)
{
FWPS_CALLOUT0 calloutInitData = { 0 };
calloutInitData.calloutKey = calloutKey;
calloutInitData.classifyFn = classifyFn;
calloutInitData.flowDeleteFn = flowDeleteFn;
calloutInitData.notifyFn = notifyFn;
return FwpsCalloutRegister0(pDevice, &calloutInitData, NULL);
}