📄 packet32.c
字号:
/*
* Copyright (c) 1999, 2000
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#define UNICODE 1
#include <windows.h>
#include <ntddndis.h>
#include <string.h>
#include <stdlib.h>
#include <packet32.h>
#include "trace.h"
/****** KERNEL Macro APIs ******************************************************/
#define GetInstanceModule(hInst) (HMODULE)(hInst)
#define GlobalPtrHandle(lp) ((HGLOBAL)GlobalHandle(lp))
#define GlobalLockPtr(lp) ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
#define GlobalUnlockPtr(lp) GlobalUnlock(GlobalPtrHandle(lp))
#define GlobalAllocPtr(flags, cb) (GlobalLock(GlobalAlloc((flags), (cb))))
#define GlobalReAllocPtr(lp, cbNew, flags) (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
#define GlobalFreePtr(lp) (GlobalUnlockPtr(lp), (BOOL)(ULONG_PTR)GlobalFree(GlobalPtrHandle(lp)))
#undef GMEM_MOVEABLE
#define GMEM_MOVEABLE 0
/// Title of error windows
TCHAR szWindowTitle[] = TEXT("PACKET.DLL");
#if DBG
#define ODS(_x) OutputDebugString(TEXT(_x))
//#define ODSEx(_x, _y)
#define ODSEx TRACE
#else
#ifdef _DEBUG_TO_FILE
#include <stdio.h>
/*!
\brief Macro to print a debug string. The behavior differs depending on the debug level
*/
#define ODS(_x) { \
FILE *f; \
f = fopen("winpcap_debug.txt", "a"); \
fprintf(f, "%s", _x); \
fclose(f); \
}
/*!
\brief Macro to print debug data with the printf convention. The behavior differs depending on
the debug level
*/
#define ODSEx(_x, _y) { \
FILE *f; \
f = fopen("winpcap_debug.txt", "a"); \
fprintf(f, _x, _y); \
fclose(f); \
}
LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
#else
#define ODS(_x)
#define ODSEx(_x, _y)
#endif
#endif
//service handles
SC_HANDLE scmHandle = NULL;
SC_HANDLE srvHandle = NULL;
LPCTSTR NPFServiceName = TEXT("NPF");
LPCTSTR NPFServiceDesc = TEXT("Netgroup Packet Filter");
LPCTSTR NPFDriverName = TEXT("\\npf.sys");
LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\ControlSet001\\Services\\NPF");
//---------------------------------------------------------------------------
/*!
\brief The main dll function.
*/
BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
{
BOOLEAN Status=TRUE;
switch ( Reason )
{
case DLL_PROCESS_ATTACH:
ODS("\n************Packet32: DllMain************\n");
#ifdef _DEBUG_TO_FILE
// dump a bunch of registry keys useful for debug to file
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
"adapters.reg");
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip",
"tcpip.reg");
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\NPF",
"npf.reg");
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services",
"services.reg");
#endif
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
return Status;
}
/*!
\brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
\param string The string to convert.
\return The converted string.
*/
WCHAR* SChar2WChar(char* string)
{
WCHAR* TmpStr;
TmpStr=(WCHAR*) malloc ((strlen(string)+2)*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, (strlen(string)+2));
return TmpStr;
}
/*!
\brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function.
\param AdapterObject Handle to the service control manager.
\return If the function succeeds, the return value is nonzero.
The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory
without performing a copy. This function tries to increase the size of that buffer.
*/
BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
{
BOOLEAN Status;
ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
PPACKET_OID_DATA OidData;
OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
if (OidData == NULL) {
ODS("PacketSetMaxLookaheadsize failed\n");
return FALSE;
}
//set the size of the lookahead buffer to the maximum available by the the NIC driver
OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD;
OidData->Length=sizeof(ULONG);
Status=PacketRequest(AdapterObject,FALSE,OidData);
OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD;
Status=PacketRequest(AdapterObject,TRUE,OidData);
GlobalFreePtr(OidData);
return Status;
}
/*!
\brief Retrieves the event associated in the driver with a capture instance and stores it in an
_ADAPTER structure.
\param AdapterObject Handle to the service control manager.
\return If the function succeeds, the return value is nonzero.
This function is used by PacketOpenAdapter() to retrieve the read event from the driver by means of an ioctl
call and set it in the _ADAPTER structure pointed by AdapterObject.
*/
BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
{
DWORD BytesReturned;
WCHAR EventName[39];
// this tells the terminal service to retrieve the event from the global namespace
wcsncpy(EventName,L"Global\\",sizeof(L"Global\\"));
// retrieve the name of the shared event from the driver
if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName+7,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE) return FALSE;
EventName[20]=0; // terminate the string
// open the shared event
AdapterObject->ReadEvent=CreateEventW(NULL,
TRUE,
FALSE,
EventName);
// in NT4 "Global\" is not automatically ignored: try to use simply the event name
if(GetLastError()!=ERROR_ALREADY_EXISTS){
if(AdapterObject->ReadEvent != NULL)
CloseHandle(AdapterObject->ReadEvent);
// open the shared event
AdapterObject->ReadEvent=CreateEventW(NULL,
TRUE,
FALSE,
EventName+7);
}
if(AdapterObject->ReadEvent==NULL || GetLastError()!=ERROR_ALREADY_EXISTS){
ODS("PacketSetReadEvt: error retrieving the event from the kernel\n");
return FALSE;
}
AdapterObject->ReadTimeOut=0;
return TRUE;
}
/*!
\brief Installs the NPF device driver.
\param ascmHandle Handle to the service control manager.
\param ascmHandle A pointer to a handle that will receive the pointer to the driver's service.
\param driverPath The full path of the .sys file to load.
\return If the function succeeds, the return value is nonzero.
This function installs the driver's service in the system using the CreateService function.
*/
BOOL PacketInstallDriver(SC_HANDLE ascmHandle, SC_HANDLE* srvHandle, TCHAR* driverPath)
{
BOOL result = FALSE;
ULONG err;
ODS("installdriver\n");
if (GetFileAttributes(driverPath) != 0xffffffff) {
*srvHandle = CreateService(ascmHandle,
NPFServiceName,
NPFServiceDesc,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
driverPath,
NULL, NULL, NULL, NULL, NULL);
if (*srvHandle == NULL) {
if (GetLastError() == ERROR_SERVICE_EXISTS) {
//npf.sys already existed
result = TRUE;
}
} else {
//Created service for npf.sys
result = TRUE;
}
}
if (result == TRUE) {
if (*srvHandle != NULL) {
CloseServiceHandle(*srvHandle);
}
}
if (result == FALSE){
err = GetLastError();
if (err != 2) {
ODSEx("PacketInstallDriver failed, Error=%d\n",err);
}
}
return result;
}
/*!
\brief Convert a Unicode dotted-quad to a 32-bit IP address.
\param cp A string containing the address.
\return the converted 32-bit numeric address.
Doesn't check to make sure the address is valid.
*/
ULONG inet_addrU(const WCHAR *cp)
{
ULONG val, part;
WCHAR c;
int i;
val = 0;
for (i = 0; i < 4; i++) {
part = 0;
while ((c = *cp++) != '\0' && c != '.') {
if (c < '0' || c > '9')
return -1;
part = part*10 + (c - '0');
}
if (part > 255)
return -1;
val = val | (part << i*8);
if (i == 3) {
if (c != '\0')
return -1; // extra gunk at end of string
} else {
if (c == '\0')
return -1; // string ends early
}
}
return val;
}
/*!
\brief Dumps a registry key to disk in text format. Uses regedit.
\param KeyName Name of the ket to dump. All its subkeys will be saved recursively.
\param FileName Name of the file that will contain the dump.
\return If the function succeeds, the return value is nonzero.
For debugging purposes, we use this function to obtain some registry keys from the user's machine.
*/
#ifdef _DEBUG_TO_FILE
LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
{
CHAR Command[256];
strcpy(Command, "regedit /e ");
strcat(Command, FileName);
strcat(Command, " ");
strcat(Command, KeyName);
/// Let regedit do the dirt work for us
system(Command);
return TRUE;
}
#endif
//---------------------------------------------------------------------------
// PUBLIC API
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -