Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


FwpsInjectNetworkSendAsync0 BSOD directly

Haitham_ElkhiderHaitham_Elkhider Member Posts: 16
The simplest form of Inject go into BSOD right away, i cloned the NBL and inject it back absorbing the old packet first, if the NBL is the cloned one the BOSD happens right away, I tried to Deep Clone with creating a new NBL, but still the same, i believe there is something wrong with the cloned NBL.

the simplified code is below showing the current state removing everything else (i have been working on crafting a new paket with MDLs and so Originally) the below code Crashes all the time on the injection.

Notice i made a new injection handle (the code is modified inspect example)
I changed the filter to capture all packets
I removed the capture on transport Layer so its on network and the ALE layers only now .

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
)
{
classifyOut->actionType = FWP_ACTION_PERMIT;
FWPS_PACKET_INJECTION_STATE packetState;
//NdisRetreatNetBufferDataStart(pNetBuffer, inMetaValues->ipHeaderSize, FALSE, NULL);

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;
}
goto Exit;
}

PNET_BUFFER_LIST pClonedNBL = NULL;

NTSTATUS status = STATUS_SUCCESS;
status = FwpsAllocateCloneNetBufferList(
(PNET_BUFFER_LIST)layerData,
NULL,
NULL,
0,
&pClonedNBL
);

if (!NT_SUCCESS(status))
goto Exit;

// CRASHES DIRECTLY HERE
status = FwpsInjectNetworkSendAsync0(
gNetworkInjectionHandle,
NULL,
0,
UNSPECIFIED_COMPARTMENT_ID,//inMetaValues->compartmentId,
pClonedNBL,//pNewNbl,
TLInspectNetworkInjectComplete,
NULL
);

if (!NT_SUCCESS(status))
{
if (pClonedNBL != NULL)
{
FwpsFreeCloneNetBufferList(pClonedNBL, 0);
}
goto Exit;
}

pClonedNBL = NULL; // ownership transferred to the
// completion function.

classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;

Exit:
classifyOut->actionType = FWP_ACTION_PERMIT;
return;
}

Comments

  • ashish_kohliashish_kohli Member - All Emails Posts: 61
    try reference the netbufferlist before cloning.
  • Haitham_ElkhiderHaitham_Elkhider Member Posts: 16
    Thank you Ashish ,

    I have referenced the NBL before cloning directly the dereferenced it after But the same result

    PNET_BUFFER_LIST pClonedNBL = NULL;

    NTSTATUS status = STATUS_SUCCESS;

    FwpsReferenceNetBufferList((PNET_BUFFER_LIST)layerData, TRUE);

    status = FwpsAllocateCloneNetBufferList(
    (PNET_BUFFER_LIST)layerData,
    NULL,
    NULL,
    0,
    &pClonedNBL
    );

    if (!NT_SUCCESS(status))
    goto Exit;

    The Crash Still happens in the injection, This is my first time injecting anything so i think i am missing something ...

    Any help will be appreciated .
  • Jason_StephensonJason_Stephenson Member Posts: 66
    How have you created gNetworkInjectionHandle ? What WFP layer is your TLInspectOutboundNetworkClassify callout for?

    Packet injection will often (always?) require the PNET_BUFFER_LIST passed to the injection function to be starting with a particular network header. For example to use FwpsInjectTransportReceiveAsync the PNET_BUFFER_LIST must begin with an IP header.

    J
  • Haitham_ElkhiderHaitham_Elkhider Member Posts: 16
    Ok The regeneration happens here :
    status = TLInspectRegisterNetworkCallouts(
    &FWPM_LAYER_OUTBOUND_IPPACKET_V4,
    &TL_INSPECT_OUTBOUND_IPPAKCET_CALLOUT_V4,
    deviceObject,
    &gOutboundTlCalloutIdV4
    );

    The injection handle is here :

    status = FwpsInjectionHandleCreate(
    AF_INET,
    FWPS_INJECTION_TYPE_NETWORK,
    &gNetworkInjectionHandle
    );

    Before i got an error when the injection handle been created for the Transport Layer, but it doesn't give a BSOD , from the status error in the debugview i figured the problem and corrected it to the proper injection type : FWPS_INJECTION_TYPE_NETWORK

    Also I am sure the NBL starts with the IP header because in the Classifyfn I can do this :

    PNET_BUFFER pNetBuffer = NET_BUFFER_LIST_FIRST_NB(pNetbufferlist);
    PMDL packet_mdl = NULL;
    PMDL CurrentMdl = NET_BUFFER_CURRENT_MDL(pNetBuffer);
    PUCHAR SrcMemory = NULL;
    ULONG Length = 0, MdlOffset = 0, DestOffset = 0, IP_HEADER_SIZE = sizeof(IP_HEADER_V4), UDP_HEADER_SIZE = sizeof(UDP_HEADER);
    PVOID Dest = ExAllocatePoolWithTag(NonPagedPool, sizeof(BYTE[1500]), 'tag9');
    while (CurrentMdl != NULL)
    {
    SrcMemory = MmGetSystemAddressForMdlSafe(CurrentMdl, LowPagePriority | MdlMappingNoExecute);
    Length = MmGetMdlByteCount(CurrentMdl);

    MdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pNetBuffer);
    SrcMemory += MdlOffset;
    Length -= MdlOffset;

    NdisMoveMemory((PUCHAR)Dest + DestOffset, SrcMemory, Length);
    DestOffset += Length;
    CurrentMdl = NDIS_MDL_LINKAGE(CurrentMdl);
    }


    DbgPrintEx(DPFLTR_IHVNETWORK_ID,
    DPFLTR_ERROR_LEVEL,
    "[status: %#x]\n", RtlUshortByteSwap((ULONG)((IP_HEADER_V4*)(Dest))->protocol));

    And the protocol either UDP or TCP will be printed properly 0x6 or 0x11(17) in the DebugView .

    what do you think ?
  • Haitham_ElkhiderHaitham_Elkhider Member Posts: 16
    To make sure the NBL starts with the IP header I done this even further :

    if (RtlUshortByteSwap((ULONG)((IP_HEADER_V4*)(Dest))->protocol) == 0x600)
    {

    status = FwpsInjectNetworkSendAsync0(
    gNetworkInjectionHandle,
    NULL,
    0,
    inMetaValues->compartmentId, //UNSPECIFIED_COMPARTMENT_ID,
    pClonedNBL,//pNewNbl,
    TLInspectNetworkInjectComplete,
    NULL
    );


    FwpsDereferenceNetBufferList(pOrgNBL, FALSE);

    }

    The protocol captured in the proper offset of the IP header , it should mean the packet is formed properly ( despite the fact i modify nothing on the received NBL in the first place)

    the injection wont be called unless the NBL ip header at least is properly formed .
  • ashish_kohliashish_kohli Member - All Emails Posts: 61
    before injection free the original netbufferlist.

    Also copy & paste the analyze -v dump.
  • Haitham_ElkhiderHaitham_Elkhider Member Posts: 16
    Thank you for the help, I figured the problem it was from a forgotten line in the completion function to free an unreserved memory .

    Completion function should only free NBL if we cloned it

    Thanks everyone
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 30 Mar 2020 OSR Seminar Space
Developing Minifilters 15 Jun 2020 LIVE ONLINE
Writing WDF Drivers 22 June 2020 LIVE ONLINE
Internals & Software Drivers 28 Sept 2020 Dulles, VA