• 基于原始套接字的嗅探器


    嗅探器这个代码我去年的时候就已经写过了,这个学期并不是非常忙,顺手复习网络,就又尝试着写了一遍。

    其实在写嗅探器的时候,最主要的还是要将网卡设置为混杂模式。在此基础之上,对抓到的数据包进行分析。

    这个是我写出来的效果图,目前只是方便于查看,连菜单都没添加:

    左面的界面显示的是主机和主机之间的链接信息,而右面则是选中主机信息之间的数据交互情况。

    我觉得我这个嗅探器应该是个失败品,或者说,没能够真正的将网卡设置为混杂模式。因为可以看到,上面的源地址全部都是本地主机地址,我在下载视频文件的时候,每秒几百kb的数据交互我的这个程序基本没响应。网页信息也都是发送的数据请求,根本抓不到接收数据。对于这一点希望高手能帮我指点一下。

    使用原始套接字写嗅探器的流程:

    1 使用socket创建基于IP协议的原始套接字。

    2 获取本地IP地址。

    3 将原始套接字绑定到本地IP地址上。

    4 使用ioctlsocket函数设置套接字选项SIO_RCVALL,即接受所有数据。

    5 无尽调用recv函数。

    为了方便界面化我将Sniffer的核心代码封装到了一个类中,原本应该做成单件类的,但是懒得改了。

     1 class CSniffer
     2 {
     3 public:
     4     static DWORD WINAPI SnifferThread(LPVOID lpData);//线程函数
     5 public:
     6     CSniffer(HostArray * pOutPut);//构造函数,数据输出指针
     7     ~CSniffer(void);//析构函数,负责终止线程
     8     DWORD IsSucceed();//判断构造函数是否成功,我代码中没用上,就是单纯的返回dwSucceed
     9 private://Method
    10     int IPHeadAnylasis(const char * pRecvBuf, const int nLen);//将IP数据存放到对应数据结构中。
    11     unsigned short q_ntohs(const unsigned short nVal);//之前的遗留代码,没用上
    12     const char * TypeTell(unsigned char type);//同上
    13     unsigned short CheckSum(const void * pData, int size);//校验和函数,可以用一下,但是我没检验
    14     void AddToInfoVector(PPortArray pInfoVector, ip_hdr * pIp, int nLen);//添加新的端口信息
    15 private://Data
    16     PHostArray pSnifferPool;//指向输出数据,全部的信息都存在其指向
    17     HANDLE hThread;//线程句柄
    18     DWORD dwSucceed;//标示参数
    19 };

    然后值得看一看的就是线程函数代码了,其余的没有太多需要介绍的,这段代码其实就是从之前的控制台程序扒下来的,现在单独放到一个函数中。

     1 DWORD WINAPI CSniffer::SnifferThread(LPVOID lpData)
     2 {
     3     CSniffer * pSniffer = (CSniffer *)lpData;
     4 
     5     SOCKET hSnifferSock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
     6     DWORD dwSetVal = 1;
     7     char szhostname[32];
     8     char RecvBuff[65536];
     9     hostent * phost;
    10     SOCKADDR_IN LocalIP;
    11     //先进行绑定,绑定前先获取本地地址
    12     LocalIP.sin_family = AF_INET;
    13     LocalIP.sin_port = htons(0);
    14     gethostname(szhostname, 32);
    15     phost = gethostbyname(szhostname);
    16     memcpy(&LocalIP.sin_addr.S_un.S_addr, phost->h_addr_list[0], phost->h_length);
    17     //cout << "LocalIP" << inet_ntoa(LocalIP.sin_addr) << endl;
    18     if(SOCKET_ERROR == bind(hSnifferSock, (sockaddr *)&LocalIP, sizeof(sockaddr)))
    19     {
    20         ;//cout << "bind error" << endl;
    21     }
    22     //设置套接字选项
    23     ioctlsocket(hSnifferSock, SIO_RCVALL, &dwSetVal);
    24     //cout << q_ntohs(0x3100) << endl;
    25     //std::vector<ConnectBetweenTwoHost> SnifferPool;
    26 
    27     while(1)
    28     {
    29         int nRecvLen = recv(hSnifferSock, RecvBuff, 65536, 0);
    30         if(nRecvLen != SOCKET_ERROR)
    31         {
    32             //cout << "Get Message" << endl;
    33             pSniffer->IPHeadAnylasis(RecvBuff, 65536);
    34         }
    35         else
    36         {
    37             continue;//cout << "Nothing Valid" << endl;
    38         }
    39     }
    40 
    41     return 0;
    42 }

    感觉这一套下来却是是没什么东西,不过我也是在程序跑出来之后,才观察到我的这个程序在数据抓包上面真心做的不怎么样。chrome浏览器的数据请求能抓到,但是反馈回来的数据就完全抓不到了。

    列表数据原本应该做个排序的,整个散列也不错,这样当数据量比较大的时候插入效率能高一点。而我这个就呵呵了。。。

    值得一提的就是我这次两个列表全部使用的虚拟列表。使用之前还查看了我以前代码中关于ListCtrl的使用文档,这算是没白写。不过这里要补充的就是,使用虚拟列表前,需要设置ownerdata选项,也即是用户拥有数据,列表仅仅负责数据的显示,而不是把所有的数据都放到列表中。

    对虚拟列表进行显示刷新的方法比较简单,只要调用SetItemCountEx就能实现刷新过程。

    另外我昨天在网上下载了一个嗅探器,这叫一个惨啊,各种弹网页,估计现在电脑是出于中木马状态。后来程序好不容易跑起来了,结果和我这个差不多,就是能判断出来网页请求信息资源的类型,仅仅是比我分析的深入了一点,至于数据接收,也是没找到。如果您知道哪有比较好的嗅探器,麻烦给发个链接,我学习下。

    另外关于网卡混杂模式设置貌似需要借助winpcap.dll的帮助,有没有大神比较了解,给个学习链接往我看一下。

  • 相关阅读:
    列表 元组
    前端 3
    前端 2
    python pymysql 表和数据的备份
    python 树 索引
    python 数据库连表查询习题
    python 数据库表查询
    python 数据库usdr 查询
    python set enum 完整性约束
    python 数据库表操作
  • 原文地址:https://www.cnblogs.com/matrix-r/p/3665109.html
Copyright © 2020-2023  润新知