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

📄 packet.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
 * Copyright (c) 2005 - 2007 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.
 *
 */

#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"

#include "ntddpack.h"

#include "debug.h"
#include "packet.h"
#include "win_bpf.h"
#include "win_bpf_filter_init.h"
#include "..\..\Common\WpcapNames.h"


#if DBG
// Declare the global debug flag for this driver.
ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;

#endif

PDEVICE_EXTENSION GlobalDeviceExtension;

//
// Global strings
//
WCHAR g_NPF_PrefixBuffer[MAX_WINPCAP_KEY_CHARS] = NPF_DEVICE_NAMES_PREFIX_WIDECHAR;
//  
//	Old registry based WinPcap names
//
//WCHAR g_NPF_PrefixBuffer[MAX_WINPCAP_KEY_CHARS];
NDIS_STRING g_NPF_Prefix;
NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
								L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
								L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
NDIS_STRING g_WinpcapGlobalKey = NDIS_STRING_CONST("\\Registry\\Machine\\" WINPCAP_INSTANCE_KEY_WIDECHAR);
//NDIS_STRING g_WinpcapGlobalKey = NDIS_STRING_CONST("\\Registry\\Machine\\" WINPCAP_GLOBAL_KEY_WIDECHAR);

/// Global variable that points to the names of the bound adapters
WCHAR* bindP = NULL;

extern struct time_conv G_Start_Time; // from openclos.c

ULONG NCpu;

ULONG TimestampMode;
UINT g_SendPacketFlags = 0;

static VOID NPF_ResetBufferContents(POPEN_INSTANCE Open);

//
//  Packet Driver's entry routine.
//
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    NDIS_PROTOCOL_CHARACTERISTICS  ProtocolChar;
    UNICODE_STRING MacDriverName;
    UNICODE_STRING UnicodeDeviceName;
    PDEVICE_OBJECT DeviceObject = NULL;
    PDEVICE_EXTENSION DeviceExtension = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    NTSTATUS ErrorCode = STATUS_SUCCESS;
    NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
    ULONG          DevicesCreated=0;
    PWSTR          BindString;
    PWSTR          ExportString;
    PWSTR          BindStringSave;
    PWSTR          ExportStringSave;
    NDIS_HANDLE    NdisProtocolHandle;
	WCHAR* bindT;
	PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
	UNICODE_STRING macName;
//  
//	Old registry based WinPcap names
//
//	UINT RegStrLen;
	ULONG			OsMajorVersion, OsMinorVersion;
	
	TRACE_ENTER();

#ifndef __NPF_NT4__

   TRACE_MESSAGE(PACKET_DEBUG_INIT, "DriverEntry -- NT4");

	//
	// Get OS version and store it in a global variable. 
	// For the moment we use the deprecated PsGetVersion() because the suggested
	// RtlGetVersion() doesn't seem to exist in Windows 2000, and we don't want
	// to have two separated drivers just for this call.
	// Morever, the NT4 version of the driver just excludes this, since those flags 
	// are not available.
	//
	// Note: both RtlGetVersion() and PsGetVersion() are documented to always return success.
	//
	//	OsVersion.dwOSVersionInfoSize = sizeof(OsVersion);
	//	RtlGetVersion(&OsVersion);
	PsGetVersion(&OsMajorVersion, &OsMinorVersion, NULL, NULL);
	TRACE_MESSAGE2(PACKET_DEBUG_INIT, "OS Version: %d.%d\n", OsMajorVersion, OsMinorVersion);

	//
	// Define the correct flag to skip the loopback packets, according to the OS
	//
	if((OsMajorVersion == 5) && (OsMinorVersion == 0))
	{
		// Windows 2000 wants both NDIS_FLAGS_DONT_LOOPBACK and NDIS_FLAGS_SKIP_LOOPBACK
		g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK | NDIS_FLAGS_SKIP_LOOPBACK_W2K;
	}
	else
	{
		// Windows XP, 2003 and follwing want only  NDIS_FLAGS_DONT_LOOPBACK
		g_SendPacketFlags =  NDIS_FLAGS_DONT_LOOPBACK;
	}
#endif //__NPF_NT4__

	//
	// Set timestamp gathering method getting it from the registry
	//
	ReadTimeStampModeFromRegistry(RegistryPath);

	TRACE_MESSAGE1(PACKET_DEBUG_INIT,"%ws",RegistryPath->Buffer);

//  
//	Old registry based WinPcap names
//
//	//
//	// Get the device names prefix from the registry
//	//
//	RegStrLen = sizeof(g_NPF_PrefixBuffer) / sizeof(g_NPF_PrefixBuffer[0]);
//
//	NPF_QueryWinpcapRegistryString(NPF_DEVICES_PREFIX_REG_KEY_WC,
//		g_NPF_PrefixBuffer,
//		RegStrLen,
//		NPF_DEVICE_NAMES_PREFIX_WIDECHAR);
//
	NdisInitUnicodeString(&g_NPF_Prefix, g_NPF_PrefixBuffer);


	//
	// Get number of CPUs and save it
	//
	NCpu = NdisSystemProcessorCount();

	RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

	//
	// Register as a protocol with NDIS
	//
#ifdef NDIS50
    ProtocolChar.MajorNdisVersion            = 5;
#else
    ProtocolChar.MajorNdisVersion            = 3;
#endif
    ProtocolChar.MinorNdisVersion            = 0;
    ProtocolChar.Reserved                    = 0;
    ProtocolChar.OpenAdapterCompleteHandler  = NPF_OpenAdapterComplete;
    ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
    ProtocolChar.SendCompleteHandler         = NPF_SendComplete;
    ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
    ProtocolChar.ResetCompleteHandler        = NPF_ResetComplete;
    ProtocolChar.RequestCompleteHandler      = NPF_RequestComplete;
    ProtocolChar.ReceiveHandler              = NPF_tap;
    ProtocolChar.ReceiveCompleteHandler      = NPF_ReceiveComplete;
    ProtocolChar.StatusHandler               = NPF_Status;
    ProtocolChar.StatusCompleteHandler       = NPF_StatusComplete;
#ifdef NDIS50
    ProtocolChar.BindAdapterHandler          = NPF_BindAdapter;
    ProtocolChar.UnbindAdapterHandler        = NPF_UnbindAdapter;
    ProtocolChar.PnPEventHandler             = NPF_PowerChange;
    ProtocolChar.ReceivePacketHandler        = NULL;
#endif
    ProtocolChar.Name                        = ProtoName;

    NdisRegisterProtocol(
        &Status,
        &NdisProtocolHandle,
        &ProtocolChar,
        sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

	if (Status != NDIS_STATUS_SUCCESS) {

		TRACE_MESSAGE(PACKET_DEBUG_INIT,"Failed to register protocol with NDIS");

		TRACE_EXIT();
		return Status;

	}
	
    // 
	// Standard device driver entry points stuff.
	//
    DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = NPF_Close;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP]= NPF_Cleanup; 
    DriverObject->MajorFunction[IRP_MJ_READ]   = NPF_Read;
    DriverObject->MajorFunction[IRP_MJ_WRITE]  = NPF_Write;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = NPF_IoControl;
    DriverObject->DriverUnload = NPF_Unload;

 	bindP = getAdaptersList();

	if (bindP == NULL) 
	{
		TRACE_MESSAGE(PACKET_DEBUG_INIT, "Adapters not found in the registry, try to copy the bindings of TCP-IP.");

		tcpBindingsP = getTcpBindings();
			
		if (tcpBindingsP == NULL)
		{
			TRACE_MESSAGE(PACKET_DEBUG_INIT, "TCP-IP not found, quitting.");
			goto RegistryError;
		}
			
		bindP = (WCHAR*)tcpBindingsP;
		bindT = (WCHAR*)(tcpBindingsP->Data);
			
	}
	else 
	{
		bindT = bindP;
	}

	for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR)) 
	{
		RtlInitUnicodeString(&macName, bindT);
		createDevice(DriverObject, &macName, NdisProtocolHandle);
	}

	TRACE_EXIT();
	return STATUS_SUCCESS;

RegistryError:

    NdisDeregisterProtocol(
        &Status,
        NdisProtocolHandle
        );

    Status=STATUS_UNSUCCESSFUL;

	TRACE_EXIT();
    return(Status);
}

//-------------------------------------------------------------------

PWCHAR getAdaptersList(void)
{
	PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
	OBJECT_ATTRIBUTES objAttrs;
	NTSTATUS status;
	HANDLE keyHandle;
	UINT BufPos=0;
	UINT BufLen=4096;

	
	PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen, '0PWA');
	
	if (DeviceNames == NULL) {
		IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
			return NULL;
	}
	
	InitializeObjectAttributes(&objAttrs, &AdapterListKey,
		OBJ_CASE_INSENSITIVE, NULL, NULL);
	status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
	if (!NT_SUCCESS(status)) {
		IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
	}
	else { //OK
		
		ULONG resultLength;
	    KEY_VALUE_PARTIAL_INFORMATION valueInfo;
		CHAR AdapInfo[1024];
		UINT i=0;
		
		IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%p\n",DeviceNames);)
			
			// Scan the list of the devices
			while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS)
			{
				WCHAR ExportKeyName [512];
				PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
				UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
				PWCHAR LinkageKeyPrefix = L"\\Linkage";
				UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
				NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
				PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
				UNICODE_STRING AdapterKeyName;
				HANDLE ExportKeyHandle;
				
				RtlCopyMemory(ExportKeyName,
					ExportKeyPrefix,
					ExportKeyPrefixSize);
				
				RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
					tInfo->Name,
					tInfo->NameLength+2);
				
				RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
					LinkageKeyPrefix,
					LinkageKeyPrefixSize);
				
				IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
										
				RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
				
				InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
					OBJ_CASE_INSENSITIVE, NULL, NULL);
				
				status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
				
				if (!NT_SUCCESS(status)) {
					IF_LOUD(DbgPrint("OpenKey Failed, %d!\n",status);)
					i++;
					continue;
				}
				
				status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
					KeyValuePartialInformation, &valueInfo,
					sizeof(valueInfo), &resultLength);
				
				if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
					IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
				}
				else {                      // We know how big it needs to be.
					ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
					PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =	(PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
					if (valueInfoP != NULL) {
						status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
							KeyValuePartialInformation,
							valueInfoP,
							valueInfoLength, &resultLength);
						if (!NT_SUCCESS(status)) {
							IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
						}
						else{
							IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
								if( BufPos + valueInfoP->DataLength > BufLen ) {
									// double the buffer size
									PWCHAR DeviceNames2 = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen
										<< 1, '0PWA');
									if( DeviceNames2 ) {
										RtlCopyMemory((PCHAR)DeviceNames2, (PCHAR)DeviceNames, BufLen);
										BufLen <<= 1;
										ExFreePool(DeviceNames);
										DeviceNames = DeviceNames2;
									}
								} 
								if( BufPos + valueInfoP->DataLength < BufLen ) {
									RtlCopyMemory((PCHAR)DeviceNames+BufPos,
										valueInfoP->Data,
										valueInfoP->DataLength);
									BufPos+=valueInfoP->DataLength-2;
								}
						}
						
						ExFreePool(valueInfoP);
					}
					else {
						IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
					}
					
				}
				
				// terminate the buffer
				DeviceNames[BufPos/2]=0;
				DeviceNames[BufPos/2+1]=0;
				
				ZwClose (ExportKeyHandle);
				i++;
				
			}
			
			ZwClose (keyHandle);
			
	}
	if(BufPos==0){
		ExFreePool(DeviceNames);
		return NULL;
	}
	return DeviceNames;
}

//-------------------------------------------------------------------

PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
{
  PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
  OBJECT_ATTRIBUTES objAttrs;
  NTSTATUS status;
  HANDLE keyHandle;

  InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
                             OBJ_CASE_INSENSITIVE, NULL, NULL);
  status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
  if (!NT_SUCCESS(status)) {
    IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
  }
  else {
    ULONG resultLength;
    KEY_VALUE_PARTIAL_INFORMATION valueInfo;

    IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)

    status = ZwQueryValueKey(keyHandle, &bindValueName,
                             KeyValuePartialInformation, &valueInfo,
                             sizeof(valueInfo), &resultLength);
    if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
      IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
    }
    else {                      // We know how big it needs to be.
      ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
      PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
        (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
      
	  if (valueInfoP != NULL) {
        status = ZwQueryValueKey(keyHandle, &bindValueName,
                                 KeyValuePartialInformation,
                                 valueInfoP,
                                 valueInfoLength, &resultLength);
      
		if (!NT_SUCCESS(status)) {
          IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
        }
        else if (valueInfoLength != resultLength) {
          IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
                     "but previous len = %u\n",
                     resultLength, valueInfoLength);)
        }
        else if (valueInfoP->Type != REG_MULTI_SZ) {
          IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
                     valueInfoP->Type);)
        }
        else {                  // It's OK
#if DBG
          ULONG i;
          WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
          IF_LOUD(DbgPrint("\n\nBind value:\n");)
          for (i = 0; *dataP != UNICODE_NULL; i++) {
            UNICODE_STRING macName;
            RtlInitUnicodeString(&macName, dataP);
            IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
            dataP +=
              (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
          }
#endif // DBG
          result = valueInfoP;
        }
      }
    }
    ZwClose(keyHandle);
  }
  return result;
}

//-------------------------------------------------------------------

BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
					 IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
{
	NTSTATUS status;
	PDEVICE_OBJECT devObjP;
	UNICODE_STRING deviceName;
	UNICODE_STRING deviceSymLink;

	IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
	if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
		devicePrefix.Length) < devicePrefix.Length) 
	{
		return FALSE;
	}

	deviceName.Length = 0;
	deviceName.MaximumLength = (USHORT)(amacNameP->Length + g_NPF_Prefix.Length + sizeof(UNICODE_NULL));
	deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');

	if (deviceName.Buffer == NULL)
		return FALSE;

⌨️ 快捷键说明

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