⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hooked_fn.c

📁 tdi fireware 网络驱动防火墙实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			HeaderBufferSize, LookaheadBufferSize, PacketSize));
		
		if (LookaheadBufferSize == PacketSize) {
			// already got the whole frame!
			
			// prepare packet for filtering
			
			NdisAllocateBuffer(&status, &hdr_buffer, g_buffer_pool, HeaderBuffer, HeaderBufferSize);
			if (status != NDIS_STATUS_SUCCESS) {
				KdPrint(("[ndis_hk] new_ReceiveHandler: NdisAllocateBuffer: 0x%x!\n", status));
				
				status = NDIS_STATUS_NOT_ACCEPTED;
				__leave;
			}
			
			NdisAllocateBuffer(&status, &data_buffer, g_buffer_pool, LookaheadBuffer, LookaheadBufferSize);
			if (status != NDIS_STATUS_SUCCESS) {
				KdPrint(("[ndis_hk] new_ReceiveHandler: NdisAllocateBuffer: 0x%x!\n", status));
				
				status = NDIS_STATUS_NOT_ACCEPTED;
				__leave;
			}
			
			NdisAllocatePacket(&status, &packet, g_packet_pool);
			if (status != NDIS_STATUS_SUCCESS) {
				KdPrint(("[ndis_hk] new_ReceiveHandler: NdisAllocatePacket: 0x%x!\n", status));
				
				status = NDIS_STATUS_NOT_ACCEPTED;
				__leave;
			}
			
			NdisChainBufferAtFront(packet, data_buffer);
			NdisChainBufferAtFront(packet, hdr_buffer);
			
			// filter it!
			
			result = filter_packet(DIRECTION_IN, adapter->adapter_index, packet);
			
		} else {
			// get the whole frame! (use NdisTransferData)
			
			// NOTE: NdisTransferData CAN return NDIS_STATUS_PENDING but pointers are only valid
			// in context of current call. That's because we're allocating memory (slow way).
			buf = malloc_np(HeaderBufferSize + PacketSize);
			if (buf == NULL) {
				KdPrint(("[ndis_hk] new_ReceiveHandler: malloc_np!\n"));
				
				status = NDIS_STATUS_NOT_ACCEPTED;
				__leave;
			}
			
			// copy header
			memcpy(buf, HeaderBuffer, HeaderBufferSize);
			
			// make buffer
			
			NdisAllocateBuffer(&status, &hdr_buffer, g_buffer_pool, buf, HeaderBufferSize);
			if (status != NDIS_STATUS_SUCCESS) {
				KdPrint(("[ndis_hk] new_ReceiveHandler: NdisAllocateBuffer: 0x%x!\n", status));
				
				status = NDIS_STATUS_NOT_ACCEPTED;
				__leave;
			}
			
			NdisAllocateBuffer(&status, &data_buffer, g_buffer_pool, (char *)buf + HeaderBufferSize, PacketSize);
			if (status != NDIS_STATUS_SUCCESS) {
				KdPrint(("[ndis_hk] new_ReceiveHandler: NdisAllocateBuffer: 0x%x!\n", status));
				
				status = NDIS_STATUS_NOT_ACCEPTED;
				__leave;
			}
			
			NdisAllocatePacket(&status, &packet, g_packet_pool);
			if (status != NDIS_STATUS_SUCCESS) {
				KdPrint(("[ndis_hk] new_ReceiveHandler: NdisAllocatePacket: 0x%x!\n", status));
				
				status = NDIS_STATUS_NOT_ACCEPTED;
				__leave;
			}
			
			NdisChainBufferAtFront(packet, data_buffer);
			
			PROTOCOL_RESERVED(packet)->buffer = hdr_buffer;		// save hdr_buffer for completion
			
			// call _original_ NdisTransferData (see ndis.h for definition of NdisTransferData)
			
			status = adapter->old_TransferDataHandler(
				((PNDIS_OPEN_BLOCK)(adapter->NdisBindingHandle))->MacBindingHandle,
				MacReceiveContext, 0, PacketSize, packet, &bytes);
			
			if (status == NDIS_STATUS_SUCCESS) {
				// chain header at the first of packet
				NdisChainBufferAtFront(packet, hdr_buffer);
				
				// got the whole packet for filter!
				result = filter_packet(DIRECTION_IN, adapter->adapter_index, packet);
				
			} else if (status == NDIS_STATUS_PENDING) {
				result = FALSE;	// wait for NdisTransferDataComplete to be called
				status = NDIS_STATUS_SUCCESS;
				
				// don't free packet and buffers
				buf = NULL;
				hdr_buffer = NULL;
				data_buffer = NULL;
				packet = NULL;
				
			} else
				result = FALSE;	// drop the packet
			
		}
		
	} __except((status = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)) {

		KdPrint(("[ndis_hk] new_ReceiveHandler: exception 0x%x!\n", status));

		status = NDIS_STATUS_NOT_ACCEPTED;
		result = FALSE;
	}
	
	if (result) {
		// call original handler (specify fake MacReceiveContext = buf see new_TransferDataHandler)
		
		if (buf == NULL) {
			
			// LookaheadBufferSize == PacketSize
			status = PCHARS_OLD_CHARS(pchars)->ReceiveHandler(ProtocolBindingContext,
				(NDIS_HANDLE)LookaheadBuffer, HeaderBuffer, HeaderBufferSize,
				LookaheadBuffer, LookaheadBufferSize, LookaheadBufferSize);

		} else {

			// LookaheadBufferSize < PacketSize
			status = PCHARS_OLD_CHARS(pchars)->ReceiveHandler(ProtocolBindingContext,
				(NDIS_HANDLE)((char *)buf + HeaderBufferSize), HeaderBuffer, HeaderBufferSize,
				(char *)buf + HeaderBufferSize, PacketSize, PacketSize);

		}
	
	}
	
	// cleanup
	if (buf != NULL)
		free(buf);
	if (hdr_buffer != NULL)
		NdisFreeBuffer(hdr_buffer);
	if (data_buffer != NULL)
		NdisFreeBuffer(data_buffer);
	if (packet != NULL)
		NdisFreePacket(packet);

	return status;
}

/**
 * Hooked TransferDataCompleteHandler from NDIS_PROTOCOL_CHARACTERISTICS.
 * This function is called _only_ when we manually call original NdisTransferData and this
 * function returns NDIS_STATUS_PENDING. We got the whole packet and call original
 * ReceiveHandler.
 * We call original ReceiveHandler with our buffer as MacReceiveContext. If protocol driver want to
 * call hooked NdisTransferData we extract data for him from this buffer.
 */
VOID
new_TransferDataCompleteHandler(
	struct PROTOCOL_CHARS *pchars,				/* added by ASM stub */
    IN NDIS_HANDLE  ProtocolBindingContext,
    IN PNDIS_PACKET  Packet,
    IN NDIS_STATUS  Status,
    IN UINT  BytesTransferred)
{
	struct ADAPTER_PROTOCOL *adapter;
	PNDIS_BUFFER hdr_buffer, data_buffer;
	void *buf;
	ULONG data_size, hdr_size;

	_CHECK_PCHARS(pchars);

	// XXX Somebody, please test the code below. I never seen it's called
	_TEST_ME_

	// get adapter
	for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
		if (adapter->ProtocolBindingContext == ProtocolBindingContext)
			break;

	// this function can be called only for our packet! (is it true?)
	NdisQueryPacket(Packet, NULL, NULL, &data_buffer, NULL);
	
	hdr_buffer = PROTOCOL_RESERVED(Packet)->buffer;

	// chain header buffer at the begin of packet
	NdisChainBufferAtFront(Packet, hdr_buffer);

	// A HACK! actually NDIS_BUFFER is MDL!
	buf = MmGetSystemAddressForMdl(hdr_buffer);

	NdisQueryBuffer(hdr_buffer, NULL, &hdr_size);
	NdisQueryBuffer(data_buffer, NULL, &data_size);

	if (adapter != NULL) {

		// 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);
}

/**
 * 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);
	}
}

/**
 * Hooked RequestCompleteHandler from NDIS_PROTOCOL_CHARACTERISTICS.
 * Check if it is completion for our call of NdisRequest set event and don't call original handler.
 */
VOID
new_RequestCompleteHandler(
	struct PROTOCOL_CHARS		*pchars,		/* added by ASM stub */
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	PNDIS_REQUEST			NdisRequest,
	IN	NDIS_STATUS				Status)
{
	if (NdisRequest == g_request.pend_req) {
		// it's our request

		KdPrint(("[ndis_hk] new_RequestCompleteHandler(our request): Status 0x%x\n", Status));
		
		g_request.status = Status;
		NdisSetEvent(&g_request.event);
	
	} else {
		// call original handler
		if (PCHARS_OLD_CHARS(pchars)->RequestCompleteHandler != NULL)
			PCHARS_OLD_CHARS(pchars)->RequestCompleteHandler(ProtocolBindingContext, NdisRequest, Status);
	}
}

/**
 * Hooked PnPEventHandler from NDIS_PROTOCOL_CHARACTERISTICS.
 * Call pnp_event() in filter chain
 */
NDIS_STATUS
new_PnPEventHandler(
	struct PROTOCOL_CHARS		*pchars,		/* added by ASM stub */
    IN NDIS_HANDLE				ProtocolBindingContext,
    IN PNET_PNP_EVENT			NetPnPEvent)
{
	struct ADAPTER_PROTOCOL *adapter;
	NDIS_STATUS status;

	_CHECK_PCHARS(pchars);

	// get adapter
	for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
		if (adapter->ProtocolBindingContext == ProtocolBindingContext)
			break;

	if (adapter != NULL)
		status = call_pnp_events(adapter->adapter_index, NetPnPEvent);
	else
		status = NDIS_STATUS_SUCCESS;

	if (status == NDIS_STATUS_SUCCESS) {
		// call original handler
		status = PCHARS_OLD_CHARS(pchars)->PnPEventHandler(ProtocolBindingContext, NetPnPEvent);
	}
	
	return 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));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -