Chapter 6. Custom Packet Generation

The Internet is based on packets: nodes on the Internet exchange packets in order to communicate. At the most primitive level, packets are just well-defined pulses traveling across a copper wire. With this in mind, it's possible to manipulate packets as they're exchanged or to craft custom packets. There are many reasons for working at this level; e.g., identifying operating systems and other software on the network, attacking other systems on the network (or verifying that their network stack is implemented correctly, which is often the same thing), or mapping out the structure of a network. This chapter introduces some tools that you can use to work with packets at this low level.

There are two basic groups of tools that an individual can use to generate custom packets on a computer network. The first group forces you to use the techniques hardcoded within the tools, which usually require less intimate knowledge of the technology and allow someone to start leveraging custom packets almost immediately. However, with this group of tools, the user is confined to the techniques included with the tool and cannot tweak, modify, or add to this pool of included techniques. The second group of tools allows you to create your own techniques and add them to your toolbox. This group offers limitless flexibility and functionality, but requires more work on the part of the user. In this chapter, we will explore some tools from both groups, but concentrate primarily on the set of tools that offer the user more flexibility and the ability to build custom techniques for generating custom packets.

A packet is a unit of very ordered information that is grouped in a specific structure. In many ways, it shares attributes with a package from one of the more expensive "efficient" mail couriers such as Fed Ex. A package from one of these couriers contains information such as the location of origin, the time of pick up, the route waypoints, the priority of the package, the package's destination, the package's weight, and of course the package's content that is intended to be delivered to the recipient. On the wire, regardless of what protocol it is, a packet contains the metadata necessary to transmit the packet correctly and the payload of the packet (i.e., the data that is to be delivered). All of this information is parsed and processed through automatic functions that adhere strictly to the published and established rules of the given protocol specifications. This is where part of the power of custom packet generation can be realized: it does not matter where the packets originate from or how they were created; if the packets are on the wire and adhere to the specification, a machine will process the packets if it receives something it is expecting.

There are several reasons why someone would want to generate custom packets. One is to communicate with black box applications or devices. For example, on a network, there might be a proprietary application or device that communicates through a proprietary protocol. This device needs to be integrated into the regular network health check, and the company does not want to pay the money to purchase the proprietary network protocol libraries that are needed to get a meaningful reply out of it. Knowing how to create custom packets to establish a connection and communicate with this device is imperative. Another reason is to test the robustness of a developed application. Rather than creating a full client to run unit tests against the application, generating raw packets on the wire that follow the protocol of the application may be perfectly acceptable and more efficient. People who are fond of fuzzing and penetration testers also recognize this feature, except they systematically alter certain areas of a packet according to their desired rules. Because the packets are parsed and processed by computers, subtle differences in a packet (especially if it is not fully protocol-compliant) have brought attention to numerous network and security issues in the past.

A classic example of a custom packet that is very simple to demonstrate and understand is the infamous Ping of Death. The term Ping of Death refers to the most popular, and simplest, form of this celebrated Denial of Service attack, where the attacker uses an especially large custom packet transmitted through the Internet Control Management Protocol (ICMP) type 8 (RFC 792), otherwise known as echo request or ping. In this instance, the size of the crafted packet has to be larger than 65,535 bytes in length, and thus will cause the affected computer to crash instantly; one packet, one kill. Network protocols have to adhere to strict rules in order to function, and 65,535 bytes is the absolute maximum that a packet can be, as defined by the Internet Protocol RFC 791. If the maximum size is specified as 65,535, then how can an ICMP packet be sent that is larger than that? RFC 791 also specifies that a single packet can be broken into smaller packets, sent across the wire, and reassembled by the receiving operating system. This is called packet fragmentation, and the individual fragmented packets also contain information that tells the receiving host how to order the information to assemble the packet, and then process the information.

