hping, a packet injection tool

hping is named afer ping because in default usage it does the same thing functionally-- contacts another machine and gets it to answer. It does so another way (arping uses yet a third way). While ping uses ICMP echo request to get talkback in the form of echo reply messages, hping uses tcp contact with port 0 to get talkback in the form of a TCP "nobody home" reset packet (arping uses arp request to get arp reply).

hping can also be used to craft and insert arbitrary byte sequences into packets. In normal usage, the packets "you" send out are usually written for you by the various software layers in the famous "network stack." The application doesn't build packets, it only generates the to-be-packetized data but hands it off to others to manufacture the actual packets. But you can roll your own with packet injection tools like hping. It is the application-- hping-- that can build a packet including data and header(s) and give that off to one of the layers to take it from there.

In this exercise, refer as needed to the header structures of the major protocols.

The exercise for you to perform:

Install hping if necessary:

yum  install  hping3

Create a file named hex2bin.sh with the following contents:

# hex2bin.sh
# input:  representation of single-byte values using hex format
#         e.g. "41" for A, "20" for space, "0A" for newline
# output: bytes of those values
#         e.g., A, space, newline
# usage:
# [root@alpha ~]# echo "416E 20 6578616D706c65 0a" | hex2bin.sh
# An example
# [root@alpha ~]#
echo -n -e $(tr -d '[:space:]' | sed 's/../\\x&/g')

Give hex2bin.sh executable permissions. Move it to a directory that is in your PATH variable, perhaps /usr/local/bin.

Default usage

Identify the IP address of a target machine on your local network and in your subnet. Use hping, much as you would ping, to test whether the target is up. While doing so, perform a Wireshark capture.

hping  -c 1  -n  <target IP>

To raise the target, hping uses the well known fact that sending to a TCP port number used by no application on the target gets the target's TCP layer to send back a TCP segment with the "reset" flag set. To avoid hitting a port that is not unused, hping adopts port zero since nobody uses it. In Wireshark, note that the TCP segment has destination port zero. Look at the reply. How much data does it carry?

Arbitrary data

Let's do the same thing again, but load some data on this wagon.

hping  -c 1  -n  <target IP>  -e "AAAA"

The -e option lets you supply data of your choosing. Find the four A's in the position of TCP's data in the outgoing frame. Note that the data are in the TCP segment, which is in the IP packet, which is in the ethernet frame. Be sure to observe that directly in Wireshark.

Different transport protocols

Do it twice more, but specifying UDP the first time and ICMP the second:

hping  -c 1  -n  <target IP>  -e "AAAA"  -2

hping  -c 1  -n  <target IP>  -e "AAAA"  -1

In Wireshark observe that your AAAA data travels in the hands of UDP the first time, and ICMP the second. Those protocols yield responses in accord with their particular rules. In the UDP case, port zero is addressed. In the ICMP case, the ICMP type used is and echo request. According to UDP's rules, in the first case an ICMP using type "destination port unreachable" comes back. In the ICMP case, an ICMP type using "echo reply" comes back. (hping in ICMP mode, with a couple very minor differences when used by default, does almost identically what ping itself does.) In both these cases your data gets across and in both the selected carrier protocol occupies the transport layer position, so is instead of TCP.

Raw IP mode

Let's get rid of the transport protocol. Instead of delivering data into the hands of a transport protocol which will consign itself into the hands of IP, you can consign data into IP's hands directly using no transport protocol at all. That's what hping's IP mode does. The data you give to IP is whatever you manufacture. Anything you want. What happens when you give your four A's to IP? What will IP make of it?

hping  -c 1  -n  <target IP>  -e "AAAA"  -0

Wireshark displays a complaint. Note specifically the value in the IP header's protocol field, which accounts for the false expectation that led IP to complain. Make two more balled-up attempts:

hping  -c 1  -n  <target IP>  -e "AAAA"  -0  --ipproto 17

hping  -c 1  -n  <target IP>  -e "AAAA"  -0  --ipproto 1

Wireshark makes different complaints now. Your data is not different. Only the values in the IP header's protocol field differ-- 6 the first time, 17 the second, 1 the third. What protocols are 6, 17, and 1 codes for? What expectations do they create in IP's mind?

Hand-made datagrams

Since your data can be arbitrary data, you should be able to get rid of those Wireshark complaints by producing data that's "right" instead of "wrong." Four A's are an appropriate poker hand but an inappropriate TCP, UDP, or ICMP header or message. How about using your "arbitrary data" power to craft something that's not wrong? How could you find out what's "not wrong," and then how could you craft it?

