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