The underlying issue with the Ping of Death is not that an illegally sized packet is sent, or even that it is fragmented into many smaller packets; rather, it is how the receiving operating system puts the information back together again and tries to process the large packet. The developers who implemented the process of receiving the fragmented packets and assembling the larger original packet never accounted for the possibility that the resulting assembled packet could be larger than the legal packet size. Not accounting for this, and pushing the assembled packet into a finite sized buffer, resulted in a buffer overflow on the receiving operating system. The really interesting part of this ordeal is that in 1996, this issue affected Linux, BSD, MS Windows, Mac OS, routers, and other network-enabled devices. The operating systems have been fixed now, but this problem is a great example of how a crafted packet can exploit a situation that a developer, and a highly reviewed protocol specification, did not specifically account for.

hping2 is a command-line program that can send custom IP, TCP, UDP, and ICMP packets. The tool gives the user access to altering most of the fields in the constructed packet. hping2 has three main modes. The first, which was originally the only one, consists of describing the packet you want to send and letting hping send it and display the replies. The second mode allows the user to configure a list of multiple ports to send the packet to, and the third listens for packets of a particular format.

Here is a simple example of generating a TCP SYN packet:

# hping --syn -p 80 www.slashdot.org
HPING www.slashdot.org (eth0 66.35.250.151): S set, 40 headers + 0 data bytes
len=46 ip=66.35.250.151 ttl=48 DF id=0 sport=80 flags=SA seq=0 win=5840 rtt=189.4 ms
len=46 ip=66.35.250.151 ttl=48 DF id=0 sport=80 flags=SA seq=1 win=5840 rtt=189.2 ms

--- www.slashdot.org hping statistic ---
3 packets transmitted, 2 packets received, 34% packet loss
round-trip min/avg/max = 189.2/189.3/189.4 ms

To create the packet of your dreams, you must choose between TCP (default), IP (−0 or --rawip), ICMP (−1 or --icmp), or UDP (−2 or --udp). Then you can set each field at the value you want. Most of the time, unset fields have a null value, so do not forget to set important fields such as TCP flags. You can display the complete list of options by calling for help (hping2 -h). For instance, here is how to send a fake ICMP echo reply packet from a spoofed source:

# hping --icmp -C 0 -K 0 -a 192.168.1.1 192.168.1.10

Additional options are available to create an ICMP citation, which makes it easy to create fake ICMP error messages. Details about these options are available from hping --icmp-help. For instance, this example breaks an established TCP connection to http://update.microsoft.com (for more, see the following section):

# hping --icmp -C 3 -K 1 -a 192.168.1.1 --icmp-ipdst update.microsoft.com
  \
       --icmp-ipsrc victim --icmp-srcport 1034 --icmp-dstport 80 victim

To add a payload to a packet, hping requires you to put the packet in a file and provide the size of the desired payload. The file is cut into as many pieces as necessary in order to reach the desired payload size. The pieces are sent one after the other; the remaining piece is padded with null bytes. After the last chunk is sent, hping loops to the first piece. If no file is provided, the filling is done with X. For instance, here is a way to send your /etc/passwd to slashdot over UDP packets by chunks of 42 bytes:

# hping --udp www.slashdot.org -p 123 -E /etc/passwd -d 42

The --tcpexitcode parameter can be of great help in shell scripts. It enables you to test the state of a TCP port:

# hping 127.0.0.1 --syn -p 22 --tcpexitcode -c 1
HPING 127.0.0.1 (lo 127.0.0.1): S set, 40 headers + 0 data bytes
len=44 ip=127.0.0.1 ttl=64 DF id=0 sport=22 flags=SA seq=0 win=32767 rtt=0.4 ms

--- 127.0.0.1 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.4/0.4/0.4 ms
# echo $?
18

# hping 127.0.0.1 --syn -p 23 --tcpexitcode -c 1
HPING 127.0.0.1 (lo 127.0.0.1): S set, 40 headers + 0 data bytes
len=40 ip=127.0.0.1 ttl=64 DF id=24359 sport=23 flags=RA seq=0 win=0 rtt=0.2 ms

--- 127.0.0.1 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
# echo $?
20

