Protocol Wrapper

33760 단어
//
//Protocol Wrapper Version 1.05
//Author:  gjp
//email:   [email protected]
//


#include "NdisHook.h"
#include "HookRule.h"

#pragma pack(push)
#pragma pack(1)
typedef struct _HOOK_CONTEXT_STRUCT
{
	//runtime code
	ubyte    code1_0x58; //0x58 | pop  eax      | pop caller IP from stack to eax
	ubyte    code2_0x68; //0x68 | push IMM      | push our hook context address
	struct _HOOK_CONTEXT_STRUCT *m_pHookContext;//point this 
	ubyte    code3_0x50; //0x50 | push eax		| push caller IP from eax to stack 
	ubyte    code4_0xE9; //0xE9 | jmp HookProc  | jump our hook proc
	udword   m_pHookProcOffset;

	//our context data

	PVOID    m_pOriginalProc;
	PVOID    m_pHookProc;
	PVOID    m_pBindAdaptHandle;
	PVOID    m_pProtocolContent;
	PVOID   *m_ppOriginPtr;

	struct _HOOK_CONTEXT_STRUCT *m_pHookNext;
	
}HOOK_CONTEXT_STRUCT;
#pragma pack(pop)

HOOK_CONTEXT_STRUCT *m_pOurAllOfHookContext = NULL;

dword		   m_IsFilterEnabled     = FALSE;
NDIS_HANDLE    m_ourPacketPoolHandle = NULL;
NDIS_HANDLE    m_ourBufferPoolHandle = NULL;
PNDIS_PACKET   m_ourPacketHandle     = NULL;
PNDIS_BUFFER   m_ourBufferHandle     = NULL;
PVOID          m_ourBuffer		     = NULL;

void      ReadPacket(PNDIS_PACKET Packet,PVOID pBuffer,udword dwBufSize);
uword     wswap(uword value);

void HookUnload(void)
{
	ReleaseHookFunc();

	if( m_ourBufferHandle )
	{
		NdisFreeBuffer(m_ourBufferHandle);
		m_ourBufferHandle = NULL;
	}
	if( m_ourBuffer )
	{
		NdisFreeMemory(m_ourBuffer,MAX_PACKET_SIZE,0);
		m_ourBuffer = NULL;
	}
	if( m_ourPacketHandle )
	{
		NdisFreePacket(m_ourPacketHandle);
		m_ourPacketHandle = NULL;
	}
	if( m_ourBufferPoolHandle )
	{
		NdisFreeBufferPool(m_ourBufferPoolHandle);
		m_ourBufferPoolHandle = NULL;
	}
	if( m_ourPacketPoolHandle )
	{
		NdisFreePacketPool(m_ourPacketPoolHandle);
		m_ourPacketPoolHandle = NULL;
	}
	return;
}
dword HookInit(void)
{
	NTSTATUS status;

	m_ourPacketPoolHandle = NULL;
	NdisAllocatePacketPool(&status,&m_ourPacketPoolHandle,0xFFF,0x10);
	if( status != NDIS_STATUS_SUCCESS )
		return FALSE;

	m_ourBufferPoolHandle = NULL;
	NdisAllocateBufferPool(&status,&m_ourBufferPoolHandle,0x10);
	if( status != NDIS_STATUS_SUCCESS )
		return FALSE;

	m_ourBuffer = NULL;
	status = NdisAllocateMemoryWithTag(&m_ourBuffer,MAX_PACKET_SIZE,'NAMW');
	if( status != NDIS_STATUS_SUCCESS )
		return FALSE;

	m_ourBufferHandle = NULL;
	NdisAllocateBuffer(&status,&m_ourBufferHandle,m_ourBufferPoolHandle,m_ourBuffer,MAX_PACKET_SIZE);
    if( status != NDIS_STATUS_SUCCESS )
		return FALSE;

	m_ourPacketHandle = NULL;
	NdisAllocatePacket(&status,&m_ourPacketHandle,m_ourPacketPoolHandle);
	if( status != NDIS_STATUS_SUCCESS )
		return FALSE;

	NdisChainBufferAtFront(m_ourPacketHandle,m_ourBufferHandle);
	return TRUE;
}

typedef struct _NDIS41_PROTOCOL_CHARACTERISTICS
{
#ifdef __cplusplus
	NDIS40_PROTOCOL_CHARACTERISTICS	Ndis40Chars;
#else
	NDIS40_PROTOCOL_CHARACTERISTICS;
#endif
	
	//
	// Start of NDIS 4.1 extensions.
	//

	CO_SEND_COMPLETE_HANDLER		CoSendCompleteHandler;
	CO_STATUS_HANDLER				CoStatusHandler;
	CO_RECEIVE_PACKET_HANDLER		CoReceivePacketHandler;
	CO_REQUEST_HANDLER				CoRequestHandler;
	CO_REQUEST_COMPLETE_HANDLER		CoRequestCompleteHandler;

} NDIS41_PROTOCOL_CHARACTERISTICS;

