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

📄 hooked_fn.c

📁 开源的防火墙代码
💻 C
📖 第 1 页 / 共 4 页
字号:
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// $Id: hooked_fn.c,v 1.10 2003/07/07 11:41:55 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);

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_RequestCompleteHandler(
	struct PROTOCOL_CHARS		*pchars,		/* added by ASM stub */
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	PNDIS_REQUEST			NdisRequest,
	IN	NDIS_STATUS				Status);

static NDIS_STATUS	new_PnPEventHandler(
	struct PROTOCOL_CHARS		*pchars,		/* added by ASM stub */
    IN NDIS_HANDLE				ProtocolBindingContext,
    IN PNET_PNP_EVENT			NetPnPEvent
    );

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

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 */

	UCHAR		asm_SendCompleteHandler[ASM_STUB_SIZE];			/**< asm stub for SendCompleteHandler */
	UCHAR		asm_RequestCompleteHandler[ASM_STUB_SIZE];		/**< asm stub for RequestCompleteHandler */
	UCHAR		asm_PnPEventHandler[ASM_STUB_SIZE];				/**< asm stub for PnPEventHandler */

	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

/** number of pchars of TCPIP protocol */
#define TCPIP_PCHARS_N		2

/** global pchars for TCPIP protocol [0] & TCPIP/WAN [1] */
static struct PROTOCOL_CHARS *g_tcpip_pchars[TCPIP_PCHARS_N];

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

/** variables for NdisRequest */
static struct {
	KMUTEX			guard;		/**< guard mutex */
	NDIS_EVENT		event;		/**< event for completion */
	NDIS_STATUS		status;		/**< status of completion */
	NDIS_REQUEST	*pend_req;	/**< pending request */
} g_request;

/*
 * --- 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);
		GENERATE_ASM_STUB(pchars, SendCompleteHandler);
		GENERATE_ASM_STUB(pchars, RequestCompleteHandler);
		GENERATE_ASM_STUB(pchars, PnPEventHandler);

		// 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);
		
		// not checking for NULL! this function must be defined see new_SendCompleteHandler
		new_ProtocolCharacteristics->SendCompleteHandler = (SEND_COMPLETE_HANDLER)(pchars->asm_SendCompleteHandler);

		new_ProtocolCharacteristics->RequestCompleteHandler = (REQUEST_COMPLETE_HANDLER)(pchars->asm_RequestCompleteHandler);
		
		if (new_ProtocolCharacteristics->MajorNdisVersion >= 4)
			new_ProtocolCharacteristics->PnPEventHandler = (PNP_EVENT_HANDLER)(pchars->asm_PnPEventHandler);

		// 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[0] = pchars;

			// and initialize some related globals
			KeInitializeMutex(&g_request.guard, 0);
			NdisInitializeEvent(&g_request.event);
			g_request.pend_req = NULL;
		
		} else {
			// working with TCPIP/WAN protocol
			g_tcpip_pchars[1] = 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,

⌨️ 快捷键说明

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