日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Raw Socket(原始套接字)实现Sniffer(嗅探)

發布時間:2024/8/1 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Raw Socket(原始套接字)实现Sniffer(嗅探) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 摘要

? ?Raw Socket: 原始套接字?

可以用它來發送和接收 IP 層以上的原始數據包, 如 ICMP, TCP, UDP...

int sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

這樣我們就創建了一個 Raw Socket

Sniffer: 嗅探器?
關于嗅探器的原理我想大多數人可能都知道?
1. 把網卡置于混雜模式;?
2. 捕獲數據包;?
3. 分析數據包.

但具體的實現知道的人恐怕就不是那么多了. 好, 現在讓我們用 Raw Socket 的做一個自已的 Sniffer.

二. 把網卡置于混雜模式?
在正常的情況下,一個網絡接口應該只響應兩種數據幀:?
一種是與自己硬件地址相匹配的數據幀?
一種是發向所有機器的廣播數據幀?
如果要網卡接收所有通過它的數據, 而不管是不是發給它的, 那么必須把網卡置于混雜模式. 也就是說讓它的思維混亂, 不按正常的方式工作. 用 Raw Socket 實現代碼如下:

setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag); //設置 IP 頭操作選項?
bind(sockRaw, (PSOCKADDR)&addrLocal, sizeof(addrLocal); //把 sockRaw 綁定到本地網卡上
ioctlsocket(sockRaw, SIO_RCVALL, &dwValue);?????? //讓 sockRaw 接受所有的數據

flag 標志是用來設置 IP 頭操作的, 也就是說要親自處理 IP 頭: bool flag = ture;?
addrLocal 為本地地址: SOCKADDR_IN addrLocal;?
dwValue 為輸入輸出參數, 為 1 時執行, 0 時取消: DWORD dwValue = 1;?
沒想到這么簡單吧?

三. 捕獲數據包?
你的 sockRaw 現在已經在工作了, 可以在局域網內其它的電腦上用 Sniffer 檢測工具檢測一下, 看你的網卡是否處于混雜模式(比如 DigitalBrain 的 ARPKiller).?
不能讓他白白的浪費資源啊, 抓包!

recv(sockRaw, RecvBuf, BUFFER_SIZE, 0); //接受任意數據包

#define BUFFER_SIZE 65535?
char RecvBuf[BUFFER_SIZE];?
越來越發現 Sniffer 原來如此的簡單了, 這么一個函數就已經完成抓取數據包的任務了.

四. 分析數據包?
這回抓來的包和平常用 Socket 接受的包可就不是一回事兒了, 里面包含 IP, TCP 等原始信息. 要分析它首先得知道這些結構.?
數據包的總體結構:?
----------------------------------------------?
| ip header | tcp header(or x header) | data |?
----------------------------------------------

IP header structure:?
4??? 8??? 16??????????????????? 32 bit?
|--------|--------|----------------|--------------------------------|?
| Ver? | IHL? |Type of service |???? Total length???? |?
|--------|--------|----------------|--------------------------------|?
| Identification |?? Flags?? |???? Fragment offset??? |?
|--------|--------|----------------|--------------------------------|?
| Time to live? |? Protocol? |???? Header checksum??? |?
|--------|--------|----------------|--------------------------------|?
|???????????? Source address????????????? |?
|--------|--------|----------------|--------------------------------|?
|??????????? Destination address???????????? |?
|--------|--------|----------------|--------------------------------|?
|??????????? Option + Padding????????????? |?
|--------|--------|----------------|--------------------------------|?
|??????????????? Data??????????????? |?
|--------|--------|----------------|--------------------------------|

TCP header structure:?
16??????????????? 32 bit?
|--------------------------------|--------------------------------|?
|???? Source port????? |??? Destination port??? |?
|--------------------------------|--------------------------------|?
|???????????? Sequence number???????????? |?
|--------------------------------|--------------------------------|?
|?????????? Acknowledgement number?????????? |?
|--------------------------------|--------------------------------|?
| Offset | Resrvd |U|A|P|R|S|F|????? Window?????? |?
|--------------------------------|--------------------------------|?
|????? Checksum?????? |??? Urgent pointer???? |?
|--------------------------------|--------------------------------|?
|???????????? Option + Padding??????????? |?
|--------------------------------|--------------------------------|?
|?????????????? Data??????????????? |?
|--------------------------------|--------------------------------|

五. 實現 Sniffer?
OK!?
現在都清楚了, 還等什么.?
下面是我用 BCB6 寫的一個 Simple Sniffer 的代碼, 僅供參考.?
(需要在工程文件里加入WS2_32.LIB這個文件)?

<span style="color: rgb(51, 51, 51); font-family: 宋體; font-size: 14px; line-height: 28px; text-indent: 28px; background-color: rgb(240, 240, 240);">//*************************************************************************//?</span> //* CPP File: WMain.cpp //* Simple Sniffer by shadowstar //* http://shadowstar.126.com/ //*************************************************************************// #include <vcl.h> #pragma hdrstop #include <winsock2.h> #include <ws2tcpip.h> #include <mstcpip.h> #include <netmon.h> #include "WMain.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TMainForm *MainForm; //--------------------------------------------------------------------------- __fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner) { <span style="white-space:pre"> </span>WSADATA WSAData; <span style="white-space:pre"> </span>BOOL flag = true; <span style="white-space:pre"> </span>int nTimeout = 1000; <span style="white-space:pre"> </span>char LocalName[16]; <span style="white-space:pre"> </span>struct hostent *pHost;<span style="white-space:pre"> </span>//檢查 Winsock 版本號 <span style="white-space:pre"> </span>if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) <span style="white-space:pre"> </span>throw Exception("WSAStartup error!");<span style="white-space:pre"> </span>//初始化 Raw Socket <span style="white-space:pre"> </span>if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == INVALID_SOCKET) <span style="white-space:pre"> </span>throw Exception("socket setup error!");<span style="white-space:pre"> </span>//設置IP頭操作選項 <span style="white-space:pre"> </span>if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR) <span style="white-space:pre"> </span>throw Exception("setsockopt IP_HDRINCL error!");<span style="white-space:pre"> </span>//獲取本機名 <span style="white-space:pre"> </span>if (gethostname((char*)LocalName, sizeof(LocalName)-1) == SOCKET_ERROR) <span style="white-space:pre"> </span>throw Exception("gethostname error!");<span style="white-space:pre"> </span>//獲取本地 IP 地址 <span style="white-space:pre"> </span>if ((pHost = gethostbyname((char*)LocalName)) == NULL) <span style="white-space:pre"> </span>throw Exception("gethostbyname error!");<span style="white-space:pre"> </span>addr_in.sin_addr = *(in_addr *)pHost->h_addr_list[0]; //IP <span style="white-space:pre"> </span>addr_in.sin_family = AF_INET; <span style="white-space:pre"> </span>addr_in.sin_port = htons(57274);<span style="white-space:pre"> </span>//把 sock 綁定到本地地址上 <span style="white-space:pre"> </span>if (bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in)) == SOCKET_ERROR) <span style="white-space:pre"> </span>throw Exception("bind error!"); <span style="white-space:pre"> </span>iSortDirection = 1; } //--------------------------------------------------------------------------- __fastcall TMainForm::~TMainForm() { <span style="white-space:pre"> </span>WSACleanup(); } //---------------------------------------------------------------------------void __fastcall TMainForm::btnCtrlClick(TObject *Sender) { <span style="white-space:pre"> </span>TListItem *Item; <span style="white-space:pre"> </span>DWORD dwValue; <span style="white-space:pre"> </span>int nIndex = 0;<span style="white-space:pre"> </span>if (btnCtrl->Caption == "&Start") <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>dwValue = 1; <span style="white-space:pre"> </span>//設置 SOCK_RAW 為SIO_RCVALL,以便接收所有的IP包 <span style="white-space:pre"> </span>if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0) <span style="white-space:pre"> </span>throw Exception("ioctlsocket SIO_RCVALL error!"); <span style="white-space:pre"> </span>bStop = false; <span style="white-space:pre"> </span>btnCtrl->Caption = "&Stop"; <span style="white-space:pre"> </span>lsvPacket->Items->Clear(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>else <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>dwValue = 0; <span style="white-space:pre"> </span>bStop = true; <span style="white-space:pre"> </span>btnCtrl->Caption = "&Start"; <span style="white-space:pre"> </span>//設置SOCK_RAW為SIO_RCVALL,停止接收 <span style="white-space:pre"> </span>if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0) <span style="white-space:pre"> </span>throw Exception("WSAIoctl SIO_RCVALL error!"); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>while (!bStop) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if (recv(sock, RecvBuf, BUFFER_SIZE, 0) > 0) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>nIndex++; <span style="white-space:pre"> </span>ip = *(IP*)RecvBuf; <span style="white-space:pre"> </span>tcp = *(TCP*)(RecvBuf + (ip.HdrLen & IP_HDRLEN_MASK));<span style="white-space:pre"> </span>Item = lsvPacket->Items->Add(); <span style="white-space:pre"> </span>Item->Caption = nIndex; <span style="white-space:pre"> </span>Item->SubItems->Add(GetProtocolTxt(ip.Protocol)); <span style="white-space:pre"> </span>Item->SubItems->Add(inet_ntoa(*(in_addr*)&ip.SrcAddr)); <span style="white-space:pre"> </span>Item->SubItems->Add(inet_ntoa(*(in_addr*)&ip.DstAddr)); <span style="white-space:pre"> </span>Item->SubItems->Add(tcp.SrcPort); <span style="white-space:pre"> </span>Item->SubItems->Add(tcp.DstPort); <span style="white-space:pre"> </span>Item->SubItems->Add(ntohs(ip.TotalLen)); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>Application->ProcessMessages(); <span style="white-space:pre"> </span>} } //---------------------------------------------------------------------------AnsiString __fastcall TMainForm::GetProtocolTxt(int Protocol) { <span style="white-space:pre"> </span>switch (Protocol) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>case IPPROTO_ICMP : //1 /* control message protocol */ <span style="white-space:pre"> </span>return PROTOCOL_STRING_ICMP_TXT; <span style="white-space:pre"> </span>case IPPROTO_TCP : //6 /* tcp */ <span style="white-space:pre"> </span>return PROTOCOL_STRING_TCP_TXT; <span style="white-space:pre"> </span>case IPPROTO_UDP : //17 /* user datagram protocol */ <span style="white-space:pre"> </span>return PROTOCOL_STRING_UDP_TXT; <span style="white-space:pre"> </span>default : <span style="white-space:pre"> </span>return PROTOCOL_STRING_UNKNOWN_TXT; <span style="white-space:pre"> </span>} } //--------------------------------------------------------------------------- //*************************************************************************// //* Header File: WMain.h for WMain.cpp class TMainForm //*************************************************************************// //---------------------------------------------------------------------------#ifndef WMainH #define WMainH //--------------------------------------------------------------------------- #define BUFFER_SIZE 65535 #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <ComCtrls.hpp> #include <ExtCtrls.hpp> #include <winsock2.h> #include "netmon.h" //--------------------------------------------------------------------------- class TMainForm : public TForm { <span style="white-space:pre"> </span>__published: // IDE-managed Components <span style="white-space:pre"> </span>TPanel *Panel1; <span style="white-space:pre"> </span>TButton *btnCtrl; <span style="white-space:pre"> </span>TListView *lsvPacket; <span style="white-space:pre"> </span>TLabel *Label1; <span style="white-space:pre"> </span>void __fastcall btnCtrlClick(TObject *Sender); <span style="white-space:pre"> </span>void __fastcall lsvPacketColumnClick(TObject *Sender, TListColumn *Column); <span style="white-space:pre"> </span>void __fastcall lsvPacketCompare(TObject *Sender, TListItem *Item1, TListItem *Item2, int Data, int &Compare); <span style="white-space:pre"> </span>void __fastcall Label1Click(TObject *Sender); <span style="white-space:pre"> </span>private: // User declarations <span style="white-space:pre"> </span>AnsiString __fastcall GetProtocolTxt(int Protocol); <span style="white-space:pre"> </span>public: // User declarations <span style="white-space:pre"> </span>SOCKET sock; <span style="white-space:pre"> </span>SOCKADDR_IN addr_in; <span style="white-space:pre"> </span>IP ip; <span style="white-space:pre"> </span>TCP tcp; <span style="white-space:pre"> </span>PSUHDR psdHeader; <span style="white-space:pre"> </span>char RecvBuf[BUFFER_SIZE]; <span style="white-space:pre"> </span>bool bStop;<span style="white-space:pre"> </span>int iSortDirection; <span style="white-space:pre"> </span>int iColumnToSort; <span style="white-space:pre"> </span>__fastcall TMainForm(TComponent* Owner); <span style="white-space:pre"> </span>__fastcall ~TMainForm(); }; //--------------------------------------------------------------------------- extern PACKAGE TMainForm *MainForm; //--------------------------------------------------------------------------- #endif偷了個懶, IP, TCP 頭及一些宏定義用了 netmon.h 的頭, 這個文件在 BCB6 的 include 目錄下可以找得到, 其中與本程序相關內容如下://*************************************************************************// //* Header File: netmon.h //*************************************************************************// // // IP Packet Structure // typedef struct _IP { <span style="white-space:pre"> </span>union <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>BYTE Version; <span style="white-space:pre"> </span>BYTE HdrLen; <span style="white-space:pre"> </span>}; <span style="white-space:pre"> </span>BYTE ServiceType; <span style="white-space:pre"> </span>WORD TotalLen; <span style="white-space:pre"> </span>WORD ID; <span style="white-space:pre"> </span>union <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>WORD Flags; <span style="white-space:pre"> </span>WORD FragOff; <span style="white-space:pre"> </span>}; <span style="white-space:pre"> </span>BYTE TimeToLive; <span style="white-space:pre"> </span>BYTE Protocol; <span style="white-space:pre"> </span>WORD HdrChksum; <span style="white-space:pre"> </span>DWORD SrcAddr; <span style="white-space:pre"> </span>DWORD DstAddr; <span style="white-space:pre"> </span>BYTE Options[0]; } IP; typedef IP * LPIP; typedef IP UNALIGNED * ULPIP; // // TCP Packet Structure // typedef struct _TCP { <span style="white-space:pre"> </span>WORD SrcPort; <span style="white-space:pre"> </span>WORD DstPort; <span style="white-space:pre"> </span>DWORD SeqNum; <span style="white-space:pre"> </span>DWORD AckNum; <span style="white-space:pre"> </span>BYTE DataOff; <span style="white-space:pre"> </span>BYTE Flags; <span style="white-space:pre"> </span>WORD Window; <span style="white-space:pre"> </span>WORD Chksum; <span style="white-space:pre"> </span>WORD UrgPtr; } TCP; typedef TCP *LPTCP; typedef TCP UNALIGNED * ULPTCP;// upper protocols #define PROTOCOL_STRING_ICMP_TXT "ICMP" #define PROTOCOL_STRING_TCP_TXT "TCP" #define PROTOCOL_STRING_UDP_TXT "UDP" #define PROTOCOL_STRING_SPX_TXT "SPX" #define PROTOCOL_STRING_NCP_TXT "NCP" #define PROTOCOL_STRING_UNKNOW_TXT "UNKNOW"這個文件也有人聲稱沒有. //*************************************************************************// //* Header File: mstcpip.h //*************************************************************************// // Copyright (c) Microsoft Corporation. All rights reserved. #if _MSC_VER > 1000 #pragma once #endif /* Argument structure for SIO_KEEPALIVE_VALS */struct tcp_keepalive { <span style="white-space:pre"> </span>u_long onoff; <span style="white-space:pre"> </span>u_long keepalivetime; <span style="white-space:pre"> </span>u_long keepaliveinterval; };// New WSAIoctl Options #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1) #define SIO_RCVALL_MCAST _WSAIOW(IOC_VENDOR,2) #define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR,3) #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) #define SIO_ABSORB_RTRALERT _WSAIOW(IOC_VENDOR,5) #define SIO_UCAST_IF _WSAIOW(IOC_VENDOR,6) #define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR,7) #define SIO_INDEX_BIND _WSAIOW(IOC_VENDOR,8) #define SIO_INDEX_MCASTIF _WSAIOW(IOC_VENDOR,9) #define SIO_INDEX_ADD_MCAST _WSAIOW(IOC_VENDOR,10) #define SIO_INDEX_DEL_MCAST _WSAIOW(IOC_VENDOR,11)// Values for use with SIO_RCVALL* options #define RCVALL_OFF 0 #define RCVALL_ON 1 #define RCVALL_SOCKETLEVELONLY 2

現在我們自已的 Sniffer 就做好了, Run, Start......哇, 這么多數據包, 都是從這一臺機器上發出的, 它在干什么? 原來 Adminstrator 密碼為空, 中了尼姆達病毒!

六. 小結?
優點: 實現簡單, 不需要做驅動程序就可實現抓包.?
缺點: 數據包頭不含幀信息, 不能接收到與 IP 同層的其它數據包, 如 ARP, RARP...?
這里提供的程序僅僅是一個 Sniffer 的例子, 沒有對數據包進行進一步的分析. 寫此文的目的在于熟悉Raw Socket 編程方法, 了解 TCP/IP 協議結構原理以及各協議之間的關系.

總結

以上是生活随笔為你收集整理的Raw Socket(原始套接字)实现Sniffer(嗅探)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。