• 抓包分析YY音频


    YY的音频数据传输是P2P协议,音频的编码为AAC,下面抓去的音频编码的信息和频谱信息。

    音频编码为AAC,采样为44K,码率24kb/s。音频编码在24kb/s码率能达到15K的音质。值得大家学习啊。

     

    1.准备工具

    procexp.exe      分析YY的进程信息

    Procmon.exe      分析YY的网络数据包

    wireshark.exe    分析网络包的内容

     

    2.分析YY的进程信息

      使用procexp分析YY的大致信息,比如进程号,网络连接等

     

     

     

    3.分析YY的网络传输信息

    使用procmon分析YY的网络数据,根据上面的得到的进程ID设置过滤,只接受YY的UDP数据包

     

    过滤后得到数据包如下:


    从上面的数据可以看到端口为8456的UDP接受数据最多,可以看出这个端口接受的就是P2P音频数据。

     

    4.使用wireshark抓取P2P音频数据包

    设置wireshark的过滤器,只抓去端口为8456的UDP数据包

     

    抓去的数据如下:

     

    查看UDP数据流,这里面存的就是YY的音频数据。从下面的数据看不出来具体的音频编码。

    不急,我们多看几个数据包就会发现,他们都有固定的数据头,紧接着都刚好是0xff|0xf1(这个刚好是aac ADTS的同步头)。所以我们可以按照这个思路分析下去。

     

     

    5. 使用代码分析pcap抓去的数据包

    详细分析参考代码:

     

      1. #include <stdio.h>  
      2. #include <stdlib.h>  
      3. #include <WinSock2.h>  
      4. #include <assert.h>  
      5.   
      6. ///  
      7. typedef unsigned int  bpf_u_int32;  
      8. typedef unsigned char u_char;  
      9. typedef unsigned short  u_short;  
      10. typedef unsigned int u_int;  
      11. typedef int bpf_int32;  
      12.   
      13. /* 
      14. Pcap文件分析如下: 
      15. +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ 
      16. |Pcap Header    |Packet Header  |Packet Body    |Packet Header  |Packet Body    |        
      17. +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ 
      18.  
      19. */  
      20. /* 
      21. Pcap文件头 
      22. +-------+-------+-------+-------+ 
      23. |       Magic 4B                | 
      24. +-------+-------+-------+-------+ 
      25. |   Major 2B    |  Minor 2B     | 
      26. +-------+-------+-------+-------+ 
      27. |       ThisZone 4B             | 
      28. +-------+-------+-------+-------+ 
      29. |       SigFigs 4B              | 
      30. +-------+-------+-------+-------+ 
      31. |       SnapLen 4B              | 
      32. +-------+-------+-------+-------+ 
      33. |       LinkType 4B             | 
      34. +-------+-------+-------+-------+ 
      35.  
      36. Pcap文件头24B各字段说明: 
      37. Magic:4B:0x1A 2B 3C 4D:用来标示文件的开始 
      38. Major:2B,0x02 00:当前文件主要的版本号      
      39. Minor:2B,0x04 00当前文件次要的版本号 
      40. ThisZone:4B当地的标准时间;全零 
      41. SigFigs:4B时间戳的精度;全零 
      42. SnapLen:4B最大的存储长度     
      43. LinkType:4B链路类型 
      44. 常用类型: 
      45. 0            BSD loopback devices, except for later OpenBSD 
      46. 1            Ethernet, and Linux loopback devices 
      47. 6            802.5 Token Ring 
      48. 7            ARCnet 
      49. 8            SLIP 
      50. 9            PPP 
      51. */  
      52. typedef struct pcap_file_header {  
      53.     bpf_u_int32 magic;  
      54.     u_short version_major;  
      55.     u_short version_minor;  
      56.     bpf_int32 thiszone;      
      57.     bpf_u_int32 sigfigs;     
      58.     bpf_u_int32 snaplen;     
      59.     bpf_u_int32 linktype;    
      60. }pcap_file_header;  
      61.   
      62. /* 
      63. Packet 包头和Packet数据组成 
      64. +-------+-------+ 
      65. |Packet Header  | 
      66. +-------+-------+ 
      67. |Packet Body    | 
      68. +-------+-------+ 
      69.  
      70. Paket 包头 
      71. +-------+-------+-------+-------+ 
      72. |       Timestamp 4B            | 
      73. +-------+-------+-------+-------+ 
      74. |       Timestamp 4B            | 
      75. +-------+-------+-------+-------+ 
      76. |       Caplen 4B               | 
      77. +-------+-------+-------+-------+ 
      78. |       Len 4B                  | 
      79. +-------+-------+-------+-------+ 
      80.  
      81. 字段说明: 
      82. Timestamp:时间戳高位,精确到seconds      
      83. Timestamp:时间戳低位,精确到microseconds 
      84. Caplen:当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置。 
      85. Len:离线数据长度:网络中实际数据帧的长度,一般不大于caplen,多数情况下和Caplen数值相等。 
      86. Packet 数据:即 Packet(通常就是链路层的数据帧)具体内容,长度就是Caplen,这个长度的后面,就是当前PCAP文件中存放的下一个Packet数据包,也就 是说:PCAP文件里面并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位置。我们需要靠第一个Packet包确定。 
      87. */  
      88. typedef struct  timestamp{  
      89.     bpf_u_int32 timestamp_s;  
      90.     bpf_u_int32 timestamp_ms;  
      91. }timestamp;  
      92.   
      93. typedef struct pcap_header{  
      94.     timestamp ts;  
      95.     bpf_u_int32 capture_len;  
      96.     bpf_u_int32 len;  
      97.   
      98. }pcap_header;  
      99.   
      100. //help funtion  
      101. void  printPcapHeader(pcap_file_header * ph)      
      102. {  
      103.     printf("===================== "  
      104.        "magic:0x%0x "  
      105.        "version_major:%u "  
      106.        "version_minor:%u "  
      107.        "thiszone:%d "  
      108.        "sigfigs:%u "  
      109.        "snaplen:%u "  
      110.        "linktype:%u "  
      111.        "===================== ",  
      112.        ph->magic,  
      113.        ph->version_major,  
      114.        ph->version_minor,  
      115.        ph->thiszone,  
      116.        ph->sigfigs,  
      117.        ph->snaplen,  
      118.        ph->linktype);  
      119. }  
      120.   
      121. void printPacketHeader(pcap_header * ph)  
      122. {  
      123.     printf("===================== "  
      124.         "ts.timestamp_s:%u "  
      125.         "ts.timestamp_ms:%u "  
      126.         "capture_len:%u "  
      127.         "len:%d "  
      128.         "===================== ",  
      129.         ph->ts.timestamp_s,  
      130.         ph->ts.timestamp_ms,  
      131.         ph->capture_len,  
      132.         ph->len);  
      133. }  
      134. //////////////////////////////////////////////////////////////////////////  
      135. /* 
      136.     UDP包分析 
      137. */  
      138. /* 4字节的IP地址 */  
      139. typedef struct ip_address{  
      140.     u_char byte1;  
      141.     u_char byte2;  
      142.     u_char byte3;  
      143.     u_char byte4;  
      144. }ip_address;  
      145.   
      146. /* IPv4头 */  
      147. typedef struct ip_header{  
      148.     u_char  ver_ihl;        // 版本 (4 bits) + 首部长度 (4 bits)  /// 首部长度  
      149.     u_char  tos;            // 服务类型(Type of service)   
      150.     u_short tlen;           // 总长(Total length)   
      151.     u_short identification; // 标识(Identification)  
      152.     u_short flags_fo;       // 标志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits)  
      153.     u_char  ttl;            // 存活时间(Time to live)  
      154.     u_char  proto;          // 协议(Protocol)  
      155.     u_short crc;            // 首部校验和(Header checksum)  
      156.     ip_address  saddr;      // 源地址(Source address)  
      157.     ip_address  daddr;      // 目的地址(Destination address)  
      158.     u_int   op_pad;         // 选项与填充(Option + Padding)  
      159. }ip_header;  
      160.   
      161. /* UDP头 */  
      162. typedef struct udp_header{  
      163.     u_short sport;          // 源端口(Source port)  
      164.     u_short dport;          // 目的端口(Destination port)  
      165.     u_short len;            // UDP数据包长度(Datagram length)   /// UDP总长度  
      166.     u_short crc;            // 校验和(Checksum)  
      167. }udp_header;  
      168.   
      169. u_char pkt_data[65536];  
      170.   
      171. int main()  
      172. {  
      173.     FILE * fp = fopen("yy.p2p.packet_long.pcap""rb");  
      174.     if (!fp)  
      175.     {  
      176.         fprintf(stderr, "open file error ");  
      177.         return -1;  
      178.     }  
      179.     FILE * aacfp = fopen("yy.p2p.packet_long.pcap.aac""wb");  
      180.     if (!fp)  
      181.     {  
      182.         fprintf(stderr, "open file error ");  
      183.         return -1;  
      184.     }  
      185.   
      186.     //1. Read pcap file header  
      187.     pcap_file_header pfh;  
      188.     fread(&pfh, 1, sizeof(pfh), fp);  
      189.     printPcapHeader(&pfh);  
      190.       
      191.   
      192.     //2. Read pcap packet  
      193.     while (!feof(fp))  
      194.     {  
      195.         pcap_header ph;  
      196.         if (fread(&ph, 1, sizeof(ph), fp) != sizeof(ph))  
      197.             break;  
      198.         printPacketHeader(&ph);  
      199.           
      200.         if (fread(pkt_data, 1, ph.capture_len, fp) != ph.capture_len)  
      201.             break;  
      202.   
      203.         //3. 分析消息包内容  
      204.         //fseek(fp, ph.capture_len, 1);  
      205.         // 获取IP数据包头的位置  
      206.         ip_header *ih = (ip_header *)(pkt_data + 14); // 14以太网头部长度  
      207.               
      208.         // 只处理UDP包  
      209.         if (ih->proto != 0x11)  
      210.             continue;  
      211.   
      212.         // 获取UDP首部的位置  
      213.         u_int ip_len = (ih->ver_ihl & 0x0f) * 4;  
      214.         udp_header * uh = (udp_header *)((u_char *)ih + ip_len);  
      215.       
      216.         //   
      217.         u_short sport = ntohs(uh->sport);    
      218.         u_short dport = ntohs(uh->dport);  
      219.         u_short udplen = ntohs(uh->len);  
      220.   
      221.         if(sport != 8455) // yy源端口为8455  
      222.             continue;   
      223.         /* 打印IP地址和UDP端口 */  
      224.         printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d ",  
      225.             ih->saddr.byte1,  
      226.             ih->saddr.byte2,  
      227.             ih->saddr.byte3,  
      228.             ih->saddr.byte4,  
      229.             sport,  
      230.             ih->daddr.byte1,  
      231.             ih->daddr.byte2,  
      232.             ih->daddr.byte3,  
      233.             ih->daddr.byte4,  
      234.             dport);  
      235.   
      236.         //  
      237.         u_char * udp_data = (u_char *)uh + 8;  
      238.         //u_char * aac_data = udp_data + 34;  
      239.         //u_short  aac_len = udplen - 8 - 34;  
      240.   
      241.         u_char * aac_data = pkt_data + 14 + ip_len + 8 + 34;  
      242.         int  aac_len = ph.capture_len - (14 + ip_len + 8 + 34);  
      243.         //assert(aac_len > 0);   
      244.         if (aac_len <= 0) continue;   /// 只有 yy头,没有aac数据  
      245.         assert(aac_len < ph.capture_len);  
      246.   
      247.         printf("aac len = %d pkt_len = %d ", aac_len, ph.capture_len);  
      248.         assert(aac_data[0] == 0xff && aac_data[1] == 0xf1);  
      249.               
      250.         fwrite(aac_data, 1, aac_len, aacfp);  
      251.   
      252.     }  
      253.   
      254.     fclose(fp);  
      255.     fclose(aacfp);  
      256.     return 0;  
      257. }  
  • 相关阅读:
    主题样式切换代码:jQuery Theme Switcher
    MongoDB北大绿卡之安全建议
    Sketch 快速创建调色板技巧(PS 同样适用)
    你未必知道的12个JavaScript技巧
    js 面向对象 打气球小游戏
    js 行走的小女孩 面向对象
    js 小练习题
    css 实现九宫格
    JDK java version "1.8.0_181"环境搭建
    juery 弹出框
  • 原文地址:https://www.cnblogs.com/fuland/p/3787825.html
Copyright © 2020-2023  润新知