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

📄 hooked_fn.c

📁 这是一本学习 window编程的很好的参考教材
💻 C
📖 第 1 页 / 共 3 页
字号:
	KdPrint(("[ndis_hk] new_NdisOpenAdapter: 0x%x\n", *Status));

	if (*Status == NDIS_STATUS_SUCCESS) {

		/*
		 * support only 802.3 and Wan adapters
		 */
		if (MediumArray[*SelectedMediumIndex] == NdisMedium802_3 ||
			MediumArray[*SelectedMediumIndex] == NdisMediumWan) {

			/*
			 * a little magic: call completion with NDIS_STATUS_PENDING
			 * it means don't call original completion and return status to us
			 */

			if (pchars != NULL)
				new_OpenAdapterCompleteHandler(pchars, ProtocolBindingContext, NDIS_STATUS_PENDING, 0);

			// don't delete adapter
			adapter = NULL;
		}

	} else if (*Status == NDIS_STATUS_PENDING) {

		// don't delete adapter
		adapter = NULL;

	}

	if (adapter != NULL) {

		/* destroy created ADAPTER_PROTOCOL */

		// unlink it from pchars
		pchars = (struct PROTOCOL_CHARS *)get_av(NdisProtocolHandle, PROTOCOL_TO_PCHARS, &irql);
		if (pchars != NULL) {
			// find adapter by pointer
			struct ADAPTER_PROTOCOL *a, *prev_a;
			for (prev_a = NULL, a = pchars->adapter; a != NULL; a = a->next) {
				if (a == adapter) {
					if (prev_a == NULL)
						pchars->adapter = adapter->next;
					else
						prev_a->next = adapter->next;
				}
				prev_a = a;
			}
			KeReleaseSpinLock(&g_av_hash_guard, irql);
		}
	
		// and free
		free(adapter);
	}
}

/**
 * Hooked NdisCloseAdapter.
 * Finds and frees ADAPTER_PROTOCOL by NdisBindingHandle
 */
VOID
new_NdisCloseAdapter(
	OUT	PNDIS_STATUS			Status,
	IN	NDIS_HANDLE				NdisBindingHandle)
{
	struct ADAPTER_PROTOCOL *adapter, *a, *prev_a;
	KIRQL irql;
	struct PROTOCOL_CHARS *pchars;

	__try {
		
		// get adapter by NdisBindingHandle
		adapter = get_av(NdisBindingHandle, BINDING_TO_ADAPTER, &irql);
		if (adapter == NULL) {
			KdPrint(("[ndis_hk] new_NdisCloseAdapter: get_av(BINDING_TO_ADAPTER)!\n"));
			__leave;
		}
		
		// unlink it from pchars
		pchars = adapter->pchars;
		for (prev_a = NULL, a = pchars->adapter; a != NULL; a = a->next) {
			if (a == adapter) {
				if (prev_a == NULL)
					pchars->adapter = adapter->next;
				else
					prev_a->next = adapter->next;
			}
			prev_a = a;
		}
		
		// delete adapter
		del_av(NdisBindingHandle, BINDING_TO_ADAPTER, TRUE);
		
	} __finally {
		if (adapter != NULL)
			KeReleaseSpinLock(&g_av_hash_guard, irql);
	}

	// call original handler
	HOOKED_OLD_FN(NdisCloseAdapter)(Status, NdisBindingHandle);
}

/*
 * --- NDIS functions from NDIS_PROTOCOL_CHARACTERISTICS ---
 */


/**
 * Hooked OpenAdapterCompleteHandler from NDIS_PROTOCOL_CHARACTERISTICS.
 * Function can be called using ASM stub in case of pending of NdisOpenAdapter or
 * function can be called by hooked NdisOpenAdapter when NdisOpenAdapter returns NDIS_STATUS_SUCCESS.
 * In last case Status == NDIS_STATUS_PENDING
 */