dword HookProtocol(void)
{
	//Default ndis version is 5.0
	NDIS_PROTOCOL_CHARACTERISTICS ourNPC;
	NDIS_STRING protoName = NDIS_STRING_CONST("HdFw_Slot");
	NDIS_STATUS Status;
	NDIS_HANDLE ourProtocolHandle = NULL;
	byte  *ProtocolChain;
	dword  offset;
	dword  len;

//	NDIS_PROTOCOL_BLOCK *pNdisBlock = NULL;

//	pNdisBlock = pNdisBlock->NextProtocol;
//	pNdisBlock->NextProtocol = NULL;

	memset(&ourNPC,0,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));


	if( m_dwMajorVersion == 0x03 )
	{
		len = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS);
		//We must need at least ndis version 3.10
		ourNPC.MajorNdisVersion = 0x03;
		ourNPC.MinorNdisVersion = 0x0A;
	}
	else
	if( m_dwMajorVersion == 0x04 )
	{
		len = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);

		ourNPC.MajorNdisVersion = 0x04;
		ourNPC.MinorNdisVersion = 0x00;
	}
	else
	{	//treat as version 5.0
		len = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
		
		ourNPC.MajorNdisVersion = 0x05;
		ourNPC.MinorNdisVersion = 0x00;
	}

    ourNPC.Name                        = protoName;
    ourNPC.OpenAdapterCompleteHandler  = PtOpenAdapterComplete;
    ourNPC.CloseAdapterCompleteHandler = PtCloseAdapterComplete;
    ourNPC.SendCompleteHandler         = PtSendComplete;
    ourNPC.TransferDataCompleteHandler = PtTransferDataComplete;
    ourNPC.ResetCompleteHandler        = PtResetComplete;
    ourNPC.RequestCompleteHandler      = PtRequestComplete;
    ourNPC.ReceiveHandler              = PtReceive;
    ourNPC.ReceiveCompleteHandler      = PtReceiveComplete;
    ourNPC.StatusHandler               = PtStatus;
    ourNPC.StatusCompleteHandler       = PtStatusComplete;
    ourNPC.BindAdapterHandler          = PtBindAdapter;
    ourNPC.UnbindAdapterHandler        = PtUnbindAdapter;
    ourNPC.UnloadHandler               = PtUnload;
    ourNPC.ReceivePacketHandler        = PtReceivePacket;
    ourNPC.PnPEventHandler             = PtPNPHandler;

	NdisRegisterProtocol(&Status,&ourProtocolHandle,&ourNPC,len);
	if( !NT_SUCCESS(Status) || ourProtocolHandle == NULL )
		return FALSE;

	//NdisRegisterProtocol  return hand reference of NDIS_PROTOCOL_BLOCK;
	ProtocolChain = (byte *)ourProtocolHandle;
	while(1)
	{
		DebugInfoCount++;

		//Obtain pointer to next protocol link.
		if( m_dwMajorVersion == 0x03 )
			offset = 4;
		else
		if( m_dwMajorVersion == 0x04 )
		{
			if( m_dwMinorVersion == 0x01 )
				offset = 0x8C;
			else
				offset = 0x60;
		}
		else
		if( m_dwMajorVersion == 0x05 )
			//NDIS_PROTOCOL_BLOCK->NextProtocol
			offset = 0x10;
		else
			//Error
			break;

		ProtocolChain = ((byte **)(ProtocolChain + offset))[0];
		if( ProtocolChain == NULL )
			break;

		HookFuncBlock(ProtocolChain);
	}
	if( m_dwMajorVersion != 4 )
		NdisDeregisterProtocol(&Status,ourProtocolHandle);
	else
	{
//		((byte *)ourProtocolHandle)[0x0C] = 0x01;
//		NdisDeregisterProtocol(&Status,ourProtocolHandle);
	}
	return TRUE;
}
// ProtocolContent
// Version      NextChain offset    NDIS_PROTOCOL_CHARACTERISTICS offset   BindingAdaptHandle offset 
// NDIS 3.XX	   0x04						  0x14									0x08
// NDIS 4.XX	   0x60						  0x14									0x00
// NDIS 4.01       0x8C						  0x14									0x00
// NDIS 5.XX       0x10						  0x14									0x00


//-----
VOID HookProtocolSendPackets(
    IN  HOOK_CONTEXT_STRUCT    *pOurContext,	  	
	IN NDIS_HANDLE				MiniportAdapterContext,
	IN PPNDIS_PACKET			PacketArray,
	IN UINT						NumberOfPackets
	);

NDIS_STATUS HookProtocolWanSend(
    IN  HOOK_CONTEXT_STRUCT    *pOurContext,	  	
	IN	NDIS_HANDLE				MacBindingHandle,
	IN	NDIS_HANDLE				LinkHandle,
	IN	PVOID					Packet
	);
NDIS_STATUS HookProtocolSend(
    IN  HOOK_CONTEXT_STRUCT    *pOurContext,	  	
	IN	NDIS_HANDLE				MacBindingHandle,
	IN	PNDIS_PACKET			Packet
	);

