#include <Winsock2.h>
#include <mstcpip.h>
#pragma comment(lib,"WS2_32.lib")
typedef struct _iphdr
{
unsigned char h_lenver; //4位首部长度+4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;
typedef struct _tcphdr //定义TCP首部
{
USHORT th_sport; //16位源端口
USHORT th_dport; //16位目的端口
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_lenres;//4位首部长度/6位保留字
unsigned char th_flag; //6位标志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位校验和
USHORT th_urp; //16位紧急数据偏移量
}TCP_HEADER;
typedef struct _udphdr //定义UDP首部
{
unsigned short uh_sport;
unsigned short uh_dport;
unsigned short uh_len;
unsigned short uh_sum;
} UDP_HEADER;
typedef struct _icmphdr //定义ICMP首部
{
BYTE i_type; //8位类型
BYTE i_code; //8位代码
USHORT i_cksum; //16位校验和
USHORT i_id; //识别号(一般用进程号作为识别号)
USHORT i_seq; //报文序列号
ULONG timestamp; //时间戳
}ICMP_HEADER;
bool DecodeIpPack(const char *,int); // IP 解包
bool DecodeTcpPack(const char *); // TCP 解包
bool DecodeUdpPack(const char *); // UDP 解包
bool DecodeIcmpPack(const char *); // ICMP 解包
const char * CheckProtocol(int);// 查询协议
int _tmain(int argc, _TCHAR* argv[])
{
// 初始化SOCKET
WSADATA wsaData;
int iErrorCode = ::WSAStartup( MAKEWORD(2,1), &wsaData );
if( SOCKET_ERROR == iErrorCode )
{
printf( "WSAStartup() error. " );
return -1;
}
SOCKET sock = ::socket( AF_INET, SOCK_RAW, IPPROTO_IP );
if( INVALID_SOCKET == sock )
{
printf( "socket() error. " );
return -1;
}
//获取本机IP地址
char szHostName[200];
iErrorCode = ::gethostname( szHostName, sizeof(szHostName) );
if( SOCKET_ERROR == iErrorCode )
{
printf( "gethostname() error. " );
return -1;
}
PHOSTENT pHostent = ::gethostbyname( szHostName );
if( NULL == pHostent )
{
printf( "gethostbyname() error. " );
return -1;
}
SOCKADDR_IN sa;
sa.sin_family = AF_INET;
memcpy( &sa.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length );
sa.sin_port = htons( 60000 );
iErrorCode = ::bind( sock, (PSOCKADDR)&sa, sizeof(sa) );
if( SOCKET_ERROR == iErrorCode )
{
printf( "bind() error. " );
return -1;
}
// 设置 SOCK_RAW 为 SIO_RCVALL,接收所有的 IP 包
DWORD dwBufferLen[10];
DWORD dwBufferInLen = 1;
DWORD dwBytesReturned = 0;
iErrorCode = ::WSAIoctl( sock, SIO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen,
sizeof( dwBufferLen ), &dwBytesReturned, NULL, NULL );
if( SOCKET_ERROR == iErrorCode )
{
printf( "Ioctl() error. " );
return -1;
}
//侦听IP报文
while( 1 )
{
char package[8 * 1024] = { 0 }; // 数据缓冲区
iErrorCode = ::recv( sock, package, sizeof(package), 0 );
if( SOCKET_ERROR == iErrorCode )
printf( "recv() error. " );
else if( !DecodeIpPack( package, iErrorCode ) ) // 解析 IP 包
printf( "DecodeIpPack() error. " );
}
// ::Closesocket( sock );
// ::WSACleanup();
return 0;
}
// 解析 IP 包
bool DecodeIpPack(const char *buf, int iBufSize)
{
IP_HEADER *pIpheader;
int iProtocol, iTTL;
char szProtocol[12];
char szSourceIP[16];
char szDestIP[16];
SOCKADDR_IN saSource, saDest;
pIpheader = (IP_HEADER *)buf;
//Check Proto
iProtocol = pIpheader->proto;
::strcpy( szProtocol, CheckProtocol(iProtocol) );
//Check Source IP
saSource.sin_addr.s_addr = pIpheader->sourceIP;
::strcpy( szSourceIP, inet_ntoa(saSource.sin_addr) );
//Check Dest IP
saDest.sin_addr.s_addr = pIpheader->destIP;
::strcpy( szDestIP, inet_ntoa(saDest.sin_addr) );
iTTL = pIpheader->ttl;
//Output
printf( "%s ", szProtocol );
printf( "%s->%s ", szSourceIP, szDestIP );
printf( "bytes=%d TTL=%d ",iBufSize,iTTL );
//Calculate IP Header Length
int iIphLen = sizeof(unsigned long) * ( pIpheader->h_lenver & 0x0f );
//Decode Sub Protocol:TCP, UDP, ICMP, etc
switch( iProtocol )
{
case IPPROTO_TCP: DecodeTcpPack( buf + iIphLen ); break;
case IPPROTO_UDP: DecodeUdpPack( buf + iIphLen ); break;
case IPPROTO_ICMP: DecodeIcmpPack( buf + iIphLen ); break;
default: break;
}
printf( " " );
int col = 0;
char ascii[17];
for( int i=0; i<iBufSize; i++ )
{
printf( "%02X ", (unsigned char)buf[i] );
ascii[ col++ ] = ( unsigned char )buf[i] < 0x20 ? '.' : buf[i];
if( 15 == i%16 )
{
ascii[ col ] = 0;
printf( "%s ", ascii );
col = 0;
}
else if( 7 == i%8 ) printf( "- " );
}
if( col )
{
for( int i=col; i<16; i++ )
{
printf( " " );
if( 15 == i%16 )
{
ascii[ col ] = 0;
printf( "%s ", ascii );
}
else if( 7 == i%8 ) printf( "- " );
}
}
return true;
}
//协议识别程序
const char * CheckProtocol(int iProtocol)
{
typedef struct _protomap //定义子协议映射表
{
int ProtoNum;
char ProtoText[12];
}PROTOMAP;
static PROTOMAP ProtoMap[]={ //为子协议映射表赋值
{ IPPROTO_IP, "IP" },
{ IPPROTO_ICMP, "ICMP" },
{ IPPROTO_IGMP, "IGMP" },
{ IPPROTO_GGP, "GGP" },
{ IPPROTO_IPV4, "IPV4" },
{ IPPROTO_TCP, "TCP" },
{ IPPROTO_PUP, "PUP" },
{ IPPROTO_UDP, "UDP" },
{ IPPROTO_IDP, "IDP" },
{ IPPROTO_IPV6, "IPV6" },
{ IPPROTO_ROUTING, "ROUTING" },
{ IPPROTO_FRAGMENT, "FRAGMENT" },
{ IPPROTO_ESP, "ESP" },
{ IPPROTO_AH, "AH" },
{ IPPROTO_ICMPV6, "ICMPV6" },
{ IPPROTO_NONE, "NONE" },
{ IPPROTO_DSTOPTS, "DSTOPTS" },
{ IPPROTO_ND, "ND" },
{ IPPROTO_ICLFXBM, "ICLFXBM" },
{ IPPROTO_RAW, "RAW" },
{ IPPROTO_MAX, "MAX" },
};
const int nProtoCount = sizeof(ProtoMap)/sizeof(PROTOMAP);
for(int i=0; i<nProtoCount; i++)
{
if(ProtoMap[i].ProtoNum==iProtocol)
return ProtoMap[i].ProtoText;
}
return "";
}
//TCP解包程序
bool DecodeTcpPack(const char * TcpBuf)
{
TCP_HEADER * pTcpHeader;
int i;
pTcpHeader = (TCP_HEADER * )TcpBuf;
printf("Port:%d->%d ", ntohs(pTcpHeader->th_sport),ntohs(pTcpHeader->th_dport));
unsigned char FlagMask = 1;
for( i=0; i<6; i++ )
{
static char * TcpFlag = "FSRPAU"; //定义TCP标志位
if( ( pTcpHeader->th_flag ) & FlagMask )
printf( "%c", TcpFlag[i] );
else printf( "-" );
FlagMask = FlagMask << 1;
}
return true;
}
//UDP解包程序
bool DecodeUdpPack(const char * UdpBuf)
{
UDP_HEADER *pUdpHeader;
pUdpHeader = (UDP_HEADER * )UdpBuf;
printf("Port:%d->%d ", ntohs(pUdpHeader->uh_sport), ntohs(pUdpHeader->uh_dport));
printf("Len=%d", ntohs(pUdpHeader->uh_len));
return true;
}
//ICMP解包程序
bool DecodeIcmpPack(const char * IcmpBuf)
{
ICMP_HEADER *pIcmpHeader;
pIcmpHeader = (ICMP_HEADER * )IcmpBuf;
printf("Type:%d,%d ", pIcmpHeader->i_type,pIcmpHeader->i_code);
printf("ID=%d SEQ=%d", pIcmpHeader->i_id, pIcmpHeader->i_seq);
return true;
}
评论
# re: 小巧玲珑的网络抓包
周星星
Posted @ 2006-11-01 13:42
60000端口是什么呀?
假如我想抓所有端口的原始数据包该怎么做?
# **,60000是自己的端口,但RAW下,它能抓任意端口的数据包
老梆菜
Posted @ 2006-11-01 13:45
你运行看看啦
# re: 小巧玲珑的网络抓包
周星星
Posted @ 2006-11-01 15:41
由于格式转化的原因,有部分空格没能粘贴出来,导致界面混乱,这是blog的问题。
8 * 1024 不是固定的,可否直接获得?
我有一点疑惑,既然这些数据被你截获了,为什么却不影响正常通讯?
# to **
老梆菜
Posted @ 2006-11-01 20:27
8*1024是随便定的,当然可以先读IP头,从IP头中的 total_len 得到真实的长度,raw socket 是内部方法,它直接读写网卡,因此不影响正常程序的正常通讯
# re: 小巧玲珑的网络抓包
周星星
Posted @ 2006-11-02 08:58
:) 老杨无秘密了
# re: 小巧玲珑的网络抓包
showgt
Posted @ 2006-11-08 23:47
老师怎么直接复制到VC++怎么运行不了的啊?
错误:atal error C1083: Cannot open include file: 'mstcpip.h': No such file or directory
Error executing cl.exe.
# to showgt
杨
Posted @ 2006-11-10 00:00
我使用 vc.net 编写,不知道 vc6 下的效果:)
# re: 小巧玲珑的网络抓包
向陽樹
Posted @ 2006-12-08 11:47
// ::Closesocket( sock );
// ::WSACleanup();
上面兩句為什麼要注釋掉呢?
# re: 小巧玲珑的网络抓包
玻璃小屋
Posted @ 2007-01-25 12:35
截到包,能破坏这个包,不让上层程序接受不???
# re: 小巧玲珑的网络抓包
困惑
Posted @ 2007-02-27 22:27
:P,梆菜,你的另一个身份是不是shotgun?