VOID
new_OpenAdapterCompleteHandler(
	struct PROTOCOL_CHARS *pchars,				/* added by ASM stub */
	IN NDIS_HANDLE  ProtocolBindingContext,
    IN NDIS_STATUS  Status,
    IN NDIS_STATUS  OpenErrorStatus)
{
	struct ADAPTER_PROTOCOL *adapter;

	_CHECK_PCHARS(pchars);

	KdPrint(("[ndis_hk] new_OpenAdapterComplete: 0x%x (context = 0x%x)\n", Status,
		ProtocolBindingContext));
	
	__try {

		if (Status != NDIS_STATUS_SUCCESS &&
			Status != NDIS_STATUS_PENDING)		// PENGING is a _magic_ value see above
			__leave;
		
		// get adapter
		for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next) {
			if (adapter->ProtocolBindingContext == ProtocolBindingContext)
				break;
		}
		
		if (adapter == NULL) {
			
			KdPrint(("[ndis_hk] new_OpenAdapterComplete: adapter not found\n"));
			
			// This adapter is not for us.
			__leave;
		}
		
		// save stuff from temporary storage & set temporary storage to zero
		
		adapter->NdisBindingHandle = *(adapter->pNdisBindingHandle);
		adapter->pNdisBindingHandle = NULL;
		
		if (adapter->pMediumArray != NULL &&
			adapter->pSelectedMediumIndex != NULL) {
			
			adapter->medium = adapter->pMediumArray[*(adapter->pSelectedMediumIndex)];
			
			adapter->pMediumArray = NULL;
			adapter->pSelectedMediumIndex = NULL;
		}
		
		if (adapter->medium == NdisMedium802_3 || adapter->medium == NdisMediumWan) {
			PNDIS_OPEN_BLOCK nob;
			
			// assign adapter index
			adapter->adapter_index = add_adapter(adapter->adapter_name);
			if (adapter->adapter_index == 0) {
				KdPrint(("[ndis_hk] new_OpenAdapterComplete: add_adapter!\n"));
				// panic()?
			}
			
			// save mapping NdisBindingHandle -> struct ADAPTER_PROTOCOL
			if (add_av(adapter->NdisBindingHandle, adapter, BINDING_TO_ADAPTER, FALSE) != STATUS_SUCCESS) {
				KdPrint(("[ndis_hk] new_OpenAdapterComplete: add_av!\n"));
				// panic()?
			}
			
			// can't use UNICODE %S to output (see DbgPrint documentation)
			KdPrint(("[ndis_hk] new_OpenAdapterComplete: (index = %d)\n",
				adapter->adapter_index));
			
			// and now hook SendHandler & SendPacketsHandler in (PNDIS_OPEN_BLOCK)NdisBindingHandle
			nob = (PNDIS_OPEN_BLOCK)adapter->NdisBindingHandle;
			
			adapter->old_SendHandler = nob->SendHandler;
			GENERATE_ASM_STUB(adapter, SendHandler);
			nob->SendHandler = (SEND_HANDLER)adapter->asm_SendHandler;
			
			KdPrint(("[ndis_hk] new_OpenAdapterCompleteHandler: SendHandler: old 0x%x new 0x%x\n",
				adapter->old_SendHandler, adapter->asm_SendHandler));
			
			if (PCHARS_OLD_CHARS(pchars)->MajorNdisVersion >= 4) {
				
				adapter->old_SendPacketsHandler = nob->SendPacketsHandler;
				GENERATE_ASM_STUB(adapter, SendPacketsHandler);
				nob->SendPacketsHandler = (SEND_PACKETS_HANDLER)adapter->asm_SendPacketsHandler;
				
				KdPrint(("[ndis_hk] new_OpenAdapterCompleteHandler: SendPacketsHandler: old 0x%x new 0x%x\n",
					adapter->old_SendPacketsHandler, adapter->asm_SendPacketsHandler));
			}
			
			// and NdisTransferData too
			adapter->old_TransferDataHandler = nob->TransferDataHandler;
			GENERATE_ASM_STUB(adapter, TransferDataHandler);
			nob->TransferDataHandler = (TRANSFER_DATA_HANDLER)adapter->asm_TransferDataHandler;
		}
		
	} __finally {

		if (Status != NDIS_STATUS_PENDING) {
			// call original handler anyway
			PCHARS_OLD_CHARS(pchars)->OpenAdapterCompleteHandler(ProtocolBindingContext,
				Status, OpenErrorStatus);
		}
	
	}
}

/**
 * Hooked ReceiveHandler from NDIS_PROTOCOL_CHARACTERISTICS.
 * Function is called when NDIS miniport adapter indicated incoming data using old scheme.
 * If we get LookaheadBuffer smaller than PacketSize (for old PIO based network cards) we
 * call original NdisTransferData manually to get the whole packet.
 * 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.
 */
NDIS_STATUS
new_ReceiveHandler(
	struct PROTOCOL_CHARS *pchars,				/* added by ASM stub */
    IN NDIS_HANDLE  ProtocolBindingContext,
    IN NDIS_HANDLE  MacReceiveContext,
    IN PVOID  HeaderBuffer,
    IN UINT  HeaderBufferSize,
    IN PVOID  LookaheadBuffer,
    IN UINT  LookaheadBufferSize,
    IN UINT  PacketSize)
{
	struct ADAPTER_PROTOCOL *adapter;
	BOOLEAN result = FALSE;
	NDIS_STATUS status;
	PNDIS_PACKET packet = NULL;
	PNDIS_BUFFER hdr_buffer = NULL, data_buffer = NULL;
	void *buf = NULL;
	ULONG bytes;

	_CHECK_PCHARS(pchars);
	
	__try {
		
		// get adapter
		for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next) {
			if (adapter->ProtocolBindingContext == ProtocolBindingContext)
				break;
		}
			
		if (adapter == NULL) {
			KdPrint(("[ndis_hk] new_ReceiveHandler: adapter not found!\n"));
			__leave;
		}
		
		// can't use UNICODE %S to output (see DbgPrint documentation)
		KdPrint(("[ndis_hk] new_ReceiveHandler: (%d) hdr %u; look %u; pkt %u\n",
			adapter->adapter_index,
			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) {

⌨️ 快捷键说明

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