Find all our projects in development below.
All source code is GNU General Public License (GPL)
Browsing clsPacketMonitor.vb (25.05 KB)
Option Explicit On
Imports System.Net
Imports System.Net.Sockets
Imports System.Runtime.InteropServices
Imports System.Text
Public Class clsPacketMonitor
''' <summary>
''' The Network Control precedence designation is intended to be used within a network only. The actual use and control of that designation is up to each network. The Internetwork Control designation is intended for use by gateway control originators only. If the actual use of these precedence designations is of concern to a particular network, it is the responsibility of that network to control the access to, and use of, those precedence designations.
''' </summary>
Public Enum Precedence
Routine = 0
Priority = 1
Immediate = 2
Flash = 3
FlashOverride = 4
CRITICECP = 5
InternetworkControl = 6
NetworkControl = 7
End Enum
''' <summary>
''' The use of the Delay, Throughput, and Reliability indications may increase the cost (in some sense) of the service. In many networks better performance for one of these parameters is coupled with worse performance on another.
''' </summary>
Public Enum Delay
NormalDelay = 0
LowDelay = 1
End Enum
''' <summary>
''' The use of the Delay, Throughput, and Reliability indications may increase the cost (in some sense) of the service. In many networks better performance for one of these parameters is coupled with worse performance on another.
''' </summary>
Public Enum Throughput
NormalThroughput = 0
HighThroughput = 1
End Enum
''' <summary>
''' The use of the Delay, Throughput, and Reliability indications may increase the cost (in some sense) of the service. In many networks better performance for one of these parameters is coupled with worse performance on another.
''' </summary>
Public Enum Reliability
NormalReliability = 0
HighReliability = 1
End Enum
''' <summary>
''' This field indicates the next level protocol used in the data portion of the internet datagram.
''' </summary>
Public Enum Protocol
Ggp = 3
Icmp = 1
Idp = 22
Igmp = 2
IP = 4
ND = 77
Pup = 12
Tcp = 6
Udp = 17
Other = -1
End Enum
Public Class clsPacket
' private variables
Private m_Raw As Byte()
Private m_Time As DateTime
Private m_Version As Integer
Private m_HeaderLength As Integer
Private m_Precedence As Precedence
Private m_Delay As Delay
Private m_Throughput As Throughput
Private m_Reliability As Reliability
Private m_TotalLength As Integer
Private m_Identification As Integer
Private m_TimeToLive As Integer
Private m_Protocol As Protocol
Private m_Checksum As Byte()
Private m_SourceAddress As IPAddress
Private m_DestinationAddress As IPAddress
Private m_SourcePort As Integer
Private m_DestinationPort As Integer
''' <summary>
''' Initializes a new version of the Packet class.
''' </summary>
''' <param name="raw">The raw bytes of the IP packet.</param>
''' <exception cref="ArgumentNullException"><paramref name="raw"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
''' <exception cref="ArgumentException"><paramref name="raw"/> represents an invalid IP packet.</exception>
''' <remarks>The intercept time will be set to DateTime.Now.</remarks>
Public Sub New(ByVal raw As Byte())
Me.New(raw, DateTime.Now)
End Sub
''' <summary>
''' Initializes a new version of the Packet class.
''' </summary>
''' <param name="raw">The raw bytes of the IP packet.</param>
''' <param name="time">The time when the IP packet was intercepted.</param>
''' <exception cref="ArgumentNullException"><paramref name="raw"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
''' <exception cref="ArgumentException"><paramref name="raw"/> represents an invalid IP packet.</exception>
Public Sub New(ByVal raw As Byte(), ByVal time As DateTime)
If raw Is Nothing Then
Throw New ArgumentNullException()
End If
If raw.Length < 20 Then
Throw New ArgumentException()
End If
' invalid IP packet
m_Raw = raw
m_Time = time
m_Version = (raw(0) And &HF0) >> 4
' sizeof(int)
m_HeaderLength = (raw(0) And &HF) * 4
If (raw(0) And &HF) < 5 Then
Throw New ArgumentException()
End If
' invalid header of packet
m_Precedence = DirectCast((raw(1) And &HE0) >> 5, Precedence)
m_Delay = DirectCast((raw(1) And &H10) >> 4, Delay)
m_Throughput = DirectCast((raw(1) And &H8) >> 3, Throughput)
m_Reliability = DirectCast((raw(1) And &H4) >> 2, Reliability)
m_TotalLength = raw(2) * 256 + raw(3)
If m_TotalLength <> raw.Length Then
Throw New ArgumentException()
End If
' invalid size of packet
m_Identification = raw(4) * 256 + raw(5)
m_TimeToLive = raw(8)
If [Enum].IsDefined(GetType(Protocol), CInt(raw(9))) Then
m_Protocol = raw(9)
Else
m_Protocol = Protocol.Other
End If
m_Checksum = New Byte(1) {}
m_Checksum(0) = raw(11)
m_Checksum(1) = raw(10)
m_SourceAddress = New IPAddress(BitConverter.ToUInt32(raw, 12))
m_DestinationAddress = New IPAddress(BitConverter.ToUInt32(raw, 16))
If m_Protocol = Protocol.Tcp OrElse m_Protocol = Protocol.Udp Then
m_SourcePort = raw(m_HeaderLength) * 256 + raw(m_HeaderLength + 1)
m_DestinationPort = raw(m_HeaderLength + 2) * 256 + raw(m_HeaderLength + 3)
Else
m_SourcePort = -1
m_DestinationPort = -1
End If
End Sub
''' <summary>
''' Gets the raw bytes of the IP packet.
''' </summary>
''' <value>An array of bytes.</value>
Public ReadOnly Property Raw() As Byte()
Get
Return m_Raw
End Get
End Property
''' <summary>
''' Gets the time when the IP packet was intercepted.
''' </summary>
''' <value>A <see cref="DateTime"/> value.</value>
Public ReadOnly Property Time() As DateTime
Get
Return m_Time
End Get
End Property
''' <summary>
''' Gets the version of the IP protocol used.
''' </summary>
''' <value>A 32-bits signed integer.</value>
Public ReadOnly Property Version() As Integer
Get
Return m_Version
End Get
End Property
''' <summary>
''' Gets the length of the IP header [in bytes].
''' </summary>
''' <value>A 32-bits signed integer.</value>
Public ReadOnly Property HeaderLength() As Integer
Get
Return m_HeaderLength
End Get
End Property
''' <summary>
''' Gets the precedence parameter.
''' </summary>
''' <value>A <see cref="Precedence"/> instance.</value>
Public ReadOnly Property Precedence() As Precedence
Get
Return m_Precedence
End Get
End Property
''' <summary>
''' Gets the delay parameter.
''' </summary>
''' <value>A <see cref="Delay"/> instance.</value>
Public ReadOnly Property Delay() As Delay
Get
Return m_Delay
End Get
End Property
''' <summary>
''' Gets the throughput parameter.
''' </summary>
''' <value>A <see cref="Throughput"/> instance.</value>
Public ReadOnly Property Throughput() As Throughput
Get
Return m_Throughput
End Get
End Property
''' <summary>
''' Gets the reliability parameter.
''' </summary>
''' <value>A <see cref="Reliability"/> instance.</value>
Public ReadOnly Property Reliability() As Reliability
Get
Return m_Reliability
End Get
End Property
''' <summary>
''' Gets the total length of the IP packet.
''' </summary>
''' <value>A 32-bits signed integer.</value>
Public ReadOnly Property TotalLength() As Integer
Get
Return m_TotalLength
End Get
End Property
''' <summary>
''' Gets the identification number of the IP packet.
''' </summary>
''' <value>A 32-bits signed integer.</value>
Public ReadOnly Property Identification() As Integer
Get
Return m_Identification
End Get
End Property
''' <summary>
''' Gets the time-to-live [hop count] of the IP packet.
''' </summary>
''' <value>A 32-bits signed integer.</value>
Public ReadOnly Property TimeToLive() As Integer
Get
Return m_TimeToLive
End Get
End Property
''' <summary>
''' Gets the protocol of the IP packet.
''' </summary>
''' <value>A <see cref="Protocol"/> instance.</value>
Public ReadOnly Property Protocol() As Protocol
Get
Return m_Protocol
End Get
End Property
''' <summary>
''' Gets the checksum of the IP packet.
''' </summary>
''' <value>An array of two bytes.</value>
Public ReadOnly Property Checksum() As Byte()
Get
Return m_Checksum
End Get
End Property
''' <summary>
''' Gets the source address of the IP packet.
''' </summary>
''' <value>An <see cref="IPAddress"/> instance.</value>
Public ReadOnly Property SourceAddress() As IPAddress
Get
Return m_SourceAddress
End Get
End Property
''' <summary>
''' Gets the destination address of the IP packet.
''' </summary>
''' <value>An <see cref="IPAddress"/> instance.</value>
Public ReadOnly Property DestinationAddress() As IPAddress
Get
Return m_DestinationAddress
End Get
End Property
''' <summary>
''' Gets the source port of the packet.
''' </summary>
''' <value>A 32-bits signed integer.</value>
''' <remarks>
''' This property will only return meaningful data if the IP packet encapsulates either a TCP or a UDP packet.
''' If the IP address encapsulates a packet of another protocol, the returned source port will be set to minus one.
''' </remarks>
Public ReadOnly Property SourcePort() As Integer
Get
Return m_SourcePort
End Get
End Property
''' <summary>
''' Gets the destination port of the packet.
''' </summary>
''' <value>A 32-bits signed integer.</value>
''' <remarks>
''' This property will only return meaningful data if the IP packet encapsulates either a TCP or a UDP packet.
''' If the IP address encapsulates a packet of another protocol, the returned destination port will be set to minus one.
''' </remarks>
Public ReadOnly Property DestinationPort() As Integer
Get
Return m_DestinationPort
End Get
End Property
''' <summary>
''' Gets a string representation of the source.
''' </summary>
''' <value>An <see cref="String"/> instance.</value>
''' <remarks>
''' If the encapsulated packet is a TCP or UDP packet, the returned string will consist of the IP address and the port number.
''' If the IP packet does not encapsulate a TCP or UDP packet, the returned string will consist of the IP address.
''' </remarks>
Public ReadOnly Property Source() As String
Get
If m_SourcePort <> -1 Then
Return SourceAddress.ToString() + ":" + m_SourcePort.ToString()
Else
Return SourceAddress.ToString()
End If
End Get
End Property
''' <summary>
''' Gets a string representation of the destination.
''' </summary>
''' <value>An <see cref="String"/> instance.</value>
''' <remarks>
''' If the encapsulated packet is a TCP or UDP packet, the returned string will consist of the IP address and the port number.
''' If the IP packet does not encapsulate a TCP or UDP packet, the returned string will consist of the IP address.
''' </remarks>
Public ReadOnly Property Destination() As String
Get
If m_DestinationPort <> -1 Then
Return DestinationAddress.ToString() + ":" + m_DestinationPort.ToString()
Else
Return DestinationAddress.ToString()
End If
End Get
End Property
''' <summary>
''' Returns a string representation of the Packet
''' </summary>
''' <returns>An instance of the <see cref="String"/> class.</returns>
Public Overrides Function ToString() As String
Return Me.ToString(False)
End Function
''' <summary>
''' Returns a string representation of the Packet
''' </summary>
''' <param name="raw"><b>true</b> if the returned string should ony contain the raw bytes, <b>false</b> if the returned string should also contain a hexadecimal representation.</param>
''' <returns>An instance of the <see cref="String"/> class.</returns>
Public Overloads Function ToString(ByVal raw__1 As Boolean) As String
Dim sb As New StringBuilder(Raw.Length)
If raw__1 Then
For i As Integer = 0 To Raw.Length - 1
If Raw(i) > 31 Then
sb.Append(Chr(Raw(i)))
Else
sb.Append(".")
End If
Next
Else
Dim rawString As String = Me.ToString(True)
For i As Integer = 0 To Raw.Length - 1 Step 16
Dim j As Integer = i
While j < Raw.Length AndAlso j < i + 16
sb.Append(Raw(j).ToString("X2") + " ")
j += 1
End While
If rawString.Length < i + 16 Then
sb.Append(" "c, ((16 - (rawString.Length Mod 16)) Mod 16) * 3)
sb.Append(" " + rawString.Substring(i) + vbCr & vbLf)
Else
sb.Append(" " + rawString.Substring(i, 16) + vbCr & vbLf)
End If
Next
End If
Return sb.ToString()
End Function
End Class
''' <summary>
''' The AllocateAndInitializeSid function allocates and initializes a security identifier (SID) with up to eight subauthorities.
''' </summary>
''' <param name="pIdentifierAuthority">Pointer to a SID_IDENTIFIER_AUTHORITY structure, giving the top-level identifier authority value to set in the SID.</param>
''' <param name="nSubAuthorityCount">Specifies the number of subauthorities to place in the SID. This parameter also identifies how many of the subauthority parameters have meaningful values. This parameter must contain a value from 1 to 8.</param>
''' <param name="dwSubAuthority0">Subauthority value to place in the SID.</param>
''' <param name="dwSubAuthority1">Subauthority value to place in the SID.</param>
''' <param name="dwSubAuthority2">Subauthority value to place in the SID.</param>
''' <param name="dwSubAuthority3">Subauthority value to place in the SID.</param>
''' <param name="dwSubAuthority4">Subauthority value to place in the SID.</param>
''' <param name="dwSubAuthority5">Subauthority value to place in the SID.</param>
''' <param name="dwSubAuthority6">Subauthority value to place in the SID.</param>
''' <param name="dwSubAuthority7">Subauthority value to place in the SID.</param>
''' <param name="pSid">Pointer to a variable that receives the pointer to the allocated and initialized SID structure.</param>
''' <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError.</returns>
<DllImport("advapi32.dll")> _
Private Shared Function AllocateAndInitializeSid(ByVal pIdentifierAuthority As Byte(), ByVal nSubAuthorityCount As Byte, ByVal dwSubAuthority0 As Integer, ByVal dwSubAuthority1 As Integer, ByVal dwSubAuthority2 As Integer, ByVal dwSubAuthority3 As Integer, _
ByVal dwSubAuthority4 As Integer, ByVal dwSubAuthority5 As Integer, ByVal dwSubAuthority6 As Integer, ByVal dwSubAuthority7 As Integer, ByRef pSid As IntPtr) As Integer
End Function
''' <summary>
''' The CheckTokenMembership function determines whether a specified SID is enabled in an access token.
''' </summary>
''' <param name="TokenHandle">Handle to an access token. The handle must have TOKEN_QUERY access to the token. The token must be an impersonation token.</param>
''' <param name="SidToCheck">Pointer to a SID structure. The CheckTokenMembership function checks for the presence of this SID in the user and group SIDs of the access token.</param>
''' <param name="IsMember">Pointer to a variable that receives the results of the check. If the SID is present and has the SE_GROUP_ENABLED attribute, IsMember returns TRUE; otherwise, it returns FALSE.</param>
''' <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError.</returns>
<DllImport("advapi32.dll")> _
Private Shared Function CheckTokenMembership(ByVal TokenHandle As IntPtr, ByVal SidToCheck As IntPtr, ByRef IsMember As Integer) As Integer
End Function
''' <summary>
''' The FreeSid function frees a security identifier (SID) previously allocated by using the AllocateAndInitializeSid function.
''' </summary>
''' <param name="pSid">Pointer to the SID structure to free.</param>
''' <returns>This function does not return a value.</returns>
<DllImport("advapi32.dll")> _
Private Shared Function FreeSid(ByVal pSid As IntPtr) As IntPtr
End Function
' <summary>
' Tests whether the current user is a member of the Administrator's group.
' </summary>
' <returns>Returns TRUE if the user is a member of the Administrator's group, FALSE if not.</returns>
'[DllImport("shell32.dll")]
'private extern static int IsUserAnAdmin();
''' <summary>
''' Represents the method that will handle the NewPacket event.
''' </summary>
''' <param name="pm">The <see cref="PacketMonitor"/> that intercepted the <see cref="Packet"/>.</param>
''' <param name="p">The newly arrived <see cref="Packet"/>.</param>
Public Delegate Sub NewPacketEventHandler(ByVal pm As clsPacketMonitor, ByVal p As clsPacket)
''' <summary>
''' Initializes a new instance of the PacketMonitor class.
''' </summary>
''' <param name="ip">The interface on which to listen for IP packets.</param>
''' <exception cref="NotSupportedException">The operating system does not support intercepting packets.</exception>
Public Sub New(ByVal ip As IPAddress)
' make sure the user runs this program on Windows NT 5.0 or higher
If Environment.OSVersion.Platform <> PlatformID.Win32NT OrElse Environment.OSVersion.Version.Major < 5 Then
Throw New NotSupportedException("This program requires Windows 2000, Windows XP or Windows .NET Server!")
End If
' make sure the user is an Administrator
If Not IsUserAnAdmin() Then
Throw New NotSupportedException("This program can only be run by administrators!")
End If
m_IP = ip
m_Buffer = New Byte(65534) {}
End Sub
''' <summary>
''' Cleans up the unmanaged resources.
''' </summary>
Protected Overrides Sub Finalize()
Try
[Stop]()
Finally
MyBase.Finalize()
End Try
End Sub
''' <summary>
''' Starts listening on the specified interface.
''' </summary>
''' <exception cref="SocketException">An error occurs when trying to intercept IP packets.</exception>
Public Sub Start()
If m_Monitor Is Nothing Then
Try
m_Monitor = New Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP)
m_Monitor.Bind(New IPEndPoint(IP, 0))
m_Monitor.IOControl(SIO_RCVALL, BitConverter.GetBytes(CInt(1)), Nothing)
m_Monitor.BeginReceive(m_Buffer, 0, m_Buffer.Length, SocketFlags.None, New AsyncCallback(AddressOf Me.OnReceive), Nothing)
Catch
m_Monitor = Nothing
Throw New SocketException()
End Try
End If
End Sub
''' <summary>
''' Stops listening on the specified interface.
''' </summary>
Public Sub [Stop]()
If m_Monitor IsNot Nothing Then
m_Monitor.Close()
m_Monitor = Nothing
End If
End Sub
''' <summary>
''' Called when the socket intercepts an IP packet.
''' </summary>
''' <param name="ar">The asynchronous result.</param>
Private Sub OnReceive(ByVal ar As IAsyncResult)
Try
Dim received As Integer = m_Monitor.EndReceive(ar)
Try
If m_Monitor IsNot Nothing Then
Dim packet As Byte() = New Byte(received - 1) {}
Array.Copy(Buffer, 0, packet, 0, received)
OnNewPacket(New clsPacket(packet))
End If
Catch
End Try
' invalid packet; ignore
m_Monitor.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, New AsyncCallback(AddressOf Me.OnReceive), Nothing)
Catch
[Stop]()
End Try
End Sub
''' <summary>
''' The interface used to intercept IP packets.
''' </summary>
''' <value>An <see cref="IPAddress"/> instance.</value>
Public ReadOnly Property IP() As IPAddress
Get
Return m_IP
End Get
End Property
''' <summary>
''' The buffer used to store incoming IP packets.
''' </summary>
''' <value>An array of bytes.</value>
Protected ReadOnly Property Buffer() As Byte()
Get
Return m_Buffer
End Get
End Property
''' <summary>
''' Raises an event that indicates a new packet has arrived.
''' </summary>
''' <param name="p">The arrived <see cref="Packet"/>.</param>
Protected Sub OnNewPacket(ByVal p As clsPacket)
NewPacket.Invoke(Me, p)
End Sub
''' <summary>
''' Holds all the listeners for the NewPacket event.
''' </summary>
Public NewPacket As NewPacketEventHandler = Nothing
' private variables
Private m_Monitor As Socket
Private m_IP As IPAddress
Private m_Buffer As Byte()
Private Const IOC_VENDOR As Integer = &H18000000
Private Const IOC_IN As Integer = -2147483648
'0x80000000; /* copy in parameters */
Private Const SIO_RCVALL As Integer = IOC_IN Or IOC_VENDOR Or 1
Private Const SECURITY_BUILTIN_DOMAIN_RID As Integer = &H20
Private Const DOMAIN_ALIAS_RID_ADMINS As Integer = &H220
''' <summary>
''' Tests whether the current user is a member of the Administrator's group.
''' </summary>
''' <returns>Returns <b>true</b> if the user is a member of the Administrator's group, <b>false</b> if not.</returns>
Private Function IsUserAnAdmin() As Boolean
Dim NtAuthority As Byte() = New Byte(5) {}
NtAuthority(5) = 5
' SECURITY_NT_AUTHORITY
Dim AdministratorsGroup As IntPtr
Dim ret As Integer = AllocateAndInitializeSid(NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, _
0, 0, 0, 0, AdministratorsGroup)
If ret <> 0 Then
If CheckTokenMembership(IntPtr.Zero, AdministratorsGroup, ret) = 0 Then
ret = 0
End If
FreeSid(AdministratorsGroup)
End If
Return (ret <> 0)
End Function
End Class