⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wanpacket.cpp

📁 Windows XP下的抓包程序实现
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 2003 - 2005 NetGroup, Politecnico di Torino (Italy)
 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Politecnico di Torino, CACE Technologies 
 * nor the names of its contributors may be used to endorse or promote 
 * products derived from this software without specific prior written 
 * permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
#define _WIN32_DCOM 

#include <tchar.h>
#include <winsock2.h>
#include <windows.h>
#include <crtdbg.h>
#include <eh.h>

HMODULE g_hModule = NULL;

#include <netmon.h>

#include "win_bpf.h"
#include "win_bpf_filter_init.h"

#include <packet32.h>
#include "wanpacket.h"

/*!
  \brief Describes an opened wan (dialup, VPN...) network adapter using the NetMon API

  This structure is the most important for the functioning of WanPacket.dll.
  This structure should be considered opaque by users.
*/
struct WAN_ADAPTER_INT
{
	HBLOB			hCaptureBlob;		///< Handle to the BLOB (the network adapter in the NetMon world) used to capture
	CRITICAL_SECTION CriticalSection;	///< Used to synchronize access to this structure.
	PUCHAR			Buffer;				///< Pointer to the ring buffer used to capture packets.
	DWORD			C;					///< Zero-based index of the consumer in the ring buffer. It indicates the first free byte to be read.
	DWORD			P;					///< Zero-based index of the producer in the ring buffer. It indicates the first free byte to be written.
	DWORD			Free;				///< Number of the free bytes in the ring buffer.
	DWORD			Size;				///< Size of the ring buffer used to capture packets.
	DWORD			Dropped;			///< Number of packets that the current instance had to drop, from its opening. A packet is dropped if there is no more space to store it in the ring buffer.
	DWORD			Accepted;			///< Number of packets that the current capture instance has accepted, from its opening. A packet is accepted if it passes the bpf filter and fits in the ring buffer. Accepted packets are the ones that reach the application. 
	DWORD			Received;			///< Number of packets received by current instance from its opening. 
	DWORD			MinToCopy;			///< Minimum amount of data in the ring buffer that unlocks a read.
	DWORD			ReadTimeout;		///< Timeout after which a read is released, also if the amount of data in the ring buffer is less than MinToCopy.
	HANDLE			hReadEvent;			///< Pointer to the event on which the read calls on this instance must wait.
	bpf_insn		*FilterCode;		///< Pointer to the filtering pseudo-code associated with current instance of capture.
	DWORD			Mode;				///< Working mode of the driver. See PacketSetMode() for details.
	LARGE_INTEGER	Nbytes;				///< Amount of bytes accepted by the filter when this instance is in statistical mode.
	LARGE_INTEGER	Npackets;			///< Number of packets accepted by the filter when this instance is in statistical mode.
	MEM_TYPE		MemEx;				///< Memory used by the TME virtual co-processor
	TME_CORE		Tme;				///< Data structure containing the virtualization of the TME co-processor
	IRTC			*pIRTC;				///< Pointer to the NetMon IRTC COM interface used to capture packets.
};

#define ALIGN_TO_WORD(x) (((x) + 3)&~(3))

BOOLEAN WanPacketAddPacketToRingBuffer(PWAN_ADAPTER pWanAdapter, LPFRAME_DESCRIPTOR lpFrameDesc, DWORD SnapToCopy, struct timeval PacketTime);
DWORD WanPacketRemovePacketsFromRingBuffer(PWAN_ADAPTER pWanAdapter, PUCHAR Buffer, DWORD BuffSize);
BOOLEAN IsWindows2000();

#if 0
/*! 
  \brief The main dll function.
*/
#ifdef WPCAP_OEM
BOOLEAN LoadNdisNpp(DWORD Reason)
#else
BOOLEAN APIENTRY DllMain( HANDLE hModule, DWORD  Reason, LPVOID lpReserved)
#endif // WPCAP_OEM
{
    switch(Reason)
    {
	case DLL_PROCESS_ATTACH:
		g_hModule = LoadLibrary("npp\\ndisnpp.dll");
		break;

	case DLL_PROCESS_DETACH:
		if (g_hModule != NULL)
			FreeLibrary(g_hModule);
		break;
	}

	return TRUE;
}

#endif

/*! 
  \brief It returns the current time formatted as a timeval structure.
  \return The current time formatted as a timeval structure.
*/
struct timeval WanPacketGetCurrentTime()
{
	struct timeval tvReturn;
	FILETIME FileTime;
	GetSystemTimeAsFileTime(&FileTime);
	tvReturn.tv_sec = (LONG)(((LARGE_INTEGER*)&FileTime)->QuadPart / 10000000);
	tvReturn.tv_usec = (LONG)(((LARGE_INTEGER*)&FileTime)->QuadPart % 10000000 / 10);

	return tvReturn;
}

