• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • Raw Socket(原始套接字)實現Sniffer(嗅探)

    發表于:2007-06-23來源:作者:點擊數: 標簽:
    一. 摘要 Raw Socket: 原始套接字 可以用它來發送和接收 IP 層以上的原始數據包, 如 ICMP, TCP, UDP... int sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 這樣我們就創建了一個 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這個文件)

    //*************************************************************************//

    //* 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)

    {

    WSADATA WSAData;

    BOOL  flag  = true;

    int   nTimeout = 1000;

    char  LocalName[16];

    struct hostent *pHost;

    //檢查 Winsock 版本號

    if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)

    throw Exception("WSAStartup error!");

    //初始化 Raw Socket

    if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == INVALID_SOCKET)

    throw Exception("socket setup error!");

    //設置IP頭操作選項

    if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR)

    throw Exception("setsockopt IP_HDRINCL error!");

    //獲取本機名

    if (gethostname((char*)LocalName, sizeof(LocalName)-1) == SOCKET_ERROR)

    throw Exception("gethostname error!");

    //獲取本地 IP 地址

    if ((pHost = gethostbyname((char*)LocalName)) == NULL)

    throw Exception("gethostbyname error!");

    addr_in.sin_addr  = *(in_addr *)pHost->h_addr_list[0]; //IP

    addr_in.sin_family = AF_INET;

    addr_in.sin_port  = htons(57274);

    //把 sock 綁定到本地地址上

    if (bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in)) == SOCKET_ERROR)

    throw Exception("bind error!");

    iSortDirection = 1;

    }

    //---------------------------------------------------------------------------

    __fastcall TMainForm::~TMainForm()

    {

    WSACleanup();

    }

    //---------------------------------------------------------------------------

    void __fastcall TMainForm::btnCtrlClick(TObject *Sender)

    {

    TListItem *Item;

    DWORD dwValue;

    int nIndex = 0;

    if (btnCtrl->Caption == "&Start")

    {

    dwValue = 1;

    //設置 SOCK_RAW 為SIO_RCVALL,以便接收所有的IP包

    if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0)

    throw Exception("ioctlsocket SIO_RCVALL error!");

    bStop = false;

    btnCtrl->Caption = "&Stop";

    lsvPacket->Items->Clear();

    }

    else

    {

    dwValue = 0;

    bStop = true;

    btnCtrl->Caption = "&Start";

    //設置SOCK_RAW為SIO_RCVALL,停止接收

    if (ioctlsocket(sock, SIO_RCVALL, &dwValue) != 0)

    throw Exception("WSAIoctl SIO_RCVALL error!");

    }

    while (!bStop)

    {

    if (recv(sock, RecvBuf, BUFFER_SIZE, 0) > 0)

    {

    nIndex++;



    ip = *(IP*)RecvBuf;

    tcp = *(TCP*)(RecvBuf + (ip.HdrLen & IP_HDRLEN_MASK));

    Item = lsvPacket->Items->Add();

    Item->Caption = nIndex;

    Item->SubItems->Add(GetProtocolTxt(ip.Protocol));

    Item->SubItems->Add(inet_ntoa(*(in_addr*)&ip.SrcAddr));

    Item->SubItems->Add(inet_ntoa(*(in_addr*)&ip.DstAddr));

    Item->SubItems->Add(tcp.SrcPort);

    Item->SubItems->Add(tcp.DstPort);

    Item->SubItems->Add(ntohs(ip.TotalLen));

    }

    Application->ProcessMessages();

    }  

    }

    //---------------------------------------------------------------------------

    AnsiString __fastcall TMainForm::GetProtocolTxt(int Protocol)

    {

    switch (Protocol)

    {

    case IPPROTO_ICMP :      //1        /* control message protocol */

    return PROTOCOL_STRING_ICMP_TXT;

    case IPPROTO_TCP :      //6        /* tcp */

    return PROTOCOL_STRING_TCP_TXT;

    case IPPROTO_UDP :      //17       /* user datagram protocol */

    return PROTOCOL_STRING_UDP_TXT;

    default :

    return PROTOCOL_STRING_UNKNOWN_TXT;

    }

    }

    //---------------------------------------------------------------------------



    //*************************************************************************//

    //* 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

    {

    __published: // IDE-managed Components

    TPanel *Panel1;

    TButton *btnCtrl;

    TListView *lsvPacket;

    TLabel *Label1;

    void __fastcall btnCtrlClick(TObject *Sender);

    void __fastcall lsvPacketColumnClick(TObject *Sender,

    TListColumn *Column);

    void __fastcall lsvPacketCompare(TObject *Sender, TListItem *Item1,

    TListItem *Item2, int Data, int &Compare);

    void __fastcall Label1Click(TObject *Sender);

    private: // User declarations

    AnsiString __fastcall GetProtocolTxt(int Protocol);

    public: // User declarations

    SOCKET   sock;

    SOCKADDR_IN addr_in;

    IP     ip;

    TCP     tcp;

    PSUHDR   psdHeader;

    char    RecvBuf[BUFFER_SIZE];

    bool    bStop;

    int iSortDirection;

    int iColumnToSort;



    __fastcall TMainForm(TComponent* Owner);

    __fastcall ~TMainForm();

    };

    //---------------------------------------------------------------------------

    extern PACKAGE TMainForm *MainForm;

    //---------------------------------------------------------------------------

    #endif

    偷了個懶, IP, TCP 頭及一些宏定義用了 netmon.h 的頭, 這個文件在 BCB6 的 include 目錄下可以找得到, 其中與本程序相關內容如下:

    //*************************************************************************//

    //* Header File: netmon.h

    //*************************************************************************//

    //

    // IP Packet Structure

    //

    typedef struct _IP

    {

    union

    {

    BYTE  Version;

    BYTE  HdrLen;

    };

    BYTE ServiceType;

    WORD TotalLen;

    WORD ID;

    union

    {

    WORD  Flags;

    WORD  FragOff;

    };

    BYTE TimeToLive;

    BYTE Protocol;

    WORD HdrChksum;

    DWORD  SrcAddr;

    DWORD  DstAddr;

    BYTE Options[0];

    } IP;

    typedef IP * LPIP;

    typedef IP UNALIGNED * ULPIP;

    //

    // TCP Packet Structure

    //

    typedef struct _TCP

    {

    WORD SrcPort;

    WORD DstPort;

    DWORD SeqNum;

    DWORD AckNum;

    BYTE DataOff;

    BYTE Flags;

    WORD Window;

    WORD Chksum;

    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 {

    u_long onoff;

    u_long keepalivetime;

    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 協議結構原理以及各協議之間的關系.

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>