65.9K
CodeProject 正在变化。 阅读更多。
Home

网络嗅探器和分析器程序 - 第一部分

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2022 年 10 月 20 日

CPOL

5分钟阅读

viewsIcon

11821

downloadIcon

1104

使用 C# .NET 6.0 Windows Form (Sharppcap, PacketDotNet) 编写的网络嗅探器和分析程序

引言

在本文中,我将介绍我的程序(网络嗅探器和分析器),并通过逐步解释代码来向您展示程序的机制。

注意:要理解本文,您应该具备网络基础知识和高级 C# 知识。

注意:为了全面解释该程序,我将把文章分为几个部分。
每个部分将包含对程序中使用的函数的完整解释。在文章的每个部分,我都会单独上传一部分程序。在文章的最后一部分,我将上传程序的最终版本,当然,这将在解释背景和如何使用程序之后。

文章的顺序如下:

  1. 基于子网掩码的 IP 地址分析
  2. 扫描网络以获取所有可用设备
  3. ARP 欺骗
  4. 监控特定设备浏览的网站

我们开始吧!

第一部分:基于子网掩码的 IP 地址分析

我们将首先获取计算机上所有可用的 IP 地址,然后根据 IP 地址的类别确定适合该 IP 地址的子网掩码。我们还将提取该 IP 地址的 Internet ID、可用的主机数、可用的网络 ID 数,以及该网络中的第一个 IP 地址和最后一个 IP 地址。首先,我们将定义给定 IP 地址的 IP 类别。

通常,要确定 IP 类别,我们需要查看 IP 地址中的第一个数字,并分析它所属的范围。 IP 地址按类别的顺序如下表所示

Range 子网掩码
A 1-126 \8
B 128-191 \16
C 192-223 \24
D 224-239 _
E 240-255 _

这可以通过以下代码完成

public enum IPClass { A, B, C, D, E, notDetected }

IPClass getIPClass(string IP)
{
    if (!string.IsNullOrEmpty(IP) && IP.Split('.').Length == 4 && 
        !string.IsNullOrEmpty(IP.Split('.').Last()))
    {
        string ipclassstr = IP.Split('.').First();
        int ipclasssnum = int.Parse(ipclassstr);
        if (0 <= ipclasssnum && ipclasssnum <= 126)
        {
            return IPClass.A;
        }
        if (128 <= ipclasssnum && ipclasssnum <= 191)
        {
            return IPClass.B;
        }
        if (192 <= ipclasssnum && ipclasssnum <= 223)
        {
            return IPClass.C;
        }
        if (224 <= ipclasssnum && ipclasssnum <= 239)
        {
            return IPClass.D;
        }
        if (240 <= ipclasssnum && ipclasssnum <= 255)
        {
            return IPClass.E;
        }
    }
    else return IPClass.notDetected;
    return IPClass.notDetected;
}

以及子网掩码

int getSubnetMaskBitsCount(string ip)
    {
        IPClass iPClass = getIPClass(ip);

        if (iPClass == IPClass.A)
            return 8;
        if (iPClass == IPClass.B)
            return 16;
        if (iPClass == IPClass.C)
            return 24;
        if (iPClass == IPClass.D)
            return 31;
        if (iPClass == IPClass.E)
            return 32;

        return -1;
    }

在下一步,我们将提取给定 IP 地址的网络 ID、可用主机数、可用网络 ID 数,以及该网络中的第一个 IP 地址和最后一个 IP 地址,这是基于当前子网掩码及其位数来灵活动态完成的。

从给定的 IP 地址提取网络 ID

在找到默认掩码值后,我们将与给定的 IP 地址进行 AND 操作,以获取网络 IP 地址。
我们将以“192.168.178.112”这个 IP 地址为例。
从 IP 地址的第一个数字可以清楚地看出,它属于 C 类,这意味着子网掩码是 \24 255.255 .255 .0
现在我们将 IP 地址及其子网掩码转换为二进制,并通过 AND 操作计算网络 ID。

     11000000.10101000.10110010.01110000       (192.168.178.112)
            &                                                                 
     11111111.11111111.11111111.00000000       (255.255 .255 .0)    

            ----------------------------------------------      

     11000000.10101000.10110010.00000000       (192.168.178.0)       

这可以通过以下代码完成

public string getNetID(string ipadresse, string subnetmask)
  {
      StringBuilder sb = new StringBuilder();

      string[] subMaskValues = subnetmask.Split('.');

      string[] subIpValues = ipadresse.Split('.');

      for (int i = 0; i < subMaskValues.Length; i++)
      {
          if (i == subMaskValues.Length - 1)
              sb.Append((int.Parse(subMaskValues[i]) & 
                         int.Parse(subIpValues[i])).ToString());
          else
          {
              int maskvalue = int.Parse(subMaskValues[i]);
              int ipvalue = int.Parse(subIpValues[i]);
              string str = ((maskvalue & ipvalue).ToString());
              str += ".";
              sb.Append(str);
          }
      }
      return sb.ToString();
  }

获取可用主机数

地址总数

我们可以使用以下公式计算子网中的总地址数

TNOA( Total number of addresses) = (2^(32 - Current Subnetmask Bits Count))

最大主机数

网络地址和广播地址不能分配给网络上的主机。因此,可以分配给主机的可用地址数是总地址数减去两个 = (2^(32 - 当前子网掩码位数))-2。

这可以通过以下代码完成

int getHostcount(int Current_Subnetmask_Bits_Count)
{
    double resultbits = Math.Max(Math.Pow(2, 
                        (32 - (Current_Subnetmask_Bits_Count))) - 2, 0);

    return (int)resultbits;
}

获取可用网络 ID 数

我们可以使用以下公式计算子网中的网络 ID 数

(2^(IP CLass Standart Subnetmask Bits Count - Current Subnetmask Bits Count))

这可以通过以下代码完成

     int getNetcount(int IP_CLass_Standart_Subnetmask_Bits_Count, 
                     int Current_Subnetmask_Bits_Count)
        {
            double resultbits = Math.Max(
                                Math.Pow(
                                     2, Current_Subnetmask_Bits_Count -
                                     IP_CLass_Standart_Subnetmask_Bits_Count),
                                     0);

            return (int)resultbits;
        }

提取子网中的第一个 IP 地址

首先,我们需要定义四个变量

  • A. 给定 IP 类别标准子网掩码位数
  • B. 给定或当前子网掩码位数
  • C. 主机部分长度 = 32 - B
  • D. 网络部分 = B - A

步骤 1:从给定的子网掩码中获取主机部分。

步骤 2:将主机部分的最后一位更改为 1。

步骤 3:如果 D>0,则从子网掩码中获取网络部分,然后对提取的网络部分和 IP 地址中的相应位数应用 And 操作。

步骤 4:将主机部分和网络部分从二进制转换为整数。

步骤 5:替换给定 IP 地址中的主机部分。

示例:地址 192.168.178.112,我们取子网掩码 255.255.255.128 作为示例。
IP 地址是 192.168.178.112 => IP 类别是 C => 标准子网掩码是 \24 255.255.255.0

步骤 1:将示例中给定的子网掩码转换为二进制,以从中获取主机部分。

                 255  .   255  .   255  . 128
              11111111.11111111.11111111.10000000
             the Subnet Part(First One) <_ ---------->host part(just the Zeros)

步骤 2:将主机部分的最后一位更改为 1 => 0000001

步骤 3:如果 D>0,则从子网掩码中获取网络部分,然后对提取的网络部分和 IP 地址中的相应位数应用 And 操作 => 网络部分位于索引:25 = 1

                192  .   168  .  178   . 112 
             11000000.10101000.10110010.01110000 
                                        ->the equivalent Bit(the first one(0)) 
so 1 & 0 = 0 => now we add the Host Part 0000001 =>00000001

步骤 4:将主机部分和网络部分从二进制转换为整数 => 00000001 = 1

步骤 5:替换给定 IP 地址中的主机部分 => 192.168.178.1

