我正在做分析数据包的项目,
现在可以得到数据包的各个包头的数据
也就是把包都打开了
问题是得到的二进制数据怎么还原?
怎么变成发送时的字符或者附件
多谢!

解决方案 »

  1.   

    关键是你得到的是哪一层过滤出来的数据,然后在根据那一层的协议来依此提取出各个头,例如以太头,IP头,TCP头,然后就是下一层的比如SMTP,HTTP,FTP头,然后再根据具体协议来组合数据包我说得太空洞了
      

  2.   

    原理基本如楼上所说,剩下的基本靠经验了。sample code:
    //IP解包程序
    int DecodeIpPack(char *buf, int iBufSize)
    {
    IP_HEADER *pIpheader;
    SOCKADDR_IN saSource, saDest;
    pIpheader = (IP_HEADER *)buf;
    //协议甄别
    iProtocol = pIpheader->proto;
    strncpy(szProtocol, CheckProtocol(iProtocol), MAX_PROTO_TEXT_LEN);
    if((iProtocol==IPPROTO_TCP) && (!ParamTcp)) return true;
    if((iProtocol==IPPROTO_UDP) && (!ParamUdp)) return true;
    if((iProtocol==IPPROTO_ICMP) && (!ParamIcmp)) return true;
    //源地址
    saSource.sin_addr.s_addr = pIpheader->sourceIP;
    strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);
    if (strFromIpFilter)
    if (strcmp(strFromIpFilter,szSourceIP)) return true;
    //目的地址
    saDest.sin_addr.s_addr = pIpheader->destIP;
    strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);
    if (strDestIpFilter)
    if (strcmp(strDestIpFilter,szDestIP)) return true;
    iTTL = pIpheader->ttl;
    //计算IP首部的长度
    int iIphLen = sizeof(unsigned long) * (pIpheader->h_lenver & 0xf);
    //根据协议类型分别调用相应的函数
    switch(iProtocol)
    {
    case IPPROTO_TCP :DecodeTcpPack(buf+iIphLen, iBufSize);break;
    case IPPROTO_UDP :DecodeUdpPack(buf+iIphLen, iBufSize);break;
    case IPPROTO_ICMP :DecodeIcmpPack(buf+iIphLen, iBufSize);break;
    default :break;
    }
    //printf("\n");
    return true;
    }//协议识别程序
    char * CheckProtocol(int iProtocol)
    {
    for(int i=0; i<MAX_PROTO_NUM; i++)
    if(ProtoMap[i].ProtoNum==iProtocol) 
    return ProtoMap[i].ProtoText;
    return "";
    }//TCP解包程序
    int DecodeTcpPack(char * TcpBuf, int iBufSize)
    {
    TCP_HEADER * pTcpHeader;
    int i;
    int iSourcePort,iDestPort;

    pTcpHeader = (TCP_HEADER * )TcpBuf;
    //计算TCP首部长度
    int TcpHeaderLen =  pTcpHeader->th_lenres>>4;
    TcpHeaderLen *= sizeof(unsigned long);
    char * TcpData=TcpBuf+TcpHeaderLen;
    //如果过滤敏感字符串则判断是否包含
    if (strSensitive) 
    if ((strstr(TcpData, strSensitive))==NULL) return true;
    //对端口进行过滤
    iSourcePort = ntohs(pTcpHeader->th_sport);
    iDestPort = ntohs(pTcpHeader->th_dport);
    if ((iPortFilter) && (iSourcePort!=iPortFilter) && (iDestPort!=iPortFilter))
    return true;
    //输出
    printf("%s ", szProtocol);
    printf("%15s:%5d ->%15s:%5d  ", szSourceIP, iSourcePort, szDestIP, iDestPort);
    printf("TTL=%3d  ", iTTL);
    //判断TCP标志位
    unsigned char FlagMask = 1;
    for( i=0; i<6; i++ )
    {
    if((pTcpHeader->th_flag) & FlagMask) printf("%c",TcpFlag[i]);
    else printf("-");
    FlagMask=FlagMask<<1;
    }
    printf("  bytes=%4d", iBufSize);
    printf("\n");
    //对于长度大于40字节的包进行数据分析(IP_HEADER+TCP_HEADER=40)
    if ((ParamDecode) && (iBufSize>40))
    {
    //分析TCP数据段
    if ((!strSensitive) || (strstr(TcpData,strSensitive)))
    {
    printf(" [DATA]\n");
    printf("%s",TcpData);
    printf("\n [DATA END]\n\n\n");
    }
    }
    return true;
    }
    //UDP解包程序
    int DecodeUdpPack(char * UdpBuf, int iBufSize)
    {
    UDP_HEADER *pUdpHeader;
    pUdpHeader = (UDP_HEADER * )UdpBuf;
    int iSourcePort = ntohs(pUdpHeader->uh_sport);
    int iDestPort = ntohs(pUdpHeader->uh_dport);
    //对端口进行过滤
    if(iPortFilter)
    if ((iSourcePort!=iPortFilter) && (iDestPort!=iPortFilter))
    return true;
    printf("%s ", szProtocol);
    printf("%15s:%5d ->%15s:%5d  ", szSourceIP, iSourcePort, szDestIP, iDestPort);
    printf("TTL=%3d ", iTTL);
    printf("Len=%4d ", ntohs(pUdpHeader->uh_len));
    printf("bytes=%4d", iBufSize);
    printf("\n");
    //对于长度大于28字节的包进行数据分析(IP_HEADER+UDP_HEADER>28)
    if ((ParamDecode) && (iBufSize>28))
    {
    printf(" [DATA]\n");
    //UDP首部长度为8
    char * UdpData=UdpBuf+8;
    //分析UDP数据段
    for(unsigned int i=0;i<(iBufSize-sizeof(UDP_HEADER));i++) 
    {
    if (!(i%8)) printf("\n"); 
    if ( (UdpData[i]>33) && (UdpData[i]<122) )
    printf("%3c [%3x]", UdpData[i], UdpData[i]);
    else printf("    [%3x]", abs(UdpData[i]));
    }
    printf("\n [DATA END]\n\n\n");
    }
    return true;
    }//ICMP解包程序
    int DecodeIcmpPack(char * IcmpBuf, int iBufSize)
    {
    ICMP_HEADER * pIcmpHeader;
    pIcmpHeader = (ICMP_HEADER * )IcmpBuf;
    int iIcmpType = pIcmpHeader->i_type;
    int iIcmpCode = pIcmpHeader->i_code;
    //对类型进行过滤
    if ((iPortFilter) && (iIcmpType!=iPortFilter)) return true;
    printf("%s ", szProtocol);
    //printf("%15s Type%d ->%15s Code%d  ", szSourceIP, iIcmpType, szDestIP, iIcmpCode);
    printf("%15s       ->%15s        ", szSourceIP, szDestIP);
    printf("TTL=%3d ", iTTL);
    printf("Type%2d,%d ",iIcmpType,iIcmpCode);
    printf("bytes=%4d", iBufSize);
    printf("\n");
    //对于包含数据段的包进行数据分析
    if ((ParamDecode) && (iBufSize>28))
    {
    char * IcmpData=IcmpBuf+4;
    //分析ICMP数据段
    printf(" [DATA]");
    for(unsigned int i=0;i<(iBufSize-sizeof(ICMP_HEADER));i++) 
    {
    if (!(i%8)) printf("\n"); 
    if ( (IcmpData[i]>33) && (IcmpData[i]<122) )
    printf("%3c [%3x]", IcmpData[i], IcmpData[i]);
    else printf("    [%3x]", abs(IcmpData[i]));
    }
    printf("\n [DATA END]\n\n\n");
    }
    return true;
    }
      

  3.   

    如果你知道了包的结构...
    struct MyStruct
    {
       ...
    }
    你截到的包的数据放在 byte Pack[]里,
    可以用
    memcpy(&MyStruct, Pack , Length);  //length是包长
      

  4.   

    可能我说的不太明白
    我的意思说已经把IP头,TCP头都解包了.
    只是不明白得到的数据如何还原
    比如:
    他发了一个QQ数据包,
    里面含有一个附件,
    我可以把这个数据包的以太头,IP头,TCP头分析出来
    但是不知道如何还原这个附件
    怎样分析这个附件(或者文字)的二进制?
      

  5.   

    附件一般是经过加密或一定格式的编码,比如邮件,是base64编码,可以将应用层整个数据全部保存下来,整个进行还原.具体情况,具体分析
      

  6.   

    QQ是加密的,难!
    一般分析:
    包头分析->TCP排队->应用层协议解析
    对于邮件,去除pop3或smtp协议内容后,tcp流就是eml文件格式,可用oe打开。
      

  7.   

    谢谢大家
    那么对于普通的Web邮件应该如何解码
    得到邮件的文字内容和附件??
      

  8.   

    你去找费尔网页侦探,下载一个,sniffer下web邮件的内容,看它怎么组包的.
      

  9.   

    普通的web邮件一般是没有加密的,这样的话楼主应该看一下smtp,这里面有邮件的封包格式,去除所有报头就可以看到了,楼主还可以找一些开源的mail软件看看
      

  10.   

    web邮件?也难!
    察看邮件和察看普通页面相同,
    发送邮件和聊天发言相同,
    都是网站相关的,post一段文字,只有网站知道它是不是邮件。
      

  11.   

    To kingzai(stevenzhu) 
    我试试。
    To ndy_w(carpe diem)
    你的意思是不是 :不能从数据包中分析得出附件的内容?
      

  12.   

    ,
    也希望学习一下如何获取数据包,我看了TCP-IP详解的实现部分,感觉很空,在Windows上还找不到切入点。
      

  13.   

    可以下载一套winpcap开发包,里面有文档和示例代码。
      

  14.   

    to fisker0303(Thinking In Love)
        我用的是winpcap开发包,
        但我想实现的是 分析数据包的数据部分,而不是包头
      

  15.   

    对于普通得web邮件
    只要不加密
    基本上是可以解析出来的
    比如163,yahoo收发信件都可解析
    有的网站邮件服务器做得不好
    甚至连用户名密码都可以得到
      

  16.   

    to qfxx(秋风萧萧) 
      那么你还原过附件吗?
      如何能把附件解析出来?
      

  17.   

    MARK!
    //============
    如果有附件还有考虑很多因素的,如是否加密,UNICODE编码等,所以要解析附件
    难度很大
      

  18.   

    web邮件也可以解析,但:网站相关!除非做脚本解释器,否则代码不通用。
    发送附件有的是在一个form里提交(如sina),有的是单独提交(多数)。接收附件跟下载文件一样。
    附件跟邮件的联系一般在cookie中。