📄 hooked_fn.c
字号:
// can't use UNICODE %S to output (see DbgPrint documentation)
KdPrint(("[ndis_hk] new_TransferDataCompleteHandler: (%d) pkt %u; bytes %u\n",
adapter->adapter_index,
hdr_size + data_size, BytesTransferred));
// filter packet
if (filter_packet(DIRECTION_IN, adapter->adapter_index, Packet)) {
// call original receive handler with packet (don't care about status)
PCHARS_OLD_CHARS(pchars)->ReceiveHandler(ProtocolBindingContext,
(NDIS_HANDLE)((char *)buf + hdr_size), buf, hdr_size,
(char *)buf + hdr_size, data_size, data_size);
}
}
// cleanup
free(buf);
NdisFreeBuffer(hdr_buffer);
NdisFreeBuffer(data_buffer);
NdisFreePacket(Packet);
}
/**
* Hooked ReceivePacketHandler from NDIS_PROTOCOL_CHARACTERISTICS.
* NDIS miniport driver indicates packet using new-style packet transfer.
* We got the whole packet! We can filter it and call original handler if we want.
*/
INT
new_ReceivePacketHandler(
struct PROTOCOL_CHARS *pchars, /* added by ASM stub */
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet)
{
struct ADAPTER_PROTOCOL *adapter;
_CHECK_PCHARS(pchars);
// get adapter
for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
if (adapter->ProtocolBindingContext == ProtocolBindingContext)
break;
if (adapter != NULL) {
// can't use UNICODE %S to output (see DbgPrint documentation)
KdPrint(("[ndis_hk] new_ReceivePacketHandler: (%d)\n",
adapter->adapter_index));
if (adapter->adapter_index != 0 &&
!filter_packet(DIRECTION_IN, adapter->adapter_index, Packet)) {
KdPrint(("[ndis_hk] new_ReceivePacketHandler: DROP!\n"));
return 0;
}
} else
KdPrint(("[ndis_hk] new_ReceivePacketHandler: adapter not found!\n"));
// call original handler
return PCHARS_OLD_CHARS(pchars)->ReceivePacketHandler(ProtocolBindingContext, Packet);
}
#ifdef NDIS50
/**
* Hooked CoReceivePacketHandler from NDIS_PROTOCOL_CHARACTERISTICS.
* I implemented this handler with no ideas. Just illustration of how to implement this handler.
* Is it used by TCP/IP on XP? I don't know...
*/
/** @todo NDIS>=5 ONLY! Do we need this handler? If yes TODO NdisCoSendPackets hook also. */
UINT
new_CoReceivePacketHandler(
struct PROTOCOL_CHARS *pchars, /* added by ASM stub */
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE ProtocolVcContext,
IN PNDIS_PACKET Packet)
{
struct ADAPTER_PROTOCOL *adapter;
_CHECK_PCHARS(pchars);
/** @test I've never seen this function is called under NT4/2k */
_TEST_ME_
// get adapter
for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
if (adapter->ProtocolBindingContext == ProtocolBindingContext)
break;
if (adapter != NULL) {
// can't use UNICODE %S to output (see DbgPrint documentation)
KdPrint(("[ndis_hk] new_CoReceivePacket: (%d)\n",
adapter->adapter_index));
if (adapter->adapter_index != 0 &&
!filter_packet(DIRECTION_IN, adapter->adapter_index, Packet)) {
KdPrint(("[ndis_hk] new_CoReceivePacketHandler: DENY!\n"));
return 0;
}
} else
KdPrint(("[ndis_hk] new_CoReceivePacket: adapter not found\n"));
// call original handler
return PCHARS_OLD_CHARS(pchars)->CoReceivePacketHandler(
ProtocolBindingContext, ProtocolVcContext, Packet);
}
#endif /* NDIS50 */
/**
* Hooked SendCompleteHandler from NDIS_PROTOCOL_CHARACTERISTICS.
* Check if it is completion for our call of NdisSend free our buffer and don't call original handler.
*/
VOID
new_SendCompleteHandler(
struct PROTOCOL_CHARS *pchars, /* added by ASM stub */
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status)
{
struct protocol_reserved *pr = PROTOCOL_RESERVED(Packet);
_CHECK_PCHARS(pchars);
/** @todo maybe using magic as ProtocolReserved is not stable solution... */
if (pr->magic == send_out_packet) {
// our completion! free buffer & packet
KdPrint(("[ndis_hk] new_SendCompleteHandler(our packet): Status 0x%x\n", Status));
free(pr->data);
NdisFreeBuffer(pr->buffer);
NdisFreePacket(Packet);
} else {
// call original handler
if (PCHARS_OLD_CHARS(pchars)->SendCompleteHandler != NULL)
PCHARS_OLD_CHARS(pchars)->SendCompleteHandler(ProtocolBindingContext, Packet, Status);
}
}
/*
* --- NDIS functions from NDIS_OPEN_BLOCK ---
*/
/**
* Hooked SendHandler (NdisSend) from NDIS_OPEN_BLOCK.
* Filter packet and maybe call original handler
*/
NDIS_STATUS
new_SendHandler(
struct ADAPTER_PROTOCOL *adapter, /* added by ASM stub */
IN NDIS_HANDLE MacBindingHandle,
IN PNDIS_PACKET Packet)
{
// we get pchars only to check adapter
_CHECK_PCHARS(adapter->pchars);
// can't use UNICODE %S to output (see DbgPrint documentation)
KdPrint(("[ndis_hk] new_SendHandler: (%d)\n", adapter->adapter_index));
if (adapter->adapter_index != 0 &&
!filter_packet(DIRECTION_OUT, adapter->adapter_index, Packet)) {
KdPrint(("[ndis_hk] new_SendHandler: DENY!\n"));
return NDIS_STATUS_SUCCESS; // let protocol driver to think it's all right
}
return adapter->old_SendHandler(MacBindingHandle, Packet);
}
/**
* Hooked SendPacketsHandler (NdisSendPackets) from NDIS_OPEN_BLOCK.
* Filter packets and call or not original handler or call it with modified array of packets
*/
VOID
new_SendPacketsHandler(
struct ADAPTER_PROTOCOL *adapter, /* added by ASM stub */
IN NDIS_HANDLE NdisBindingHandle,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets)
{
struct PROTOCOL_CHARS *pchars = adapter->pchars;
// we get pchars only to check adapter
_CHECK_PCHARS(pchars);
// can't use UNICODE %S to output (see DbgPrint documentation)
KdPrint(("[ndis_hk] new_SendPacketsHandler: (%d)\n", adapter->adapter_index));
if (adapter->adapter_index != 0) {
UINT i, n_allow, j;
// first get number of allow packets (and set status for deny packets)
n_allow = NumberOfPackets;
for (i = 0; i < NumberOfPackets; i++) {
if (!filter_packet(DIRECTION_OUT, adapter->adapter_index, PacketArray[i])) {
n_allow--;
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_FAILURE);
} else
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
}
if (n_allow < NumberOfPackets) {
PPNDIS_PACKET new_PacketArray;
// deny some packets
KdPrint(("new_SendPacketsHandler: DENY!\n"));
if (n_allow == 0) {
// deny all packets
for (i = 0; i < NumberOfPackets; i++) {
// call ProtocolSendComplete handler for each packet
PCHARS_OLD_CHARS(pchars)->SendCompleteHandler(adapter->ProtocolBindingContext,
PacketArray[i], NDIS_STATUS_SUCCESS); // let protocol driver to think it's all right
}
return;
}
/** @test Somebody, please test the code below. I never seen it's called */
_TEST_ME_
// allocate new PacketArray
new_PacketArray = (PPNDIS_PACKET)malloc_np(sizeof(PPNDIS_PACKET) * n_allow);
if (new_PacketArray == NULL) {
// have not resources
KdPrint(("new_SendPacketsHandler: malloc_np!\n"));
for (i = 0; i < NumberOfPackets; i++) {
// call ProtocolSendComplete handler for each packet
PCHARS_OLD_CHARS(pchars)->SendCompleteHandler(adapter->ProtocolBindingContext,
PacketArray[i], NDIS_STATUS_RESOURCES);
}
return;
}
// fill new PacketArray
j = 0;
for (i = 0; i < NumberOfPackets; i++)
if (NDIS_GET_PACKET_STATUS(PacketArray[i]) == NDIS_STATUS_SUCCESS) {
// save allowed packet in new PacketArray
// sanity check
if (j >= n_allow)
break;
new_PacketArray[j++] = PacketArray[i];
} else {
// call ProtocolSendComplete handler to deny packet
PCHARS_OLD_CHARS(pchars)->SendCompleteHandler(adapter->ProtocolBindingContext,
PacketArray[i], NDIS_STATUS_SUCCESS); // let protocol driver to think it's all right
}
// call original handler with new_PacketArray
adapter->old_SendPacketsHandler(NdisBindingHandle, new_PacketArray, NumberOfPackets);
// DDK: As soon as a protocol calls NdisSendPackets, it relinquishes ownership of the following...
// So, don't care about packets in new_PacketArray
// finally free new PacketArray and return
free(new_PacketArray);
return;
}
}
// call original handler
adapter->old_SendPacketsHandler(NdisBindingHandle, PacketArray, NumberOfPackets);
}
/**
* Hooked TransferDataHandler (NdisTransferData) from NDIS_OPEN_BLOCK.
* MacReceiveContext is our buffer so just copy data from our buffer to packet
*/
NDIS_STATUS
new_TransferDataHandler(
struct ADAPTER_PROTOCOL *adapter, /* added by ASM stub */
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE MacReceiveContext,
IN UINT ByteOffset,
IN UINT BytesToTransfer,
OUT PNDIS_PACKET Packet,
OUT PUINT BytesTransferred)
{
PNDIS_BUFFER buffer;
// we get pchars only to check adapter
_CHECK_PCHARS(adapter->pchars);
/** @test Somebody, please test the code below. I never seen it's called */
_TEST_ME_
// can't use UNICODE %S to output (see DbgPrint documentation)
KdPrint(("[ndis_hk] new_TransferDataHandler: (%d)\n", adapter->adapter_index));
// this function can be called _only_ inside new_ReceiveHandler -> old_ReceiveHandler (is it true?)
// so MacReceiveContext is a buffer to the whole packet data: copy them
NdisQueryPacket(Packet, NULL, NULL, &buffer, NULL);
// A HACK! actually NDIS_BUFFER is MDL so use TdiCopyBufferToMdl (i don't know NDIS equialent)
TdiCopyBufferToMdl((PVOID)MacReceiveContext, 0, BytesToTransfer, (PMDL)buffer, ByteOffset, BytesTransferred);
return NDIS_STATUS_SUCCESS;
}
NTSTATUS
send_out_packet(int iface, PNDIS_PACKET packet)
{
NTSTATUS status;
struct PROTOCOL_CHARS *pchars = g_tcpip_pchars;
struct ADAPTER_PROTOCOL *adapter;
PNDIS_BUFFER buffer, new_buffer = NULL;
PNDIS_PACKET new_packet = NULL;
struct protocol_reserved *pr;
char *data = NULL;
ULONG size;
// sanity check
if (pchars == NULL) {
KdPrint(("[ndis_hk] send_out_packet: no TCPIP protocol!\n"));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
// get adapter
for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
if (adapter->adapter_index == iface)
break;
if (adapter == NULL) {
KdPrint(("[ndis_hk] send_out_packet: no adapter %d!\n", iface));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
NdisQueryPacket(packet, NULL, NULL, &buffer, &size);
data = (char *)malloc_np(size);
if (data == NULL) {
KdPrint(("[ndis_hk] send_out_packet: malloc_np!\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
__try {
// A HACK! actually NDIS_BUFFER is MDL so use TdiCopyBufferToMdl (i don't know NDIS equialent)
TdiCopyMdlToBuffer((PMDL)buffer, 0, data, 0, size, &size);
// now create our own new_packet
NdisAllocateBuffer(&status, &new_buffer, g_buffer_pool, data, size);
if (status != NDIS_STATUS_SUCCESS) {
KdPrint(("[ndis_hk] send_out_packet: NdisAllocateBuffer: 0x%x\n", status));
__leave;
}
NdisAllocatePacket(&status, &new_packet, g_packet_pool);
if (status != NDIS_STATUS_SUCCESS) {
KdPrint(("[ndis_hk] send_out_packet: NdisAllocatePacket: 0x%x\n", status));
__leave;
}
NdisChainBufferAtFront(new_packet, new_buffer);
// setup ProtocolReserved for completion
pr = PROTOCOL_RESERVED(new_packet);
pr->magic = send_out_packet;
pr->buffer = new_buffer;
pr->data = data;
// send it! (call original handler see NdisSend() macro in ndis.h)
KdPrint(("[ndis_hk] send_out_packet: sending new_packet...\n"));
status = adapter->old_SendHandler(
((PNDIS_OPEN_BLOCK)(adapter->NdisBindingHandle))->MacBindingHandle, new_packet);
if (status == NDIS_STATUS_PENDING) {
// don't free resources (will be freed in completion)
data = NULL;
new_buffer = NULL;
new_packet = NULL;
}
KdPrint(("[ndis_hk] send_out_packet: status: 0x%x\n", status));
} __except((status = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)) {
KdPrint(("[ndis_hk] send_out_packet: exception 0x%x!\n", status));
}
if (data != NULL)
free(data);
if (new_buffer != NULL)
NdisFreeBuffer(new_buffer);
if (new_packet != NULL)
NdisFreePacket(new_packet);
return status;
}
NTSTATUS
send_in_packet(int iface, ULONG hdr_size, ULONG data_size, char *packet_data)
{
NTSTATUS status;
struct PROTOCOL_CHARS *pchars = g_tcpip_pchars;
struct ADAPTER_PROTOCOL *adapter;
KIRQL irql;
// sanity check
if (pchars == NULL) {
KdPrint(("[ndis_hk] send_in_packet: no TCPIP protocol!\n"));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
// get adapter
for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
if (adapter->adapter_index == iface)
break;
if (adapter == NULL) {
KdPrint(("[ndis_hk] send_in_packet: no adapter %d!\n", iface));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
/* send packet to protocol driver */
// sanity check
if (PCHARS_OLD_CHARS(pchars)->ReceiveHandler == NULL) {
KdPrint(("[ndis_hk] send_in_packet: no ProtocolReceive!\n"));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
/** @todo Need to simulate NdisGetReceivedPacket for stability? */
// raise IRQL to DISPATCH_LEVEL for ReceiveHandler
KeRaiseIrql(DISPATCH_LEVEL, &irql);
// simulate ProtocolReceive is called (MacReceiveContext is our buffer)
status = PCHARS_OLD_CHARS(pchars)->ReceiveHandler(adapter->ProtocolBindingContext,
(NDIS_HANDLE)(packet_data + hdr_size), packet_data, hdr_size,
packet_data + hdr_size, data_size, data_size);
KeLowerIrql(irql);
return status;
}
/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -