📄 hooked_fn.c
字号:
// -*- 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 + -