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

📄 hooked_fn.c

📁 这是一本学习 window编程的很好的参考教材
💻 C
📖 第 1 页 / 共 3 页
字号:
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// $Id: hooked_fn.c,v 1.9 2003/06/11 09:20:51 dev Exp $

/** @addtogroup hook_driver
 *@{
 */

/**
 * @file hooked_fn.c
 * Hooked NDIS functions
 */

#include <ntddk.h>
#include <tdikrnl.h>			// for TdiCopyBufferToMdl

#include "adapters.h"
#include "av.h"
#include "memtrack.h"
#include "ndis_hk.h"
#include "filter.h"
#include "except.h"

/* prototypes */

static VOID		new_OpenAdapterCompleteHandler(
	struct PROTOCOL_CHARS *pchars,				/* added by ASM stub */
	IN NDIS_HANDLE  ProtocolBindingContext,
    IN NDIS_STATUS  Status,
    IN NDIS_STATUS  OpenErrorStatus);

static 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);

static 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);

static INT		new_ReceivePacketHandler(
	struct PROTOCOL_CHARS		*pchars,		/* added by ASM stub */
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	PNDIS_PACKET			Packet);

#ifdef NDIS50
static UINT		new_CoReceivePacketHandler(
	struct PROTOCOL_CHARS		*pchars,		/* added by ASM stub */
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	NDIS_HANDLE				ProtocolVcContext,
	IN	PNDIS_PACKET			Packet);
#endif	/* NDIS50 */

static NDIS_STATUS	new_SendHandler(
	struct ADAPTER_PROTOCOL		*adapter,		/* added by ASM stub */
	IN	NDIS_HANDLE				MacBindingHandle,
	IN	PNDIS_PACKET			Packet);

static VOID			new_SendCompleteHandler(
	struct PROTOCOL_CHARS *pchars,				/* added by ASM stub */
    IN NDIS_HANDLE  ProtocolBindingContext,
    IN PNDIS_PACKET  Packet,
    IN NDIS_STATUS Status);

static VOID			new_SendPacketsHandler(
	struct ADAPTER_PROTOCOL		*adapter,		/* added by ASM stub */
	IN NDIS_HANDLE				NdisBindingHandle,
	IN PPNDIS_PACKET			PacketArray,
	IN UINT						NumberOfPackets);

static 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);

/* typedefs */

#define ASM_STUB_SIZE		12		/**< pop eax; push context; push eax; jmp new_fn */

/**
 * generate ASM code: pop eax; push pchars; push eax; jmp new_fn .
 * eax is ret address; we insert new first parameter for function - pchars
 */
#define GENERATE_ASM_STUB(pchars, fn_name)																	\
	do {																									\
		(pchars)->asm_##fn_name[0] = 0x58;	/* pop eax */													\
		(pchars)->asm_##fn_name[1] = 0x68;	/* push pchars */												\
		*(ULONG *)&(pchars)->asm_##fn_name[2] = (ULONG)(pchars);											\
		(pchars)->asm_##fn_name[6] = 0x50;	/* push eax */													\
		(pchars)->asm_##fn_name[7] = 0xe9;	/* jmp new_fn */												\
		*(ULONG *)&(pchars)->asm_##fn_name[8] = (UCHAR *)new_##fn_name - &(pchars)->asm_##fn_name[12];		\
	} while (0)

#define PCHARS_MAGIC		'PcHa'		/**< magic prefix for struct PROTOCOL_CHARS */

/** information about registered protocol */
struct PROTOCOL_CHARS {

	ULONG		magic;					/**< PCHARS_MAGIC */

	/* ASM stubs for NDIS_PROTOCOL_CHARACTERISTICS */

	UCHAR		asm_OpenAdapterCompleteHandler[ASM_STUB_SIZE];	/**< asm stub for OpenAdapterCompleteHandler */
	
	UCHAR		asm_ReceiveHandler[ASM_STUB_SIZE];				/**< asm stub for ReceiveHandler */
	UCHAR		asm_TransferDataCompleteHandler[ASM_STUB_SIZE];	/**< asm stub for TransferDataCompleteHandler */
	
