Im hooking FWPM_LAYER_OUTBOUND_IPPACKET_V4, and the filter is empty there, so I should capture every single packet going outside. The problem Deep Cloning and injection WITHOUT Modification doesn’t work for me, I get invoked in the completion function and things seems ok, also I have registered a callout at FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD Layer, just to see if my injected packets are getting discarded for any reason, but nothing shows up in there .
(Am I looking at the correct discard layer ? )
What I get is any browsing or any network activity stops, like the packets are not even making it through .
void
TLInspectOutboundNetworkClassify(
In const FWPS_INCOMING_VALUES* inFixedValues,
In const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
Inout_opt void* layerData,
In const FWPS_FILTER* filter,
In UINT64 flowContext,
Inout FWPS_CLASSIFY_OUT* classifyOut
)
{
FWPS_PACKET_INJECTION_STATE packetState;
packetState = FwpsQueryPacketInjectionState(
gNetworkInjectionHandle,
layerData,
NULL
);
if ((packetState == FWPS_PACKET_INJECTED_BY_SELF) ||
(packetState == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF))
{
classifyOut->actionType = FWP_ACTION_PERMIT;
if (filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)
{
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
}
return;
}
classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
//classifyOut->actionType = FWP_ACTION_PERMIT;
PNET_BUFFER_LIST pClonedNBL = NULL, pOrgNBL = layerData;
NTSTATUS status = STATUS_SUCCESS;
status = FwpsAllocateCloneNetBufferList(
pOrgNBL,
NULL,
NULL,
0,
&pClonedNBL
);
if (!NT_SUCCESS(status))
{
if (pClonedNBL != NULL)
{
FwpsFreeCloneNetBufferList(pClonedNBL, 0);
}
return;
}
PNET_BUFFER_LIST pNewNbl = NULL;
PNET_BUFFER pNetBuffer = NULL;
const UINT32 BUFFER_SIZE = 2048;
for (pNetBuffer = NET_BUFFER_LIST_FIRST_NB(pClonedNBL);
pNetBuffer != NULL;
pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer))
{
BYTE* pBuffer = 0;
HLPR_NEW_ARRAY(pBuffer,BYTE,BUFFER_SIZE,‘TAG5’);
if (pBuffer == 0) continue;
PVOID pContiguousData = 0;
PVOID pBuffer_IPHEADER = NULL;
PVOID pBuffer_TRANSPORTHEADER = NULL;
pBuffer_IPHEADER = ExAllocatePoolWithTag(NonPagedPool, 400, ‘TAG1’);
pBuffer_TRANSPORTHEADER = ExAllocatePoolWithTag(NonPagedPool, 400, ‘TAG2’);
PVOID pBuffer_PAYLOAD = ExAllocatePoolWithTag(NonPagedPool, 1500, ‘TAG3’);
UINT32 ip = 0, transport = 0;
///////////////////////////////////////////
//////////// IP HEADER ////////////////////
if (pNetBuffer != NULL)
{
pContiguousData = NdisGetDataBuffer(pNetBuffer,
inMetaValues->ipHeaderSize,
pBuffer,
1,
0);
if (pContiguousData == NULL)
{
status = STATUS_NO_MEMORY;
return;
}
if (pContiguousData != NULL)
RtlCopyMemory(pBuffer_IPHEADER, pContiguousData, inMetaValues->ipHeaderSize);
NdisAdvanceNetBufferDataStart(pNetBuffer, inMetaValues->ipHeaderSize, 0, NULL);
ip = inMetaValues->ipHeaderSize;
pContiguousData = NULL;
}
///////////////////////////////////////////
//////////// TRANSPORT HEADER /////////////
if (pNetBuffer != NULL)
{
pContiguousData = NdisGetDataBuffer(pNetBuffer,
inMetaValues->transportHeaderSize,
pBuffer,
1,
0);
if (pContiguousData != NULL)
RtlCopyMemory(pBuffer_TRANSPORTHEADER, pContiguousData, inMetaValues->transportHeaderSize);
NdisAdvanceNetBufferDataStart(pNetBuffer, inMetaValues->transportHeaderSize, FALSE, NULL);
transport = inMetaValues->transportHeaderSize;
pContiguousData = NULL;
}
///////////////////////////////////////////
//////////// PAYLOAD// ////////////////////
if (pNetBuffer != NULL)
{
pContiguousData = NdisGetDataBuffer(pNetBuffer,
NET_BUFFER_DATA_LENGTH(pNetBuffer),
pBuffer,
1,
0);
if (pContiguousData != NULL)
RtlCopyMemory(pBuffer_PAYLOAD, pContiguousData, NET_BUFFER_DATA_LENGTH(pNetBuffer));
pContiguousData = NULL;
}
PMDL p1 = NULL, p2 = NULL, p3 = NULL;
p1 = IoAllocateMdl(pBuffer_IPHEADER, inMetaValues->ipHeaderSize, FALSE, FALSE, NULL);
if(p1 != NULL) MmBuildMdlForNonPagedPool(p1);
inMetaValues->ipHeaderSize;
p2 = IoAllocateMdl(pBuffer_TRANSPORTHEADER, inMetaValues->transportHeaderSize, FALSE, FALSE, NULL);
if (p2 != NULL) MmBuildMdlForNonPagedPool(p1);
inMetaValues->transportHeaderSize;
p3 = IoAllocateMdl(pBuffer_PAYLOAD, NET_BUFFER_DATA_LENGTH(pNetBuffer), FALSE, FALSE, NULL);
if (p3 != NULL) MmBuildMdlForNonPagedPool(p1);
p1->Next = p2;
p2->Next = p3;
if ( p1 == NULL || p2 == NULL || p3 == NULL)
{
status = STATUS_NO_MEMORY;
return;
}
status = FwpsAllocateNetBufferAndNetBufferList(g_pNDISPoolData->nblPoolHandle, 0, 0, p1, 0,
NET_BUFFER_DATA_LENGTH(pNetBuffer) + inMetaValues->transportHeaderSize + inMetaValues->ipHeaderSize, &pNewNbl);
if (!NT_SUCCESS(status))
return;
if (p1 != NULL) IoFreeMdl(p1);
if (p2 != NULL) IoFreeMdl(p2);
if (p3 != NULL) IoFreeMdl(p3);
HLPR_DELETE_ARRAY(pBuffer, ‘TAG5’);
ExFreePoolWithTag(pBuffer_IPHEADER, ‘TAG1’);
ExFreePoolWithTag(pBuffer_TRANSPORTHEADER, ‘TAG2’);
ExFreePoolWithTag(pBuffer_PAYLOAD, ‘TAG3’);
if (pNetBuffer != NULL)
NdisRetreatNetBufferDataStart(pNetBuffer, transport + ip, FALSE, NULL);
}
status = FwpsInjectNetworkSendAsync0(
gNetworkInjectionHandle,
NULL,
0,
UNSPECIFIED_COMPARTMENT_ID,//inMetaValues->compartmentId, //
pNewNbl,
TLInspectNetworkInjectComplete,
NULL
);
if (pClonedNBL != NULL)
{
FwpsFreeCloneNetBufferList(pClonedNBL, 0);
}
return;
}