For those who are bored by sending the same packet over and over, there is a SIGINT handler (Ctrl-Z) to increment or decrement either the TCP/UDP destination port or the IP TTL:

# hping2 www.slashdot.org --syn -p 79
HPING www.slashdot.org (eth0 66.35.250.151): S set, 40 headers + 0 data bytes
ICMP Unreachable type=10 from ip=66.35.250.151 name=star.slashdot.org
ICMP Unreachable type=10 from ip=66.35.250.151 name=star.slashdot.org ❶
80: len=46 ip=66.35.250.151 ttl=49 DF id=0 sport=80 flags=SA seq=2 win=5840 rtt=194.2
ms
len=46 ip=66.35.250.151 ttl=49 DF id=0 sport=80 flags=SA seq=3 win=5840 rtt=194.4 ms
len=46 ip=66.35.250.151 ttl=49 DF id=0 sport=80 flags=SA seq=4 win=5840 rtt=194.4 ms

In the preceding example, Ctrl-Z is pressed after the second line, at ❶. The destination port was incremented and there is an answer on port 80. Great, Slashdot is up! But you don't want to scan 65,535 ports like this. hping2 is not a port scanner.

The second mode actually does enable you to provide a list of destination ports you want hping2 to go through. All other parameters work the same as before:

# hping2 --scan 79-81 www.slashdot.org -S
Scanning www.slashdot.org (66.35.250.151), port 79-81
3 ports to scan, use -V to see all the replies
+----+-----------+---------+---+-----+-----+
|port| serv name |  flags  |ttl| id  | win |
+----+-----------+---------+---+-----+-----+
   79:                      241  9223       (ICMP   3  10 from 66.35.250.151)
   80 www        : .S..A...  49     0  5840
   81:                      241  9224       (ICMP   3  10 from 66.35.250.151)
All replies received. Done.
Not responding ports:

The third mode just listens to incoming packets, waiting to recognize a pattern. It then prints all the data from the end of the pattern to the end of the packet. For example, we can display content following a 404. We should catch HTTP errors for Not Found pages:

# hping2 --listen "404"
 Not Found
Server: Apache
Transfer-Encoding: chunked
[...]

Alas, this mode captures incoming packets only. You cannot use this to peek at packets sent by programs running on your box.

hping2 is a simple tool, and while it's useful in basic situations, you have to know its limitations and shortcomings in order to get to something juicier.

First, hping does not provide every field you may need. In the previous ICMP examples, some crucial fields necessary to really fake an answer are missing. For instance the ICMP ID field, which makes it possible to have two ping sessions working in parallel without interfering, is not available. Actually, hping uses its PID to choose the ICMP ID, which basically means you can never fake an ICMP echo reply. The same issue applies to ICMP error messages. Despite the presence of options to set fields for the ICMP citation, the TCP sequence number is absent. Most TCP/IP stacks have been checking this number for a long time now, in order to avoid easy blind connection breaking. Such attacks were widely used during old IRC wars and have been recently renewed with more modern techniques.

hping occasionally mistakes external packets for replies to a packet sent previously, particularly when two instances of hping are running and the responses to packets sent by one instance are caught by both.

hping2 also has limited scanning ability. Either you automatically scan the TCP/UDP destination port with the --scan option, or you manually increment the IP or IP TTL field with Ctrl-Z.

Moreover, you cannot have more than one varying field. Forget about scanning a network on interesting ports or tracerouting to many destinations. If you have a compulsive need to scan everything, do not put all your hopes in hping2; it wasn't designed for that.

Finally, note that in hping2, the TCP/UDP source port of the first packet is either chosen randomly or taken from the −s option. Then, the source port is incremented for each packet. This process prevents packets from being misinterpreted as retransmissions of the same packet,[24] but even when it is correctly documented,[25] you may end up with inaccurate results if you expect the source port to always be the same. Do not forget the -k option if you really want the source port to remain the same, and keep in mind that if two packets have the same IP address and ports, one may be read as a replica and dropped.



[24] They all have the same source IP/port and destination IP/port.

[25] -s is described as the base source port.