	UCHAR		asm_ReceivePacketHandler[ASM_STUB_SIZE];		/**< asm stub for ReceivePacketHandler */
#ifdef NDIS50
	UCHAR		asm_CoReceivePacketHandler[ASM_STUB_SIZE];		/**< asm stub for CoReceivePacketHandler */
#endif

	UCHAR		asm_SendCompleteHandler[ASM_STUB_SIZE];			/**< asm stub for SendCompleteHandler */

	struct		ADAPTER_PROTOCOL *adapter;		/**< single-linked list of open adapters */

	UINT		chars_len;						/**< size of old NDIS_PROTOCOL_CHARACTERISTICS */
	char		chars[0];	/**< old NDIS_PROTOCOL_CHARACTERISTICS and new NDIS_PROTOCOL_CHARACTERISTICS */
};

/** macro to get old NDIS_PROTOCOL_CHARACTERISTICS from struct PROTOCOL_CHARS */
#define PCHARS_OLD_CHARS(pchars)	((PNDIS_PROTOCOL_CHARACTERISTICS)((pchars)->chars))
/** macro to new old NDIS_PROTOCOL_CHARACTERISTICS from struct PROTOCOL_CHARS */
#define PCHARS_NEW_CHARS(pchars)	((PNDIS_PROTOCOL_CHARACTERISTICS)((pchars)->chars + (pchars)->chars_len))

/** @def _CHECK_PCHARS macro to check magic of struct PROTOCOL_CHARS */

#if DBG
#	define _CHECK_PCHARS(pchars)			\
	if ((pchars)->magic != PCHARS_MAGIC) {	\
		__asm int 3							\
	}
#else
#	define _CHECK_PCHARS(pchars)
#endif

/** global pchars for TCPIP protocol */
static struct PROTOCOL_CHARS *g_tcpip_pchars;

/** information about opened adapter by protocol */
struct ADAPTER_PROTOCOL {

	struct		ADAPTER_PROTOCOL *next;		/**< next adapter in single-linked list of open adapters */
	struct		PROTOCOL_CHARS *pchars;		/**< related pchars structure */
	
	int			adapter_index;				/**< index of adapter */
	NDIS_MEDIUM	medium;						/**< medium (ethernet for example) of adapter */

	NDIS_HANDLE NdisBindingHandle;			/**< NdisBindingHandle for this adapter */
	NDIS_HANDLE	ProtocolBindingContext;		/**< ProtocolBindingContext for this adapter */

	/* temporary storage */
	PUINT			pSelectedMediumIndex;	/**< pSelectedMediumIndex pointer for NdisOpenAdapter completion */
	PNDIS_MEDIUM	pMediumArray;			/**< pMediumArray pointer for NdisOpenAdapter completion */
	PNDIS_HANDLE	pNdisBindingHandle;		/**< pNdisBindingHandle pointer for NdisOpenAdapter completion */

	/* hooked SendHandler & SendPacketsHandler */

	/** ASM stub to call new SendHandler */
	UCHAR			asm_SendHandler[ASM_STUB_SIZE];
	/** original SendHandler address */
	SEND_HANDLER	old_SendHandler;
	
	/** ASM stub to call new SendPacketsHandler */
	UCHAR					asm_SendPacketsHandler[ASM_STUB_SIZE];
	/** original SendPacketsHandler address */
	SEND_PACKETS_HANDLER	old_SendPacketsHandler;

	/* hooked TransferDataHandler */

	/** ASM stub to call new TransferDataHandler */
	UCHAR					asm_TransferDataHandler[ASM_STUB_SIZE];
	/** original old_TransferDataHandler address */
	TRANSFER_DATA_HANDLER	old_TransferDataHandler;

	/** adapter name */
	wchar_t		adapter_name[0];
};

/*
 * --- hooked NDIS functions ---
 */

