📄 packet.c
字号:
/*
* 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 + -