2012年7月5日星期四

sniffer.cpp


#pragma comment(linker, "/ENTRY:Entry") 
#pragma comment(linker, "/subsystem:windows")

#include <winsock2.h> //这一行应该加在前面,并且注释掉//#include <Windows.h> 
#pragma comment(lib, "WS2_32")// 链接到WS2_32.lib

#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")

#include <mstcpip.h>

typedef struct _IPHeader// 20字节的IP头
{
  UCHAR     iphVerLen;      // 版本号和头长度(各占4位)
  UCHAR     ipTOS;          // 服务类型 
  USHORT    ipLength;       // 封包总长度,即整个IP报的长度
  USHORT    ipID;      // 封包标识,惟一标识发送的每一个数据报
  USHORT    ipFlags;      // 标志
  UCHAR     ipTTL;        // 生存时间,就是TTL
  UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等
  USHORT    ipChecksum;     // 校验和
  ULONG     ipSource;       // 源IP地址
  ULONG     ipDestination;  // 目标IP地址
} IPHeader, *PIPHeader; 

struct ICMPPacketHead {
  BYTE Type;
  BYTE Code;
  WORD ChkSum;
};

struct TCPPacketHead {
  WORD SourPort;
  WORD DestPort;
  DWORD SeqNo;
  DWORD AckNo;
  BYTE HLen;
  BYTE Flag;
  WORD WndSize;
  WORD ChkSum;
  WORD UrgPtr;
};

struct UDPPacketHead {
  WORD SourPort;
  WORD DestPort;
  WORD Len;
  WORD ChkSum;
};

#define ICMP_HEAD_LEN 4
#define UDP_HEAD_LEN 8

HWND h_list;
DWORD tid = 0;
int i = 1;

class CInitSock
{
public:
  CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
  {    // 初始化WS2_32.dll
    WSADATA wsaData;
    WORD sockVersion = MAKEWORD(minorVer, majorVer);
    if(::WSAStartup(sockVersion, &wsaData) != 0)
    {
      exit(0);
    }
  }
  ~CInitSock()
  {
    ::WSACleanup();
  }
};

DWORD WINAPI start( LPVOID lpParam ) 
{  
  SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
  int x = GetLastError();

  char szHostName[128];// 获取本地IP地址
  gethostname(szHostName, sizeof(szHostName));
  struct hostent * pHost = gethostbyname((char*)szHostName);

  SOCKADDR_IN addr_in;
  addr_in.sin_family  = AF_INET;
  addr_in.sin_port    = htons(0);
  memcpy(&addr_in.sin_addr.S_un.S_addr, pHost->h_addr_list[0], pHost->h_length);
  bind(sRaw, (PSOCKADDR)&addr_in, sizeof(addr_in));// 在调用ioctl之前,套节字必须绑定

  DWORD dwValue = 1;// 设置SIO_RCVALL控制代码,以便接收所有的IP包
  ioctlsocket(sRaw, SIO_RCVALL, &dwValue); //WSAIoctl 更先进。
  /*
  DWORD dwBufferLen[10] ;
  DWORD dwBufferInLen= 1 ;
  DWORD dwBytesReturned = 0 ;
  WSAIoctl(sRaw, SIO_RCVALL , &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned ,0,0) ;*/

  for(;;)
  {
    MSG   msg ;
    // PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE) ; 
    if( PeekMessage( &msg , 0 , WM_CLOSE,WM_CLOSE,PM_NOREMOVE ) )
    {
      closesocket( sRaw ) ;
      break ;
    }

    char buff[1024];
    if(recv(sRaw, buff, 1024, 0) != SOCKET_ERROR ) //> 0
    {
      LV_ITEM lvi;
      RtlZeroMemory(&lvi,sizeof(lvi));

      lvi.iItem = 0;//设置为i有的列有时不会显示。
      wchar_t tem[64] = {0};
      wsprintf(tem,L"%d",i);
      lvi.pszText = tem;
      lvi.mask = LVIF_TEXT;
      lvi.iSubItem = 0;
      SendMessage(h_list,LVM_INSERTITEM,0,(LPARAM)&lvi);

      IPHeader * pIPHdr = (IPHeader*)buff;
      in_addr source, dest;
      char szSourceIp[32], szDestIp[32]; 
      source.S_un.S_addr = pIPHdr->ipSource;// 从IP头中取出源IP地址和目的IP地址
      dest.S_un.S_addr = pIPHdr->ipDestination;
      strcpy(szSourceIp, inet_ntoa(source));
      strcpy(szDestIp, inet_ntoa(dest));

      MultiByteToWideChar(CP_ACP, 0,szSourceIp,lstrlenA(szSourceIp),tem,sizeof(tem));
      lvi.pszText = tem;
      lvi.iSubItem = 1;
      SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

      MultiByteToWideChar(CP_ACP, 0,szDestIp,lstrlenA(szDestIp),tem,sizeof(tem));
      lvi.pszText = tem;
      lvi.iSubItem = 3;
      SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

      int nHeaderLen = (pIPHdr->iphVerLen & 0xf) * sizeof(ULONG);// IP头长度

      switch(pIPHdr->ipProtocol)
      {
      case IPPROTO_TCP: // TCP协议
        {
          struct TCPPacketHead*pTCPHead = (struct TCPPacketHead *)(buff+nHeaderLen);

          WORD port = ntohs(pTCPHead->SourPort);
          TCHAR tem[260] = {0};
          wsprintf(tem,L"%d",port);
          lvi.pszText = tem;
          lvi.iSubItem = 2;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          port = ntohs(pTCPHead->DestPort);
          wsprintf(tem,L"%d",port);
          lvi.pszText = tem;
          lvi.iSubItem = 4;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          if (port == 80)
          {
            lvi.pszText = L"tcp-http";
          }
          else if (port == 23)
          {
            lvi.pszText = L"tcp-telnet";//还可以继续添加其他的。数据也可以格式化。
          }
          else if (port == 25)
          {
            lvi.pszText = L"tcp-smtp";
          }
          else 
          {
            lvi.pszText = L"tcp";
          }          
          lvi.iSubItem = 5;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          int totallen = ntohs(pIPHdr->ipLength);
          totallen -= nHeaderLen;

          nHeaderLen = (pTCPHead->HLen)>>4;  
          nHeaderLen *= 4;
          totallen -= nHeaderLen;

          wsprintf(tem,L"%d",totallen);
          lvi.pszText = tem;
          lvi.iSubItem = 6;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          byte * pdata=((BYTE *)pTCPHead)+nHeaderLen;  
          char tem1[2600] = {0}; //明明清空了,可是还有数据,为何?还没有解决。
          wsprintfA(tem1,"%s",pdata);
          TCHAR tem2[2600] = {0};
          MultiByteToWideChar(CP_ACP, 0,(LPCSTR)tem1,lstrlenA(tem1),tem2,sizeof(tem2));
          lvi.pszText =tem2;
          lvi.iSubItem = 7;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi); /**/
        }
        break;
      case IPPROTO_UDP:
        {
          struct UDPPacketHead*pUDPHead = (struct UDPPacketHead *)(buff + nHeaderLen);

          WORD port = ntohs(pUDPHead->SourPort);
          TCHAR tem[260] = {0};
          wsprintf(tem,L"%d",port);
          lvi.pszText = tem;
          lvi.iSubItem = 2;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          port = ntohs(pUDPHead->DestPort);
          wsprintf(tem,L"%d",port);
          lvi.pszText = tem;
          lvi.iSubItem = 4;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          lvi.pszText = L"udp";
          lvi.iSubItem = 5;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          int totallen = ntohs(pIPHdr->ipLength);
          totallen -= nHeaderLen;
          totallen -= UDP_HEAD_LEN;          
          wsprintf(tem,L"%d",totallen);
          lvi.pszText = tem;
          lvi.iSubItem = 6;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          byte * pdata=((BYTE *)pUDPHead)+UDP_HEAD_LEN;
          char tem1[2600] = {0};
          wsprintfA(tem1,"%s", pdata);
          TCHAR tem2[2600] = {0};
          MultiByteToWideChar(CP_ACP, 0,(LPCSTR)tem1,lstrlenA(tem1),tem2,sizeof(tem2));
          lvi.pszText =tem2;
          lvi.iSubItem = 7;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi); /**/
        }
        break;
      case IPPROTO_ICMP:
        {
          lvi.pszText = L"不使用";
          lvi.iSubItem = 2;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          lvi.pszText = L"不使用";
          lvi.iSubItem = 4;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          lvi.pszText = L"ICMP";
          lvi.iSubItem = 5;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          int totallen = ntohs(pIPHdr->ipLength);
          totallen -= nHeaderLen;
          totallen -= ICMP_HEAD_LEN;
          TCHAR tem[260] = {0};
          wsprintf(tem,L"%d",totallen);
          lvi.pszText = tem;
          lvi.iSubItem = 6;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);

          struct ICMPPacketHead * pICMPHead = (struct ICMPPacketHead *)(buff+nHeaderLen);
          byte * pdata=((BYTE *)pICMPHead)+ICMP_HEAD_LEN;  
          char tem1[2600] = {0};
          wsprintfA(tem1,"type:%d code:%d data:%s", pICMPHead->Type,pICMPHead->Code,pdata);
          TCHAR tem2[2600] = {0};
          MultiByteToWideChar(CP_ACP, 0,(LPCSTR)tem1,lstrlenA(tem1),tem2,sizeof(tem2));
          lvi.pszText =tem2;
          lvi.iSubItem = 7;
          SendMessage(h_list,LVM_SETITEM,0,(LPARAM)&lvi);
        }
        break; 
      case IPPROTO_IGMP:
        //暂且不写。
        break; 
      default://还有很多,请参考ws2def.h 
        ;//
        break;

      }
    }
    i++;
  }
  closesocket(sRaw);
  return 0;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
  HWND h_Static;

  switch (uMsg) 
  {
  case WM_CREATE:
    InitCommonControls();
    h_list = CreateWindowEx(0,L"SysListView32",0,WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL,0,0,994,480,hWnd,0,GetModuleHandle(0),0);
    SendMessage(h_list,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT);

    LV_COLUMN lvc;
    RtlZeroMemory(&lvc,sizeof(lvc));

    lvc.mask = LVCF_TEXT+LVCF_WIDTH; 
    lvc.pszText = L"数据id";
    lvc.cx = 60;
    SendMessage(h_list, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc);

    lvc.cx = 105;
    lvc.pszText = L"发送地址";
    SendMessage(h_list,LVM_INSERTCOLUMN, 1, (LPARAM)&lvc);

    lvc.cx = 60;
    lvc.pszText = L"发送端口";
    SendMessage(h_list,LVM_INSERTCOLUMN, 2, (LPARAM)&lvc);

    lvc.cx = 105;
    lvc.pszText = L"接收地址";
    SendMessage(h_list,LVM_INSERTCOLUMN, 3, (LPARAM)&lvc);

    lvc.cx = 60;
    lvc.pszText = L"接受端口";
    SendMessage(h_list,LVM_INSERTCOLUMN, 4, (LPARAM)&lvc);

    lvc.pszText = L"网络协议";
    SendMessage(h_list,LVM_INSERTCOLUMN, 5, (LPARAM)&lvc);

    lvc.pszText = L"数据大小";
    SendMessage(h_list,LVM_INSERTCOLUMN, 6, (LPARAM)&lvc);

    lvc.cx = 450;
    lvc.pszText = L"数据内容";
    SendMessage(h_list,LVM_INSERTCOLUMN, 7, (LPARAM)&lvc);


    CreateWindowEx(NULL,L"button",L"开始",WS_CHILD | WS_VISIBLE,0,480,90,20,hWnd,(HMENU)9,GetModuleHandle(0),NULL);
    CreateWindowEx(NULL,L"button",L"停止",WS_CHILD | WS_VISIBLE,90,480,90,20,hWnd,(HMENU)99,GetModuleHandle(0),NULL);
    CreateWindowEx(NULL,L"button",L"清空",WS_CHILD | WS_VISIBLE,180,480,90,20,hWnd,(HMENU)999,GetModuleHandle(0),NULL);

    h_Static = CreateWindowEx(WS_EX_CLIENTEDGE,L"Static",0,WS_CHILD | WS_VISIBLE | SS_LEFT | WS_GROUP,0,500,994,150,hWnd,0,GetModuleHandle(0),0);
    SendMessage(h_Static,WM_SETTEXT,0,(LPARAM)L"email:leguanyuan at 126 dot com\t\homepage:http://correy.webs.com\n\
不足之处,敬请指导 \n\
要更彻底的听说可以使用网络驱动:NDIS。");

    break;
  case WM_COMMAND:
    if (wParam == 9)
    {//处理开始按钮
      if(tid == 0)
      {//确保只运行一个辅助线程。不用线程,很难利用下面的两个按钮。
        CreateThread(0, 0, start, 0, 0, &tid);
      }     
    }
    if (wParam == 99)
    {//处理停止按钮。
      if(tid)
      {
        PostThreadMessage(tid,WM_CLOSE,0,0) ;
        tid = 0;
      }
      else
      {
        MessageBox(0,L"还没有开始哟!",0,0);
      }        
    }
    if (wParam == 999)
    {//处理清空按钮。
      SendMessage(h_list,LVM_DELETEALLITEMS,0,0);
      i = 0;
    }
    break;
  case WM_DESTROY: 
    PostQuitMessage(0); 
    break; 
  default: 
    return(DefWindowProc(hWnd, uMsg, wParam, lParam)); 
  }
  return(0); 
}

void Entry() 
{
  { 
    CInitSock theSock;//这个类放置到全局是不会执行的,可能是指定了入口。这样析构函数也不会运行。加个括号能析构。
    WNDCLASSEX sWndClassEx = {48,3,WindowProc,0,0,GetModuleHandle(0),0,LoadCursor(0,IDC_ARROW),(HBRUSH)6,0,L"correy",0}; 
    ATOM a = RegisterClassEx(&sWndClassEx); 
    ShowWindow(CreateWindowEx(0,L"correy",L"made by correy",0x0Ca0000,CW_USEDEFAULT,CW_USEDEFAULT,999,666,0,0, GetModuleHandle(0),0),1); 

    MSG sMsg; 
    while (GetMessage(&sMsg, 0, 0, 0)) 
    {
      DispatchMessage(&sMsg); 
    }
  }
  ExitProcess(0); 
}
//made at 2012.01.03

没有评论:

发表评论