Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 网络安全 > 黑客技术 > RawSocke原始套接字实现Sniffer嗅探 上
【标  题】:RawSocke原始套接字实现Sniffer嗅探 上
【关键字】:c,if,Sniffer,Raw,RawSocke,Sniffer
【来  源】:网络

RawSocke原始套接字实现Sniffer嗅探 上

Your Ad Here 一. 摘要
  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
#pragma hdrstop

#include
#include
#include
#include
#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();
  }  
}
//---------------------------------------------------
病毒的高级编写技巧:【上一篇】
常用软件加密方法一览:【下一篇】
【相关文章】
  • RawSocke原始套接字实现Sniffer嗅探 下
  • JavaScript与Java的区别
  • gcc常用的编译选项对代码的影响
  • 中国计算机教学网的mysql.class.php
  • EXE变DOC的方法
  • 高质量C++/C编程指南 -- C++函数的高级特性
  • 关于Recordset持久性的一点点研究
  • CCProxy Log Stack Overflow 漏洞浅析(1)
  • CCProxy Log Stack Overflow 漏洞浅析(2)
  • CCProxy Log Stack Overflow 漏洞浅析(3)
  • 【随机文章】
  • 你有「澳主管」吗?问题不大!--练好功夫来面对主管
  • MySQL转CSV文件
  • PXE远程安装linux系统-----汪工-使用效果很快
  • 《天翼之链》TYZL6小时经验
  • STL之set&multiset容器(笔记)
  • 代理服务器系列
  • Sybex CCNA 第四章读书笔记
  • ruby on rails有多流行
  • C#中string与byte[]的转换帮助类
  • cdrmaker web计费查询版已制作完成
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.