하아찡
C# 패킷 캡쳐-2 본문
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 |