하아찡

C# 패킷 캡쳐-2 본문

네트워크

C# 패킷 캡쳐-2

하아찡 2022. 9. 12. 18:36

1편에서 적지 못한 소스코드

정리 후 Git에 올려둘게요

 

장치 찾는 Form 소스

using System;
using System.Windows.Forms;

namespace Packet.Forms
{
    public partial class DeviceList : Form
    {
        Main main;
        public DeviceList(Main _main)
        {
            InitializeComponent();
            main = _main;
        }

        private void DeviceList_Load(object sender, EventArgs e)
        {
            foreach(var item in main.pcap.DeviceList())
            {
                LbDevice.Items.Add(item);
            }
        }

        private void LbDevice_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (LbDevice.SelectedIndex == -1)
                MessageBox.Show("장치를 선택해주세요");

            main.pcap.SetDevice(LbDevice.Items[LbDevice.SelectedIndex].ToString());
            this.Close();
        }
    }
}

 

메인 폼

using System;
using System.Collections.Generic;
using System.Windows.Forms;


namespace Packet
{
    public partial class Main : Form
    {

        //슬라이딩 최대 최소 폭
        const int MAX_SLIDING_WIDTH = 200;
        const int MIN_SLIDING_WIDTH = 60;

        //슬라이딩 속도
        const int STEP_SLIDING = 10;
        //최초 슬라이딩 메뉴 크기
        int _posSliding = 200;

        //버튼 추가될시 텍스트 저장해두고 출력
        List<string> BtnSideTexts = new List<string>();

        const float panelData = 0.8f;
        const float panelinfo = 0.2f;


        public Capture pcap;
        public Main()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            pcap = new Capture();
            SetFormSize();
            BtnSideTexts.Add("장치선택");
            BtnSideTexts.Add("버전확인");
            pcap.Setlb(lbPackets);
        }

        private void CheckSide_CheckedChanged(object sender, EventArgs e)
        {
            int index = panelSideMenu.Controls.Count - 1;
            if (CheckSide.Checked)
            {
                foreach (var control in panelSideMenu.Controls)
                {
                    Type BtnCheck = control.GetType();
                    if (BtnCheck.Name == "Button")
                    {
                        ((Button)control).Text = BtnSideTexts[index - 1];
                        index--;
                    }

                }
                CheckSide.Text = "<";
            }
            else
            {
                
                //내부 버튼 텍스트를 숫자로 변경
                foreach (var control in panelSideMenu.Controls)
                {
                    Type BtnCheck = control.GetType();
                    if (BtnCheck.Name == "Button")
                    {
                        ((Button)control).Text = index.ToString();
                        index--;
                    }

                }
                CheckSide.Text = ">";
            }


            timerSideMenu.Start();
        }

        private void timerSideMenu_Tick(object sender, EventArgs e)
        {
            if (CheckSide.Checked)
            {
                _posSliding += STEP_SLIDING;
                if (_posSliding >= MAX_SLIDING_WIDTH)
                    timerSideMenu.Stop();
            }
            else
            {
                _posSliding -= STEP_SLIDING;
                if (_posSliding <= MIN_SLIDING_WIDTH)
                    timerSideMenu.Stop();
            }
            panelSideMenu.Width = _posSliding;
        }

        

        private void SetFormSize()
        {
            panelDatas.Height = Convert.ToInt32(this.Size.Height * panelData) - 50;
            //panelinfos.Height = Convert.ToInt32(this.Size.Height * panelData);
        }
        private void Form1_Resize(object sender, EventArgs e)
        {
            //폼 사이즈 변경이 끝났을경우
            SetFormSize();
        }

        private void BtnVersion_Click(object sender, EventArgs e)
        {
            var version = pcap.Versions();
            MessageBox.Show(version.pcap + '\n' + version.sharpcap);
        }

        private void BtnSelectDevice_Click(object sender, EventArgs e)
        {
            
            Form fc = Application.OpenForms["DeviceList"];

            //디바이스 장치 찾는 폼이 안켜져있을때
            if(fc == null)
            {
                Forms.DeviceList form = new Forms.DeviceList(this);
                form.Show();
            }
                
        }

        private void BtnTest_Click(object sender, EventArgs e)
        {
            //패킷읽기 시작
            pcap.ReadPacket();
        }
    }
}

슬라이딩 소스코드 설명은 1편에 있는 블로그 참조

 

캡쳐 소스

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using SharpPcap;

namespace Packet
{
    public class Capture
    {
        //해당 디바이스 패킷데이터를 읽어옴
        ICaptureDevice PcapDevice = null;

        //디바이스가 검색했는지
        bool bDeviceCheck = false;

        //디바이스를 선택했는지
        bool bSetDevice = false;