Find out what's "not wrong" the same way as on an exam, for example. Copy it from a source that's right! Let's do ping-by-artifice. We should be able to do anything-by-artifice but let's choose ping as our example and first attempt. Run ping (real ping, which gets ICMP echo request right every time) and through Wireshark see what shows up immediately after the IP header. That's our model; try to produce that in binary and feed it to hping as data in raw IP mode.

There are a number of ways we might reproduce what ping did. Because we might want to change it later, let's capture it in a hex representation (e.g. "4" and "1" as characters for a binary 01000001, which is ASCII's letter A) and use the hex2bin.sh converter script to convert it to binary. The benefit of storing it in hex representation is we can manipulate it with a plain text editor, then run it through the converter and have control over what we output in binary. Try this. Open a second terminal window. In it, run:

tcpdump  -nnti  eth0  icmp  -c 1  -xx  |  tee  tempfile.hex

This will capture only icmp frames, will stop after the very first one it gets, will expand it into hex representation including the ethernet header, and will place it in tempfile.hex. Once this is running, in the first terminal window, shoot out a ping:

ping  -c 1  -s 0  <target IP>

That will send a single ping packet with zero data. The tcpdump will capture it and terminate. The significance of zero data is that ping, which usually produces an ICMP header followed by some generated data (56 bytes by default) will omit that data leaving the header only. Your file tempfile.hex will contain something like:

IP > ICMP echo request, id 46608, seq 1, length 8
	0x0000:  0018 8bba faa4 000c 29d6 e531 0800 4500
	0x0010:  001c 0000 4000 4001 b67f c0a8 018e c0a8
	0x0020:  0183 0800 41ee b610 0001

Above, you're looking at 42 bytes. The first 14 are ethernet header, the next 20 are IP header, and the remaining 8 are ICMP header. Use a text editor and remove everything from tempfile.hex except those last 8 bytes. You would end up with "0800 41ee b610 0001" in this example.

Now convert to binary:

cat  tempfile.hex  |  hex2bin.sh  >  tempfile.bin

The tempfile.bin file now contains binary data that's should be properly formed and acceptable to IP as an ICMP echo request. You can now submit the file contents to hping as packet ingredient. First run Wireshark then the following command.

hping  -c 1  -0  -d 8  -E tempfile.bin  -H 1  <target IP>

hping will send a single packet, using raw IP mode where the IP header will be provided but everything beyond that is up to you. No UDP, TCP, nor ICMP header will be supplied unless you supply it. That's what we're doing here. What IP is going to carry is the first 8 bytes from tempfile.bin. And the protocol field of the IP header will be stuffed with "1," we insist, so that IP will expect to see an ICMP header instead of something else, and judge what we supply as such. If it is looking for a TCP header it will think our stuff is wrong, which it is since our stuff is not a TCP header. So make what IP expects and what it gets match by controlling the value in IP's protocol field.

When you run the above hping command, does it seem "successful" according to hping's screen output? according to Wireshark's? Is it successful or not?

Ethernet padding

As a bonus, hping gives an opportunity to observe ethernet padding. In the above "Arbitrary data" section, you used this command: hping -c 1 -n <target IP> -e "AAAA". It adds four A's of data onto 3 headers. The headers add up to 54 bytes-- 14 for ethernet plus 20 for IP plus 20 for TCP. The whole frame is therefore 58 bytes long. Wireshark on your machine shows that. But a Wireshark capture of that same frame received on the target machine shows two extra space characters (0x20) tacked on. If you send five A's there is a single added space. Six or more A's and no added spaces. Why? Ethernet has a payload minimum of 46 bytes, or equivalently a frame minimum of 60. If you only give it 44 bytes of payload ethernet expands it to 46 by space padding.

Wireshark of the packet on the way out of the sending machine doesn't show any padding. This would appear to position Wireshark "upstream" of code that does the padding on the sender, and upstream of the code that does the stripping on the receiver. You can similarly observe this on the reply (which is a TCP reset, recall). No padding seen where sent, but apparent where received. The pad characters may sometimes be spaces, sometimes zeros. The Windows version of Wireshark doesn't show padding when receiving. It must be positioned differently in the stack there. So there are variations but, visible or not, ethernet is enforcing its minimum rule. Experiment and see it for yourself.

How could real data be distinguished from padding, so the latter won't contaminate the application?