NDIS filter driver : Cloning and modifying NBL not worked

Hello,
Thanks to you experts, I could read ethernet header and ip header through lwf.

My final goal is modifying packets’ IP address so now I’m trying it.
However, the amount of data is so small that I’m having a lot of trouble.

I thought of the following methods :

  1. read eth header and ip header from NB
  2. using NdisAdvanceNetBufferDataStart() function, logically remove eth header + ip header from NBL
  3. make clone of NBL using NdisAllocateCloneNetBufferList
  4. using NdisRetreatNetBufferDataStart() function, make space for header to cloned NBL (all underneath steps are ‘to cloned NBL’)
  5. get an starting address that eth header should be located in cloned NBL, using NdisGetDataBuffer() and add the eth header(got from 1st step)
  6. using NdisAdvanceNetBufferDataStart() and NdisGetDataBuffer, get an starting address of ip header and add the ip header(got from 1st step) to the address
  7. I want to modify dest ip from ip header, so get an dest ip address through using NdisAdvanceNetBufferDataStart() for sizeof(ipheader)-4 and NdisGetDataBuffer()
  8. overwrite dest ip in ip header
  9. in FilterSendNetBufferListsComplete, free the cloned NBL

Is the way I thought of the right way to modify the packet?

If it is, I still don’t know about detail how to implement it.

Question1. I wrote code and in FilterSendNetBufferLists function, it seems destination ip changed successfully at least in the function, but how can I check that it sends properly?
Question2. Nevertheless, the code didn’t work. It occured error (I think after SendNBLComplete). Why does it happen and how can I fix it?
I think there are sth wrong about handling of cloned buffer and original buffer.

These are some parts of my code.(FilterSendNetBufferLists, FilterSendNetBufferListsComplete)

FilterSendNetBufferLists

… //This code starts from 6th step of above method

		struct ip_h *m_ip = NdisGetDataBuffer(Clone_NetBuffer, sizeof(buffer2), NULL, 1, 0);
		*m_ip = *ip;

		NdisAdvanceNetBufferDataStart(Clone_NetBuffer, sizeof(buffer2) - 4, FALSE, NULL);
		struct in_addr *m_dst = (struct in_addr *)NdisGetDataBuffer(Clone_NetBuffer, 4, NULL, 1, 0);
		struct in_addr m_dst_ip = {0};
		PCSTR strip = "0.0.0.0";
		
		if (STATUS_SUCCESS == RtlIpv4StringToAddress(TEXT("0.0.0.0"), TRUE, &strip, &m_dst_ip)) {
			*m_dst = m_dst_ip;
		}
		else {
			DEBUGP(DL_TRACE, "Failed RtlIpv4StringToAddress");
		}
		NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO nblChecksumInfo;
		nblChecksumInfo.Value = NET_BUFFER_LIST_INFO(CurrNbl, TcpIpChecksumNetBufferListInfo);
		NET_BUFFER_LIST_INFO(CloneNbl, TcpIpChecksumNetBufferListInfo) = nblChecksumInfo.Value;

		CurrNbl->ChildRefCount++;
		CloneNbl->ParentNetBufferList = CurrNbl;
		CloneNbl->SourceHandle = FilterModuleContext;
		NdisRetreatNetBufferListDataStart(CloneNbl, back_size-4, FALSE, NULL, NULL);

		NdisFSendNetBufferLists(pFilter->FilterHandle, CloneNbl, PortNumber, SendFlags);
	}
	else {
		NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);
	}

###FilterSendNetBufferListsComplete

// Send complete the NBLs.  If you removed any NBLs from the chain, make
// sure the chain isn't empty (i.e., NetBufferLists!=NULL).

//---added code---
CurrNbl = NetBufferLists;
if (CurrNbl->ParentNetBufferList) {
	CurrNbl->ParentNetBufferList->Status = CurrNbl->Status;
	CurrNbl->ParentNetBufferList = NULL;
	NdisFreeCloneNetBufferList(CurrNbl, 0);
}

NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, SendCompleteFlags);
debug text

nat_driver_prac1: <===SendNBLComplete.
KDTARGET: Refreshing KD connection

*** Fatal System Error: 0x0000001e
(0xFFFFFFFFC0000005,0xFFFFF8065051F120,0x0000000000000000,0xFFFFFFFFFFFFFFFF)

Break instruction exception - code 80000003 (first chance)
Connected to Windows 10 19041 x64 target at (Thu Sep 24 17:38:27.270 2020 (UTC + 9:00)), ptr64 TRUE
Loading Kernel Symbols



Loading User Symbols


Loading unloaded module list


  •                                                                         *
    
  •                    Bugcheck Analysis                                    *
    
  •                                                                         *
    

Use !analyze -v to get detailed debugging information.

BugCheck 1E, {ffffffffc0000005, fffff8065051f120, 0, ffffffffffffffff}

Probably caused by : E1G6032E.sys ( E1G6032E!ProcessTransmitInterrupts+148 )

Followup: MachineOwner

nt!DbgBreakPointWithStatus:
fffff806`4e802d40 cc int 3

Whether wrong or right, I’m ready for your advice.
Please forgive me for my lack of english.
Thank you.

I think I couldn’t restore original NBL so I changed my method.
To restore original NBL, I think it is better way making a new MDL for header and link it instead of original header MDL.
However, there is a problem. I don’t know where is the proper position to link MDL because I could not know what MDL have header and what MDL ends the header. How can I know it?
Is this method is the better way? If not, please help me to restore original NBL on my original method.