c/c++写的Mini Sniffer(嗅探工具)

来源:互联网 发布:iot js 机 编辑:程序博客网 时间:2024/05/21 14:01
                                                 c/c++写的Mini Sniffer
前两天写了一个mini sniffer 原理很简单,就是利用原始套接字将网卡设置成混杂模式,然后利用套接字监听经过本主机的所有网络IP封包,但是由于本人现在能力有限,还不能很好的对数据包进行解码分析,就只能将它们的十六进制ASCL码输出..以下是源代码.编译器是vs2005
//头文件 DataStruct.h
#ifndef _DATASTRUCT_H_
#define _DATASTRUCT_H_
char szText[1024];
typedef 
struct _IP_HDR
{
UCHAR ipVersion;
//IP版本号和头长度
UCHAR ipTos;//服务类型
USHORT ipLength;//总长度
USHORT ipID;//封包标识,用于将分片重新组装成封包
USHORT ipFlag;//标志,目前只有前两位有意义,|DF|MF|...DF是不能分片,MF是有更多的分片
UCHAR ipTTL;//封包生存时间,也就是经过的路由个数
UCHAR ipProtocol;//指定数据包携带的数据是使用的是那种协议:TCP,UDP,ICMP??
USHORT ipCheckSum;//首部校验和
ULONG ipSourceAdd;//数据报源地址
ULONG ipDestination;//数据报目的地址
}
IPHEADER, *PIPHEADER;
typedef 
struct _UDP_HDR
{
USHORT sourcePort;
//源端口号
USHORT destinationPort;//目的端口号
USHORT len;//封包长度
USHORT chekSum;//校验和
}
UDPHEADER, *PUDPHEADER;
­
/*该程序没有ICMP数据包的解析
typedef struct _ICMP_HDR
{
USHORT icmp_type;
USHORT icmp_code;
USHORT icmp_chekSum;
USHORT icmp_id;
USHORT icmp_sequuence;
ULONG icmp_timestamp;
}ICMP_HDR, *PICMP_HDR;
*/

typedef  
struct _TCP_HDR
{
USHORT sourcePort;
//16位源端口号
USHORT destPort;//目的端口号
ULONG sequenceNumber;// 序列号
ULONG ACK;//确认号
UCHAR dataOffset;//4位首部长度/6位保留字
UCHAR flags;//6位标志位
USHORT windowLen;//窗口大小
USHORT checkSum;//校验和
USHORT urgentPointer;//紧急指针|紧急数据偏移量
}
TCPHEADER, *PTCPHEADER;
­
#endif //_DATASTRUCT_H_
­
//头文件 InitSocket.h
/* winsock应用程序必须加载Winsock Dll
* 加载该Dll的函数就是::WSAStartup()
* 使用结束后还得释放Dll 用::WSACleanup()函数可以实现
*/