/*! 
  \brief This is the callback used by the NetMon IRTC interface to pass the packets to the user.
  \param Event. An UPDATE_EVENT structure containing the packets.
  \return Not clearly defined by the NetMon IRTC MSDN documentation.
*/
DWORD WINAPI WanPacketReceiverCallback(UPDATE_EVENT Event)
{
    DWORD i;
    LPFRAMETABLE lpFrameTable;
	LPFRAME_DESCRIPTOR lpFrameDesc;
	PWAN_ADAPTER pWanAdapter;
	u_int FilterResult;
	struct time_conv TimeConv;
	struct timeval PacketTime;

	pWanAdapter = (PWAN_ADAPTER)Event.lpUserContext;
	lpFrameTable = Event.lpFrameTable;

	// the frame table can wrap the indices
    for (i = lpFrameTable->StartIndex; i != lpFrameTable->EndIndex; (i == lpFrameTable->FrameTableLength) ? i=0: i ++ )
	{
	    lpFrameDesc = &lpFrameTable->Frames[i];

		PacketTime.tv_sec = (ULONG) (lpFrameDesc->TimeStamp / (__int64)1000000 - 11644473600);
		PacketTime.tv_usec= (ULONG) (lpFrameDesc->TimeStamp % (__int64)1000000);

		FORCE_TIME(&PacketTime, &TimeConv);

		EnterCriticalSection( &pWanAdapter->CriticalSection );
		pWanAdapter->Received ++;

		FilterResult = bpf_filter(pWanAdapter->FilterCode, 
			lpFrameDesc->FramePointer, 
			lpFrameDesc->FrameLength, 
			lpFrameDesc->nBytesAvail,
			&pWanAdapter->MemEx,
			&pWanAdapter->Tme,
			&TimeConv);

		if ( pWanAdapter->Mode == PACKET_MODE_MON && FilterResult == 1 )
			SetEvent( pWanAdapter->hReadEvent );

		if (FilterResult == (u_int) -1 || FilterResult > lpFrameDesc->nBytesAvail )
			FilterResult = lpFrameDesc->nBytesAvail;
		
		if ( pWanAdapter->Mode == PACKET_MODE_STAT )
		{
			pWanAdapter->Npackets.QuadPart ++;
			if ( lpFrameDesc->FrameLength < 60 )
				pWanAdapter->Nbytes.QuadPart += 60;
			else
				pWanAdapter->Nbytes.QuadPart += lpFrameDesc->FrameLength;
			// add preamble+SFD+FCS to the packet
			// these values must be considered because are not part of the packet received from NDIS
			pWanAdapter->Nbytes.QuadPart += 12;
		}

			if ( pWanAdapter->Mode == PACKET_MODE_CAPT && FilterResult > 0 )
		{
			if ( WanPacketAddPacketToRingBuffer(pWanAdapter, lpFrameDesc,  FilterResult, PacketTime ) )
				pWanAdapter->Accepted++;
			else	
				pWanAdapter->Dropped++;
		}

		LeaveCriticalSection( &pWanAdapter->CriticalSection );
	}
	
	return NOERROR;
}

/*! 
  \brief Tries to open the wan (dialup, vpn...) adapter, and immediately closes it.
  \return TRUE on success.
*/
BOOLEAN WanPacketTestAdapter()
{
	PBLOB_TABLE pBlobTable = NULL;
	HBLOB hFilterBlob = NULL;
	BOOLEAN retVal;
	DWORD i;
	HRESULT hResult;

	if ( g_hModule == NULL)
	{
		g_hModule = LoadLibrary("npp\\ndisnpp.dll");
	}

	if ( g_hModule == NULL)
	{
		return FALSE;
	}

	hResult = CoInitialize(NULL);

	//
 	// if  the calling thread has already initialized COM with a 
 	// different threading model, we have this error
 	// however, we are able to support another threading model,
 	// so we try to initialize COM with another threading model.
 	// This new call should succeed with S_FALSE.
 	//
 	if (hResult == RPC_E_CHANGED_MODE)
	{
		hResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
	
		//MULTITHREADED threading is only supported on Windows 2000
		if (hResult == RPC_E_CHANGED_MODE && IsWindows2000())
		{
			hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
		}
	}

	if (hResult != S_OK && hResult != S_FALSE)
		return FALSE;

	if ( CreateBlob(&hFilterBlob) != NMERR_SUCCESS )
	{
		CoUninitialize();
		return FALSE;
	}
	
	if ( SetBoolInBlob(hFilterBlob, OWNER_NPP, CATEGORY_CONFIG, TAG_INTERFACE_REALTIME_CAPTURE, TRUE) != NMERR_SUCCESS )
	{
		DestroyBlob( hFilterBlob);
		CoUninitialize();
		return FALSE;
	}

	if ( SetBoolInBlob(hFilterBlob, OWNER_NPP, CATEGORY_LOCATION, TAG_RAS, TRUE) != NMERR_SUCCESS )
	{
		DestroyBlob( hFilterBlob);
		CoUninitialize();
		return FALSE;
	}

	if ( GetNPPBlobTable(hFilterBlob, &pBlobTable) != NMERR_SUCCESS )
	{
		DestroyBlob( hFilterBlob);
		CoUninitialize();
		return FALSE;
	}

	DestroyBlob (hFilterBlob);

	if (pBlobTable->dwNumBlobs == 1)
		retVal = TRUE;
	else
		retVal = FALSE;

	for ( i = 0 ; i < pBlobTable->dwNumBlobs ; i++ )
		DestroyBlob(pBlobTable->hBlobs[i]);
		
	GlobalFree(pBlobTable);	
	CoUninitialize();
			
	return retVal;
}

/*!
	\brief Returns true if the system is running windows 2000
	\return TRUE if the system is running windows 2000. FALSE otherwise.
*/
BOOLEAN IsWindows2000()
{
	OSVERSIONINFOEX osvi;
	BOOL bOsVersionInfoEx;

	// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
	// If that fails, try using the OSVERSIONINFO structure.

	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

	bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
	if( !bOsVersionInfoEx )
	{
		osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
		if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) 
			return FALSE;
	}

	if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
		//windows 2000
		return TRUE;
	return FALSE;

}

/*! 
  \brief Opens the wan (dialup, vpn...) adapter.
  \return If the function succeeds, the return value is the pointer to a properly initialized WAN_ADAPTER structure,
   otherwise the return value is NULL.
*/
PWAN_ADAPTER WanPacketOpenAdapter()
{
	PWAN_ADAPTER pWanAdapter = NULL;
	PBLOB_TABLE pBlobTable = NULL;
	HBLOB hFilterBlob = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -