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