在练用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));   }
   
}

解决方案 »

  1.   

    没用过raw socket,不过抓包工具都是用NDIS驱动实现的,raw socket自身有相当的局限性
      

  2.   

    RAW socket可以捕获发送包?没有吧?
    RAW socket是基于协议驱动之上的,所以它提交的包是正确顺序的,不用担心包错的情况
      

  3.   

    RCVALL就是只能捕获接收的数据。你要捕获发送的数据,用HOOK,SPI LSP来搞吧
      

  4.   

    可以捕获发送包的,只是不能发送TCP 、UDP数据包而已!看看是不是防火墙,还有什么软件权限之类的~~~~