NDIS_STATUS  HookProtocolReceive(
	  IN HOOK_CONTEXT_STRUCT *pOurContext,	  	
	  IN NDIS_HANDLE  ProtocolBindingContext,
      IN NDIS_HANDLE  MacReceiveContext,
      IN PVOID		  HeaderBuffer,
      IN UINT		  HeaderBufferSize,
      IN PVOID		  LookAheadBuffer,
      IN UINT		  LookaheadBufferSize,
      IN UINT		  PacketSize
      );
NDIS_STATUS  HookWanReceive(
	    IN  HOOK_CONTEXT_STRUCT	   *pOurContext,	  	
		IN	NDIS_HANDLE				NdisLinkHandle,
		IN	PUCHAR					Packet,
		IN	ULONG					PacketSize
		);
INT	HookProtocolReceivePacket(
    IN  HOOK_CONTEXT_STRUCT    *pOurContext,	  	
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	PNDIS_PACKET			Packet
	);

VOID HookBindAdapterHandler(
						    IN  HOOK_CONTEXT_STRUCT *pOurContext,	  	
							OUT PNDIS_STATUS	Status,
							IN  NDIS_HANDLE		BindContext,
							IN  PNDIS_STRING	DeviceName,
							IN  PVOID			SystemSpecific1,
							IN  PVOID			SystemSpecific2);

VOID  HookSendComplete(
      IN  HOOK_CONTEXT_STRUCT *pOurContext,	  	
      IN NDIS_HANDLE  ProtocolBindingContext,
      IN PNDIS_PACKET  Packet,
      IN NDIS_STATUS Status
      );


void   ReleaseHookFunc(void)
{

	HOOK_CONTEXT_STRUCT *pHookContext,*pNext;

	pHookContext = m_pOurAllOfHookContext;
	m_pOurAllOfHookContext = NULL;
	while(pHookContext)
	{
		pNext = pHookContext->m_pHookNext;
		pHookContext->m_ppOriginPtr[0] = pHookContext->m_pOriginalProc;
		ExFreePool(pHookContext);
		pHookContext = pNext;
	}
	return;
}

HOOK_CONTEXT_STRUCT *IsHookedNdisFunc(PVOID pAddr)
{

	HOOK_CONTEXT_STRUCT *pHookContext;

	pHookContext = m_pOurAllOfHookContext;
	while(pHookContext)
	{
		if( pHookContext == pAddr )
			break;
		pHookContext = pHookContext->m_pHookNext;
	}
	return pHookContext;
}
HOOK_CONTEXT_STRUCT *IsHookedNdisFuncEx(PVOID *pAddr)
{

	HOOK_CONTEXT_STRUCT *pHookContext;

	pHookContext = m_pOurAllOfHookContext;
	while(pHookContext)
	{
		if( pHookContext->m_ppOriginPtr == pAddr )
			break;
		pHookContext = pHookContext->m_pHookNext;
	}
	return pHookContext;
}

HOOK_CONTEXT_STRUCT *HookNdisFunc(PVOID pHookProc,PVOID *ppOrigProc,PVOID pBindAdaptHandle,PVOID pProtocolContent)
{

	HOOK_CONTEXT_STRUCT *pHookContext;
	PVOID OrgFunc;

	pHookContext = IsHookedNdisFunc(ppOrigProc[0]);
	if( pHookContext )
		OrgFunc = pHookContext->m_pOriginalProc;
	else
		OrgFunc = ppOrigProc[0];
	if( OrgFunc == NULL )
		return NULL;

	pHookContext = IsHookedNdisFuncEx(ppOrigProc);
	if( pHookContext )
		return pHookContext;
	pHookContext = ExAllocatePoolWithTag(NonPagedPool,sizeof(HOOK_CONTEXT_STRUCT),'HCSP');
	if( pHookContext == NULL )
		return NULL;
	memset(pHookContext,0,sizeof(HOOK_CONTEXT_STRUCT));

	pHookContext->code1_0x58 = 0x58;
	pHookContext->code2_0x68 = 0x68;
	pHookContext->code3_0x50 = 0x50;
	pHookContext->code4_0xE9 = 0xE9;

	pHookContext->m_pHookContext     = pHookContext;
	pHookContext->m_pHookProcOffset	 = ((udword)pHookProc) - (((udword)&pHookContext->m_pHookProcOffset) + sizeof(udword));
	pHookContext->m_pBindAdaptHandle = pBindAdaptHandle;
	pHookContext->m_pProtocolContent = pProtocolContent;
	pHookContext->m_pOriginalProc    = OrgFunc;//ppOrigProc[0];
	pHookContext->m_ppOriginPtr      = ppOrigProc;
	pHookContext->m_pHookProc        = pHookProc;
	pHookContext->m_pHookNext        = m_pOurAllOfHookContext;
	m_pOurAllOfHookContext			 = pHookContext;

	ppOrigProc[0] = pHookContext;
	return pHookContext;
}

typedef 
struct _NDIS40_OPEN_BLOCK
{
	PNDIS_MAC_BLOCK				MacHandle;			// pointer to our MAC
	NDIS_HANDLE					MacBindingHandle;	// context when calling MacXX funcs
	PNDIS_ADAPTER_BLOCK			AdapterHandle;		// pointer to our adapter
	PNDIS_PROTOCOL_BLOCK		ProtocolHandle;		// pointer to our protocol
	NDIS_HANDLE					ProtocolBindingContext;// context when calling ProtXX funcs
	PNDIS_OPEN_BLOCK			AdapterNextOpen;	// used by adapter's OpenQueue
	PNDIS_OPEN_BLOCK			ProtocolNextOpen;	// used by protocol's OpenQueue
	PFILE_OBJECT				FileObject;			// created by operating system
	BOOLEAN						Closing;			// TRUE when removing this struct
	BOOLEAN						Unloading;			// TRUE when processing unload
	NDIS_HANDLE					CloseRequestHandle;	// 0 indicates an internal close
	KSPIN_LOCK					SpinLock;			// guards Closing
	PNDIS_OPEN_BLOCK			NextGlobalOpen;

	//
	// These are optimizations for getting to MAC routines.	They are not
	// necessary, but are here to save a dereference through the MAC block.
	//

	SEND_HANDLER				SendHandler;
	TRANSFER_DATA_HANDLER		TransferDataHandler;

	//
	// These are optimizations for getting to PROTOCOL routines.  They are not
	// necessary, but are here to save a dereference through the PROTOCOL block.
	//

	SEND_COMPLETE_HANDLER		SendCompleteHandler;
	TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler;
	RECEIVE_HANDLER				ReceiveHandler;
	RECEIVE_COMPLETE_HANDLER	ReceiveCompleteHandler;

	//
	// Extentions to the OPEN_BLOCK since Product 1.
	//
	RECEIVE_HANDLER				PostNt31ReceiveHandler;
	RECEIVE_COMPLETE_HANDLER	PostNt31ReceiveCompleteHandler;

	//
	// NDIS 4.0 extensions
	//
	RECEIVE_PACKET_HANDLER		ReceivePacketHandler;
	SEND_PACKETS_HANDLER		SendPacketsHandler;

	//
	// Needed for PnP
	//
	UNICODE_STRING				AdapterName;		// Upcased name of the adapter we are bound to
}NDIS40_OPEN_BLOCK,*PNDIS40_OPEN_BLOCK;

void HookFuncBlock(byte *ProtocolContent)
{

	PNDIS_PROTOCOL_CHARACTERISTICS pProChar;
	dword IsWan;
	NDIS_STRING WanString       = NDIS_STRING_CONST("NDISWAN");
	NDIS_STRING DeviceWanString = NDIS_STRING_CONST("//DEVICE//NDISWAN");

	NDIS_STRING TcpipString     = NDIS_STRING_CONST("Tcpip");
	NDIS_STRING TcpArpString    = NDIS_STRING_CONST("TCPIP_WANARP");
	NDIS_STRING RasArpString    = NDIS_STRING_CONST("RASARP");

	if( ProtocolContent == NULL )
		return;
	//Get pointer to NDIS_PROTOCOL_CHARACTERISTICS from protocol content
	pProChar = (PNDIS_PROTOCOL_CHARACTERISTICS)(ProtocolContent + 0x14);

	if( KeGetCurrentIrql() == PASSIVE_LEVEL )
	{
		//Check protocol name whether is Wan Lan protocol so that we can correctly hook our function
		if( !RtlCompareUnicodeString(&pProChar->Name,&WanString,TRUE) ||
			!RtlCompareUnicodeString(&pProChar->Name,&DeviceWanString,TRUE) )
		{ 
			IsWan = 1;
		}
		else
			IsWan = 0;

		//We r only interest in following protocol 
		if( !(!RtlCompareUnicodeString(&pProChar->Name,&TcpipString,TRUE) ||
			!RtlCompareUnicodeString(&pProChar->Name,&TcpArpString,TRUE) ||
			!RtlCompareUnicodeString(&pProChar->Name,&RasArpString,TRUE)) )
		{ 
			return;
		}
	}
	else
		IsWan = 0;

	//
	if( !IsWan )
	{
		HookNdisFunc(HookProtocolReceive,(PVOID *)&pProChar->ReceiveHandler,NULL,ProtocolContent);

		//{{added by gjp 6.24
//		__asm int 3;
//		HookNdisFunc(HookSendComplete,(PVOID *)&pProChar->SendCompleteHandler,NULL,ProtocolContent);
		//}}
	}
	else
		HookNdisFunc(HookWanReceive,(PVOID *)&pProChar->WanReceiveHandler,NULL,ProtocolContent);
	
	if(pProChar->MajorNdisVersion > 0x03 )
	{
		HookNdisFunc(HookProtocolReceivePacket,(PVOID *)&pProChar->ReceivePacketHandler,NULL,ProtocolContent);
		HookNdisFunc(HookBindAdapterHandler,(PVOID *)&pProChar->BindAdapterHandler,NULL,ProtocolContent);
		
	}

	//pProChar->Name;
	//We should obtain and save BindAdaptHandle in order to pass it to NdisTransferData
	//BindAdaptHandle is pNdisOpenBlock
	if( m_dwMajorVersion == 0x05 )
	{
		PNDIS_OPEN_BLOCK pNdisOpenBlock;

		pNdisOpenBlock = ((PNDIS_OPEN_BLOCK *)ProtocolContent)[0];
		while(pNdisOpenBlock)
		{
			//__asm int 3;
			if( !IsWan )
			{
				HookNdisFunc(HookProtocolSend,(PVOID *)&pNdisOpenBlock->SendHandler,pNdisOpenBlock,ProtocolContent);
				HookNdisFunc(HookProtocolReceive,(PVOID *)&pNdisOpenBlock->PostNt31ReceiveHandler,pNdisOpenBlock,ProtocolContent);
				//{{added by gjp 6.24
//				__asm int 3;
//				HookNdisFunc(HookSendComplete,(PVOID *)&pNdisOpenBlock->SendCompleteHandler,pNdisOpenBlock,ProtocolContent);
				//}}
			}
			else
			{
				HookNdisFunc(HookProtocolWanSend,(PVOID *)&pNdisOpenBlock->WanSendHandler,pNdisOpenBlock,ProtocolContent);
				HookNdisFunc(HookWanReceive,(PVOID *)&pNdisOpenBlock->WanReceiveHandler,pNdisOpenBlock,ProtocolContent);
			}
			HookNdisFunc(HookProtocolReceive,(PVOID *)&pNdisOpenBlock->ReceiveHandler,pNdisOpenBlock,ProtocolContent);
			HookNdisFunc(HookProtocolReceivePacket,(PVOID *)&pNdisOpenBlock->ReceivePacketHandler,pNdisOpenBlock,ProtocolContent);
			HookNdisFunc(HookProtocolSendPackets,(PVOID *)&pNdisOpenBlock->SendPacketsHandler,pNdisOpenBlock,ProtocolContent);
			pNdisOpenBlock = pNdisOpenBlock->ProtocolNextOpen;
		}
	}
	else
	if( m_dwMajorVersion == 0x04 )
	{
		PNDIS40_OPEN_BLOCK pNdisOpenBlock;
		pNdisOpenBlock = ((PNDIS40_OPEN_BLOCK *)ProtocolContent)[0];

		while(pNdisOpenBlock)
		{
			if( !IsWan )
			{
				HookNdisFunc(HookProtocolSend,(PVOID *)&pNdisOpenBlock->SendHandler,pNdisOpenBlock,ProtocolContent);
				HookNdisFunc(HookProtocolReceive,(PVOID *)&pNdisOpenBlock->PostNt31ReceiveHandler,pNdisOpenBlock,ProtocolContent);
			}
			else
			{
				HookNdisFunc(HookProtocolWanSend,(PVOID *)&pNdisOpenBlock->SendHandler,pNdisOpenBlock,ProtocolContent);
				HookNdisFunc(HookWanReceive,(PVOID *)&pNdisOpenBlock->PostNt31ReceiveHandler,pNdisOpenBlock,ProtocolContent);
			}

			HookNdisFunc(HookProtocolReceive,(PVOID *)&pNdisOpenBlock->ReceiveHandler,pNdisOpenBlock,ProtocolContent);
			HookNdisFunc(HookProtocolReceivePacket,(PVOID *)&pNdisOpenBlock->ReceivePacketHandler,pNdisOpenBlock,ProtocolContent);
			HookNdisFunc(HookProtocolSendPackets,(PVOID *)&pNdisOpenBlock->SendPacketsHandler,pNdisOpenBlock,ProtocolContent);
			pNdisOpenBlock = (PNDIS40_OPEN_BLOCK)pNdisOpenBlock->ProtocolNextOpen;
		}
//		HookNdisFunc(HookProtocolReceivePacket,(PVOID *)&pNdisOpenBlock->ReceivePacketHandler,pNdisOpenBlock,ProtocolContent);
		
	}
	else
	if( m_dwMajorVersion == 0x03 )
	{//Unknown information of ndis3.0 NDIS_OPEN_BLOCK struct

	}
	return;
}
void CheckSendHandle(HOOK_CONTEXT_STRUCT *pOurContext)
{
	HOOK_CONTEXT_STRUCT *pHookContext;

	if( pOurContext == NULL ||
		pOurContext->m_pBindAdaptHandle == NULL )
		return;

	if( m_dwMajorVersion == 5 )
	{
		PNDIS_OPEN_BLOCK pNdisOpenBlock;

		pNdisOpenBlock = (PNDIS_OPEN_BLOCK)pOurContext->m_pBindAdaptHandle;

		pHookContext = (HOOK_CONTEXT_STRUCT *)pNdisOpenBlock->SendHandler;
		if( pHookContext )
		{
			if( !(pHookContext->m_ppOriginPtr == (PVOID *)&pNdisOpenBlock->SendHandler 
			 && pHookContext->m_pHookProc   == (PVOID)HookProtocolSend) )
			{

				pHookContext = IsHookedNdisFuncEx((PVOID *)&pNdisOpenBlock->SendHandler);
				if( pHookContext )
				{
					if( pHookContext->m_pOriginalProc == (PVOID)pNdisOpenBlock->SendHandler)
					{
						pNdisOpenBlock->SendHandler = (SEND_HANDLER)pHookContext;
					}
				}
			}
		}

		pHookContext = (HOOK_CONTEXT_STRUCT *)pNdisOpenBlock->SendPacketsHandler;
		if( pHookContext )
		{
			if( !(pHookContext->m_ppOriginPtr == (PVOID *)&pNdisOpenBlock->SendPacketsHandler
			 && pHookContext->m_pHookProc   == (PVOID)HookProtocolSendPackets) )
			{

				pHookContext = IsHookedNdisFuncEx((PVOID *)&pNdisOpenBlock->SendPacketsHandler);
				if( pHookContext )
				{
					if( pHookContext->m_pOriginalProc == (PVOID)pNdisOpenBlock->SendPacketsHandler)
					{
						pNdisOpenBlock->SendPacketsHandler = (SEND_PACKETS_HANDLER)pHookContext;
					}
				}
			}
		}
	}
	else
	if( m_dwMajorVersion == 4 )
	{
		PNDIS40_OPEN_BLOCK pNdisOpenBlock;
		pNdisOpenBlock = (PNDIS40_OPEN_BLOCK)pOurContext->m_pBindAdaptHandle;

		pHookContext = (HOOK_CONTEXT_STRUCT *)pNdisOpenBlock->SendHandler;
		if( pHookContext )
		{
			if( !(pHookContext->m_ppOriginPtr == (PVOID *)&pNdisOpenBlock->SendHandler 
			 && pHookContext->m_pHookProc   == (PVOID)HookProtocolSend) )
			{

				pHookContext = IsHookedNdisFuncEx((PVOID *)&pNdisOpenBlock->SendHandler);
				if( pHookContext )
				{
					if( pHookContext->m_pOriginalProc == (PVOID)pNdisOpenBlock->SendHandler)
					{
						pNdisOpenBlock->SendHandler = (SEND_HANDLER)pHookContext;
					}
				}
			}
		}

		pHookContext = (HOOK_CONTEXT_STRUCT *)pNdisOpenBlock->SendPacketsHandler;
		if( pHookContext )
		{
			if( !(pHookContext->m_ppOriginPtr == (PVOID *)&pNdisOpenBlock->SendPacketsHandler
			 && pHookContext->m_pHookProc   == (PVOID)HookProtocolSendPackets) )
			{

				pHookContext = IsHookedNdisFuncEx((PVOID *)&pNdisOpenBlock->SendPacketsHandler);
				if( pHookContext )
				{
					if( pHookContext->m_pOriginalProc == (PVOID)pNdisOpenBlock->SendPacketsHandler)
					{
						pNdisOpenBlock->SendPacketsHandler = (SEND_PACKETS_HANDLER)pHookContext;
					}
				}
			}
		}
	}
	return;
}

