1 、Sniff軟體即是網路竊聽器, 由於乙太網路是以廣播的方式來傳輸同一網路區段的資料,因此當網路
連接方式是使用HUB而非Switch或Route,則只須將網路卡設定為混雜模式(promisscuous)來接
收所有輸送至網路卡的資料並進行資料封包的分析即可。
2、C#使用Windows API時必須先使用DllImport來Include Library,主要使用下列14個網路相關的API:
2-01、int WSAStartup(ushort wVersionrequested,ref WSDATA lpWSAData)
一 使用Windows Socket必須成功的調用此函式,才可以完成其他一系列的初始化。
2-02、int sock(int af,int type,int protocol) 一 建立一個具體傳輸服務的Socket。
2-03、int WSAGetLastError() 一 擷取使用Windows Socket函式失敗時的錯誤訊息。
2-04、uint GetIpAddrTable(IntPtr pIpAddrTable,ref int pdwSize,bool bOrder)
一 取得目前主機有多少介面有IPv4 Address。
2-05、ushort ntohs(ushort netshort) 一 將TCP/IP的網路格式轉換成Inter Processors格式
2-06、ushort htons(ushort hostshort) 一 將Inter Processors格式轉換成TCP/IP的網路格式
PS:big-endian - TCP/IP的網路格式 little-endian - Inter Processor格式
Ex. 0x1000 (big-endian) = 0x0010 (little-endian) = 4 (Decimal)
2-07、uint inet_addr(Intptr cp) 一 將帶有dot的字串IP轉換成網路格式(big-endian)的uint。
2-08、string inet_ntoa(uint sin_addr) 一 將網路格式(big-endian)的ushort轉換成帶有dot的字串IP。
2-09、int setsockopt(int s,int level,int optname,IntPtr optval,int optlen)
一 設定Socket 相關選項的函式。
Ex. send/receive timeout or 設定IP_HDRINCL 由應用程式產生IP Header。
2-10、int bind(int s,ref SOCKADDR_IN name,int namelen) 一
2-11、int WSAIoctl( int s,
uint dwIoControlCode,
IntPtr lpvInBuffer,
uint cbInBuffer,
IntPtr lpvOutBuffer,
uint cbOutBuffer,
IntPtr lpOverlapped,
IntPtr lpCompletionRoutine
);
一 設定Socket 模式的函式,對於一般網路卡提供四種不同的模式:
1. 廣播模式(broadcast):接收網路中的廣播資訊。
2. 組播模式(multicast):接收網路中的組播資訊。
3. 直接模式(unicast):只接收目的位址符合網路卡位址的資訊。
4. 混雜模式(promiscuous):接收所有經過網路卡的所有資訊。
(實現Sniff功能必須將Socket設為該模式)
2-12、int recv(int s,IntPtr buf,int len,int flags) 一 接收連接的Socket或Bound未連接的Socket。
2-13、int closesocket(int s) 一 關閉指定的Socket。
2-14、int WSACleanup() 一 終止使用Windows Socket 2 DLL (to close WSAStartup)
3、實作Sniff功能時,在成功的調用WAStartup函式之後;由於必須讀取各種的網路封包資訊,因此必須使用
SOCK_RAW即原始的SOCKET並設定協為PROTOCOL_IP,讓應用程式自已來對封包進行檢查及分析。
設定方式如下:
Ex. openSocket = socket(AF_INET,SOCK_RAW,PROTOCOL_IP)
AF_INET:設定使用IPv4(Inter Protocol Version 4) PS. IPv6是使用AF_INET6
SOCK_RAW:接收/傳送包含IP Header 和 UDP/TCP/ICMP Header
PROTOCOL_IP:設定接收 IP 封包的傳送協定。
PS. 由於使用SOCK_RAW程式必須有管理人權限,因此可以執行下列的步驟。
系統將會自動詢問(Vista) 是否以管理人權限來執行。
1. 在專案目錄下建立manifest File內容如下。
Ex. .../PingTrace/PringTrace/PingTrace.manifest
<?xml version="1.0" encoding="utf-8" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="someExecName"
type="win32" />
<description>Your Program Description</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" /> <==主要在這一行
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
2. Project -> Properties
4、另外還必須使用WSAIoctl函式來設定Socekt模式為混雜模式(promiscuous)來接收所有同一網路區段的
封包。設定方式如下:
Ex.
4.1 IntPtr dwBufferInLen = Marshal.AllocHGlobal(sizeof(int));
Marshal.WriteInt32(dwBufferInLen, RCVALL_ON);
int retMessage = WSAIoctl(
openSocket,
WSAIO("w",IOC.IOC_VENDOR, 1), //SIO_RCVALL
dwBufferInLen, // Set parameter value of SIO_RCVALL
sizeof(int), // The data length of the parameter value
IntPtr.Zero
0,
ref dwBytesReturned,
IntPtr.Zero,
IntPtr.Zero
);
Marshal.FreeHGlobal(dwBufferInLen);
4.2 WSAIO函式是我模擬winsock2.h內 1.WSAIO 2.WSAIOR 3. WSAIOW 4.WSAIORW
四個巨集的函式,主要用來產生socket的控制碼。
5、當電腦有兩張網路卡擁有IP位址時,則可先用GetIpAddrTable函式來取得目前擁有IP位址的網
路卡,再依需求對特定的網路卡使用bind函式。
6、當使用recv函式接收到網路封包後則依到下列步驟進行解析。
6.1、判斷接收到的網路封包長度是否小於IP Header的長度。
6.2、分析IP Header取得下一層的協定類型和整個封包長度
6.3、判斷接收封包長度與IP Header內的封包長度是否相等。
6.3.1、 當接收封包長度小於IP Header內的封包長度則表示資料沒有接收完整必須再執行
recv函式並累加接收封包長度,直到等於IP Header內的封包長度。
6.3.2、當接收封包長度大於IP Header內的封包長度則表示資料內有兩筆以上的不同封包,因此
必須依序以IP Header內的封包長度將接收到的封包進行分解成個獨立的封包。
6.3.3、當接收封包長度等於IP Header內的封包長度則表示完整接收封包資料。
6.4、依照IP Header內的協定內容將封包以ICMP、UDP or TCP Header來取得封包的資訊。
Download: Sniff (Source Code) Sniff(EXE)
Result: