This article teaches you how to use C code to parse a network data packet?

This article teaches you how to use C code to parse a network data packet?

[[416402]]

The purpose of this article is to randomly intercept a network data packet and then parse this memory according to the protocol type.

Basic knowledge you need to master to study this article:

  1. Network Protocol
  2. C
  3. Linux Operation
  4. Use of packet capture tools

The installation and use of the packet capture tool are as follows:

"Learn how to capture network data in one article"

The video tutorial link is as follows:

"Teach you how to capture data packets on the network! Essential skills for hackers"

1. Intercept a network data packet

Use the packet capture tool to randomly capture a TCP data packet


The data packet information parsed by the Collet packet capture tool is as follows:


Memory information of the data packet:


The data information can be copied directly:


2. Structures used

Next, I will teach you step by step how to parse the information of these data packets.

We can find the definition of the protocol header from the Linux kernel

Ether Header:

  1. drivers\staging\rtl8188eu\include\if_ether.h
  1. struct ethhdr {
  2. unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
  3. unsigned char h_source[ETH_ALEN]; /* source ether addr */
  4. unsigned short h_proto; /* packet type ID field */
  5. };

IP header

  1. include_uapi_linux_ip.h
  1. struct iphdr {
  2. #if defined(__LITTLE_ENDIAN_BITFIELD) //little endian mode
  3. __u8 ihl:4,
  4. version:4;
  5. #elif defined(__BIG_ENDIAN_BITFIELD) //Big endian mode
  6. __u8 version:4,
  7. ihl:4;
  8. #endif
  9. __u8 tos;
  10. __u16 tot_len;
  11. __u16 id;
  12. __u16 frag_off;
  13. __u8 ttl;
  14. __u8 protocol;
  15. __u16 check ;
  16. __u32 saddr;
  17. __u32 daddr;
  18. /*The options start here. */
  19. };

TCP header

  1. include_uapi_linux_tcp.h
  1. struct tcphdr {
  2. __be16 source;
  3. __be16 dest;
  4. __be32 seq;
  5. __be32 ack_seq;
  6. #if defined(__LITTLE_ENDIAN_BITFIELD)
  7. __u16 res1:4,
  8. doff:4,
  9. fin:1,
  10. syn:1,
  11. rst:1,
  12. psh:1,
  13. ack:1,
  14. urg:1,
  15. ece:1,
  16. cwr:1;
  17. #elif defined(__BIG_ENDIAN_BITFIELD)
  18. __u16 doff:4,
  19. res1:4,
  20. cwr:1,
  21. ece:1,
  22. urg:1,
  23. ack:1,
  24. psh:1,
  25. rst:1,
  26. syn:1,
  27. fin:1;
  28. # else  
  29. #error "Adjust your <asm/byteorder.h> defines"  
  30. #endif
  31. __be16 window;
  32. __sum16 check ;
  33. __be16 urg_ptr;
  34. };

Because the protocol header length is defined according to the standard protocol,

So the Ethernet length is 14, the IP header length is 20, and the TCP header length is 20.

The memory space corresponding to each protocol header is as follows:


3. Parsing the Ethernet Header

  1. #define MAC_ARG(p) p[0],p[1],p[2],p[3],p[4],p[5]
  1. struct ethhdr *ethh;
  2. unsigned char *p = pkt;
  3.   
  4. ethh = (struct ethhdr *)p;
  5.  
  6. printf( "h_dest:%02x:%02x:%02x:%02x:%02x:%02x \n" , MAC_ARG(ethh->h_dest));
  7. printf( "h_source:%02x:%02x:%02x:%02x:%02x:%02x \n" , MAC_ARG(ethh->h_source));
  8. printf( "h_proto:%04x\n" ,ntohs(ethh->h_proto));
  • Note that the data in the data packet is in network byte order. If you want to extract data, you must pay attention to the byte order. ethh->h_proto is a short type, which occupies 2 bytes, so you need to use the function ntohs to store it locally.
  • n:network network byte order
  • h: host host byte order
  • s: short 2 bytes l:
  • long 4 bytes
  • ntohl(): Convert 4-byte network byte order data to host byte order
  • htons() : Convert 2-byte host byte order data to network byte order
  • ntohs() : Convert 2-byte network byte order data to host byte order
  • htonl() : Convert 4-byte host byte order data to network byte order

When executing the following statement,

  1. ethh = (struct ethhdr *)p;

The member correspondence of the structure pointer variable eth is as follows:


The final print result is as follows:


4. Parsing IP header

The idea of ​​parsing the IP header is very simple.

That is, you can find the IP header by offsetting the Ethernet header length (14 bytes) from the pkt header.

The parsing code is as follows:

  1. #define IP_ARG(p) p[0],p[1],p[2],p[3]
  1. /*
  2. Parsing IP header
  3. */
  4. if(ntohs(ethh->h_proto) == 0x0800)
  5. {
  6.  
  7. iph = (struct iphdr *)(p + sizeof(struct ethhdr));
  8.  
  9. q = (unsigned char *)&(iph->saddr);
  10. printf( "src ip:%d.%d.%d.%d\n" ,IP_ARG(q));
  11.  
  12. q = (unsigned char *)&(iph->daddr);
  13. printf( "dest ip:%d.%d.%d.%d\n" ,IP_ARG(q));
  14. }

IiP

The final analysis results are as follows:


It can be seen that we have correctly parsed the IP address, and the result is consistent with the data analyzed by the packet capture tool.

The protocol field indicates the protocol type following the IP protocol. Common values ​​are as follows:


5. Parsing TCP header

The idea of ​​finding the TCP header is very simple.

That is, you can find the TCP header by offsetting the Ethernet header length (14 bytes) and the IP header length (20 bytes) from the pkt header.

  1. switch(iph->protocol)
  2. {
  3. case 0x1:
  4. //icmp
  5. break;
  6. case 0x6:
  7. //tcp
  8. tcph = (struct tcphdr *)(p + sizeof(struct ethhdr) + sizeof(struct iphdr));
  9. printf( "source:%d dest:%d \n" ,ntohs(tcph->source),ntohs(tcph->dest);
  10.  
  11. break;
  12. case 0x11:
  13. //udp
  14.     
  15. break;
  16. }

Correspondence between structure and memory


The print results are as follows:


6. Learn to print this memory in different formats

In actual projects, we may not parse standard TCP/IP protocol packets.

It may be our own defined protocol data packet,

Once you have mastered the above methods,

All protocol analysis is at your fingertips!

Sometimes we also need to print the content of the data frame sent by the other party.

Often we print out all the data in hexadecimal format.

This is most conducive to our analysis of data content.

1. Print by bytes

The code is as follows:

  1. for (i=0;i<400;i++)
  2. {
  3. printf( "%02x " ,pkt[i]);
  4. if(i%20 == 19)
  5. {
  6. printf( "\n" );
  7. }
  8. }

2. Analyze a section of memory by short type

When we receive data, although we use an unsigned char array,

But sometimes the data sent by the other party may be an array of 2 bytes.

Then we just need to use a short pointer to point to the head of the memory.

Then you can access the data sent by the other party through this pointer.

At this time, you must pay attention to the byte order problem.

Different scenarios may be different, so we must analyze specific issues specifically.

In this example, network byte order data is converted into host byte order.

So the byte order needs to be converted.

  1. //Convert short byte order
  2. void indian_reverse(unsigned short arr[], int num)
  3. {
  4. int i;
  5. unsigned short temp ;
  6.  
  7. for (i=0;i<num;i++)
  8. {
  9. temp = 0;
  10.  
  11. temp = (arr[i]&0xff00)>>8;
  12. temp |= (arr[i]&0xff)<<8;
  13. arr[i] = temp ;
  14. }
  15. }
  16. main()
  17. {
  18. unsigned short spkt[200];
  19.   
  20. ………………
  21. memcpy(spkt,pkt,sizeof(pkt));
  22.  
  23. indian_reverse(spkt,ARRAY_SIZE(spkt));
  24.   
  25. for (i=0;i<200;i++)
  26. {
  27. printf( "%04x " , spkt[i]);
  28. if(i%10 == 9)
  29. {
  30. printf( "\n" );
  31. }
  32. }
  33. ………………
  34. }

The results are as follows:

Please contact Yikou Linux public account for reprinting this article.

<<:  Server-Speaks-First is a bit of a bummer, protocol detection and opaque ports in Linkerd 2.10

>>:  For the first time in 21 years! SpaceX acquires satellite communications startup

Recommend

F5 security experts talk about DevSecOps: security by design

If someone asks, "What is changing the techn...

Let us say goodbye to TCP together!

PS: This article does not involve knowledge about...

Four indicators to help you choose the best multi-service data center provider

A new report from MarketsandMarkets predicts that...

Common status codes and usage scenarios in HTTP

Hello everyone, I am the front-end developer. Tod...

After China leads the world in 5G, beware of being "led by the pace"

From the blank of 1G to the comprehensive leaders...

The Three Realms of Industrial Internet

The Industrial Internet platform is now very popu...

How SD-WAN as a Service Addresses MPLS Limitations

While MPLS has served enterprises well for many y...

Breakthrough in electricity usage could lead to big savings for data centers

Serial links are responsible for transferring dat...

How to deploy multiple computer rooms? How to synchronize data?

Author: Guo Guanhua, unit: China Mobile Smart Hom...

Seven trends revealing the future of mobile app development

【51CTO.com Quick Translation】 Undoubtedly, mobile...