📄 hooked_fn.c
字号:
/**
* Hooked SendPacketsHandler (NdisSendPackets) from NDIS_OPEN_BLOCK.
* Filter packets and call or not original handler or call it with modified array of packets
*/
VOID
new_SendPacketsHandler(
struct ADAPTER_PROTOCOL *adapter, /* added by ASM stub */
IN NDIS_HANDLE NdisBindingHandle,
IN PPNDIS_PACKET PacketArray,
IN UINT NumberOfPackets)
{
struct PROTOCOL_CHARS *pchars = adapter->pchars;
// we get pchars only to check adapter
_CHECK_PCHARS(pchars);
// can't use UNICODE %S to output (see DbgPrint documentation)
KdPrint(("[ndis_hk] new_SendPacketsHandler: (%d)\n", adapter->adapter_index));
if (adapter->adapter_index != 0)
{
UINT i, n_allow, j;
// first get number of allow packets (and set status for deny packets)
n_allow = NumberOfPackets;
for (i = 0; i < NumberOfPackets; i++)
{
if (!filter_packet(DIRECTION_OUT, adapter->adapter_index, PacketArray[i]))
{
n_allow--;
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_FAILURE);
}
else
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
}
if (n_allow < NumberOfPackets)
{
PPNDIS_PACKET new_PacketArray;
// deny some packets
KdPrint(("new_SendPacketsHandler: DENY!\n"));
if (n_allow == 0)
{
// deny all packets
for (i = 0; i < NumberOfPackets; i++)
{
// call ProtocolSendComplete handler for each packet
PCHARS_OLD_CHARS(pchars)->SendCompleteHandler(adapter->ProtocolBindingContext,
PacketArray[i], NDIS_STATUS_SUCCESS); // let protocol driver to think it's all right
}
return;
}
/** @test Somebody, please test the code below. I never seen it's called */
_TEST_ME_
// allocate new PacketArray
new_PacketArray = (PPNDIS_PACKET)malloc_np(sizeof(PPNDIS_PACKET) * n_allow);
if (new_PacketArray == NULL)
{
// have not resources
KdPrint(("new_SendPacketsHandler: malloc_np!\n"));
for (i = 0; i < NumberOfPackets; i++)
{
// call ProtocolSendComplete handler for each packet
PCHARS_OLD_CHARS(pchars)->SendCompleteHandler(adapter->ProtocolBindingContext,
PacketArray[i], NDIS_STATUS_RESOURCES);
}
return;
}
// fill new PacketArray
j = 0;
for (i = 0; i < NumberOfPackets; i++)
if (NDIS_GET_PACKET_STATUS(PacketArray[i]) == NDIS_STATUS_SUCCESS)
{
// save allowed packet in new PacketArray
// sanity check
if (j >= n_allow)
break;
new_PacketArray[j++] = PacketArray[i];
}
else
{
// call ProtocolSendComplete handler to deny packet
PCHARS_OLD_CHARS(pchars)->SendCompleteHandler(adapter->ProtocolBindingContext,
PacketArray[i], NDIS_STATUS_SUCCESS); // let protocol driver to think it's all right
}
// call original handler with new_PacketArray
adapter->old_SendPacketsHandler(NdisBindingHandle, new_PacketArray, NumberOfPackets);
// DDK: As soon as a protocol calls NdisSendPackets, it relinquishes ownership of the following...
// So, don't care about packets in new_PacketArray
// finally free new PacketArray and return
free(new_PacketArray);
return;
}
}
// call original handler
adapter->old_SendPacketsHandler(NdisBindingHandle, PacketArray, NumberOfPackets);
}
/**
* Hooked TransferDataHandler (NdisTransferData) from NDIS_OPEN_BLOCK.
* MacReceiveContext is our buffer so just copy data from our buffer to packet
*/
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)
{
PNDIS_BUFFER buffer;
// we get pchars only to check adapter
_CHECK_PCHARS(adapter->pchars);
/** @test Somebody, please test the code below. I never seen it's called */
_TEST_ME_
// can't use UNICODE %S to output (see DbgPrint documentation)
KdPrint(("[ndis_hk] new_TransferDataHandler: (%d)\n", adapter->adapter_index));
// this function can be called _only_ inside new_ReceiveHandler -> old_ReceiveHandler (is it true?)
// so MacReceiveContext is a buffer to the whole packet data: copy them
NdisQueryPacket(Packet, NULL, NULL, &buffer, NULL);
// A HACK! actually NDIS_BUFFER is MDL so use TdiCopyBufferToMdl (i don't know NDIS equialent)
TdiCopyBufferToMdl((PVOID)MacReceiveContext, 0, BytesToTransfer, (PMDL)buffer, ByteOffset, BytesTransferred);
return NDIS_STATUS_SUCCESS;
}
NTSTATUS
send_out_packet(int iface, PNDIS_PACKET packet)
{
NTSTATUS status;
int i;
struct PROTOCOL_CHARS *pchars;
struct ADAPTER_PROTOCOL *adapter;
PNDIS_BUFFER buffer, new_buffer = NULL;
PNDIS_PACKET new_packet = NULL;
struct protocol_reserved *pr;
char *data = NULL;
ULONG size;
for (i = 0; i < TCPIP_PCHARS_N; i++) {
pchars = g_tcpip_pchars[i];
if (pchars == NULL)
continue;
// get adapter
for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
if (adapter->adapter_index == iface)
break;
if (adapter != NULL)
break;
}
// sanity check
if (pchars == NULL) {
KdPrint(("[ndis_hk] send_out_packet: no TCPIP protocol!\n"));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
if (adapter == NULL) {
KdPrint(("[ndis_hk] send_out_packet: no adapter %d!\n", iface));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
NdisQueryPacket(packet, NULL, NULL, &buffer, &size);
data = (char *)malloc_np(size);
if (data == NULL) {
KdPrint(("[ndis_hk] send_out_packet: malloc_np!\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
__try {
// A HACK! actually NDIS_BUFFER is MDL so use TdiCopyBufferToMdl (i don't know NDIS equialent)
TdiCopyMdlToBuffer((PMDL)buffer, 0, data, 0, size, &size);
// now create our own new_packet
NdisAllocateBuffer(&status, &new_buffer, g_buffer_pool, data, size);
if (status != NDIS_STATUS_SUCCESS) {
KdPrint(("[ndis_hk] send_out_packet: NdisAllocateBuffer: 0x%x\n", status));
__leave;
}
NdisAllocatePacket(&status, &new_packet, g_packet_pool);
if (status != NDIS_STATUS_SUCCESS) {
KdPrint(("[ndis_hk] send_out_packet: NdisAllocatePacket: 0x%x\n", status));
__leave;
}
NdisChainBufferAtFront(new_packet, new_buffer);
// setup ProtocolReserved for completion
pr = PROTOCOL_RESERVED(new_packet);
pr->magic = send_out_packet;
pr->buffer = new_buffer;
pr->data = data;
// send it! (call original handler see NdisSend() macro in ndis.h)
KdPrint(("[ndis_hk] send_out_packet: sending new_packet...\n"));
status = adapter->old_SendHandler(
((PNDIS_OPEN_BLOCK)(adapter->NdisBindingHandle))->MacBindingHandle, new_packet);
if (status == NDIS_STATUS_PENDING) {
// don't free resources (will be freed in completion)
data = NULL;
new_buffer = NULL;
new_packet = NULL;
}
KdPrint(("[ndis_hk] send_out_packet: status: 0x%x\n", status));
} __except((status = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)) {
KdPrint(("[ndis_hk] send_out_packet: exception 0x%x!\n", status));
}
if (data != NULL)
free(data);
if (new_buffer != NULL)
NdisFreeBuffer(new_buffer);
if (new_packet != NULL)
NdisFreePacket(new_packet);
return status;
}
NTSTATUS
send_in_packet(int iface, ULONG hdr_size, ULONG data_size, char *packet_data)
{
NTSTATUS status;
int i;
struct PROTOCOL_CHARS *pchars;
struct ADAPTER_PROTOCOL *adapter;
KIRQL irql;
for (i = 0; i < TCPIP_PCHARS_N; i++) {
pchars = g_tcpip_pchars[i];
if (pchars == NULL)
continue;
// get adapter
for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
if (adapter->adapter_index == iface)
break;
if (adapter != NULL)
break;
}
// sanity check
if (pchars == NULL) {
KdPrint(("[ndis_hk] send_in_packet: no TCPIP protocol!\n"));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
if (adapter == NULL) {
KdPrint(("[ndis_hk] send_in_packet: no adapter %d!\n", iface));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
/* send packet to protocol driver */
// sanity check
if (PCHARS_OLD_CHARS(pchars)->ReceiveHandler == NULL) {
KdPrint(("[ndis_hk] send_in_packet: no ProtocolReceive!\n"));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
/** @todo Need to simulate NdisGetReceivedPacket for stability? */
// raise IRQL to DISPATCH_LEVEL for ReceiveHandler
KeRaiseIrql(DISPATCH_LEVEL, &irql);
// simulate ProtocolReceive is called (MacReceiveContext is our buffer)
status = PCHARS_OLD_CHARS(pchars)->ReceiveHandler(adapter->ProtocolBindingContext,
(NDIS_HANDLE)(packet_data + hdr_size), packet_data, hdr_size,
packet_data + hdr_size, data_size, data_size);
KeLowerIrql(irql);
return status;
}
NDIS_STATUS
ndis_request(int iface, NDIS_REQUEST *req)
{
int i;
struct PROTOCOL_CHARS *pchars;
struct ADAPTER_PROTOCOL *adapter;
NDIS_STATUS status;
for (i = 0; i < TCPIP_PCHARS_N; i++) {
pchars = g_tcpip_pchars[i];
if (pchars == NULL)
continue;
// get adapter
for (adapter = pchars->adapter; adapter != NULL; adapter = adapter->next)
if (adapter->adapter_index == iface)
break;
if (adapter != NULL)
break;
}
// sanity check
if (pchars == NULL) {
KdPrint(("[ndis_hk] ndis_request: no TCPIP protocol!\n"));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
if (adapter == NULL) {
KdPrint(("[ndis_hk] ndis_request: no adapter %d!\n", iface));
return STATUS_OBJECT_NAME_NOT_FOUND;
}
// to simplify processing serialize requests
KeWaitForSingleObject(&g_request.guard, Executive, KernelMode, FALSE, NULL);
g_request.pend_req = req;
NdisResetEvent(&g_request.event);
NdisRequest(&status, adapter->NdisBindingHandle, req);
if (status == NDIS_STATUS_PENDING) {
NdisWaitEvent(&g_request.event, 0);
status = g_request.status;
}
g_request.pend_req = NULL;
KeReleaseMutex(&g_request.guard, FALSE);
return status;
}
/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -