ICMP                                                                                                                                                                                                                                         

____________________________________________________________________

 

ICMP or The Internet Control Message Protocol is the de facto protocol used to communicate error messages reporting errors that might have occurred while transferring data over networks. Besides, the normal use of reporting error messages, ICMP also plays an extremely important role in gathering information about the remote system. This manual explores everything about ICMP, its uses and how to use ICMP to gather more information on the target system and of course, countermeasures.

The ICMP protocol communicates error messages and other malfunctions or problems that might have occurred while the data transactions between two systems were taking place. Thus, it can also be called the ‘Network Problem Diagnosis’ protocol. It is basically the protocol, which reports any error that might have occurred while the data transfer was still taking place.

All ICMP messages are transmitted as IP datagrams. A Typical ICMP message encapsulated within an IP datagram would be as follows:

_______________________________________________________

|                                               |                                                                              |               

|               IP Header              |               ICMP Message                                    |                                                                               

|                                               |                                                                              |               

|____________________|_________________________________ |

              20 Bytes

       

|-------------------------------IP Datagram-----------------------------------|

 

The first 4 bytes have the same format and specification for all the messages; however, the remaining part of the datagram differs from message to message depending upon the kind or message i.e. the type of error message carried by the datagram. This means that the first 4 bytes are common to all ICMP messages, while the remaining bytes are different for different error messages, depending upon the type of error transmitted by that particular message. 

The format of a typical ICMP message is as follows:

 

0                         7    8                                     15      16                                                             31

____________________________________________________________________

|                               |                                               |                                                                            | 

|     8-Bit Type        |               8-bit Code              |               16-Bit Checksum                               |

|                               |                                               |                                                                            |

|_____________ |____________________ |_________________________________|

|                                                                                                                                                            |

|                                                                                                                                                            |

|                                                                                                                                                            |

|                               (Contents depending upon Type and Code)                                               |

|                                                                                                                                                            | 

|                                                                                                                                                            | 

|                                                                                                                                                            |

|___________________________________________________________________|

 

The ‘type’ field can have any of the 15 different values, which determine or represent a particular ICMP error message. For Example, a value of 3 in the type field specifies the ‘Destination unreachable’ error message. Like this there are 15 different values, which the ‘type’ field can have, with each value representing a particular specific error type.  

An error message like the above was a very general or rather a very broad error message. It does not tell you the exact cause of the error or where exactly or what exactly caused the error to occur. Thus, it is not that useful for diagnose purposes. In order to ensure that the user or application running on either the client side or the server side knows about the error occurred in a more detailed fashion, ICMP has the provision whereby, each main error specified by the ‘type’ value has a number of sub errors, which give a more specific reason or cause of the error.  

Such sub-errors, which are more specific and more helpful, are specified in ICMP in the ‘code’ field.

For Example, a ‘Type’ Value of 3 and a ‘code’ value of 0 specify that the error caused is: ‘Network Unreachable’. While a ‘Type’ Value of 3 and a ‘code’ value of 1 specifies that the error caused is: ‘Host Unreachable’ 

The following table gives the complete list of type values, code values and their corresponding errors, which are allowed by ICMP: 

Type

Name

Code

0

Echo Reply

0 No Code

1

Unassigned

 

2

Unassigned

 

3

Destination Unreachable:

0 Net Unreachable
1 Host Unreachable
2 Protocol Unreachable
3 Port Unreachable
4 Fragmentation Needed and Don't Fragment was Set
5 Source Route Failed
6 Destination Network Unknown
7 Destination Host Unknown
8 Source Host Isolated
9 Communication with Destination
Network is Administratively Prohibited
10 Communication with Destination Host is
Administratively Prohibited6
11 Destination Network Unreachable for Type of
Service.
12 Destination Host Unreachable
for Type of Service.
13 Communication Administratively Prohibited.
14 Host Precedence Violation

15 Precedence cutoff in effect

4

Source Quench
0 No Code

5

Redirect

 

 

 

0 Redirect Datagram for the Network (or subnet)

 

 

1 Redirect Datagram for the Host

 

 

2 Redirect Datagram for the Type of Service and
Network

 

 

3 Redirect Datagram for the Type of Service and
Host

6

Alternate Host Address
0 Alternate Address for Host

7

Unassigned

 

8

Echo Request
0 No Code

9

Router Advertisement
0 No Code

10

Router Selection
0 No Code

11

Time Exceeded

 

 

 

0 Time to Live exceeded in Transit

 

 

1 Fragment Reassembly Time Exceeded

12

Parameter Problem

 

 

 

0 Pointer indicates the error

 

 

1 Missing a Required Option

 

 

2 Bad Length

13

Timestamp
0 No Code

14

Timestamp Reply
0 No Code

15

Information Request
0 No Code (Obsolete)

16

Information Reply
0 No Code (Obsolete)

17

Address Mask Request
0 No Code

18

Address Mask Reply
0 No Code

 

As soon as TCP/IP encounters an error in the data transfer from the source to the destination, ICMP is used to inform the client, server and the user process about the details of the error encountered.  Thus, the prime usage of ICMP is in relaying error occurred in the data transit.  

Remote Host Information Gathering with ICMP

 

The various ICMP messages having different code and type values can be used to get different kinds of information on the remote system. Information gathering is the first step that a hacker goes through in his attempt to detect any loopholes in the target system. Although sending ICMP messages will not tell you everything that you will need to know about the target system, but still they will give you quite a lot of information. 

Using the Echo Request and Echo Reply Messages 

The Echo request message is the ICMP message with a type value of 8 and a code value of 0, while the Echo reply message is the ICMP message with a type value of 0 and a code value of 0. We can use the ICMP Echo Request and Echo Reply messages to determine whether or not the target host is connected to the Internet (is alive) or not. 

In order to determine whether the target host is alive or not, all we have to do is send an Echo Request message to the remote system and wait for an Echo reply message. 

  1. If the remote system replies with an Echo Reply message, then it means that it is alive and is connected to the Internet.
  2. However, if we do not receive any reply from the remote system, then it probably means that the remote system is not connected to the Internet.

 

However, one note of caution, it is more than possibility that the target host to whom you send out the Echo request datagram might have a filtering device installed which discards all Echo Request ICMP messages, thus showing that the remote system is not connected to the Internet even though it might as well be connected. Some better firewalls even send out spoofed Echo Replies on encountering such echo requests, thus throwing the malicious intruders off the track.

 

***********************
HACKING TRUTH: Does the working of the Echo Request and Echo Reply Messages sound familiar? You guessed it, they are indeed same as the popular Unix network diagnosing command: ping.

**********************

How exactly do the ICMP Echo Request and Reply Messages work? To understand their working, let us first take a look at their structures: 

The format of a typical ICMP ‘echo request’ and ‘echo reply’ message would be as follows: 

0                         7    8                                     15      16                                                                 31

____________________________________________________________________

|                               |                                               |                                                                             |

|     Type =0or 8     |               Code =0                 |               16-Bit Checksum                                |

|                               |                                               |                                                                             |

|_____________ |____________________ |________________________________  | 

|                                                                               |                                                                             |

|               Identifier                                                |               sequence number                               |

|__________________________________|_________________________________|

|                                                                                                                                                            |

|                                                                                                                                                            | 

|                                                             (Optional Data)                                                                    | 

|                                                                                                                                                            |

|___________________________________________________________________|

 The sender initializes an ICMP echo request message giving the Identifier field the value of the Process ID of the sending process, the sequence number field a sequence number and adding some binary data to the data field. The target system then on receiving the request, simply echoes back the identifier, data (unchanged) and sequence number fields in the form of an ICMP reply message. When the sender receives this message, it can deduce that the target system is alive. 

This method can easily be carried out using the ping utility. For Example, 

# ping hackingtruths.box.sk 

Pinging hackingtruths.box.sk [194.x.yyy.227] with 32 bytes of data:

32 bytes from 194.x.yyy.227: icmp_seq=0 ttl=225 time=0 ms

32 bytes from 194.x.yyy.227: icmp_seq=1 ttl=225 time=0 ms

32 bytes from 194.x.yyy.227: icmp_seq=2 ttl=225 time=0 ms

32 bytes from 194.x.yyy.227: icmp_seq=3 ttl=225 time=0 ms

32 bytes from 194.x.yyy.227: icmp_seq=4 ttl=225 time=0 ms

32 bytes from 194.x.yyy.227: icmp_seq=5 ttl=225 time=0 ms

32 bytes from 194.x.yyy.227: icmp_seq=6 ttl=225 time=0 ms

……..

Countermeasures 

Echo Requests or Ping is widely carried out over the Internet and almost all servers are bound to encounter such instances (wherein they are on the receiving end) every now and then. One easy method in which you can block ping requests at the router level is by adding the following ACL: 

access-list 101 deny icmp any any 8 

This line will filter out all echo request packets at the router level and discard them. There will be no echo replies sent back to the attacker. However, if you want to filter out all echo requests coming to your network except those coming from your ISP, (who send out echo requests for routine checks) then the following ACL rules will do the job for you: 

access-list 101 permit icmp xx.xx.xx.xx 0.0.0.255 any 8

access-list 101 deny icmp any any 8 

The above access rules will discard all echo requests except those that are coming from your ISP, whose IP Address is xx.xx.xx.xx.  

Using the Timestamp Request and Timestamp Reply Messages 

The ICMP Timestamp Request message has a type value of 13, while an ICMP Timestamp Reply message has a type value of 14. These messages in conjugation with one another help one system to query another system for the current time in the latter system. The time returned is actually the number of milliseconds since midnight, Coordinated Universal Time. (UTC)  

The typical format of a Timestamp message is as follows:

 

0                         7    8                                     15      16                                                                  31

____________________________________________________________________

|                               |                                               |                                                                            | 

|   Type =13or14    |               Code =0                 |               16-Bit Checksum                               |

|                               |                                               |                                                                            |

|_____________ |____________________ |________________________________ |  

|                                                                               |                                                                            |

|               Identifier                                                |               sequence number                              |

|_________________________________  |_________________________________|

|                                                                                                                                                            |

|                                                                                                                                                            | 

|                                               32-bit originate timestamp                                                               | 

|                                                                                                                                                            |

|_________________________________________________________________  _|

|                                                                                                                                                            |                 

|                                                                                                                                                            | 

|                                               32-bit receive Timestamp                                                                 | 

|                                                                                                                                                            | 

|                                                                                                                                                            |

|__________________________________________________________________  |  

|                                                                                                                                                           |                  

|                                                                                                                                                           |  

|                                               32-bit transmit Timestamp                                                              |  

|                                                                                                                                                           |  

|                                                                                                                                                           |

|__________________________________________________________|

 

How exactly does the Timestamp process work? The sender prepares a datagram of the above type and fills in the time at which the message was sent in the Originate Timestamp field. Then, the receiving end fills in the time at which it receives the ICMP Time request message in the Receive Timestamp field. After that, the time at which the receiving end sends back the Timestamp reply message is recorded in the Transmit Timestamp field. However, nowadays the same value filled in the receive Timestamp field is filled in the transmit Timestamp field also. 

Thus, if you receive a Timestamp reply message from the remote system to which you had sent the Timestamp request message it means that particular host is alive.  

************************

HACKING TRUTH: One can also use the Timestamp messages to differentiate between the types of Operating System running on the target host. For Example, Some versions of Windows NT are known to not reply to a Timestamp request.

*********************** 

To actually implement the ICMP Timestamp feature, all you need is a Unix box and a kewl utility named icmpquery whose source code is as follows: (This utility can also be used for ICMP Address Mask Requests, which are discussed later in the manual)

----------------------

/*
 * icmpquery.c - send and receive ICMP queries for address mask
 *               and current time.
 *
 * Version 1.0
 *
 * Copyright 1998, 1998 David G. Andersen 
 *                                               http://www.angio.net/
 *
 * Verified to work on:
 *    FreeBSD (2.x, 3.x)
 *    Linux 2.0.x
 *    NetBSD 1.3
 *
 * Should work on Solaris and other platforms with BSD-ish stacks. *
 * If you compile it somewhere else, or it doesn't work somewhere,
 * please let me know. *
 * Compilation:  gcc icmpquery.c -o icmpquery
 */
 /* Some portions of this code are taken from FreeBSD's ping source.
 * Those portions are subject to the BSD copyright, which is appended
 * at the end of this file.
 */ 
#define A(bit)          rcvd_tbl[(bit)>>3]      /* identify byte in array */
#define B(bit)          (1 << ((bit) & 0x07))   /* identify bit in byte */
#define SET(bit)        (A(bit) |= B(bit))
#define CLR(bit)        (A(bit) &= (~B(bit)))
#define TST(bit)        (A(bit) & B(bit)) 

#include <time.h>

#include <sys/time.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <netinet/in.h>

#include <netinet/in_systm.h>

#include <netinet/ip.h>

#include <netinet/ip_icmp.h>

#include <errno.h>

#include <string.h>

#include <signal.h> 

/*
 * We perform lookups on the hosts, and then store them in a chain
 * here.
 *
 * Yes, it's linear.  No, I don't care.
 */ 
struct hostdesc {
                    char *hostname;
                    struct in_addr hostaddr;
                    struct hostdesc *next;
}; 
struct hostdesc *hostnames;
struct hostdesc *hosttail;
 
void resolv_from(char *hostfrom, struct in_addr *fromaddr)
{
                    struct hostent *hp;
                    if (hostfrom == NULL) {
                                         fromaddr->s_addr = 0;
                                         return;
                    }
                    
                    if ((hp = gethostbyname(hostfrom)) == NULL) {
                                         if ((fromaddr->s_addr = inet_addr(hostfrom)) == -1) {
                                                             fprintf(stderr, "could not resolve from address\n");
                                                             exit(0);
                                         }
 &