WFP & IP headers
Hi there,
I’ve recently decided I should probably learn some driver development and for better or for worse I’ve started with WFP.
I figured that this would be a good place to start as (correct me if im wrong) it’s a much simpler API to use than NDIS and
I’ve always wanted to learn more about the network side of things without being swamped in too much detail too soon.
Anyway, I’ve been having a go at redirecting ip packets into a different network adapter by altering the ipv4 header source ip.
I have the following set up:
An exe for calling the WFE and adding my callout
At layer: FWPM_LAYER_OUTBOUND_IPPACKET_V4
Filtering on : FWPM_CONDITION_IP_LOCAL_ADDRESS
An associated WFP callout driver
Using PnP and the clone drop reinject pattern
Creating a g_Injection handle using FwpsInjectionHandleCreate(AF_INET, FWPS_INJECTION_TYPE_NETWORK, &g_InjectionHandle);
The following snippet of code is my classifyFn callback.
void ProcessNetworkData(
In const FWPS_INCOMING_VALUES* inFixedValues,
In const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
Inout_opt void* layerData,
In_opt const void* classifyContext,
In const FWPS_FILTER* filter,
In UINT64 flowContext,
Inout FWPS_CLASSIFY_OUT* classifyOut)
{
/*UNREFERENCED_PARAMETERS*/
NET_BUFFER_LIST* clonedNetBufferList = NULL;
NTSTATUS status = STATUS_SUCCESS;
FWPS_PACKET_INJECTION_STATE packetState = FwpsQueryPacketInjectionState(g_InjectionHandle, layerData, NULL);
if (packetState == FWPS_PACKET_INJECTED_BY_SELF || packetState == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF)
classifyOut->actionType = FWP_ACTION_PERMIT;
else
{
if (classifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
{
classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
classifyOut->rights ^= FWPS_RIGHT_ACTION_WRITE;
NET_BUFFER_LIST* netBufferList = (NET_BUFFER_LIST*)layerData;
status = FwpsAllocateCloneNetBufferList(netBufferList, NULL, NULL, 0, &clonedNetBufferList);
if (NT_SUCCESS(status))
{
for (NET_BUFFER* netBuffer = NET_BUFFER_LIST_FIRST_NB(clonedNetBufferList); netBuffer != NULL; netBuffer = NET_BUFFER_NEXT_NB(netBuffer))
{
IPV4_HEADER* ipHeader = NdisGetDataBuffer(netBuffer, sizeof(IPV4_HEADER), NULL, 1, 0);
ipHeader->SourceAddress.S_un.S_addr = 3044277929;
//ipHeader->DestinationAddress.S_un.S_addr = 1387265705;
}
status = FwpsInjectNetworkSendAsync(g_InjectionHandle, NULL, 0, inMetaValues->compartmentId, clonedNetBufferList, PacketInjectionComplete, NULL);
}
}
}
if (!NT_SUCCESS(status) && clonedNetBufferList != NULL)
FwpsFreeCloneNetBufferList(clonedNetBufferList, 0);
}
I’ve excluded the other calls for brevity. (EvtDriverUnload, DriverEntry, EvtDeviceAdd) I’m pretty sure they’re not of interest here but can be provided if desired.
Why can I use the above code to successfully redirect a ping request (ICMP) down a different NIC (to a different destination if desired), but I can’t redirect tcp(http) down a different NIC - they just timeout?
What I’m seeing is that reinjected packets for tcp(http) never appear in the classifyFn callback again (and hence never hit classifyOut->actionType = FWP_ACTION_PERMIT)
I would have thought that altering the source address of all ip packets would have sent all network traffic down the second NIC?
I think this can be achieved with ALE_BIND_REDIRECT but I’m more interest in why my example is not working?
Thanks for your time
Jason