基于Raw Socket的嗅探器设计与实现选座题目及资料.docx
《基于Raw Socket的嗅探器设计与实现选座题目及资料.docx》由会员分享,可在线阅读,更多相关《基于Raw Socket的嗅探器设计与实现选座题目及资料.docx(11页珍藏版)》请在冰豆网上搜索。
基于RawSocket的嗅探器设计与实现选座题目及资料
基于RawSocket的嗅探器设计与实现(选座题目及资料)
基于RawSocket的嗅探器设计与实现
功能:
基于RawSocket实现IP层以上原始数据包的发送和接收。
一.摘要
RawSocket:
原始套接字,可以用它来发送和接收IP层以上的原始数据包,如ICMP,TCP,UDP...
intsockRaw=socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
Sniffer(嗅探器)基本原理与实现过程
1.把网卡置于混杂模式;
2.捕获数据包;
3.分析数据包.
二.把网卡置于混杂模式
在正常的情况下,一个网络接口应该只响应两种数据帧:
与自己硬件地址相匹配的数据帧
发向所有机器的广播数据帧
如果要网卡接收发向所有机器的广播数据帧,就必须把网卡置于混杂模式。
用RawSocket实现代码如下:
//设置IP头操作选项
setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(flag);
//把sockRaw绑定到本地网卡上
bind(sockRaw,(PSOCKADDR)&addrLocal,sizeof(addrLocal);
//让sockRaw接受所有的数据
ioctlsocket(sockRaw,SIO_RCVALL,&dwValue);
flag标志是用来设置IP头操作的,也就是说要亲自处理IP头:
boolflag=ture;
addrLocal为本地地址:
SOCKADDR_INaddrLocal;
dwValue为输入输出参数,为1时执行,0时取消:
DWORDdwValue=1;
TCPheaderstructure:
1632bit
|--------------------------------|--------------------------------|
|Sourceport|Destinationport|
|--------------------------------|--------------------------------|
|Sequencenumber|
|--------------------------------|--------------------------------|
|Acknowledgementnumber|
|--------------------------------|--------------------------------|
|Offset|Resrvd|U|A|P|R|S|F|Window|
|--------------------------------|--------------------------------|
|Checksum|Urgentpointer|
|--------------------------------|--------------------------------|
|Option+Padding|
|--------------------------------|--------------------------------|
|Data|
|--------------------------------|--------------------------------|
五.实现Sniffer
用BCB6写的一个SimpleSniffer的代码,仅供参考.
(需要在工程文件里加入WS2_32.LIB这个文件)
//*************************************************************************//
//*CPPFile:
WMain.cpp
//*SimpleSnifferbyshadowstar
//*
//*************************************************************************//
#include
#pragmahdrstop
#include
#include
#include
#include
#include"WMain.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource"*.dfm"
TMainForm*MainForm;
//---------------------------------------------------------------------------
__fastcallTMainForm:
:
TMainForm(TComponent*Owner)
:
TForm(Owner)
{
WSADATAWSAData;
BOOLflag=true;
intnTimeout=1000;
charLocalName[16];
structhostent*pHost;
//检查Winsock版本号
if(WSAStartup(MAKEWORD(2,2),&WSAData)!
=0)
throwException("WSAStartuperror!
");
//初始化RawSocket
if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))==INVALID_SOCKET)
throwException("socketsetuperror!
");
//设置IP头操作选项
if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(flag))==SOCKET_ERROR)
throwException("setsockoptIP_HDRINCLerror!
");
//获取本机名
if(gethostname((char*)LocalName,sizeof(LocalName)-1)==SOCKET_ERROR)
throwException("gethostnameerror!
");
//获取本地IP地址
if((pHost=gethostbyname((char*)LocalName))==NULL)
throwException("gethostbynameerror!
");
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)
throwException("binderror!
");
iSortDirection=1;
}
//---------------------------------------------------------------------------
__fastcallTMainForm:
:
~TMainForm()
{
WSACleanup();
}
//---------------------------------------------------------------------------
void__fastcallTMainForm:
:
btnCtrlClick(TObject*Sender)
{
TListItem*Item;
DWORDdwValue;
intnIndex=0;
if(btnCtrl->Caption=="&Start")
{
dwValue=1;
//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
if(ioctlsocket(sock,SIO_RCVALL,&dwValue)!
=0)
throwException("ioctlsocketSIO_RCVALLerror!
");
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)
throwException("WSAIoctlSIO_RCVALLerror!
");
}
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__fastcallTMainForm:
:
GetProtocolTxt(intProtocol)
{
switch(Protocol)
{
caseIPPROTO_ICMP:
//1/*controlmessageprotocol*/
returnPROTOCOL_STRING_ICMP_TXT;
caseIPPROTO_TCP:
//6/*tcp*/
returnPROTOCOL_STRING_TCP_TXT;
caseIPPROTO_UDP:
//17/*userdatagramprotocol*/
returnPROTOCOL_STRING_UDP_TXT;
default:
returnPROTOCOL_STRING_UNKNOWN_TXT;
}
}
//---------------------------------------------------------------------------
//*************************************************************************//
//*HeaderFile:
WMain.hforWMain.cppclassTMainForm
//*************************************************************************//
//---------------------------------------------------------------------------
#ifndefWMainH
#defineWMainH
//---------------------------------------------------------------------------
#defineBUFFER_SIZE65535
#include
#include
#include
#include
#include
#include
#include
#include"netmon.h"
//---------------------------------------------------------------------------
classTMainForm:
publicTForm
{
__published:
//IDE-managedComponents
TPanel*Panel1;
TButton*btnCtrl;
TListView*lsvPacket;
TLabel*Label1;
void__fastcallbtnCtrlClick(TObject*Sender);
void__fastcalllsvPacketColumnClick(TObject*Sender,
TListColumn*Column);
void__fastcalllsvPacketCompare(TObject*Sender,TListItem*Item1,
TListItem*Item2,intData,int&Compare);
void__fastcallLabel1Click(TObject*Sender);
private:
//Userdeclarations
AnsiString__fastcallGetProtocolTxt(intProtocol);
public:
//Userdeclarations
SOCKETsock;
SOCKADDR_INaddr_in;
IPip;
TCPtcp;
PSUHDRpsdHeader;
charRecvBuf[BUFFER_SIZE];
boolbStop;
intiSortDirection;
intiColumnToSort;
__fastcallTMainForm(TComponent*Owner);
__fastcall~TMainForm();
};
//---------------------------------------------------------------------------
externPACKAGETMainForm*MainForm;
//---------------------------------------------------------------------------
#endif
IP,TCP头及一些宏定义用了netmon.h的头,这个文件在BCB6的include目录下可以找得到,其中与本程序相关内容如下:
//*************************************************************************//
//*HeaderFile:
netmon.h
//*************************************************************************//
//
//IPPacketStructure
//
typedefstruct_IP
{
union
{
BYTEVersion;
BYTEHdrLen;
};
BYTEServiceType;
WORDTotalLen;
WORDID;
union
{
WORDFlags;
WORDFragOff;
};
BYTETimeToLive;
BYTEProtocol;
WORDHdrChksum;
DWORDSrcAddr;
DWORDDstAddr;
BYTEOptions[0];
}IP;
typedefIP*LPIP;
typedefIPUNALIGNED*ULPIP;
//
//TCPPacketStructure
//
typedefstruct_TCP
{
WORDSrcPort;
WORDDstPort;
DWORDSeqNum;
DWORDAckNum;
BYTEDataOff;
BYTEFlags;
WORDWindow;
WORDChksum;
WORDUrgPtr;
}TCP;
typedefTCP*LPTCP;
typedefTCPUNALIGNED*ULPTCP;
//upperprotocols
#definePROTOCOL_STRING_ICMP_TXT"ICMP"
#definePROTOCOL_STRING_TCP_TXT"TCP"
#definePROTOCOL_STRING_UDP_TXT"UDP"
#definePROTOCOL_STRING_SPX_TXT"SPX"
#definePROTOCOL_STRING_NCP_TXT"NCP"
#definePROTOCOL_STRING_UNKNOW_TXT"UNKNOW"
这个文件也有人声称没有.
//*************************************************************************//
//*HeaderFile:
mstcpip.h
//*************************************************************************//
//Copyright(c)MicrosoftCorporation.Allrightsreserved.
#if_MSC_VER>1000
#pragmaonce
#endif
/*ArgumentstructureforSIO_KEEPALIVE_VALS*/
structtcp_keepalive{
u_longonoff;
u_longkeepalivetime;
u_longkeepaliveinterval;
};
//NewWSAIoctlOptions
#defineSIO_RCVALL_WSAIOW(IOC_VENDOR,1)
#defineSIO_RCVALL_MCAST_WSAIOW(IOC_VENDOR,2)
#defineSIO_RCVALL_IGMPMCAST_WSAIOW(IOC_VENDOR,3)
#defineSIO_KEEPALIVE_VALS_WSAIOW(IOC_VENDOR,4)
#defineSIO_ABSORB_RTRALERT_WSAIOW(IOC_VENDOR,5)
#defineSIO_UCAST_IF_WSAIOW(IOC_VENDOR,6)
#defineSIO_LIMIT_BROADCASTS_WSAIOW(IOC_VENDOR,7)
#defineSIO_INDEX_BIND_WSAIOW(IOC_VENDOR,8)
#defineSIO_INDEX_MCASTIF_WSAIOW(IOC_VENDOR,9)
#defineSIO_INDEX_ADD_MCAST_WSAIOW(IOC_VENDOR,10)
#defineSIO_INDEX_DEL_MCAST_WSAIOW(IOC_VENDOR,11)
//ValuesforusewithSIO_RCVALL*options
#defineRCVALL_OFF0
#defineRCVALL_ON1
#defineRCVALL_SOCKETLEVELONLY2
六.小结
优点:
实现简单,不需要做驱动程序就可实现抓包.
缺点:
数据包头不含帧信息,不能接收到与IP同层的其它数据包,如ARP,RARP;没有对数据包进行进一步的分析。