这可以通过以下代码完成

 public string getFirstIpAdresse(string ipadresse, 
        int standard_subnet_mask_bits_count, int current_subnet_mask_bits_count, 
        string current_subnet_mask_bits)
        {

            int hostlength = 32 - current_subnet_mask_bits_count;

            int subnet_length = current_subnet_mask_bits_count - 
                                standard_subnet_mask_bits_count;

            string hostpart = current_subnet_mask_bits.Substring
                              (current_subnet_mask_bits_count, hostlength);

            string ip_bits = ip_to_bit_string(ipadresse);

            StringBuilder stringBuilder = new StringBuilder();

            for (int i = 0; i < hostpart.Length; i++)
            {
                if (i == hostpart.Length - 1) stringBuilder.Append("1");
                else stringBuilder.Append("0");
            }
            string net_id_plus_host = stringBuilder.ToString();

            if (subnet_length > 0)
            {

                string subnet_part = current_subnet_mask_bits.Substring
                              (standard_subnet_mask_bits_count, subnet_length);

                string to_operat_ip_bits = ip_bits.Substring
                       (standard_subnet_mask_bits_count, subnet_length);

             //   var And_operation_result = Convert.ToByte(to_operat_ip_bits, 2) & 
             //   Convert.ToByte(subnet_part, 2);

                StringBuilder sb = new StringBuilder();

                for (int i = 0; i < subnet_part.Length; i++)
                    sb.Append(Convert.ToUInt64(to_operat_ip_bits[i].ToString(), 2) 
                              & Convert.ToUInt64(subnet_part[i].ToString(), 2));

                for (int i = 0; i < hostpart.Length; i++)
                    if (i == hostpart.Length - 1) sb.Append("1");
                    else sb.Append("0");

                net_id_plus_host = sb.ToString();
            }

            //*****************
            int IPPartsLength = net_id_plus_host.Length / 8;

            string[] ipnewparts = new string[IPPartsLength];

            int j = 0;

            for (int i = 0; i < ipnewparts.Length; i++)
            {
                ipnewparts[i] = net_id_plus_host.Substring(j, 8);
                j = j + 8;
            }

            string[] ipparts = ipadresse.Split('.');

            j = ipparts.Length - 1;
            for (int i = ipnewparts.Length - 1; i >= 0; i--)
            {
                ipparts[j] = Convert.ToInt64(ipnewparts[i], 2).ToString();
                j--;
            }
            StringBuilder stringBuilder1 = new StringBuilder();
            for (int i = 0; i < ipparts.Length; i++)
                if (i == ipparts.Length - 1) stringBuilder1.Append(ipparts[i]);
                else stringBuilder1.Append(ipparts[i] + ".");

            return stringBuilder1.ToString();            

            //*****************
        }

提取子网中的最后一个 IP 地址

为了提取最后一个 IP 地址,我们遵循与“第一个 IP 地址”相同的步骤,但我们修改第二步,将所有主机位数更改为 1,除了最后一位保持为 0,以及代码

 public string getLastIpAdresse(string ipadresse, 
 int standard_subnet_mask_bits_count, int current_subnet_mask_bits_count, 
 string current_subnet_mask_bits)
        {

            int hostlength = 32 - current_subnet_mask_bits_count;

            int subnet_length = current_subnet_mask_bits_count - 
                                standard_subnet_mask_bits_count;

            string hostpart = current_subnet_mask_bits.Substring
                              (current_subnet_mask_bits_count, hostlength);

            string ip_bits = ip_to_bit_string(ipadresse);

            StringBuilder stringBuilder = new StringBuilder();

            for (int i = 0; i < hostpart.Length; i++)
            {
                if (i == hostpart.Length - 1) stringBuilder.Append("0");
                else stringBuilder.Append("1");
            }
            string net_id_plus_host = stringBuilder.ToString();

            if (subnet_length > 0)
            {

                //   string net_id_part = current_subnet_mask_bits.Substring
                //  (standard_subnet_mask_bits_count, net_id_length).PadRight
                //  (net_id_length + hostlength, '0');
                string subnet_part = current_subnet_mask_bits.Substring
                                     (standard_subnet_mask_bits_count, subnet_length);

                string to_operat_ip_bits = ip_bits.Substring
                       (standard_subnet_mask_bits_count, subnet_length);

              //  var And_operation_result = Convert.ToByte(to_operat_ip_bits, 2) 
              //  & Convert.ToByte(subnet_part, 2);

                StringBuilder sb = new StringBuilder();

                for (int i = 0; i < subnet_part.Length; i++)
                    sb.Append(Convert.ToUInt64(to_operat_ip_bits[i].ToString(), 2) 
                              & Convert.ToUInt64(subnet_part[i].ToString(), 2));

                for (int i = 0; i < hostpart.Length; i++)
                    if (i == hostpart.Length - 1) sb.Append("0");
                    else sb.Append("1");

                net_id_plus_host = sb.ToString();
            }

            //*****************
            int IPPartsLength = net_id_plus_host.Length / 8;

            string[] ipnewparts = new string[IPPartsLength];

            int j = 0;

            for (int i = 0; i < ipnewparts.Length; i++)
            {
                ipnewparts[i] = net_id_plus_host.Substring(j, 8);
                j = j + 8;
            }

            string[] ipparts = ipadresse.Split('.');

            j = ipparts.Length - 1;
            for (int i = ipnewparts.Length - 1; i >= 0; i--)
            {
                ipparts[j] = Convert.ToInt64(ipnewparts[i], 2).ToString();
                j--;
            }
            StringBuilder stringBuilder1 = new StringBuilder();
            for (int i = 0; i < ipparts.Length; i++)
                if (i == ipparts.Length - 1) stringBuilder1.Append(ipparts[i]);
                else stringBuilder1.Append(ipparts[i] + ".");

            return stringBuilder1.ToString();

            //*****************
        }

历史

  • 2022 年 10 月 20 日:初始版本
© . All rights reserved.