        ListBox lb = null;
        public Capture()
        {
            if(0 < CaptureDeviceList.Instance.Count)
            {
                //해당값이 false 경우 모든 함수 작동x
                //버전 확인 예외
                bDeviceCheck = true;
            }
        }

        public struct Version
        {
            public string pcap { get; set; }
            public string sharpcap { get; set; }
        };
        public Version Versions()
        {
            Version val = new Version();
            val.pcap = Pcap.Version.Substring(0, Pcap.Version.IndexOf('('));
            //val.sharpcap = SharpPcap.Version.VersionString;

            return val;
        }
        
        public void Setlb(ListBox _lb)
        {
            lb = _lb;
        }
        public List<string> DeviceList()
        {
            List<string> list = new List<string>();
            if (!bDeviceCheck)
                return list;

            
            
            foreach(var nic in CaptureDeviceList.Instance)
            {
                var friendName = nic.ToString().Split('\n')[1];
                //FriendName: "해당데이터"
                list.Add(friendName.Substring(friendName.IndexOf(' ') + 1));
                //Console.WriteLine(nic);
            }

            return list;
        }

        public string test()
        {
            return PcapDevice.ToString();
        }

        
        public void SetDevice(string FriendName)
        {
            //디바이스를 선택해줌
            if (!bDeviceCheck)
                return;

            foreach (var nic in CaptureDeviceList.Instance)
            {
                var friendName = nic.ToString().Split('\n')[1];
                string str = friendName.Substring(friendName.IndexOf(' ') + 1);
                //선택한 디바이스와 같을경우 선택한다
                if (str == FriendName)
                {
                    bSetDevice = true;
                    PcapDevice = nic;
                    break;
                }
            }
        }


        public void ReadPacket()
        {
            if (!bSetDevice)
                return;

            PcapDevice.Open();
            PcapDevice.OnPacketArrival += Device_OnPacketArrival; 
            PcapDevice.StartCapture();

            
        }
        private string IPHeadProtocal(int i)
        {
            string ProtocolType = "";
            if (i == 1)
                ProtocolType = "ICMP";
            else if (i == 6)
                ProtocolType = "TCP";
            else if (i == 17)
                ProtocolType = "UDP";
            else
                ProtocolType = "NONE";
            return ProtocolType;
        }

        private void Device_OnPacketArrival(object s, PacketCapture e)
        {
            //패킷읽는 이벤트 부분

            //패킷데이터를 출력창으로 확인해보고싶을때 주석 풀기
            //ReadOnlySpan<byte> test = e.Data;
            //Console.WriteLine(test.ToString());

            string str = "";
            EthernetFrame Frame = new EthernetFrame(e.Data);
            str = $"{IPHeadProtocal(Frame.iphead.Protocol)}    {Frame.iphead.PrintSourceAdd()} -> {Frame.iphead.PrintDestAdd()}";

            ListviewAddItem(IPHeadProtocal(Frame.iphead.Protocol), Frame.iphead.PrintSourceAdd(), Frame.iphead.PrintDestAdd());
            
        }

        private delegate void Dgt_ListboxAddItem(string Type, string Source, string Dest);
        private void ListviewAddItem(string Type,string Source, string Dest)
        {
            if (lb.InvokeRequired)
            {
                Dgt_ListboxAddItem t = ListviewAddItem;
                object[] objs = new object[] { Type,Source,Dest };
                lb.Invoke(t, objs);
            }
            else
            {

                lb.Items.Add($"{String.Format("{0,4}", Type)}   {Source} -> {Dest}");
                //lv.TopItem = lv.Items[lv.Items.Count - 1];
            }
        }
    }

    public class IPHead
    {
        public IPHead(List<byte> _data)
        {
            int index = 0;
            byte BitCheck = 0b_1111_0000; 
            int keepIndex = 0;

            TotalLen = new byte[2];
            identifi = new byte[2];
            FragmentOffset = new byte[2];
            HeaderChecksum = new byte[2];
            SourceAdd = new byte[4];
            DestAdd = new byte[4];

            

            Version = (byte)((byte)(_data[index] &  BitCheck) >> 4);

            BitCheck = 0b_0000_1111;
            HL = (byte)(((byte)(_data[index] & BitCheck)) * 4) ;
            index++;
            TOS = _data[index++];
            keepIndex = index;

            for (int i = index; i < keepIndex + TotalLen.Length; i++, index++)
                TotalLen[i - keepIndex] = _data[i];
            keepIndex = index;

            for (int i = index; i < keepIndex + identifi.Length; i++, index++)
                identifi[i - keepIndex] = _data[i];
            keepIndex = index;

            for (int i = index; i < keepIndex + FragmentOffset.Length; i++, index++)
                FragmentOffset[i - keepIndex] = _data[i];
            keepIndex = index;

            BitCheck = 0b_1110_0000;
            IPFlags = (byte)((byte)(FragmentOffset[0] & BitCheck) >> 5);

            BitCheck = 0b_0001_0000;
            FragmentOffset[0] = (byte)(FragmentOffset[0] & BitCheck);

            TTL = _data[index++];
            Protocol = _data[index++];
            keepIndex = index;

            for (int i = index; i < keepIndex + HeaderChecksum.Length; i++, index++)
                HeaderChecksum[i - keepIndex] = _data[i];
            keepIndex = index;

            
            for (int i = index; i < keepIndex + SourceAdd.Length; i++, index++)
                SourceAdd[i - keepIndex] = _data[i];
            keepIndex = index;

            for (int i = index; i < keepIndex + DestAdd.Length; i++, index++)
                DestAdd[i - keepIndex] = _data[i];
            keepIndex = index;

            if (HL == 0)
            {
                IPOption = new byte[1];
            }
            else if(HL == 20)
            {
                IPOption = new byte[1];
                //데이터가있을경우
            }
            else
            {

                IPOption = new byte[HL - 20];
                for (int i = index; i < keepIndex + (HL - 20); i++, index++)
                    IPOption[i - keepIndex] = _data[i];

            }
                


        }

        public string PrintSourceAdd()
        {
            string str = $"{String.Format("{0,3}", SourceAdd[0])}.{String.Format("{0,3}", SourceAdd[1])}.{String.Format("{0,3}", SourceAdd[2])}.{String.Format("{0,3}", SourceAdd[3])}";

            return str;
        }

        public string PrintDestAdd()
        {
            string str = $"{String.Format("{0,3}", DestAdd[0])}.{String.Format("{0,3}", DestAdd[1])}.{String.Format("{0,3}", DestAdd[2])}.{String.Format("{0,3}", DestAdd[3])}";

            return str;
        }

        public byte Version { get; set; }//4bit
        public byte HL { get; set; }//4bit --header len
        public byte TOS { get; set; }//1byte
        public byte[] TotalLen { get; set; }//2byte
        public byte[] identifi { get; set; }//2byte

        public byte IPFlags { get; set; }//3bit
        public byte[] FragmentOffset { get; set; }//1byte + 5bit

        public byte TTL { get; set; }//1byte
        public byte Protocol { get; set; }//1byte

        public byte[] HeaderChecksum { get; set; }//2byte
        public byte[] SourceAdd { get; set; }
        public byte[] DestAdd { get; set; }

        public byte[] IPOption { get; set; }
    }


    public class EthernetFrame
    {
        public EthernetFrame(ReadOnlySpan<byte> _data)
        {
            int DataLen = _data.Length;
            int index = 0;
            int keepIndex = 0;
            Preamble = new byte[7];
            DestAdd = new byte[6];
            SourceAdd = new byte[6];
            Type = new byte[2];
            FCS = new byte[4];
            Data = new List<byte>();
            SFD = 0;

            /*
            for (int i = index; i < keepIndex + 7; i++, index++)
            {
                Preamble[i] = _data[i];
            }
            SFD = _data[index++];
            */
            keepIndex = index;
            //Dest Address
            for (int i = index; i < keepIndex + DestAdd.Length; i++, index++)
                DestAdd[i - keepIndex] = _data[i];
            keepIndex = index;

            //Source Address
            for (int i = index; i < keepIndex + SourceAdd.Length; i++, index++)
                SourceAdd[i - keepIndex] = _data[i];
            keepIndex = index;

            //Type
            for (int i = index; i < keepIndex + Type.Length; i++, index++)
                Type[i - keepIndex] = _data[i];
            keepIndex = index;

            //Data
            for (int i = index; i < DataLen - FCS.Length; i++, index++)
                Data.Add(_data[i]);
            keepIndex = index;

            //Data
            for (int i = index; i < keepIndex + FCS.Length; i++, index++)
                FCS[i - keepIndex] = _data[i];

            iphead = new IPHead(Data);
        }
        public byte[] Preamble { get; set; }
        public byte SFD { get; set; }
        public byte[] DestAdd { get; set; }
        public byte[] SourceAdd { get; set; }
        public byte[] Type { get; set; }
        public List<byte> Data { get; set; }
        public byte[] FCS { get; set; }

        public IPHead iphead { get; set; }
    }
    public class PacketData
    {
        

        //데이터 저장
        List<byte> Data;
        public PacketData(ReadOnlySpan<byte> _data)
        {

        }
    }
}

해당 코드 설명들은 3편에 올릴예정

반응형

'네트워크' 카테고리의 다른 글

C# 패킷 캡쳐 - 4  (0) 2023.08.03
C# 패킷 캡쳐 -3  (3) 2022.09.13
C# 패킷 캡쳐-1  (0) 2022.09.08