Hold up packages from network adepter and analyze it. Part 2
在上一篇
我們已經成功的攔截到網路卡的封包
在這一篇我們將開始進行解析
封包的資料格式有一定的資料結構
首先我們將對IP的表頭進行拆解
然後再以TCP的資料結構為範例
進行解析
關於IP表頭的資料格式
可以參考以下連結
http://freesoft.org/CIE/Course/Section3/7.htm
在下面的程式碼中
我們首先跟據表頭的格式進行拆解
拆解完畢之後
判斷協定是否為TCP
如果是的話
才繼續往下進行分析
namespace WindowsFormsApplication1 { public class AnalyzePackage { private eProtocol _Protocol; public eProtocol Protocol { get { return _Protocol; } } private int _HeaderLength; private int _Version; private int _DesPort; public int DesPort { get { return _DesPort; } } private int _SrcPort; public int SrcPort { get {return _SrcPort;} } private IPAddress _DesIP; public IPAddress DesIP { get { return _DesIP; } } private IPAddress _SrcIP; public IPAddress SrcIP { get { return _SrcIP; } } private TcpPackage _mTcpPackage; public TcpPackage Tcp { get { return _mTcpPackage; } } public AnalyzePackage(byte[] byData, int iLength) { byte[] byData_ = new byte[iLength]; Array.Copy(byData, 0, byData_, 0, iLength); // get Header length _Version = (byData_[0] & 0xF0) >> 4; _HeaderLength = (byData_[0] & 0x0F) * 4 /* sizeof(int) */; // get protocol if (Enum.IsDefined(typeof(eProtocol), (int)byData_[9])) _Protocol = (eProtocol)byData_[9]; else _Protocol = eProtocol.Other; // get ip byte[] byIP_ = new byte[4]; Array.Copy(byData_, 12, byIP_, 0, 4); _SrcIP = new IPAddress(byIP_); Array.Copy(byData_, 16, byIP_, 0, 4); _DesIP = new IPAddress(byIP_); // get port _SrcPort = byData_[_HeaderLength] * 256 + byData_[_HeaderLength + 1]; _DesPort = byData_[_HeaderLength + 2] * 256 + byData_[_HeaderLength + 3]; if (_Protocol == eProtocol.Tcp) { byte[] byTcp_ = new byte[byData_.Length - _HeaderLength]; Array.Copy(byData_, _HeaderLength, byTcp_, 0, byTcp_.Length); _mTcpPackage = new TcpPackage(byTcp_); } else { _mTcpPackage = null; } } } public enum eProtocol { Ggp = 3, Icmp = 1, Idp = 22, Igmp = 2, IP = 4, ND = 77, Pup = 12, Tcp = 6, Udp = 17, Other = -1 } }
上面程式碼中的列舉eProtocol中的定義
可以參考這邊
http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml
接下來則是對TCP的格是進行解析
TCP格式的內容可以參考這邊
http://tools.ietf.org/html/rfc793
下面程式碼中的類別
其中有一個欄位 ApplicationData
便是儲存解析完後應用層的資料
namespace WindowsFormsApplication1 { public class TcpPackage { private UInt16 _SrcPort; public int SourcePort { get { return (int)_SrcPort; } } private UInt16 _DesPort; public int DesPort { get { return (int)_DesPort; } } private UInt32 _SeqNum; public int SeqNum { get { return (int)_SeqNum; } } private UInt32 _AckNum; public int AckNum { get { return (int)_AckNum; } } private UInt16 _Windows; public int Windows { get { return (int)_Windows; } } private UInt16 _Shecksum; public int Shecksum { get { return (int)_Shecksum; } } private UInt16 _UrgentPoint; public int UrgentPoint { get { return (int)_UrgentPoint; } } private byte[] _ApplicationData; public byte[] ApplicationData { get { return _ApplicationData; } } public TcpPackage(byte[] byData) { byte[] byPort_ = new byte[4]; Array.Copy(byData, 0, byPort_, 0, 4); Array.Reverse(byPort_); _SrcPort = BitConverter.ToUInt16(byPort_, 2); _DesPort = BitConverter.ToUInt16(byPort_, 0); _SeqNum = BitConverter.ToUInt32(byData, 12); _AckNum = BitConverter.ToUInt32(byData, 8); _Windows = BitConverter.ToUInt16(byData, 4); _Shecksum = BitConverter.ToUInt16(byData, 2); _UrgentPoint= BitConverter.ToUInt16(byData, 0); _ApplicationData = new byte[byData.Length - 20]; Array.Copy(byData, 20, _ApplicationData, 0, byData.Length - 20); } } }