#ifndef _INITSOCKET_H_
#define _INITSOCKET_H_
#include 
<winsock2.h>
#include 
<Mswsock.h>
#include 
<Ws2tcpip.h>
#pragma comment(lib, "WS2_32")
class CInitSocket
{
public:
CInitSocket(BYTE minorVer 
= 2, BYTE majorVer = 2)
{
  WSADATA wsaData;
  WORD sockVersion 
= MAKEWORD(minorVer, majorVer);
  
if (::WSAStartup(sockVersion, &wsaData) != 0)
  
{
   
return;
  }

}

~CInitSocket()
{
  ::WSACleanup();
}

}
;
#endif _INITSOCKET_H_
­
//头文件HdFuns.h
#ifndef _HDFUNS_H_
#define _HDFUNS_H_
extern  int nRet;
void AnalyzeIpPackets(char *buff);//分析IP数据包
void AnalyzeTcpPackets(char *buff);//分析TCP数据包
void AnalyzeUdpPackets(char *buff);//分析UDP数据包
#endif //_HDFUNS_H_
该头文件的实现文件HdFuns.cpp如下:
#include 
"HdFuns.h"
#include 
<stdio.h>
#include 
<winsock2.h>
#include 
"DataStruct.h"
void AnalyzeIpPackets(char *buff)
{
PIPHEADER pIphdr 
= (PIPHEADER)buff;
in_addr source, dest;
//源地址和目的地址
char szSourceIp[32], szDestIp[32];
printf(
" ----------------------------------- ");
source.S_un.S_addr 
= pIphdr->ipSourceAdd;//源IP
dest.S_un.S_addr = pIphdr->ipDestination;//目的IP
::strcpy(szSourceIp, ::inet_ntoa(source));
::strcpy(szDestIp, ::inet_ntoa(dest));
­
printf(
"%s -> %s ", szSourceIp, szDestIp);
//IP头长度
int nIpHeaderLen = (pIphdr->ipVersion & 0xf* sizeof(ULONG);
­
switch(pIphdr->ipProtocol)
{
case IPPROTO_TCP://TCP
  AnalyzeTcpPackets(buff + nIpHeaderLen);
  
break;
case IPPROTO_UDP://UDP
  AnalyzeUdpPackets(buff + nIpHeaderLen);
  
break;
case IPPROTO_ICMP:
  
break;
}

}

­
void AnalyzeTcpPackets(char *buff)
{
PTCPHEADER pTcpHdr 
= (PTCPHEADER)buff;
printf(
"This is a Tcp packet!! ");
//输出端口号
printf("Port : %d -> %d ", ::ntohs(pTcpHdr->sourcePort), ::ntohs(pTcpHdr->destPort));
::memset(szText, 
' ', nRet);
int dataLen = nRet - sizeof(IPHEADER) - sizeof(TCPHEADER);//计算数据的长度
::memcpy(szText, &buff[sizeof(TCPHEADER)], dataLen);//将数据包中的数据拷贝到缓冲区中
­
for (int i = 0; i < dataLen; i++)
{
  
//按字节分析数据
  if (szText[i] < 0 )
  
{
   szText[i] 
= -szText[i];
  }

  printf(
"%X ", szText[i]);
}

switch(::ntohs(pTcpHdr->destPort))
{
case 21:
  
break;
case 80:
case 8080:
  
break;
}

}

void AnalyzeUdpPackets(char *buff)
{
printf(
"This is a Udp packet!! ");
PUDPHEADER pUdpHdr 
= (PUDPHEADER)buff;
printf(
"%d--->%d ", ::ntohs(pUdpHdr->sourcePort), ::ntohs(pUdpHdr->destinationPort));
::memset(szText, 
' ' , nRet);//清空缓冲区
int dataLen =nRet - sizeof(UDPHEADER) - sizeof(IPHEADER);
::memcpy(szText, buff 
+ sizeof(UDPHEADER), dataLen);
for (int i = 0; i < dataLen; i++)
{
  
if (szText[i] < 0 )
  
{
   szText[i] 
= -szText[i];
  }

  printf(
"%X ", szText[i]);
}

}

­
//主函数内容
#include "InitSocket.h"
#include 
<iostream>
#include 
"HdFuns.h"
#include 
<mstcpip.h>
using namespace std;
CInitSocket initSock;
int nRet;
int main(void)
{
SOCKET sRaw 
= ::socket(AF_INET, SOCK_RAW, IPPROTO_IP);//原始套接字
char szHostName[56];//主机名
SOCKADDR_IN localAddr;//本地地址
­
struct hostent *pHost;
::gethostname(szHostName, 
56);//获取主机名
if ((pHost = ::gethostbyname((char*)szHostName)) == NULL)
{
  
return 0;
}

localAddr.sin_family 
= AF_INET;
localAddr.sin_port  
= ::htons(0);
::memcpy(
&localAddr.sin_addr.S_un.S_addr, pHost->h_addr_list[0], pHost->h_length);
cout
<<"Bind to interface :"<<::inet_ntoa(localAddr.sin_addr)<<endl;
if (::bind(sRaw, (PSOCKADDR)&localAddr, sizeof(localAddr)) == SOCKET_ERROR)
{
  
return 0;
}

DWORD dwValue 
= 1;
if (::ioctlsocket(sRaw, SIO_RCVALL, &dwValue) != 0)//设置网卡为混杂模式
{
  
return 0;
}

char buff[1024];
while(true)
{
  nRet 
= ::recv(sRaw, buff, 10240);//接受网络中数据包
  if (nRet > 0)
  
{
   buff[nRet] 
= '';
   AnalyzeIpPackets(buff);
//分析IP数据包
  }

}

::closesocket(sRaw);
//关闭套接字
return 0;
}
 

­
执行结果如下(部分截图,一直处于滚屏状态):

原创粉丝点击