Sniffer Detection (and AntiSniffers)

A sniffer is a program that intercepts data transmitted over the network.
In principle, sniffers are difficult to detect; their nature makes them send the minimum number of data packets.
1. Detection Methods
It’s not always possible to detect a sniffer; it’s something difficult due to its nature. However, detecting a machine that is sniffing is easier.
In some way, we can differentiate the different methods that exist into two groups depending on whether they are:
- Local detection
- Remote detection
1.1 Local Detection
It’s a determining method, but a long process. We must study each machine, each operating system…
We’ll look for evidence such as interfaces in promiscuous mode, suspicious processes.
In a system like Linux, we could use route
or netstat
to see the usage of an interface.
bockvan@tango:~$ netstat -re
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.16.0.0 * 255.255.255.0 U 0 0 0 eth0
default 172.16.0.1 0.0.0.0 UG 0 0 0 eth0
In case the usage of an interface is more than suspicious, we’ll use ifconfig
to see if it’s in promiscuous mode.
bockvan@tango:~$ /sbin/ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:05:1C:13:CE:F0
inet addr:172.16.0.3 Bcast:172.16.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1
RX packets:11583 errors:0 dropped:0 overruns:0 frame:0
TX packets:11306 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:3799031 (3.6 MiB) TX bytes:10693650 (10.1 MiB)
Interrupt:11 Base address:0xc000
As you can see, there’s an interface in promiscuous mode. To deactivate this mode, we’ll use: ifconfig <interface> -promisc
We can also check the logs to see if any interface was put in promiscuous mode:
root@tango:/home/bockvan# tail /var/log/messages
Feb 12 18:40:08 tango kernel: device eth0 entered promiscuous mode
Feb 12 18:41:47 tango kernel: device eth0 left promiscuous mode
Feb 12 18:42:01 tango kernel: eth0: Promiscuous mode enabled.
Feb 12 18:42:01 tango kernel: device eth0 entered promiscuous mode
Feb 12 18:42:02 tango kernel: eth0: Promiscuous mode enabled.
Feb 12 18:42:02 tango kernel: device eth0 left promiscuous mode
Feb 12 18:44:37 tango kernel: eth0: Promiscuous mode enabled.
Feb 12 18:44:37 tango kernel: device eth0 entered promiscuous mode
Feb 12 18:47:28 tango kernel: eth0: Promiscuous mode enabled.
Feb 12 18:47:28 tango kernel: device eth0 left promiscuous mode
In any case, if the attacker who installed the sniffer has great control over the machine, they could hide all this evidence, delete logs, etc.
A good example of this is RhideS, which is an LKM programmed by Ripe that hides promiscuous mode in network interfaces. You can find this module and many more things on the 7a69 website [1].
1.2 Remote Detection
There are mainly two tests to detect a sniffer on our network.
1.2.1 Passive Method
Listens to all packets circulating on the network looking for suspicious activity. For example, the sending of ARP requests.
1.2.2 Active Method
Sends modified packets expecting the response that a machine with an interface in promiscuous mode would give us. In this type of test, the characteristics of the sniffers themselves come into play, as well as those of the systems on which they are found. The latter implies studying the TCP/IP stack of the operating system and finding characteristics that allow us to determine the existence of a sniffer.
Some of the best-known tests are:
- ICMP tests
- ARP tests
- DNS tests
- LATENCY tests
2. Detection Techniques
For example, the GNU/Linux operating system, being in promiscuous mode, will respond to TCP/IP packets sent to its IP ADDRESS even if the MAC ADDRESS in that packet is wrong, when normally packets containing an incorrect MAC ADDRESS are not answered because the network interface ignores them (they are dropped). For this reason, if we send TCP/IP packets with incorrect MAC ADDRESS information to an entire subnet, machines in promiscuous mode will respond to us (they will respond with RESET -RST-).
2.1 Techniques
Depending on the operating system being used, we’ll need to send modified packets in one way or another, since the TCP/IP stack of each system, despite following a standard, is not defined for non-standardized requests.
2.1.1 PING
A flaw in the TCP/IP stack implementation in some GNU/Linux kernels can be exploited to discover sniffers in the system. The kernel checks each and every packet to verify if the IP belongs to the machine in question; if so, this packet goes to the TCP/IP stack to be processed. What is not checked is that the (ethernet) address of the network card contained in the packet matches the MAC ADDRESS of the network card interface. The reason this is not checked is because the network card allows incoming packets that don’t match its network address to pass through. If we send an ICMP “echo request” with a correct IP ADDRESS and a false MAC ADDRESS, if the target of our test responds, it means that it’s probably sniffing the network and has the interface in promiscuous mode.
In some FreeBSD kernels something similar happens, only that instead of using a correct IP ADDRESS we should use a correct broadcast address.
In Microsoft Windows systems, we can perform this test using a correct IP ADDRESS and as ethernet address ff:00:00:00:00:00
, which is not a broadcast address but due to the poor implementation of the TCP/IP stack in these systems, when making this type of requests we’ll get a response. When performing this test, it’s known that certain network devices curiously also respond without necessarily meaning that their interface (or interfaces) are in promiscuous mode.
Current sniffers come equipped with a MAC ADDRESS filter, so they don’t respond with ECHO REPLY.
2.1.2 ARP
There are several ways to remotely check for the existence of an interface in promiscuous mode. The simplest method would be to send an ARP request to an address that is not broadcast. If the machine responds, it must be in promiscuous mode.
A more elaborate method could take advantage of the ARP cache. Each ARP has complete information from both origin and destination. If a single ARP is sent to a broadcast address, including my own address in such a way that in the following minutes other equipment will remember this information. Then if we send an ARP but not to broadcast and then we ping broadcast, anyone who responds without ARPing could only have obtained the MAC address by sniffing.
A variation of this method (used by nepped, developed by savage of apostols) uses a flaw in arp.c in Linux kernel systems, it’s the arp_rcv()
function. This function is responsible for determining when to send ARP responses. When insufficient and damaged requests arrive, Linux systems will respond with ARP requests regardless of the destination MAC. In general, only frames with the machine’s MAC are processed, so it’s not a problem. In promiscuous mode, as we know, all frames are processed without checking the destination MAC address and there’s no way to differentiate if the packet was really intended for the machine that’s listening.
2.1.3 DNS
Many sniffers offer the possibility of showing the name resolution of the machines they’re sniffing, so that more information is presented to the user.
DNS request sniffers capture raw network traffic, and it’s necessary to translate IP addresses to machine names. It’s common for sniffers to make DNS requests to translate the IPs of captured packets. An example of this is AntiSniff, which sends fake packets with fake IPs (both origin and destination) and listens (sniffs) for DNS requests looking for a resolution for the fake IPs it created. Machines that make resolution requests for the IPs we put in the test packets will have a sniffer and will be listening to our network traffic.
A solution that new last-generation sniffers are implementing is to resolve names with some delay that depends on the data we receive and decode, so that if we don’t manage to sniff data, there’s no need to resolve the IP. Thanks to this, sniffers don’t saturate the network with DNS resolution requests.
2.1.4 Latency Tests
It consists of comparing the reaction time of a machine before and after saturating the network traffic with irrelevant information. In this way, equipment with a sniffer installed will analyze all the useless traffic to then process it and will take longer to respond to us than when there’s no saturation on the network.
There are cases where this technique can fail:
Due to network load, there can be false alarms; this is because the medium cannot support so much quantity and some packets arrive with some delay. To fix these, we just need to load the network a bit less.
Sniffers usually run in user mode, while sending ICMP packets has to be executed in kernel mode, being independent of the machine load for each process, so possible sniffers won’t be detected since the system will try to respond the same way as if there were no sniffer.
3. Fooling AntiSniff
This antisniffer is capable of working with most sniffers, but follows very specific patterns, so it’s enough to modify something to detect it. There are techniques that allow sniffing without AntiSniff being able to avoid it. But it’s certainly annoying to have to write a sniffer for each antisniffer when the sniffers on the market are really good. If Mohammed doesn’t want to rewrite the program, a kernel module is made… what is this module going to do? Well, simple, modify the TCP/IP stack of our system a bit, so that all the common tools that AntiSniff is capable of detecting will be filtered. The sniffing technique is already very worked on, the network utilities are very good, the only thing we would have to do would be to make modules for the antisniffers.
Some final tips for developing a sniffer:
- Don’t make DNS requests (not even with delay).
- Stop sniffing when there’s too much activity on the network.