dword HookFilterBuffer(HOOK_CONTEXT_STRUCT *pOurContext,PVOID pBuffer,udword PacketSize,dword isOutgoing)
{
	NTSTATUS status;
	dword result = TRUE;

	switch(wswap(((PETHHDR)pBuffer)->h_proto))
	{
		case ETH_P_IP:
		{
			if( isOutgoing )
				TotalSendBytes	  += PacketSize;
			else
				TotalReceiveBytes += PacketSize;
			TotalIPPackets++;
			result = AnalyzeIP( (PIPHdr)(&((byte *)pBuffer)[sizeof(ETHHDR)]),PacketSize - sizeof(ETHHDR), isOutgoing);
			break;
		}
		case ETH_P_ARP:
			TotalARPPackets++;
			break;
		case ETH_P_RARP:
			break;
		default:
			TotalOtherPackets++;
			break;
	}
	return result;
}

dword HookFilterReceivePacket(HOOK_CONTEXT_STRUCT *pOurContext,udword TotalPacketSize,PVOID pHeadBuffer,udword dwHeadSize,PNDIS_PACKET pPacket,dword isOutgoing)
{
	dword PacketSize;
	PVOID pBuffer = NULL;
	NTSTATUS status;
	PNDIS_BUFFER firstBuffer,nextBuffer;
	dword result = TRUE;
	byte *pBuf;

    NdisQueryPacket(pPacket,NULL,NULL,NULL,&PacketSize);
	if( /*!PacketSize ||*/ PacketSize + dwHeadSize < sizeof(ETHHDR) )
		return TRUE;


	status = NdisAllocateMemoryWithTag(&pBuffer,PacketSize + dwHeadSize,'NAMW');
	if( status != NDIS_STATUS_SUCCESS || pBuffer == NULL )
		return TRUE;//FALSE;
//obtain content from the packet 

	pBuf = (byte *)pBuffer;
	NdisMoveMemory(pBuf,pHeadBuffer,dwHeadSize);
	ReadPacket(pPacket,&pBuf[dwHeadSize],PacketSize);

	result = HookFilterBuffer(pOurContext,pBuffer,TotalPacketSize + dwHeadSize,isOutgoing);
	NdisFreeMemory(pBuffer,PacketSize + dwHeadSize,0);
	return result;
}

// Filter Packet
// return 0 = block this packet

dword HookFilterPacket(HOOK_CONTEXT_STRUCT *pOurContext,PNDIS_PACKET pPacket,dword isOutgoing)
{
	dword PacketSize;
	PVOID pBuffer = NULL;
	NTSTATUS status;
	PNDIS_BUFFER firstBuffer,nextBuffer;
	dword result = TRUE;

    NdisQueryPacket(pPacket,NULL,NULL,NULL,&PacketSize);
	if( /*!PacketSize ||*/ PacketSize < sizeof(ETHHDR) )
		return TRUE;


	status = NdisAllocateMemoryWithTag(&pBuffer,PacketSize,'NAMW');
	if( status != NDIS_STATUS_SUCCESS || pBuffer == NULL )
		return TRUE;//FALSE;
//obtain content from the packet 
	ReadPacket(pPacket,pBuffer,PacketSize);

	result = HookFilterBuffer(pOurContext,pBuffer,PacketSize,isOutgoing);
	NdisFreeMemory(pBuffer,PacketSize,0);
	return result;
}

__declspec( naked ) 
uword wswap(uword value)
{
	__asm
	{
		movzx eax,byte ptr [esp + 5];
		mov   ah ,byte ptr [esp + 4];
		ret	  4
	}
}

void ReadPacket(PNDIS_PACKET Packet,PVOID pBuffer,udword dwBufSize)
{
	PVOID           virtualAddress;
	PNDIS_BUFFER    firstBuffer, nextBuffer;
	ULONG           totalLength;
	UINT			len;
	PVOID           pBuf = NULL;
	dword           count = 0;

	NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, NULL);
	while( firstBuffer != NULL)
	{
//NdisQueryBufferSafe can't use in wdm1.0
//		NdisQueryBufferSafe(firstBuffer, &virtualAddress, 
//								&len, 16 );
		NdisQueryBuffer(firstBuffer, &virtualAddress, 
							&len);
		if(!virtualAddress) 
		{
			//
			// System is running low on memory resources. 
			// So fail the read.
			// 
			break;
		}
		if( count + len > dwBufSize )
			break;
		NdisMoveMemory(&((byte *)pBuffer)[count],virtualAddress,len);
		count += len;
		NdisGetNextBuffer(firstBuffer,  &nextBuffer);
		firstBuffer = nextBuffer;
	}
	return;
}

//----
VOID HookProtocolSendPackets(
    IN HOOK_CONTEXT_STRUCT     *pOurContext,	  	
	IN NDIS_HANDLE				MiniportAdapterContext,
	IN PPNDIS_PACKET			PacketArray,
	IN UINT						NumberOfPackets
	)
{
	udword x;

	PPNDIS_PACKET FilterPacketArray;
	UINT          NumberOfFilterPackets;
	
	if( pOurContext )
	{

		if( NumberOfPackets == 0 )
		{
			((SEND_PACKETS_HANDLER)pOurContext->m_pOriginalProc)(
				MiniportAdapterContext,
				PacketArray,
				NumberOfPackets);
			return;
		}

		FilterPacketArray = ExAllocatePoolWithTag(NonPagedPool,sizeof(PNDIS_PACKET) * NumberOfPackets,'HFPA');
		if( FilterPacketArray == NULL )
		{
			((SEND_PACKETS_HANDLER)pOurContext->m_pOriginalProc)(
				MiniportAdapterContext,
				PacketArray,
				NumberOfPackets);
			return;
		}

		for(NumberOfFilterPackets = 0,x = 0; x < NumberOfPackets; x++ )
		{

			if( HookFilterPacket(pOurContext,PacketArray[x],TRUE) )
			{
				FilterPacketArray[NumberOfFilterPackets++] = PacketArray[x];
			}
		}
		if( NumberOfFilterPackets )
		{
			((SEND_PACKETS_HANDLER)pOurContext->m_pOriginalProc)(
				MiniportAdapterContext,
				FilterPacketArray,
				NumberOfFilterPackets);
		}
		ExFreePool(FilterPacketArray);
	}
	return;
}

NDIS_STATUS HookProtocolWanSend(
    IN  HOOK_CONTEXT_STRUCT    *pOurContext,	  	
	IN	NDIS_HANDLE				MacBindingHandle,
	IN	NDIS_HANDLE				LinkHandle,
	IN	PVOID					Packet
	)
{
	if( pOurContext )
	{
		return ((WAN_SEND_HANDLER)pOurContext->m_pOriginalProc)(
			MacBindingHandle,
			LinkHandle,
			Packet);
	}
	return NDIS_STATUS_SUCCESS;
}

