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

📄 packet.h

📁 Windows XP下的抓包程序实现
💻 H
📖 第 1 页 / 共 3 页
字号:
/*!
  \brief Contains the state of a running instance of the NPF driver.
  
  This is the most important structure of NPF: it is used by almost all the functions of the driver. An
  _OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
  to the driver.
*/
typedef struct _OPEN_INSTANCE
{
	PDEVICE_EXTENSION   DeviceExtension;	///< Pointer to the _DEVICE_EXTENSION structure of the device on which
											///< the instance is bound.
	NDIS_HANDLE         AdapterHandle;		///< NDIS idetifier of the adapter used by this instance.
	UINT				Medium;				///< Type of physical medium the underlying NDIS driver uses. See the
											///< documentation of NdisOpenAdapter in the MS DDK for details.
	NDIS_HANDLE         PacketPool;			///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
	KSPIN_LOCK			RequestSpinLock;	///< SpinLock used to synchronize the OID requests.
	LIST_ENTRY          RequestList;		///< List of pending OID requests.
	LIST_ENTRY          ResetIrpList;		///< List of pending adapter reset requests.
    INTERNAL_REQUEST    Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request.
	PMDL				BufferMdl;			///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory.
	PKEVENT				ReadEvent;			///< Pointer to the event on which the read calls on this instance must wait.
	PUCHAR				bpfprogram;			///< Pointer to the filtering pseudo-code associated with current instance of the driver.
											///< This code is used only in particular situations (for example when the packet received
											///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
											///< the filtering routine created by the JIT compiler and pointed by the next field 
											///< is used. See \ref NPF for details on the filtering process.
#ifdef __NPF_x86__
	JIT_BPF_Filter		*Filter;			///< Pointer to the native filtering function created by the jitter. 
											///< See BPF_jitter() for details.
#endif
	UINT				MinToCopy;			///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
											///< BIOCSMINTOCOPY IOCTL. 
	LARGE_INTEGER		TimeOut;			///< Timeout after which a read is released, also if the amount of data in the buffer is 
											///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
											
	int					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.
	NDIS_SPIN_LOCK		CountersLock;		///< SpinLock that protects the statistical mode counters.
	UINT				Nwrites;			///< Number of times a single write must be physically repeated. See \ref NPF for an 
											///< explanation
	ULONG				Multiple_Write_Counter;	///< Counts the number of times a single write has already physically repeated.
	NDIS_EVENT			WriteEvent;			///< Event used to synchronize the multiple write process.
	BOOLEAN				WriteInProgress;	///< True if a write is currently in progress. NPF currently allows a single wite on 
											///< the same open instance.
	NDIS_SPIN_LOCK		WriteLock;			///< SpinLock that protects the WriteInProgress variable.
	NDIS_EVENT			NdisRequestEvent;	///< Event used to synchronize I/O requests with the callback structure of NDIS.
	BOOLEAN				SkipSentPackets;	///< True if this instance should not capture back the packets that it transmits.
	NDIS_STATUS			IOStatus;			///< Maintains the status of and OID request call, that will be passed to the application.
	HANDLE				DumpFileHandle;		///< Handle of the file used in dump mode.
	PFILE_OBJECT		DumpFileObject;		///< Pointer to the object of the file used in dump mode.
	PKTHREAD			DumpThreadObject;	///< Pointer to the object of the thread used in dump mode.
	HANDLE				DumpThreadHandle;	///< Handle of the thread created by dump mode to asynchronously move the buffer to disk.
	NDIS_EVENT			DumpEvent;			///< Event used to synchronize the dump thread with the tap when the instance is in dump mode.
	LARGE_INTEGER		DumpOffset;			///< Current offset in the dump file.
	UNICODE_STRING      DumpFileName;		///< String containing the name of the dump file.
	UINT				MaxDumpBytes;		///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it 
											///< will be closed. A value of 0 means unlimited size.
	UINT				MaxDumpPacks;		///< Maximum number of packets that will be saved in the dump file. If this number of 
											///< packets is reached the dump will be closed. A value of 0 means unlimited number of 
											///< packets.
	BOOLEAN				DumpLimitReached;	///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is 
											///< reached.
	MEM_TYPE			mem_ex;				///< Memory used by the TME virtual co-processor
	TME_CORE			tme;				///< Data structure containing the virtualization of the TME co-processor
	NDIS_SPIN_LOCK		MachineLock;		///< SpinLock that protects the BPF filter and the TME engine, if in use.
	UINT				MaxFrameSize;		///< Maximum frame size that the underlying MAC acceptes. Used to perform a check on the 
											///< size of the frames sent with NPF_Write() or NPF_BufferedWrite().
	CpuPrivateData		CpuData[32];		///< Pool of kernel buffer structures, one for each CPU.
	ULONG				ReaderSN;			///< Sequence number of the next packet to be read from the pool of kernel buffers.
	ULONG				WriterSN;			///< Sequence number of the next packet to be written in the pool of kernel buffers.
											///< These two sequence numbers are unique for each capture instance.
	ULONG				Size;				///< Size of each kernel buffer contained in the CpuData field.
	ULONG			   AdapterHandleUsageCounter;
	NDIS_SPIN_LOCK	   AdapterHandleLock;
	ULONG			   AdapterBindingStatus;	///< Specifies if NPF is still bound to the adapter used by this instance, it's unbinding or it's not bound.	

	NDIS_EVENT		   NdisOpenCloseCompleteEvent;
	NDIS_EVENT		   NdisWriteCompleteEvent;	///< Event that is signalled when all the packets have been successfully sent by NdisSend (and corresponfing sendComplete has been called)
	NTSTATUS		   OpenCloseStatus;
	ULONG			   TransmitPendingPackets;	///< Specifies the number of packets that are pending to be transmitted, i.e. have been submitted to NdisSendXXX but the SendComplete has not been called yet.
}
OPEN_INSTANCE, *POPEN_INSTANCE;

enum ADAPTER_BINDING_STATUS
{
	ADAPTER_UNBOUND,
	ADAPTER_BOUND,
	ADAPTER_UNBINDING,
};

/*!
  \brief Structure prepended to each packet in the kernel buffer pool.
  
  Each packet in one of the kernel buffers is prepended by this header. It encapsulates the bpf_header, 
  which will be passed to user level programs, as well as the sequence number of the packet, set by the producer (the tap function),
  and used by the consumer (the read function) to "reorder" the packets contained in the various kernel buffers.
*/
struct PacketHeader
{
	ULONG SN;								///< Sequence number of the packet.
	struct bpf_hdr header;					///< bpf header, created by the tap, and copied unmodified to user level programs.
};

extern ULONG NCpu;


#define TRANSMIT_PACKETS 256	///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
								///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.


/// Macro used in the I/O routines to return the control to user-mode with a success status.
#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\
	Irp->IoStatus.Status = STATUS_SUCCESS;\
	IoCompleteRequest(Irp, IO_NO_INCREMENT);\
	return STATUS_SUCCESS;\

/// Macro used in the I/O routines to return the control to user-mode with a failure status.
#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\
	Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\
	IoCompleteRequest(Irp, IO_NO_INCREMENT);\
	return STATUS_UNSUCCESSFUL;\

/**
 *  @}
 */


/***************************/
/*       Prototypes        */
/***************************/

/** @defgroup NPF_code NPF functions 
 *  @{
 */


/*!
  \brief The initialization routine of the driver.
  \param DriverObject The driver object of NPF created by the system.
  \param RegistryPath The registry path containing the keys related to the driver.
  \return A string containing a list of network adapters.

  DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called
  by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver, 
  performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O
  callbacks, creates the devices, defines NPF as a protocol inside NDIS.
*/ 
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    );

/*!
  \brief Returns the list of the MACs available on the system.
  \return A string containing a list of network adapters.

  The list of adapters is retrieved from the 
  SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key. 
  NPF tries to create its bindings from this list. In this way it is possible to be loaded
  and unloaded dynamically without passing from the control panel.
*/
PWCHAR getAdaptersList(VOID);

/*!
  \brief Returns the MACs that bind to TCP/IP.
  \return Pointer to the registry key containing the list of adapters on which TCP/IP is bound.

  If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function.
*/
PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID);

/*!
  \brief Creates a device for a given MAC.
  \param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF.
  \param amacNameP The name of the network interface that the device will point.
  \param aProtoHandle NDIS protocol handle of NPF.
  \return If the function succeeds, the return value is nonzero.

  NPF creates a device for every valid network adapter. The new device points to the NPF driver, but contains
  information about the original device. In this way, when the user opens the new device, NPF will be able to
  determine the correct adapter to use.
*/
BOOLEAN createDevice(
	IN OUT PDRIVER_OBJECT adriverObjectP,
	IN PUNICODE_STRING amacNameP,
	NDIS_HANDLE aProtoHandle);

/*!
  \brief Opens a new instance of the driver.
  \param DeviceObject Pointer to the device object utilized by the user.
  \param Irp Pointer to the IRP containing the user request.
  \return The status of the operation. See ntstatus.h in the DDK.

  This function is called by the OS when a new instance of the driver is opened, i.e. when a user application 
  performs a CreateFile on a device created by NPF. NPF_Open allocates and initializes variables, objects
  and buffers needed by the new instance, fills the OPEN_INSTANCE structure associated with it and opens the 
  adapter with a call to NdisOpenAdapter.
*/
NTSTATUS
NPF_Open(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

/*!
  \brief Ends the opening of an adapter.
  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
  \param Status Status of the opening operation performed by NDIS.
  \param OpenErrorStatus not used by NPF.

  Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC 
  driver has finished an open operation that was previously started by NPF_Open().
*/
VOID
NPF_OpenAdapterComplete(
    IN NDIS_HANDLE  ProtocolBindingContext,
    IN NDIS_STATUS  Status,
    IN NDIS_STATUS  OpenErrorStatus
    );

/*!
  \brief Closes an instance of the driver.
  \param DeviceObject Pointer to the device object utilized by the user.
  \param Irp Pointer to the IRP containing the user request.
  \return The status of the operation. See ntstatus.h in the DDK.

  This function is called when a running instance of the driver is closed by the user with a CloseHandle(). 
  It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the 
  instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter. 
*/
NTSTATUS
NPF_Cleanup(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
NPF_Close(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );



/*!
  \brief Ends the closing of an adapter.
  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
  \param Status Status of the close operation performed by NDIS.

  Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC 
  driver has finished a close operation that was previously started by NPF_Close().
*/
VOID
NPF_CloseAdapterComplete(
    IN NDIS_HANDLE  ProtocolBindingContext,
    IN NDIS_STATUS  Status
    );

/*!
  \brief Callback invoked by NDIS when a packet arrives from the network.
  \param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies 
   the NPF instance to which the packets are destined.
  \param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request. 
   This value must be used when the packet is transferred from the NIC driver with NdisTransferData().
  \param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet.
  \param HeaderBufferSize Size in bytes of the header.
  \param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's 
   data <b>available to NPF</b>. This value does not necessarily coincide with the actual size of the packet,
   since only a portion can be available at this time. The remaining portion can be obtained with the
   NdisTransferData() NDIS function.
  \param LookaheadBufferSize Size in bytes of the lookahead buffer.
  \param PacketSize Total size of the incoming packet, excluded the header.
  \return The status of the operation. See ntstatus.h in the DDK.

  NPF_tap() is called by the underlying NIC for every incoming packet. It is the most important and one of 
  the most complex functions of NPF: it executes the filter, runs the statistical engine (if the instance is in 
  statistical mode), gathers the timestamp, moves the packet in the buffer. NPF_tap() is the only function,
  along with the filtering ones, that is executed for every incoming packet, therefore it is carefully 
  optimized.
*/
NDIS_STATUS
NPF_tap(
    IN NDIS_HANDLE ProtocolBindingContext,
    IN NDIS_HANDLE MacReceiveContext,
    IN PVOID HeaderBuffer,
    IN UINT HeaderBufferSize,
    IN PVOID LookAheadBuffer,
    IN UINT LookaheadBufferSize,
    IN UINT PacketSize
    );

/*!
  \brief Ends the transfer of a packet.
  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
  \param Packet Pointer to the NDIS_PACKET structure that received the packet data.
  \param Status Status of the transfer operation.
  \param BytesTransferred Amount of bytes transferred.

  Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC 
  driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer.
*/
VOID
NPF_TransferDataComplete(
    IN NDIS_HANDLE ProtocolBindingContext,
    IN PNDIS_PACKET Packet,
    IN NDIS_STATUS Status,
    IN UINT BytesTransferred
    );

/*!
  \brief Callback function that signals the end of a packet reception.
  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.

  does nothing in NPF
*/
VOID
NPF_ReceiveComplete(IN NDIS_HANDLE  ProtocolBindingContext);

/*!
  \brief Handles the IOCTL calls.
  \param DeviceObject Pointer to the device object utilized by the user.
  \param Irp Pointer to the IRP containing the user request.
  \return The status of the operation. See ntstatus.h in the DDK.

  Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands
  using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF.
  The following commands are recognized: 
  - #BIOCSETBUFFERSIZE 
  - #BIOCSETF 
  - #BIOCGSTATS 
  - #BIOCSRTIMEOUT
  - #BIOCSMODE 
  - #BIOCSWRITEREP 
  - #BIOCSMINTOCOPY 
  - #BIOCSETOID 
  - #BIOCQUERYOID 
  - #BIOCSETDUMPFILENAME
  - #BIOCGEVNAME
  -	#BIOCSENDPACKETSSYNC
  -	#BIOCSENDPACKETSNOSYNC
*/
NTSTATUS
NPF_IoControl(

⌨️ 快捷键说明

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