Click here to Skip to main content
15,885,141 members
Articles / Desktop Programming / Windows Forms

NDIS MONITOR .NET 32-bit v1.00

Rate me:
Please Sign up or sign in to vote.
4.81/5 (36 votes)
27 Apr 20078 min read 176K   9.9K   90  
NDIS Monitor allows to catch and log the exchange of packet data between NDIS miniport drivers and network protocol modules that occurs in kernel space.
using System;
using System.Text;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using System.Runtime.InteropServices;

namespace NdisMonitor
{
	/// <summary>
	/// Summary description for HexViewer.
	/// </summary>
	public class dlgPacketViewer : System.Windows.Forms.Form, IMessageFilter
	{
		private System.Windows.Forms.RichTextBox ctrlHexView;
		private System.Windows.Forms.ListBox ctrlDetails;
		private System.Windows.Forms.ToolBar ctrlToolbar;
		private System.Windows.Forms.Splitter ctrlSplitter;
		private System.Windows.Forms.ImageList toolbarImgs;
		private System.Windows.Forms.ToolBarButton ctrlUpBtn;
		private System.Windows.Forms.ToolBarButton ctrlDownBtn;
		private System.ComponentModel.IContainer components;

		public delegate RawPacket GetPrevOrNextPacketDelegate( int dir );

		public dlgPacketViewer( RawPacket rp, GetPrevOrNextPacketDelegate pnp )
		{
			this._rp = rp;
			this._pnp = pnp;

			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		//
		// Data.
		//

		RawPacket						_rp = null;
		GetPrevOrNextPacketDelegate		_pnp = null;

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(dlgPacketViewer));
			this.ctrlHexView = new System.Windows.Forms.RichTextBox();
			this.ctrlDetails = new System.Windows.Forms.ListBox();
			this.ctrlToolbar = new System.Windows.Forms.ToolBar();
			this.ctrlUpBtn = new System.Windows.Forms.ToolBarButton();
			this.ctrlDownBtn = new System.Windows.Forms.ToolBarButton();
			this.toolbarImgs = new System.Windows.Forms.ImageList(this.components);
			this.ctrlSplitter = new System.Windows.Forms.Splitter();
			this.SuspendLayout();
			// 
			// ctrlHexView
			// 
			this.ctrlHexView.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(240)), ((System.Byte)(240)), ((System.Byte)(210)));
			this.ctrlHexView.Dock = System.Windows.Forms.DockStyle.Top;
			this.ctrlHexView.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.ctrlHexView.Location = new System.Drawing.Point(0, 28);
			this.ctrlHexView.Name = "ctrlHexView";
			this.ctrlHexView.ReadOnly = true;
			this.ctrlHexView.ShowSelectionMargin = true;
			this.ctrlHexView.Size = new System.Drawing.Size(568, 150);
			this.ctrlHexView.TabIndex = 6;
			this.ctrlHexView.Text = "";
			this.ctrlHexView.WordWrap = false;
			// 
			// ctrlDetails
			// 
			this.ctrlDetails.Dock = System.Windows.Forms.DockStyle.Fill;
			this.ctrlDetails.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.ctrlDetails.IntegralHeight = false;
			this.ctrlDetails.ItemHeight = 14;
			this.ctrlDetails.Location = new System.Drawing.Point(0, 181);
			this.ctrlDetails.Name = "ctrlDetails";
			this.ctrlDetails.Size = new System.Drawing.Size(568, 208);
			this.ctrlDetails.TabIndex = 0;
			this.ctrlDetails.SelectedIndexChanged += new System.EventHandler(this.ctrlDetails_SelectedIndexChanged);
			// 
			// ctrlToolbar
			// 
			this.ctrlToolbar.Appearance = System.Windows.Forms.ToolBarAppearance.Flat;
			this.ctrlToolbar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] {
																						   this.ctrlUpBtn,
																						   this.ctrlDownBtn});
			this.ctrlToolbar.ButtonSize = new System.Drawing.Size(16, 16);
			this.ctrlToolbar.DropDownArrows = true;
			this.ctrlToolbar.ImageList = this.toolbarImgs;
			this.ctrlToolbar.Location = new System.Drawing.Point(0, 0);
			this.ctrlToolbar.Name = "ctrlToolbar";
			this.ctrlToolbar.ShowToolTips = true;
			this.ctrlToolbar.Size = new System.Drawing.Size(568, 28);
			this.ctrlToolbar.TabIndex = 2;
			this.ctrlToolbar.ButtonClick += new System.Windows.Forms.ToolBarButtonClickEventHandler(this.ctrlToolbar_ButtonClick);
			// 
			// ctrlUpBtn
			// 
			this.ctrlUpBtn.ImageIndex = 0;
			this.ctrlUpBtn.ToolTipText = "Go to the previous packet (F3).";
			// 
			// ctrlDownBtn
			// 
			this.ctrlDownBtn.ImageIndex = 1;
			this.ctrlDownBtn.ToolTipText = "Go to the next packet (F4).";
			// 
			// toolbarImgs
			// 
			this.toolbarImgs.ImageSize = new System.Drawing.Size(16, 16);
			this.toolbarImgs.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("toolbarImgs.ImageStream")));
			this.toolbarImgs.TransparentColor = System.Drawing.Color.Transparent;
			// 
			// ctrlSplitter
			// 
			this.ctrlSplitter.Dock = System.Windows.Forms.DockStyle.Top;
			this.ctrlSplitter.Location = new System.Drawing.Point(0, 178);
			this.ctrlSplitter.Name = "ctrlSplitter";
			this.ctrlSplitter.Size = new System.Drawing.Size(568, 3);
			this.ctrlSplitter.TabIndex = 3;
			this.ctrlSplitter.TabStop = false;
			// 
			// dlgPacketViewer
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(568, 389);
			this.Controls.Add(this.ctrlDetails);
			this.Controls.Add(this.ctrlSplitter);
			this.Controls.Add(this.ctrlHexView);
			this.Controls.Add(this.ctrlToolbar);
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.Name = "dlgPacketViewer";
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
			this.Text = "Packet Viewer";
			this.Load += new System.EventHandler(this.dlgPacketViewer_Load);
			this.Closed += new System.EventHandler(this.dlgPacketViewer_Closed);
			this.ResumeLayout(false);

		}
		#endregion

		internal class DetailsElement
		{
			// construction.
			public DetailsElement( Packet_Part part, PartInfoAttribute partInfo, FieldInfoAttribute fieldInfo, int baseOffset, FieldInfo field )
			{
				// remember the params.
				this._part = part;
				this._partInfo = partInfo;
				this._fieldInfo = fieldInfo;
				this._baseOffset = baseOffset;
				this._field = field;

				// get the data to display.
				if ( _field != null && _fieldInfo != null )
				{
					// get value.
					object		val = _field.GetValue( _part );

					// get the size of the field.
					if ( _fieldInfo.Size != -1 )
					{
						this._fieldSize = _fieldInfo.Size;
					}
					else if ( _fieldInfo.FieldSizeFn != null )
					{
						try
						{
							this._fieldSize = (int) _part.GetType().GetMethod( _fieldInfo.FieldSizeFn ).Invoke( _part, null );
						}
						catch
						{
							this._fieldSize = 0;
						}
					}
					else
					{
						try
						{
							if ( val.GetType() == typeof( bool ) )
								this._fieldSize = 1;
							else
								this._fieldSize = Marshal.SizeOf( val );
						}
						catch
						{
							if ( val.GetType() == typeof( byte[] ) )
								this._fieldSize = ( (byte[]) val ).Length;
							else
								this._fieldSize = 0;
						}
					}

					// get the value as a string.
					if ( _fieldInfo.PrintFn != null )
					{
						try
						{
							this._valueAsString = (string) _part.GetType().GetMethod( _fieldInfo.PrintFn ).Invoke( _part, null );
						}
						catch
						{
							this._valueAsString = null;
						}
					}
					else if ( val.GetType() == typeof( byte ) )
						this._valueAsString = "0x" + ((byte) val).ToString ( "X2" );
					else if ( val.GetType() == typeof( ushort ) )
						this._valueAsString = "0x" + ((ushort) val).ToString ( "X4" );
					else if ( val.GetType() == typeof( uint ) )
						this._valueAsString = "0x" + ((uint) val).ToString ( "X8" );
					else if ( val.GetType() == typeof( byte[] ) )
					{
						byte[]		arr = (byte[]) val;
						string		s = "";
						for( int i=0; i<arr.Length; i ++ )
							s += arr[ i ].ToString( "X2" ) + ( i==arr.Length-1 ? "" : "," );
						this._valueAsString = s;
					}
					else
						this._valueAsString = val.ToString ();
				}
			}

			// data.
			public Packet_Part				_part = null;
			public PartInfoAttribute		_partInfo = null;
			public FieldInfoAttribute		_fieldInfo = null;
			public int						_baseOffset = 0;
			public FieldInfo				_field = null;
			public int						_fieldSize = 0;
			public string					_valueAsString = null;

			// methods.
			public override string ToString()
			{
				string		retval = "";

				if ( _partInfo != null && _fieldInfo == null )
				{
					// return the name of the packet part.
					retval = _partInfo.Name;
				}
				else if ( _fieldInfo != null )
				{
					// return name + value.
					retval = "\t" + _fieldInfo.Name + " = ";
					if ( _fieldSize == 0 || _valueAsString == null || _valueAsString.Length == 0 )
						retval += "???";
					else
						retval += _valueAsString;
				}

				return retval;
			}
		}

		private void dlgPacketViewer_Load(object sender, System.EventArgs e)
		{
			Application.AddMessageFilter( this );

			// load rp data.
			LoadRp ();
		}

		protected void LoadRp ()
		{
			ctrlDetails.Items.Clear ();

			// set the text in the rich edit box.

			StringBuilder	text = new StringBuilder();
			int				index = 0;
			string			ascii = "";

			foreach( byte b in _rp._data )
			{
				// print offset.

				if ( ( index % 16 ) == 0 )
				{
					if ( index != 0 )
					{
						// print ascii chrs.
						text.Append( "  " + ascii + " " );

						// CR.
						text.Append( "\r\n" );
					}
					text.Append( index.ToString( "X8" ) + "  " );

					ascii = "";
				}

				// print byte.

				text.Append( b.ToString( "X2" ) );

				if ( ( (index+1) % 16 ) != 0 && index != _rp._data.Length - 1 )
				{
					if ( ( (index+1) % 8 ) == 0 )
						text.Append( " " );
					text.Append( " " );
				}

				if ( b <= 0x20 )
					ascii += ".";
				else
					ascii += (char) b;

				// increment index.

				index ++;
			}

			if ( ascii.Length != 0 )
			{
				int			rem = 16 - ( index % 16 );
				int			spaces = rem * 3;
				if ( rem >= 8 )
					spaces ++;

				for( int i=0; i<spaces; i ++ )
					text.Append( ' ' );
				text.Append( "  " + ascii + " " );
				for( int j=0; j<rem; j ++ )
					text.Append( ' ' );
			}

			ctrlHexView.Text = text.ToString ();

			// populate the Details View.

			Packet_Part[]		parts = _rp.GetParts ();

			if ( parts == null )
			{
				ctrlDetails.Items.Add( ">> RawPacket provides no meaningful information <<" );
			}
			else
			{
				foreach( Packet_Part part in parts )
				{
					Type		t = part.GetType ();
					ArrayList	list = new ArrayList ();

					int			baseOffset = RawPacket.GetTotalLength( parts, part, false );

					// make the list of types.

					Type		baseType = t;
					while( baseType != null )
					{
						list.Add( baseType );
						baseType = baseType.BaseType;
					}

					// iterate starting from the base type going on.

					for( int i=list.Count - 1; i >= 0; i -- )
					{
						Type			thisType = (Type) list[ i ];
						Attribute[]		vAttrs = Attribute.GetCustomAttributes( thisType, typeof( PartInfoAttribute ) );
						if ( vAttrs != null && vAttrs.Length == 1 )
						{
							PartInfoAttribute		partInfo = (PartInfoAttribute) vAttrs[ 0 ];

							// add header string in list box.

							ctrlDetails.Items.Add( new DetailsElement( part, partInfo, null, baseOffset, null ) );

							// iterate through the fields.

							FieldInfo[]		fields = thisType.GetFields ();
							foreach( FieldInfo field in fields )
							{
								if ( field.DeclaringType == thisType )
								{
									Attribute[]		fieldInfo = Attribute.GetCustomAttributes( field, typeof( FieldInfoAttribute ) );
									if ( fieldInfo != null && fieldInfo.Length == 1 )
									{
										FieldInfoAttribute		info = (FieldInfoAttribute) fieldInfo[ 0 ];

										// add field string in list box.

										ctrlDetails.Items.Add( new DetailsElement( part, partInfo, info, baseOffset, field ) );
									}
								}
							}
						}
					}
				}
			}

			// return.

			return;
		}

		protected void SetSelectionStart( int selStartX, int selStartY )
		{
			ctrlHexView.SelectionStart =
				( selStartY * 78 ) + selStartX;
		}

		protected void SetSelectionLength( int len )
		{
			ctrlHexView.SelectionLength = len;
		}

		protected void HighlightSelText( Color clrFore, Color clrBack )
		{
			RichTextBox_Interop.CHARFORMAT2		format = new RichTextBox_Interop.CHARFORMAT2 ();
			format.cbSize = Marshal.SizeOf( format );
			format.dwMask = RichTextBox_Interop.CFM_BACKCOLOR | RichTextBox_Interop.CFM_COLOR;
			format.crTextColor = ColorTranslator.ToOle( clrFore );
			format.crBackColor = ColorTranslator.ToOle( clrBack );

			RichTextBox_Interop.CHARFORMAT2_Funcs.SendMessageA(
				ctrlHexView.Handle,
				RichTextBox_Interop.EM_SETCHARFORMAT,
				RichTextBox_Interop.SCF_SELECTION,
				ref format );
		}

		protected void HighlightText( int selStartX, int selStartY, int len, Color clrFore, Color clrBack )
		{
			SetSelectionStart( selStartX, selStartY );
			SetSelectionLength( len );
			HighlightSelText( clrFore, clrBack );
		}

		protected void HighlightBytes( int offset, int size, Color clrFore, Color clrBack )
		{
			if ( size == 0 )
				return;

			// highlight in the rich text box...

			int					byteStartX = offset % 16;
			int					selStartY = offset / 16;
			int					selStartX = 10 + byteStartX * 3;
			if ( byteStartX >= 8 )
				selStartX ++;

			int					offsetEnd = offset + size - 1;
			int					byteEndX = offsetEnd % 16;
			int					selEndY = offsetEnd / 16;
			int					selEndX = 10 + byteEndX * 3;
			if ( byteEndX >= 8 )
				selEndX ++;

			int					len;
			if ( selStartY == selEndY )
				len = selEndX - selStartX + 2;
			else
				len = 58 - selStartX;

			HighlightText( selStartX, selStartY, len, clrFore, clrBack );
			if ( selStartY != selEndY )
			{
				for( int i=selStartY+1; i<=selEndY-1; i ++ )
					HighlightText( 10, i, 48, clrFore, clrBack );
				HighlightText( 10, selEndY, selEndX - 8, clrFore, clrBack );
			}
		}

		private void ctrlDetails_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			int			selIndex = ctrlDetails.SelectedIndex;
			if ( selIndex != -1 )
			{
				DetailsElement		sel = (DetailsElement) ctrlDetails.Items[ selIndex ];

				// start editing the rich text box...

				RichTextBox_Interop.LockWindowUpdate( ctrlHexView.Handle );
				try
				{
					// unhighlight the text.

					ctrlHexView.SelectAll ();
					HighlightSelText( ctrlHexView.ForeColor, ctrlHexView.BackColor );

					// calculate the offset and size vars.

					int					offset = sel._baseOffset;
					int					size = sel._part._length;
					HighlightBytes( offset, size, Color.White, Color.Red );

					if ( sel._fieldInfo != null )
						HighlightBytes( offset + sel._fieldInfo.Offset, sel._fieldSize, Color.White, Color.Black );

					// unselect text.

					SetSelectionLength( 0 );
				}
				finally
				{
					RichTextBox_Interop.LockWindowUpdate( IntPtr.Zero );
				}
			}

			// return.

			return;
		}

		protected void PrevPacket ()
		{
			if ( _pnp != null )
			{
				// get the previous packet.
				RawPacket			rp = _pnp( 0 );
				if ( rp != null )
				{
					_rp = rp;
					LoadRp ();
				}
			}
		}

		protected void NextPacket ()
		{
			if ( _pnp != null )
			{
				// get the next packet.
				RawPacket			rp = _pnp( 1 );
				if ( rp != null )
				{
					_rp = rp;
					LoadRp ();
				}
			}
		}

		private void ctrlToolbar_ButtonClick(object sender, System.Windows.Forms.ToolBarButtonClickEventArgs e)
		{
			if ( e.Button == ctrlUpBtn )
				PrevPacket ();
			else if ( e.Button == ctrlDownBtn )
				NextPacket ();
		}

		#region IMessageFilter Members

		public bool PreFilterMessage(ref Message m)
		{
			// which msg ?
			switch( m.Msg )
			{
				case /*WM_KEYDOWN*/ 0x0100:
					if ( m.WParam == new IntPtr( /*VK_F3*/ 0x72 ) )
					{
						PrevPacket ();
						return true;
					}
					else if ( m.WParam == new IntPtr( /*VK_F4*/ 0x73 ) )
					{
						NextPacket ();
						return true;
					}
					break;
			}

			// return.
			return false;
		}

		#endregion

		private void dlgPacketViewer_Closed(object sender, System.EventArgs e)
		{
			Application.RemoveMessageFilter( this );
		}
	}

	internal class RichTextBox_Interop
	{
		//
		// Structures.
		//

		[ StructLayout( LayoutKind.Sequential ) ]
		internal struct CHARFORMAT2
		{
			public Int32		cbSize;
			public Int32		dwMask;
			public Int32		dwEffects;
			public Int32		yHeight;
			public Int32		yOffset;
			public Int32		crTextColor;
			public Byte			bCharSet;
			public Byte			bPitchAndFamily;
			[ MarshalAs( UnmanagedType.ByValTStr, SizeConst = 32 ) ]
			public String		szFaceName;
			public Int16		wWeight;
			public Int16		sSpacing;
			public Int32		crBackColor;
			public Int32		lcid;
			public Int32		dwReserved;
			public Int16		sStyle;
			public Int16		wKerning;
			public Byte			bUnderlineType;
			public Byte			bAnimation;
			public Byte			bRevAuthor;
			public Byte			bReserved1;
		}

		//
		// Constants.
		//

		internal const Int32		CFM_COLOR = 0x40000000;
		internal const Int32		CFM_BACKCOLOR = 0x4000000;
		internal const Int32		EM_SETCHARFORMAT = 0x444;
		internal const Int32		SCF_SELECTION = 0x1;

		//
		// Functions.
		//

		[DllImport("user32.dll")]
		internal static extern bool LockWindowUpdate( IntPtr hWndLock );

		internal class CHARFORMAT2_Funcs // this will simplify the whole marshal thing...
		{
			[ DllImport( "user32.dll" ) ]
			internal static extern IntPtr SendMessageA( IntPtr hWnd, uint Msg, /*UIntPtr*/ UInt32 wParam, /*IntPtr*/ ref CHARFORMAT2 lParam );
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Italy Italy
Vito is a former videogame programmer. Now, Vito is the founder and CEO of VPC Technologies, a company that specializes in online services. VPC Technologies also provides consulting, developing and training services to several italian companies and government agencies in the field of kernel, component, enterprise and tridimensional software, for the Microsoft Windows platform.

Vito has attended as a speaker several italian conferences and events on development and security, such as the Microsoft Security Roadshow 2006.

Vito is the man behind GoToTerminal, a secure, reliable and innovative web technology to control remote Microsoft Windows, Telnet and VNC servers over the internet. He is also the author of BugChecker, an independent research project to create the only clone of SoftICE to date, NDIS Monitor, MapGen and Image Downloader.

For more information, you can visit Vito Plantamura's technical website at www.VitoPlantamura.com.

Comments and Discussions