NDIS_STATUS HookProtocolSend(
    IN  HOOK_CONTEXT_STRUCT    *pOurContext,	  	
	IN	NDIS_HANDLE				MacBindingHandle,
	IN	PNDIS_PACKET			Packet
	)
{
//	udword PacketSize;
	NTSTATUS status = NDIS_STATUS_SUCCESS;

	if( pOurContext )
	{
		if( HookFilterPacket(pOurContext,Packet,TRUE) )
		{
			status = ((SEND_HANDLER)pOurContext->m_pOriginalProc)(
				MacBindingHandle,
				Packet);
		}
		else
			status = NDIS_STATUS_NOT_ACCEPTED;
	}
	return status;
}

INT	HookProtocolReceivePacket(
    IN  HOOK_CONTEXT_STRUCT    *pOurContext,	  	
	IN	NDIS_HANDLE				ProtocolBindingContext,
	IN	PNDIS_PACKET			Packet
	)
{
	NTSTATUS status = NDIS_STATUS_SUCCESS;

	if( pOurContext )
	{
		CheckSendHandle(pOurContext);

		if( HookFilterPacket(pOurContext,Packet,FALSE) )
		{
			status = ((RECEIVE_PACKET_HANDLER)pOurContext->m_pOriginalProc)(
					ProtocolBindingContext,
					Packet);
		}
		else
			status = NDIS_STATUS_NOT_ACCEPTED;
	}
	return status;
}

NDIS_STATUS  HookWanReceive(
	    IN  HOOK_CONTEXT_STRUCT    *pOurContext,	  	
		IN	NDIS_HANDLE				NdisLinkHandle,
		IN	PUCHAR					Packet,
		IN	ULONG					PacketSize
		)
{

	if( pOurContext )
	{
		return ((WAN_RECEIVE_HANDLER)pOurContext->m_pOriginalProc)(
					NdisLinkHandle,
					Packet,
					PacketSize);
	}
	return NDIS_STATUS_SUCCESS;
}

NDIS_STATUS  HookProtocolReceive(
	  IN HOOK_CONTEXT_STRUCT *pOurContext,	  	
	  IN NDIS_HANDLE  ProtocolBindingContext,
      IN NDIS_HANDLE  MacReceiveContext,
      IN PVOID		  HeaderBuffer,
      IN UINT		  HeaderBufferSize,
      IN PVOID		  LookAheadBuffer,
      IN UINT		  LookAheadBufferSize,
      IN UINT		  PacketSize
      )
{
	NTSTATUS status = NDIS_STATUS_SUCCESS;

	if( pOurContext )
	{

		CheckSendHandle(pOurContext);
//		TotalReceiveBytes += PacketSize;

		if( pOurContext->m_pBindAdaptHandle )
		{
			udword len = 0;

			if( PacketSize > LookAheadBufferSize )
			{
				NdisTransferData(&status,pOurContext->m_pBindAdaptHandle,MacReceiveContext,0,PacketSize,m_ourPacketHandle,&len);
			}
			else
			{
				NdisMoveMemory(m_ourBuffer,LookAheadBuffer,PacketSize);
			}
				
			if( status == NDIS_STATUS_SUCCESS )
			{
				TotalTransferPackets++;

				if( !HookFilterReceivePacket(pOurContext,PacketSize,HeaderBuffer,HeaderBufferSize,m_ourPacketHandle,FALSE) )
				//if( !HookFilterPacket(pOurContext,m_ourPacketHandle,FALSE) )
					return NDIS_STATUS_NOT_ACCEPTED;
			}
			else
			if( status == NDIS_STATUS_PENDING )
				//Warning: Here An Error will be occured.
				TotalTransferPendingPackets++;
			else
				TotalTransferErrorPackets++;
			
		}
		else
		{
			TotalUnbindTransferPackets++;
		}
		status = ((RECEIVE_HANDLER)pOurContext->m_pOriginalProc)(
					ProtocolBindingContext,
					MacReceiveContext,
					HeaderBuffer,
					HeaderBufferSize,
					LookAheadBuffer,
					LookAheadBufferSize,
					PacketSize);
	}
	return status;
}
VOID HookBindAdapterHandler(
						    IN  HOOK_CONTEXT_STRUCT *pOurContext,	  	
							OUT PNDIS_STATUS	Status,
							IN  NDIS_HANDLE		BindContext,
							IN  PNDIS_STRING	DeviceName,
							IN  PVOID			SystemSpecific1,
							IN  PVOID			SystemSpecific2)
{

	if( pOurContext )
	{
		((BIND_HANDLER)pOurContext->m_pOriginalProc)(Status,BindContext,
								DeviceName,
								SystemSpecific1,
								SystemSpecific2);

		HookFuncBlock(pOurContext->m_pProtocolContent);
		TotalTransferErrorPackets++;
	}
	return;
}

VOID  HookSendComplete(
      IN  HOOK_CONTEXT_STRUCT *pOurContext,	  	
      IN NDIS_HANDLE  ProtocolBindingContext,
      IN PNDIS_PACKET  Packet,
      IN NDIS_STATUS Status
      )
{

	__asm int 3;
	((SEND_COMPLETE_HANDLER)pOurContext->m_pOriginalProc)(
		ProtocolBindingContext,
		Packet,
		Status
		);
	return;
}



좋은 웹페이지 즐겨찾기