在练用raw socket来捕获 数据包然后分析其中的http协议的数据
本来可以捕获发送的包和接受的包的,今天还原了下系统,发现只能捕获接受的包。完全没有头绪.还有个问题就是,用raw socket捕获的是IP层的数据包,如果要分析的其中的TCP的数据
请问raw socket 接受的IP包顺序,剥离IP头后获取的TCP包是有序的吗?还是乱序?如果是乱序请问怎样处理?
如果有多个程序发送了TCP数据,那么使用raw socket捕获后的tcp数据是乱序的吗?要怎么处理?
#include "stdafx.h"
#include "stdio.h"
#include "winsock2.h"
#include "wtypes.h"
#include "string.h"
#include "atltime.h"
#include <Mstcpip.h>
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#pragma comment(lib,"ws2_32.lib")
//IPv4包头结构体
typedef struct ip_header {
unsigned char ver_ihl; //Version (4 bits) + Internet header length (4 bits)
unsigned char tos; //Type of service
unsigned short tlen; //Total length
unsigned short identification; //Identification
unsigned short flags_fo; //Flags (3 bits) + Fragment offset (13 bits)
unsigned char ttl; //Time to live
unsigned char proto; //Protocol
unsigned short crc; //Header checksum
u_char ip_src[4]; //Source address
u_char ip_dst[4]; //Destination address
}IPHEADER,*PIPHEADER;//IPv4包头结构体//TCP包头结构体
typedef struct tcp_header {
WORD SourPort; //源端口号
WORD DestPort; //目的端口号
DWORD SeqNo; //序号
DWORD AckNo; //确认序号
BYTE HLen; //首部长度(保留位)
BYTE Flag; //标识(保留位)
WORD Window; //窗口大小
WORD ChkSum; //校验和
WORD UrgPtr; //紧急指针
}TCPHEADER,*PTCPHEADER;
/* 函数声明 */
typedef void (* PACKPROCESS_HANDLE)(const IPHEADER * ip_header,const void* pack_Data);
void InitWinsock2(void);
void BindSocket(void);
void ReceivePackage(const char *filerCode,PACKPROCESS_HANDLE process);
void Package_Handle(const IPHEADER * ip_header,const void* pack_Data);
SOCKET s = INVALID_SOCKET;
int _tmain(int argc, _TCHAR* argv[])
{InitWinsock2();
BindSocket();
ReceivePackage(NULL,Package_Handle);
if(INVALID_SOCKET !=s)
closesocket(s);
WSACleanup();
return 0;
}//初始化WinSock2
void InitWinsock2()
{
WSADATA wsaData;
WORD version;
int ret; version=MAKEWORD(2,2);
ret=WSAStartup(version,&wsaData);
if(ret!=0) {
printf("Failed to load winsock2 library.\n");
return ;
}
}void BindSocket()
{
PHOSTENT pHost; pHost = gethostbyname(NULL);
if(NULL == pHost)
{
printf("Get Host Info Error.\n");
return;
}
SOCKADDR_IN hostAddr; memcpy(&hostAddr.sin_addr.S_un.S_addr,pHost->h_addr_list[0],pHost->h_length); printf("HostName:%s\n",pHost->h_name);
printf("Addr:%s\n",inet_ntoa(hostAddr.sin_addr));
hostAddr.sin_family = AF_INET;
hostAddr.sin_port = htons(0);
s = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
if(INVALID_SOCKET == s)
{printf("Get socket fail!.\n");return;}
if(SOCKET_ERROR== ::bind(s,(SOCKADDR *)&hostAddr,sizeof(hostAddr)))
{
printf("Bind Socket fail.%d\n",WSAGetLastError());return;
}
DWORD dwBytesRet;
DWORD dwVal=1;
//
if(WSAIoctl(s,SIO_RCVALL,&dwVal,sizeof(dwVal),NULL,0,&dwBytesRet,NULL,NULL)==SOCKET_ERROR)
{
printf("WSAIoctl fail.%d\n",WSAGetLastError());return;
}
}void Package_Handle(const IPHEADER * ip_header,const void* pack_Data)
{
PTCPHEADER tcp_header;
char *pData = NULL;
size_t tcpDataSize = 0;
unsigned short ipPackLen = 0,tcpHLen = 0,ipHLen = 0;
unsigned short webport = htons(80); ipPackLen = ntohs(ip_header->tlen);
ipHLen = 4 * (ip_header->ver_ihl&0xF);
tcp_header = (TCPHEADER *)(pack_Data);
tcpHLen = tcp_header->HLen>>2;
//捕获80端口数据
if(ip_header->proto == IPPROTO_TCP && (tcp_header->SourPort == webport || tcp_header->DestPort == webport))
{
pData = (char *)pack_Data + tcpHLen;
printf("%d.%d.%d.%d -> %d.%d.%d.%d ",
ip_header->ip_src[0],ip_header->ip_src[1],ip_header->ip_src[2],ip_header->ip_src[3],
ip_header->ip_dst[0],ip_header->ip_dst[1],ip_header->ip_dst[2],ip_header->ip_dst[3]
);
printf("源端口:%d ",ntohs(tcp_header->SourPort));
printf("目的端口:%d ",ntohs(tcp_header->DestPort));
printf("\n\n");
tcpDataSize = ipPackLen - ipHLen - tcpHLen; //处理发送数据
if( (pData[0]=='G' && pData[1]=='E' && pData[2]=='T' )||
(pData[0]=='P' && pData[1]=='O' && pData[2]=='S' && pData[3]=='T'))
{
printf("\b\bHttp Request:\n");
}
else if((pData[0]=='H' && pData[1]=='T' && pData[2]=='T' && pData[3]=='P'))
{
printf("\b\bHttp Response:\n");
}
}//end of if
}void ReceivePackage(const char *filerCode,PACKPROCESS_HANDLE process)
{
PIPHEADER ip_header;
int nRet =0;
const int bufSize=0xFFFF;
char buf[bufSize];
memset((void *)buf,0,bufSize);
unsigned short ipHLen;
while(true)
{
//receive package data
nRet = recv(s,buf,bufSize,0); ip_header = (IPHEADER *)buf;
ipHLen = 4 * (ip_header->ver_ihl&0xF); //Call the Handler funcion
if(NULL!= process)
(*process)(ip_header,(void *)((unsigned char *)ip_header + ipHLen)); }
}
本来可以捕获发送的包和接受的包的,今天还原了下系统,发现只能捕获接受的包。完全没有头绪.还有个问题就是,用raw socket捕获的是IP层的数据包,如果要分析的其中的TCP的数据
请问raw socket 接受的IP包顺序,剥离IP头后获取的TCP包是有序的吗?还是乱序?如果是乱序请问怎样处理?
如果有多个程序发送了TCP数据,那么使用raw socket捕获后的tcp数据是乱序的吗?要怎么处理?
#include "stdafx.h"
#include "stdio.h"
#include "winsock2.h"
#include "wtypes.h"
#include "string.h"
#include "atltime.h"
#include <Mstcpip.h>
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#pragma comment(lib,"ws2_32.lib")
//IPv4包头结构体
typedef struct ip_header {
unsigned char ver_ihl; //Version (4 bits) + Internet header length (4 bits)
unsigned char tos; //Type of service
unsigned short tlen; //Total length
unsigned short identification; //Identification
unsigned short flags_fo; //Flags (3 bits) + Fragment offset (13 bits)
unsigned char ttl; //Time to live
unsigned char proto; //Protocol
unsigned short crc; //Header checksum
u_char ip_src[4]; //Source address
u_char ip_dst[4]; //Destination address
}IPHEADER,*PIPHEADER;//IPv4包头结构体//TCP包头结构体
typedef struct tcp_header {
WORD SourPort; //源端口号
WORD DestPort; //目的端口号
DWORD SeqNo; //序号
DWORD AckNo; //确认序号
BYTE HLen; //首部长度(保留位)
BYTE Flag; //标识(保留位)
WORD Window; //窗口大小
WORD ChkSum; //校验和
WORD UrgPtr; //紧急指针
}TCPHEADER,*PTCPHEADER;
/* 函数声明 */
typedef void (* PACKPROCESS_HANDLE)(const IPHEADER * ip_header,const void* pack_Data);
void InitWinsock2(void);
void BindSocket(void);
void ReceivePackage(const char *filerCode,PACKPROCESS_HANDLE process);
void Package_Handle(const IPHEADER * ip_header,const void* pack_Data);
SOCKET s = INVALID_SOCKET;
int _tmain(int argc, _TCHAR* argv[])
{InitWinsock2();
BindSocket();
ReceivePackage(NULL,Package_Handle);
if(INVALID_SOCKET !=s)
closesocket(s);
WSACleanup();
return 0;
}//初始化WinSock2
void InitWinsock2()
{
WSADATA wsaData;
WORD version;
int ret; version=MAKEWORD(2,2);
ret=WSAStartup(version,&wsaData);
if(ret!=0) {
printf("Failed to load winsock2 library.\n");
return ;
}
}void BindSocket()
{
PHOSTENT pHost; pHost = gethostbyname(NULL);
if(NULL == pHost)
{
printf("Get Host Info Error.\n");
return;
}
SOCKADDR_IN hostAddr; memcpy(&hostAddr.sin_addr.S_un.S_addr,pHost->h_addr_list[0],pHost->h_length); printf("HostName:%s\n",pHost->h_name);
printf("Addr:%s\n",inet_ntoa(hostAddr.sin_addr));
hostAddr.sin_family = AF_INET;
hostAddr.sin_port = htons(0);
s = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
if(INVALID_SOCKET == s)
{printf("Get socket fail!.\n");return;}
if(SOCKET_ERROR== ::bind(s,(SOCKADDR *)&hostAddr,sizeof(hostAddr)))
{
printf("Bind Socket fail.%d\n",WSAGetLastError());return;
}
DWORD dwBytesRet;
DWORD dwVal=1;
//
if(WSAIoctl(s,SIO_RCVALL,&dwVal,sizeof(dwVal),NULL,0,&dwBytesRet,NULL,NULL)==SOCKET_ERROR)
{
printf("WSAIoctl fail.%d\n",WSAGetLastError());return;
}
}void Package_Handle(const IPHEADER * ip_header,const void* pack_Data)
{
PTCPHEADER tcp_header;
char *pData = NULL;
size_t tcpDataSize = 0;
unsigned short ipPackLen = 0,tcpHLen = 0,ipHLen = 0;
unsigned short webport = htons(80); ipPackLen = ntohs(ip_header->tlen);
ipHLen = 4 * (ip_header->ver_ihl&0xF);
tcp_header = (TCPHEADER *)(pack_Data);
tcpHLen = tcp_header->HLen>>2;
//捕获80端口数据
if(ip_header->proto == IPPROTO_TCP && (tcp_header->SourPort == webport || tcp_header->DestPort == webport))
{
pData = (char *)pack_Data + tcpHLen;
printf("%d.%d.%d.%d -> %d.%d.%d.%d ",
ip_header->ip_src[0],ip_header->ip_src[1],ip_header->ip_src[2],ip_header->ip_src[3],
ip_header->ip_dst[0],ip_header->ip_dst[1],ip_header->ip_dst[2],ip_header->ip_dst[3]
);
printf("源端口:%d ",ntohs(tcp_header->SourPort));
printf("目的端口:%d ",ntohs(tcp_header->DestPort));
printf("\n\n");
tcpDataSize = ipPackLen - ipHLen - tcpHLen; //处理发送数据
if( (pData[0]=='G' && pData[1]=='E' && pData[2]=='T' )||
(pData[0]=='P' && pData[1]=='O' && pData[2]=='S' && pData[3]=='T'))
{
printf("\b\bHttp Request:\n");
}
else if((pData[0]=='H' && pData[1]=='T' && pData[2]=='T' && pData[3]=='P'))
{
printf("\b\bHttp Response:\n");
}
}//end of if
}void ReceivePackage(const char *filerCode,PACKPROCESS_HANDLE process)
{
PIPHEADER ip_header;
int nRet =0;
const int bufSize=0xFFFF;
char buf[bufSize];
memset((void *)buf,0,bufSize);
unsigned short ipHLen;
while(true)
{
//receive package data
nRet = recv(s,buf,bufSize,0); ip_header = (IPHEADER *)buf;
ipHLen = 4 * (ip_header->ver_ihl&0xF); //Call the Handler funcion
if(NULL!= process)
(*process)(ip_header,(void *)((unsigned char *)ip_header + ipHLen)); }
}
RAW socket是基于协议驱动之上的,所以它提交的包是正确顺序的,不用担心包错的情况