Posts
22
Comments
75
Trackbacks
0
Using Netbios-NS to get Information about a computer within a LAN

Last time I posted something regarding Converting IP Addresses to Decimal and Looping an IP Address Range The next step is to do something with those remote IP Addresses. The first thing that we can play with is to get some information from a remote host using Netbios Name Service.

Some of the information that we can get using the class below are

  1. Mac Address
  2. Netbios Name (Computer Name)
  3. Netbios Group (Workgroup name, Domain Name)
  4. Netbios Username

Below is the initial helper class I coded

Sample Usage

NBNS nbnsPacket = new NBNS();
NBNSData nbnsData = new NBNSData();
nbnsData = nbnsPacket.SendNBNSPacket("192.168.50.200",137);
MessageBox.Show(nbnsData.NetbiosUser);

Class Definition

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace NetworkLib
{
    // Coded by: Humprey E: Cogay
    //     Date: February 2011
    //      Use: Low Level Netbios Over TCP Packet
    public class NBNSData
    {
        public string MacAddress { get; set; }
        public string NetbiosUser { get; set; }
        public string NetbiosComputer { get; set; }
        public string NetbiosGroup { get; set; }
    }

    public class NBNS
    {

        //Recieves an IP address and any available port to listen on
        public NBNSData SendNBNSPacket(string strIPCur, int intPortNum)
        {
            //IPAddress in
            IPAddress server = IPAddress.Parse(strIPCur);

            //NBNS Data
            NBNSData nbnsData = new NBNSData();

            //Declare MAC Address
            string strMAC = "";
            string strNetbiosComputer = "";
            string strNetbiosGroup = "";
            string strNetbiosUser = "";

            Socket soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            System.Net.IPEndPoint ipEndPT = new System.Net.IPEndPoint(IPAddress.Parse(strIPCur), 137);
            System.Net.EndPoint endPT = (System.Net.EndPoint)ipEndPT;

            System.Net.IPEndPoint inIPEndPT = new System.Net.IPEndPoint(IPAddress.Parse(strIPCur), intPortNum);
            System.Net.EndPoint inEndPT = (System.Net.EndPoint)inIPEndPT;

            soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 50);
            soc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 50);

            //Datagram declaration expected to receive from host
            byte[] dataIn = new byte[4096];


            int intTries = 0;

            bool bolResponded = false;

            do
            {
                soc.SendTo(NBQuery(), endPT);
                try
                {
                    //Get data from host
                    soc.ReceiveFrom(dataIn, ref inEndPT);
                    bolResponded = true;
                }
                catch (SocketException se)
                {
                    intTries++;
                    if (se.ErrorCode == 10060)
                    {
                        //handleTimed out
                    }
                }
            }
            while ((!bolResponded) && intTries < 1);

            if (bolResponded)
            {
                //parse the MAC Address from the data received from host
                strMAC = getMAC(dataIn);
                strNetbiosComputer = getNebiosComputer(dataIn);
                strNetbiosGroup = getNebiosGroup(dataIn);
                strNetbiosUser = getRemoteMachineNameTable(dataIn).Count.ToString();
            }
            else
            {
                strMAC = "Host Unreachable";
            }

            nbnsData.MacAddress = strMAC;
            nbnsData.NetbiosComputer = strNetbiosComputer;
            nbnsData.NetbiosGroup = strNetbiosGroup;
            nbnsData.NetbiosUser = strNetbiosUser;
            return nbnsData;
        }

        //NBNS Request Packet Contents
        private byte[] NBQuery()
        {

            byte[] bdata = new byte[50]{ 0x80, 0xff, 0x00, 0x00, 0x00,
             0x01, 0x00, 0x00, 0x00, 0x00,
             0x00, 0x00, 0x20, 0x43, 0x4B,
             0x41, 0x41, 0x41, 0x41, 0x41,
             0x41, 0x41, 0x41, 0x41, 0x41,
             0x41, 0x41, 0x41, 0x41, 0x41,
             0x41, 0x41, 0x41, 0x41, 0x41,
             0x41, 0x41, 0x41, 0x41, 0x41,
             0x41, 0x41, 0x41, 0x41, 0x41,
             0x00, 0x00, 0x21, 0x00, 0x01};

            return bdata;
        }

       
        //Parse the Packet sent by the host and get the value @byt 56
        private string getNebiosComputer(byte[] dtResponse)
        {
            string strNetbiosComputer = "";

            int intStart = (int)dtResponse[56];

            int intOffset = 57;
            for (int x = 0; x < 15; x++)
            {           
                strNetbiosComputer += Convert.ToChar(dtResponse[intOffset + x]);
            }
            return strNetbiosComputer;
        }

        private List<string> getRemoteMachineNameTable(byte[] dtResponse)
        {
            Int32 strNoOfRemoteMachineName = 0;
            String CurrentName = "";
            List<string> RemoteMachineNames = new List<string>();

            //Get no of names in the Response Packet (position 56 of response Packet)
            strNoOfRemoteMachineName = Convert.ToInt32(dtResponse[56]);

            for (int remoteNameCounter = 0; remoteNameCounter <= strNoOfRemoteMachineName - 1; remoteNameCounter++)
            {
                CurrentName = "";
                //Get first 15 characters after position 56
                for (int x = 1; x <= 15; x++)
                {
                    //18 characters per name,
                    byte newByte = dtResponse[x + (56 + remoteNameCounter * 18)];

                    //checked if printable chars  0x21 to 0x7E
                    //0x20 = space
                    //0x7F = Delete
                    //TRAP GROUP NAMES - Must have a 1E NetBios Suffix                                       
                    if (newByte > 0x19 && newByte < 0x7E)
                        CurrentName += Convert.ToChar(newByte);
                    else
                        CurrentName += " ";
                }

                //HEC Notes
                //NAME_FLAGS = Bytes 17 and 18 Definition
                //Taken from http://www.faqs.org/rfcs/rfc1002.html
                //
                //RESERVED     7-15   Reserved for future use.  Must be zero (0).
                //PRM             6   Permanent Name Flag.  If one (1) then entry
                //                    is for the permanent node name.  Flag is zero
                //                    (0) for all other names.
                //ACT             5   Active Name Flag.  All entries have this flag
                //                    set to one (1).
                //CNF             4   Conflict Flag.  If one (1) then name on this
                //                    node is in conflict.
                //DRG             3   Deregister Flag.  If one (1) then this name
                //                    is in the process of being deleted.
                //ONT           1,2   Owner Node Type:
                //                       00 = B node
                //                       01 = P node
                //                       10 = M node
                //                       11 = Reserved for future use
                //G               0   Group Name Flag.
                //                    If one (1) then the name is a GROUP NetBIOS
                //                    name.
                //                    If zero (0) then it is a UNIQUE NetBIOS name.

                RemoteMachineNames.Add(CurrentName + String.Format("{0:X2}", dtResponse[16 + (56 + remoteNameCounter * 18)]) + Convert.ToString(dtResponse[17 + (56 + remoteNameCounter * 18)], 2).PadLeft(8, '0'));
            }

            return RemoteMachineNames;
        }

        private string getNebiosGroup(byte[] dtResponse)
        {
            String netbiosGroupName = "";
            foreach (string tmpString in getRemoteMachineNameTable(dtResponse))
            {
                if (tmpString.Substring(15, 2) == "1E" || tmpString.Substring(17, 1) == "1")
                {
                    netbiosGroupName = tmpString.Substring(0, 15);
                    break;
                }

            }

            return netbiosGroupName;
        }

        private string getMAC(byte[] dtResponse)
        {
            string strMac = "";
            //intStart reads the value @ byte 56 which contains the
            //no of names in the Response Packet
            int intStart = (int)dtResponse[56];

            //1 name contains 16 bytes followed by 2 bytes name flag = 18 Bytes
            int intOffset = 56 + intStart * 18 + 1;

            for (int x = 0; x < 6; x++)
            {
                strMac += String.Format("{0:X2}", dtResponse[intOffset + x]) + ":";
            }

            strMac = strMac.Remove(strMac.Length - 1, 1);
            return strMac;
        }

    }
}

 

 

posted on Thursday, April 7, 2011 12:45 PM Print
Comments
Gravatar
# re: Using Netbios-NS to get Information about a remote computer
Shiv
4/12/2011 7:49 PM
Thanks a lot sir. very useful.

Post Comment

Title *
Name *
Email
Comment *  
Verification
Tag Cloud