最近接触到一个需求,就是要在每个SYN包前面发送一个自定义用户包,实现代码如下,可是会蓝屏,不知道什么原因,请高手指点:
方法一:
在MPSendPackets一开始的地方就填入如下代码:
PNDIS_PACKET MyPkt1;
PNDIS_BUFFER MyPktBuf1;
PMDL MyPktMDL;
if (pAdapt->PTDeviceState > NdisDeviceStateD0)
{
return;
}
NdisAllocatePacket(&Status,
&MyPkt1,pAdapt->SendPacketPoolHandle);
if(NT_SUCCESS(Status))
{
PSEND_RSVD SendRsvd;
//NdisAllocateBuffer(&Status,&MyPktBuf1,pAdapt->SendPacketPoolHandle,"1234567890",10);
MyPktMDL=IoAllocateMdl("1234567890",10,FALSE,FALSE,NULL);
MmBuildMdlForNonPagedPool(MyPktMDL);
MyPktBuf1=MyPktMDL;
NdisChainBufferAtFront(MyPkt1,MyPktBuf1);
MyPkt1->Private.Head=NULL;
MyPkt1->Private.Tail=NULL;
NdisSetPacketFlags(MyPkt1,NDIS_FLAGS_DONT_LOOPBACK);
SendRsvd = (PSEND_RSVD)(MyPkt1->ProtocolReserved);
SendRsvd->MyPktMDL=MyPktMDL;
NdisSend(&Status,pAdapt->BindingHandle,MyPkt1);//就在这里蓝屏了
}
方法二:
这一段是网上的代码。其实我觉得还是比较有问题的,
其中
NdisAllocatePacket(&status, &pSendPacket, NdisSendPacketPool);
和
NdisAllocateBuffer( &status,
&pSendPacketBuffer,
NdisSendPacketPool,
pSendBuffer,
dwSendBufferLength );
用的都是NdisSendPacketPool,但是我们知道NdisSendPacketPool和NdisSendBufferPool是两个概念。
NDIS_STATUS
MySendPacket (
NDIS_HANDLE NdisBindingHandle,
NDIS_HANDLE NdisSendPacketPool,
PVOID pBuffer,
ULONG dwBufferLength
)
{
NDIS_STATUS status;
PNDIS_PACKET pSendPacket = NULL;
PNDIS_BUFFER pSendPacketBuffer = NULL;
PUCHAR pSendBuffer = NULL;
ULONG dwSendBufferLength;
NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress;
PSEND_RSVD SendRsvd = NULL;
if (!NdisBindingHandle)
return NDIS_STATUS_FAILURE;
if (!pBuffer)
return NDIS_STATUS_FAILURE;
if (dwBufferLength > 1024)
return NDIS_STATUS_FAILURE;
HighestAcceptableAddress.QuadPart = -1;
dwSendBufferLength = max(dwBufferLength, 14);
status = NdisAllocateMemory(&pSendBuffer, dwSendBufferLength, 0, HighestAcceptableAddress);
if (status != NDIS_STATUS_SUCCESS)
{
return status;
}
RtlZeroMemory(pSendBuffer, dwSendBufferLength);
RtlMoveMemory(pSendBuffer, pBuffer, dwSendBufferLength);
NdisAllocatePacket(&status, &pSendPacket, NdisSendPacketPool);
if (status != NDIS_STATUS_SUCCESS)
{
NdisFreeMemory(pSendBuffer, dwSendBufferLength, 0);
return status;
}
NdisAllocateBuffer( &status,
&pSendPacketBuffer,
NdisSendPacketPool,
pSendBuffer,
dwSendBufferLength );
if (status != NDIS_STATUS_SUCCESS)
{
NdisFreeMemory(pSendBuffer, dwSendBufferLength, 0);
NdisDprFreePacket(pSendPacket);
return status;
}
NdisChainBufferAtFront(pSendPacket, pSendPacketBuffer);
SendRsvd = (PSEND_RSVD)(pSendPacket->ProtocolReserved);
SendRsvd->OriginalPkt = NULL; //注意这里
pSendPacket->Private.Head->Next=NULL;
pSendPacket->Private.Tail=NULL;
//NDIS_SET_PACKET_HEADER_SIZE(pSendPacket, 14);
NdisSetPacketFlags(pSendPacket, NDIS_FLAGS_DONT_LOOPBACK);
NdisSend(&status, NdisBindingHandle, pSendPacket);//就在这里蓝屏了
if (status != STATUS_PENDING)
{
NdisUnchainBufferAtFront(pSendPacket ,&pSendPacketBuffer);
NdisQueryBufferSafe( pSendPacketBuffer,
(PVOID *)&pSendBuffer,
&dwSendBufferLength,
HighPagePriority );
NdisFreeBuffer(pSendPacketBuffer);
NdisFreeMemory(pSendBuffer, dwSendBufferLength, 0);
NdisDprFreePacket(pSendPacket);
}
return status;
}
最后的结果都是在NdisSend的时候蓝屏。可能有人说在PtSendComplete没有释放造成的,但是我做了释放的代码也一样,而且崩溃的时候并不是在PtSendComplete里面。而是在NdisSend的同时。
下面黏贴两种方法的释放,都放在PtSendComplete的开头处:
第一种方法:
PSEND_RSVD SendRsvd1;
PNDIS_BUFFER pMySendPacketBuffer;
PVOID pMySendBuffer;
UINT dwMySendBufferLength;
SendRsvd1 = (PSEND_RSVD)(Packet->ProtocolReserved);
if(SendRsvd1->MyPktMDL)
{
NdisUnchainBufferAtFront(Packet, &SendRsvd1->MyPktMDL);
IoFreeMdl(SendRsvd1->MyPktMDL);
NdisDprFreePacket(Packet);
NdisMSendComplete(pAdapt->MiniportHandle,
Packet,Status);
return;
}
第二种方法:
PSEND_RSVD SendRsvd1;
PNDIS_BUFFER pMySendPacketBuffer;
PVOID pMySendBuffer;
UINT dwMySendBufferLength;
SendRsvd1 = (PSEND_RSVD)(Packet->ProtocolReserved);
Pkt = SendRsvd1->OriginalPkt;
if (!Pkt)
{
NdisUnchainBufferAtFront(Packet, &pMySendPacketBuffer);
if (pMySendPacketBuffer)
{
NdisQueryBufferSafe( pMySendPacketBuffer,
(PVOID *)&pMySendBuffer,
&dwMySendBufferLength,
HighPagePriority );
if (pMySendBuffer && dwMySendBufferLength)
{
NdisFreeMemory(pMySendBuffer, dwMySendBufferLength,0);
}
NdisFreeBuffer( pMySendPacketBuffer );
}
NdisDprFreePacket(Packet);
NdisMSendComplete(pAdapt->MiniportHandle,
Pkt,Status);
return;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)