/**
 * Hooked NdisRegisterProtocol.
 * If protocol is TCP/IP related, function makes copy of
 * NDIS_PROTOCOL_CHARACTERISTICS, changed some functions in it, creates struct PROTOCOL_CHARS
 * and calls original NdisRegisterProtocol function.
 * PROTOCOL_CHARS stored in "av" with NdisProtocolHandle as key.
 */
VOID
new_NdisRegisterProtocol(
	OUT	PNDIS_STATUS			Status,
	OUT	PNDIS_HANDLE			NdisProtocolHandle,
	IN	PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
	IN	UINT					CharacteristicsLength)
{
	struct PROTOCOL_CHARS *pchars = NULL;
	PNDIS_PROTOCOL_CHARACTERISTICS new_ProtocolCharacteristics;
	NTSTATUS status;

	// working at PASSIVE_LEVEL - can use UNICODE %S to output (see DbgPrint documentation)
	KdPrint(("[ndis_hk] new_NdisRegisterProtocol: %S\n", ProtocolCharacteristics->Name.Buffer));
	
	__try {
		
		// working only with "TCPIP" (and "TCPIP_WANARP" (2k) or "RASARP" protocol (NT))
		if (wcscmp(ProtocolCharacteristics->Name.Buffer, L"TCPIP") != 0 &&
			wcscmp(ProtocolCharacteristics->Name.Buffer, L"TCPIP_WANARP") != 0 &&
			wcscmp(ProtocolCharacteristics->Name.Buffer, L"RASARP") != 0) {
			
			HOOKED_OLD_FN(NdisRegisterProtocol)(Status, NdisProtocolHandle,
				ProtocolCharacteristics, CharacteristicsLength);
			
			KdPrint(("[ndis_hk] new_NdisRegisterProtocol(!TCPIP): 0x%x\n", *Status));
			__leave;
		}
		
		// create PROTOCOL_TO_CHARS
		pchars = (struct PROTOCOL_CHARS *)malloc_np(sizeof(*pchars) + CharacteristicsLength * 2);
		if (pchars == NULL) {
			
			KdPrint(("[ndis_hk] new_NdisRegisterProtocol: malloc_np!\n"));
			
			// simulate error
			*Status = NDIS_STATUS_RESOURCES;
			__leave;
		}
		memset(pchars, 0, sizeof(*pchars) + CharacteristicsLength);
		
		pchars->magic = PCHARS_MAGIC;
		
		// save copy of ProtocolCharacteristics
		pchars->chars_len = CharacteristicsLength;
		memcpy(PCHARS_OLD_CHARS(pchars), ProtocolCharacteristics, CharacteristicsLength);
		
		// generate ASM code for handlers
		
		GENERATE_ASM_STUB(pchars, OpenAdapterCompleteHandler);
		GENERATE_ASM_STUB(pchars, ReceiveHandler);
		GENERATE_ASM_STUB(pchars, TransferDataCompleteHandler);
		GENERATE_ASM_STUB(pchars, ReceivePacketHandler);
#ifdef NDIS50
		GENERATE_ASM_STUB(pchars, CoReceivePacketHandler);
#endif
		GENERATE_ASM_STUB(pchars, SendCompleteHandler);
		
		// prepare new ProtocolCharacteristics
		new_ProtocolCharacteristics = PCHARS_NEW_CHARS(pchars);
		
		memcpy(new_ProtocolCharacteristics, ProtocolCharacteristics, CharacteristicsLength);
		
		// patch new ProtocolCharacteristics
		
		KdPrint(("[ndis_hk] new_NdisRegisterProtocol: MajorNdisVersion %u (len: %u)\n",
			new_ProtocolCharacteristics->MajorNdisVersion, CharacteristicsLength));
		
		new_ProtocolCharacteristics->OpenAdapterCompleteHandler = (OPEN_ADAPTER_COMPLETE_HANDLER)(pchars->asm_OpenAdapterCompleteHandler);
		
		if (new_ProtocolCharacteristics->ReceiveHandler != NULL)
			new_ProtocolCharacteristics->ReceiveHandler = (RECEIVE_HANDLER)(pchars->asm_ReceiveHandler);
		
		if (new_ProtocolCharacteristics->TransferDataCompleteHandler != NULL)
			new_ProtocolCharacteristics->TransferDataCompleteHandler =
			(TRANSFER_DATA_COMPLETE_HANDLER)(pchars->asm_TransferDataCompleteHandler);
		
		if (new_ProtocolCharacteristics->MajorNdisVersion >= 4 &&
			new_ProtocolCharacteristics->ReceivePacketHandler != NULL)
			new_ProtocolCharacteristics->ReceivePacketHandler = (RECEIVE_PACKET_HANDLER)(pchars->asm_ReceivePacketHandler);
		
#ifdef NDIS50
		if (new_ProtocolCharacteristics->MajorNdisVersion >= 5 &&
			new_ProtocolCharacteristics->CoReceivePacketHandler != NULL)
			new_ProtocolCharacteristics->CoReceivePacketHandler = (CO_RECEIVE_PACKET_HANDLER)(pchars->asm_CoReceivePacketHandler);
#endif
		
		// not checking for NULL! this function must be defined see new_SendCompleteHandler
		new_ProtocolCharacteristics->SendCompleteHandler = (SEND_COMPLETE_HANDLER)(pchars->asm_SendCompleteHandler);
		
		// call original function with new ProtocolCharacteristics
		HOOKED_OLD_FN(NdisRegisterProtocol)(Status, NdisProtocolHandle,
			new_ProtocolCharacteristics, CharacteristicsLength);
		
		KdPrint(("[ndis_hk] new_NdisRegisterProtocol: 0x%x\n", *Status));
		
		if (*Status != NDIS_STATUS_SUCCESS)
			__leave;
		
		// for "TCPIP" protocol save pchars
		if (wcscmp(ProtocolCharacteristics->Name.Buffer, L"TCPIP") == 0)
			g_tcpip_pchars = pchars;
		
		// save NdisProtocolHandle -> pchars
		status = add_av(*NdisProtocolHandle, pchars, PROTOCOL_TO_PCHARS, FALSE);
		if (status != STATUS_SUCCESS) {
			
			// deregister protocol
			NdisDeregisterProtocol(Status, *NdisProtocolHandle);
			
			// simulate error
			*Status = NDIS_STATUS_RESOURCES;
			__leave;
		}
		
		// don't free pchars
		pchars = NULL;
	
	} __except((*Status = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)) {
		KdPrint(("[ndis_hk] new_NdisRegisterProtocol: exception 0x%x!\n", *Status));
	}

	if (pchars != NULL)
		free(pchars);
}

/**
 * Hooked NdisDeregisterProtocol.
 * Function deletes NDIS_PROTOCOL_CHARACTERISTICS by NdisProtocolHandle
 * and calls original NdisDeregisterProtocol function
 */
VOID
new_NdisDeregisterProtocol(
    OUT PNDIS_STATUS  Status,
    IN NDIS_HANDLE  NdisProtocolHandle)
{
	// delete NdisProtocolHandle -> pchars
	del_av(NdisProtocolHandle, PROTOCOL_TO_PCHARS, FALSE);

	// call original handler
	HOOKED_OLD_FN(NdisDeregisterProtocol)(Status, NdisProtocolHandle);
}

/**
 * Hooked NdisOpenAdapter.
 * Function creates struct ADAPTER_PROTOCOL, calls original NdisOpenAdapter and on success addes
 * ADAPTER_PROTOCOL to related PROTOCOL_CHARS. ADAPTER_PROTOCOL is added in "av" with NdisBindingHandle
 * as key in open adapter completion. ADAPTER_PROTOCOL is added into PROTOCOL_CHARS to help completion
 * find ADAPTER_PROTOCOL by PROTOCOL_CHARS and ProtocolBindingContext.
 */
VOID
new_NdisOpenAdapter(
	OUT	PNDIS_STATUS			Status,
	OUT	PNDIS_STATUS			OpenErrorStatus,
	OUT	PNDIS_HANDLE			NdisBindingHandle,
	OUT	PUINT					SelectedMediumIndex,
	IN	PNDIS_MEDIUM			MediumArray,
	IN	UINT					MediumArraySize,
	IN	NDIS_HANDLE				NdisProtocolHandle,
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	PNDIS_STRING			AdapterName,
	IN	UINT					OpenOptions,
	IN	PSTRING					AddressingInformation OPTIONAL)
{
	struct PROTOCOL_CHARS *pchars = NULL;
	KIRQL irql;
	struct ADAPTER_PROTOCOL *adapter = NULL;
	ULONG size;
	UINT i;
	NTSTATUS status;
	
	// working at PASSIVE_LEVEL - can use UNICODE %S to output (see DbgPrint documentation)
	KdPrint(("[ndis_hk] new_NdisOpenAdapter: %S (context = 0x%x)\n", AdapterName->Buffer,
		ProtocolBindingContext));
	
	__try {
		
		/*
		 * search MeduimArray for NdisMedium802_3 or NdisMediumWan
		 */
		
		for (i = 0; i < MediumArraySize; i++) {
			if (MediumArray[i] == NdisMedium802_3 || MediumArray[i] == NdisMediumWan)
				break;
		}
		
		if (i >= MediumArraySize) {
			
			// not found
			KdPrint(("[ndis_hk] new_NdisOpenAdapter: unsupported medium for this adapter\n"));
			
			// anyway call original handler
			*Status = NDIS_STATUS_SUCCESS;
			__leave;
		}
		
		// get pchars
		pchars = (struct PROTOCOL_CHARS *)get_av(NdisProtocolHandle, PROTOCOL_TO_PCHARS, &irql);
		if (pchars == NULL) {
			
			KdPrint(("[ndis_hk] new_NdisOpenAdapter: get_av(PROTOCOL_TO_PCHARS)!\n"));
			
			// This protocol is not for us. Call original handler but don't call our function.
			*Status = NDIS_STATUS_SUCCESS;
			__leave;
		}
		
		// allocate ADAPTER_PROTOCOL
		size = sizeof(*adapter) + (wcslen(AdapterName->Buffer) + 1) * sizeof(wchar_t);
		adapter = (struct ADAPTER_PROTOCOL *)malloc_np(size);
		if (adapter == NULL) {
			
			KdPrint(("[ndis_hk] new_NdisOpenAdapter: get_av(PROTOCOL_TO_PCHARS)!\n"));
			
			*Status = NDIS_STATUS_RESOURCES;
			__leave;
		}
		memset(adapter, 0, size);
		
		// save copy of AdapterName
		wcscpy(adapter->adapter_name, AdapterName->Buffer);
		
		// save ProtocolBindingContext
		adapter->ProtocolBindingContext = ProtocolBindingContext;
		
		// link adapter with pchars
		adapter->next = pchars->adapter;
		pchars->adapter = adapter;
		
		adapter->pchars = pchars;
		
		if (MediumArraySize > 1) {
			// save temporary pointers
			adapter->pMediumArray = MediumArray;
			adapter->pSelectedMediumIndex = SelectedMediumIndex;
		} else {
			// we have only one index and one chance to choose. do it now.
			adapter->medium = MediumArray[0];
		}
		
		adapter->pNdisBindingHandle = NdisBindingHandle;	// in completion we'll have NdisBindingHandler here
		
		// that's all
		*Status = NDIS_STATUS_SUCCESS;
		
	} __except((*Status = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)) {
		KdPrint(("[ndis_hk] new_NdisOpenAdapter: exception 0x%x!\n", *Status));
	}
	
	// cleanup
	if (pchars != NULL)
		KeReleaseSpinLock(&g_av_hash_guard, irql);

	if (*Status != NDIS_STATUS_SUCCESS)
		return;			// no need to call original handler - our errors

	// call original handler
	HOOKED_OLD_FN(NdisOpenAdapter)(Status, OpenErrorStatus, NdisBindingHandle,
		SelectedMediumIndex, MediumArray, MediumArraySize, NdisProtocolHandle,
		ProtocolBindingContext, AdapterName, OpenOptions, AddressingInformation);

⌨️ 快捷键说明

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