SniffJoke – Defeating Interception Framework

August 11, 2011, by | Start Discussion


If you try the command “traceroute” (under windows, called tracert) you will see a lots of network elements between you and the target host. An interception could happen in every location. If you are using some attack tool like airsnort, ettercap, or simple analysis tool with promisc mode support (wireshark, dsniff) you are sniffing in your LAN. Your LAN, is either the first hop for the outgoing session and the last hop for the incoming sessions.

The image showed is useful because it shows how many hops will separate two hosts in Internet. Every hop will be monitored, every nation will have different law, and if you get passively sniffed will never be notified to you.

This funny image syntethize this concept:


For this reason, the most safe solution is the cryptography: the encryption of a data between the two endpoints. This require that both element supports an encrypted protocol, like HTTPS or SSH. What’s if you want to protect yourself, but your remote peer don’t support cryptography ? SniffJoke is the answer!


What's SniffJoke ?

An internet client running SniffJoke injects in the transmission flow, some packets are able to seriously disturb passive analysis like sniffing, interception and low level information theft. No server support is needed!


Definition of battlefield

In passive wiretapping, packets are analyzed after begin reassembled in flow, this operation, present in every kind of PASSIVE network analyzer (IDS, sniffer, trojan, stats generator) is called "protocol reassembly". In order to obtain an information, the number of reassembly has to be done in equal complexity of the transmissions layer.

Example: if you are analyzing "ftp protocol" you have only the binary data transmitted to be collected and dumped: the passive third party have record the packet flow, save in the correct order and extract the transmitted file.

If you are sniffing HTTP traffic, you have to track all the IP involved in the transmission, all the TCP stream, the applicative meaning, detect cached element not transmitted, reassembly HTML and javascript, execute javascript and, now, the third party will view precisely what the web client has visualized. In short = more layer bring more complexity. the goals of the sniffer has been unroll this complexity wishing to reach, with the least possible effort, to obtain the data.

For touch by hands, this is how some “internet traffic” should be seen when captured as series of packets:

[email protected]:/tmp# tcpdump -ni eth0 –

vvv not port 22 | more

tcpdump: listening on eth0, link-type

EN10MB (Ethernet), capture size 96 bytes

17:34:42.363512 IP (tos 0x0, ttl 53, id

58611, offset 0, flags [DF], proto TCP (6),

length 1492) > . 35607446

32:3560746072(1440) ack 3951869403 win

32749 <nop,nop,timestamp 157917267


17:34:42.364122 IP (tos 0x0, ttl 53, id

58612, offset 0, flags [DF], proto TCP (6),

length 72) > P, cksum 0xd

Issue 19 – Aug2011 | Page – 13

9dd (correct), 1440:1460(20) ack 1 win

32749 <nop,nop,timestamp 157917267



This series of packet would show mixed packets between different sessions, different source host: in short, is not an useful data collection.

Flow Reassembly

 The algorithm inside every packet sniffer is called “flow reassembly”. This algorithm goes inside the TCP field of every packet, dumping in ordinate sequence the data exchange.

Client sent packet , ordered by time

Server sent packets, ordered by time




GET / HTTP 1.1/

ACK (of the client data)

HTTP/1.0 403 Forbidden

Date: Thu, 18 Jun 2009 19:39:09 GMT

Server: BProxy 0.1

Content-Length: 25

Content-Type: application/json

{"error":"403 Forbidden"}

ACK (of the server data, the error)



The table on right hand side shows how many packets will be present (10), for the basic http exchange. The goal of a reassembly algorithm is to analyze the packets flow, dump the data only, interpret the SYN/FIN/ACK packets (are packets without data, but with signaling, synchronization and coordination purposes) correctly, and close the session under analysis when closed.


How does SniffJoke works ?

Internet is based on distributed network device, that may fault. The strength of the network is that percept the broken segment as a problem, and route around them. When a fault happen, some packets get lost, links is broken, there are retransmissions and packet duplication. Is supported by TCP/IP, and in invisible way happens a lot of times during a navigation.

Suppose that a packet is recorded by a sniffer, dumped, but never reach the destination: this network fault have caused a desynchronization between which has been recorded and which is real been exchanged.

Sniffjoke exploit this ambiguities, between what is presumed recorded by the sniffer and what is transmitted by your client, to exploit this inconsistency, making go for the worst the algorithm of packet reassembly.


Ok, I get it. Is a bug ? There are a patch ?

No! Beside I’ve explained this technique easily, shall be possible use and abuse every ambiguity in the TCP/IP stacks. In twenty years, the number of technical specification published by the IETF has make TCP/IP concept grown in complexity. In the 1998, a scientifical papers “Insertion, Evasion and Denial of Service: Eluding Network Intrusion Detections (Secure Network INC, 1998)” has described this problem as permanent and present in every kind of dissector. Simply, is really difficult to implement and to exploit, for this reason the work behind sniffjoke was really painful (and is again, because we are far away from a stable usage)

 SniffJoke uses the network protocol in a permitted way, exploiting the implicit difference of network stack present in an operating system respect the sniffers dissector. This difference details, beside really difficult to detect from a passive analyzer, are CPU intensive operation and matching, this is the reason of sniffjoke motto “downgrade multigigabit sniffer to multikilobit”. In fact, sniffing, wiretapping, interception technology could always work, goal of sniffjoke is make the session the most difficult available to be collected and reassembled.

The packet injected from sniffjoke, showed as a masked hero, is discarded by the remote host, simply the packet sniffer has not enough knowledge for understand if a packet must be discarded or recorded.


Installation and simple usage

If you are using BackTrack5, you will found sniffjoke in the package repository. Anyway I suggest to download the latest release, because development is in progress and, begin a technology that move your traffic over the razor’s edge, has seldom some instability that we must face.

The source release at the main site: or the code repository is under github, once downloaded, requires cmake and g++, gpp to compile the package.

It runs only under Linux (at the moment) because some system dependent operations are required.

From the sniffjoke-0.4.x/ directory:

mkdir build

cd build

cmake ..

sudo -s

make install

Now You’ve installed SniffJoke in your system! Is not usable at the moment, and I will take a bit of time to explain.


The packet expiration trick

The traceroute discover the network paths used by Internet, to permit a communication from you to a remote destination.

For discover this path, traceroute use trick nested in the IP protocol header, the Time To Live.


What’s Time To Live

When the engineer that build the first release of IP (Internet Protocol) has planned the routing mechanism, had found that sometimes a packet could loop, flooding the network and being forwarded at the infinite. This was a problem, and they implemented an expiration solution.

Every packets sent in a IP network, has a field with a Time To Live value, is a numeric value since 0 to 255, and every time is forwarded by a gateway, is decremented by 1. This will not prevent the generation of the loops, but prevent that such error will cause a total interruption in the network.

Traceroute send some meaningless packet to the destination, with an incremental value of time to live. When TTL is set with the value of 1, the packet will be decremented at the default gateway and expire. Every expired packet cause the generation of an error message, carried inside an ICMP packet. Traceroute receive the ICMP packet, and print the source of the first hop in the path.

It increment the TTL and continue until the packets get an answer different from the ICMP error (ICMP time exceeded).

Usually, every packet reach the remote destination, because the default TTL is 64 and every network path has less than 30-35 hops (usually a path has around 10 hops).


How use/abuse TTL in connection scrambling?

The Sniffjoke goal is to cause desynchronization between the sniffer data and the received data, I’ll show below a simple schema, it represent the hops series (1 and 8 are computers, the other are routers) that connect the host 1 (Alice) and 8 (Bob)

A sniffer is present in the network of the route 5. This example should be apply also if the sniffer is in your LAN (like a promisc ethernet, or a weak wireless password)

The client Alice, has sniffjoke, and has to sent 40 byte. The application, in the example, split this bulk of data in two segments of 20 bytes each. The kernel inside Alice’s computer, use the TCP sequence number for signaling the packets order.

Packet 1: 1 – 20, when is received the Bob host sent an ACK (acknowledge) packet ACKing the value of “20”, for tell to Alice that in fact he has received the first 20 byte.

Packet 2: Alice flush the remaining data, sending 20 byte with a sequence of 40, this mean that the 20 byte of the second packets must be appended after the first 20 bytes. Bob ACK-ing 40 is expected (if not, Alice retransmit, because suppose the packet get lost)

 What I’ve described will happen in a common communication, but not in a box with SniffJoke, below is showed how Sj interacts:


Packet 1: first 20 data packet, (AAAAA…) the sniffer record them, and Bob received them. Bob ACK 20.

Packet 2: is a fake packet injected by sniffjoke, has a TTL value of 6, has sequence of 40 like expected, and contain a payload with bad data (B4dB4dB4…). The sniffer, at the hop 5, read this packet as good (is, in fact, totally good!) and record them. When the packets reach the hop 7 it expire!

Packet 3: the real second packets is send, the sniffer see a packet with seq of 40, he already get them so will ignore, the packets reach Bob and is received.

This is how a network based desynchronization would work! But, we are talking about an installation…


The Location concept

Using traceroute will not be efficient for every session, and has been implemented a caching mechanics. But traceroute, return a different output for every destination hosts and from every source location.

A ‘location’ in the SniffJoke point of view is a network environment you are using. Your home, your office, the home of your friend. Every network environment require a dedicated location.

Sniffjoke has this option as mandatory, and you need to restart sniffjoke with the appropriate configuration. The command line is “sniffjooke –location LOCATION_NAME”, but configure a location will not be so easy (SniffJoke is without any doubt a tool for expert and patient users 🙂 )


How to setup a location

When you are attached in the location that you need to configure, it’s the time to use “sniffjoke-autotest”

#sniffjoke-autotest  -l nameofLocation -d /usr/local/var/sniffjoke -n 1

It start various autoprobe. In short, sniffjoke has to be tested every working modality, because maybe some location don’t permit some kind of network use. After the tests verify the outputs, generating the most coherent configuration file for the location under tests.


How does it work the automatic probe

Sniffjoke-autotest generate a meaningless file with inside a lot of digit. Using a POST HTTP with curl, send those digits to a file.php that echo back the same received number. Curl dumps the received output in a file. If the received file has the same checksum of the sent one, the sniffjoke modality has not broken the session, and thus is marked in the configuration file as usable. If the checksum differs, is marked as invalid.

The script is really simple:


if(isset($_POST['sparedata'])) {

        for($x = 0; $x < strlen($_POST['sparedata']); $x++)


                if( is_numeric($_POST['sparedata'][$x]) )


                echo "bad value in $x offset";



        echo $_POST['sparedata'];



At the moment is hosted in, but everyone should copy/paste in a personal server and use them as test. (sniffjoke-autotest will take this options with –s and –a).

When sniffjoke-autotest has finished him probes, it copy a new location in /usr/local/var/sniffjoke, and you’re ready to use that location!

Locations files, installed in /usr/local/var/sniffjoke/{locationName}/ :- 







ipblacklist.conf: it contains a list of ip address that will never be considered by sniffjoke. This will help if some hosts present troubles in establishing connections

iptcp-options.conf: this file is generated by sniffjoke-autotest, it does contain the working use/abuse of the IP/TCP options. It’s one of the more sensible files, when something goes wrong in your session, mostly depends from the value here written. Is under analysis, stabilization and research. Some explanation will follow below at the voice “MALFORMED”

ipwhitelist.conf: the same of blacklist, simple if specify to use whitelist, from this file is imported the list of the IP address to handle by sniffjoke. I use it during the tests, so will avoid to ruin eventually other sessions.

plugins-enabled.conf: this file is generated by sniffjoke-autotest, and contains the combination of plugins + scramble that have passed the test correctly. Take a look of the contents:

 # cat plugins-enabled.conf 












It contains, before the comma, the name of the plugin loaded at SniffJoke startup, and after the comma, the name of the enabled scramble.

port-aggressivity.conf: The injection of bogus packets inside the flow is not constant, is randomized. But randomization with differenced weight depending on the TCP/UDP service the session is pointing. In example, an encrypted session like SSH don’t require to be protected, because it is already protected. A session like HTTP or IRC, have pattern of communication, for this reason port-aggressivity.conf contains the frequency of injection.

sniffjoke-service.conf: this is the system configuration file: which group drop privileges after the chroot, the port and the interface binding for remote administration, logging, etc…

Once the location is ready and configured, SniffJoke is usable!

# sniffjoke –location home

This is the common usage: sniffjoke know which location use, goes in background after the start, and by default is stopped, you should contact the service and checkup the general process with:

# sniffjokectl stat

That usually has an answer like:

received (250 bytes) confirm of STAT command

SniffJoke not running

debug level:             2

gateway hw address:     04:44:E4:43:34:31

gateway IP address:

hijacked interface:      eth0

hijacked local IPaddr:

hijacked MTU interface: 1500

tunnel interface:        sniffjoke

tunnel local IPaddr:

tunnel MTU interface:   1420

admin address: 

admin UDP port:          8844

running user:            nobody

running group:           nogroup

location name:           home

hack chaining:           disabled

tcp mangling:            enabled

udp mangling: enabled


This output confirms that sniffjoke is present, is not running actively, and has a tunnel interface… why?

Sniffjoke need to inject, delay, modify outgoing packets, but the packets are send by the kernel, and no one user process could operate after the kernel … exception noted for the VPN software.

The vpn software, usually open a “tun0” device, that should be used with a static route, a network associated or as default gateway. Is a virtual interface, usually encapsulating the traffic inside an encrypted connection (the tunnel) that bring the session in a remote environment, linked to us as will be in LAN.

 Sniffjoke change the default gateway with a tunnel interface, lets see an example. This is the routing table without SniffJoke:

Kernel IP routing table

Destination  Gateway  Genmask Flags Metric  Ref  Use Iface UH    0      0        0 tun0 UGH   0      0        0 tun1 UH    0      0        0 tun1   UG    0      0        0 tun1   U     0      0        0 eth0     U     1000   0        0 eth0         UG    0      0        0 eth0

The default gateway, which one with “” as destination, is reachable via eth0 and as an IP address of

Starting sniffjoke, here is how routing table change:

Kernel IP routing table

Destination   Gateway    Genmask     Flags Metric Ref    Use Iface UH    0      0        0 tun0 UH    0      0        0 sniffjoke UGH   0      0        0 tun1 UH    0      0        0 tun1   UG    0      0        0 tun1   U     0      0        0 eth0     U     1000   0        0 eth0         UG    0      0        0 sniffjoke

The virtual interface “sniffjoke” has been created, and is become the default gateway. This permits sniffjoke to receive and manage all the outgoing packets. If is running, apply the modification, if not, simply forward the packets.

# sniffjokeclt start

This is the command that start sniffjoke engine. Now:

  1. Every session will be simil-tracerouted and cached (sniffjokectl ttlmap show them)
  2. Every packets will have TTL modify also without aiming to make the packet expire
  3. Every packets will be added some IP/TCP options that don’t ruin the packet integrity
  4. If a debug level of 5 or more is specify, print verbose logging to every packets passing through sniffjoke.

# sniffjoke –location home –foreground –debug 6 –start –force

“force” options kill previously instanced sniffjoke, “start” make sniffjoke immediately active, without sniffjokectl requirement, “debug 6” enable the most verbose logging supported, and “foreground” show these log in standard output instead of a logfile. I use this combination when I’m debugging.


Sniffjoke internal architecture

being a modular framework is useful for easy development and usage of technology able to disrupt passive protocol reassembly at every layer. the release 0.4 only bring attack at IP and TCP/UDP layer, in the next release we plan an escalation, like HTTP, MAIL, chat, and specific layer 5+ protocol injections.

exploiting the swiftness of the network supports, the differences of every ISP configuration and (not yet implemented) of the Operating System TCP/IP stack differences, sniffjoke put the sniffers under the difficult option of: drop every packets that have something weird, in order to follow the growing bandwidth and the demanding hardware requests, or to improve analysis, expeding CPU and time, and implicitly increase the costs per megabit. this will demotivate massive sniffing from evil entities. This is almost the target goal.


Scramble and Plugins

From a Sniffjoke point of view a Scramble is the fundamental way to permit packet injection to disturb the sniffer flow reconstruction while not disturbing the communication, while Plugins (sometimes referred as Hacks) are particular packets conformed as real one that using the scramble will reach the sniffer only. Without going into details, for which we suggest to read [2], SniffJoke actually implements quite all literature attacks and actually implements three Scrambles: 

The TTL packet expire has been already told, and, for the hackers who want to read the code,, and explain a lot better than an article 🙂 


Bad IP/TCP header options

sending bad IP/TCP options inside an hack packet permits the destination to drop it; the sniffer instead not implementing a real tcp/ip stack won't filter it; Actually we have also tried to go beyond this searching tcp/ip options that will result good also to a complete sniffer exploiting some end to end states variables unknown to the sniffer. this is one of SniffJoke specific implementation, arised during test, and bad discussed by literature. 

What you see below is an image with the usage of TCP MD5 header options. You know ? is pretty rare, but modern kernel support the signature of a TCP packet with an hash algorithm. Has been inserted for the dynamic routing authentication (in BGP, a protocol used by huge provider) but in fact no one deny us to use it in an IRC or HTTP session!

Follow the usage of IP_TIMESTAMP, a duplicated TIMESTAMP that is caused a problem in some kernel an is barely trapped as a problem by the sniffers. What’s happen in these cases ? that the sniffer is desynchronized and our session became opaque to the interception tool. IP_RA stay for router advertising, the SACK for selective acknowledge. Both useful options, but in determinate and restricted context. No one deny their use and abuse, so, why not?

Using and abusing of the IP/TCP options imply some consideration…

  1. This exploit attack the slow possibility of the hardware sniffer to be update regardless the last supported IP options or the last abuse popped out from the hacker community
  2. Need hopefully to be tested for each destination (like a traceroute) because every ISP handle these options differently
  3. The options that don’t cause damage will be put in the good and innocent packets containing our real data, this will cause, in some cases, that the sniffer don’t even capture them because of the options presence. In short, we are forcing the sniffer to support the most detailed and weird IP/TCP options combination, but doing this downgrade their performances.


Invalid checksum

This is one of the primordial literature idea, that arise by the fact that a gigabit realtime sniffer would probably avoid to verify ip/tcp checksum. SniffJoke, as for others tricks we mentioned, always keep a sneaky approach while trying to adopt generic techniques only. 

For example for the checksum the more sneaky option is the tcp one, while the ip one will be probably checked by a lot of sniffers.

The scramble causes the desyncronization, but what kind of damage is bring to the session?

This is implemented in the plugins! The code of the plugins stays in sniffjoke-0.4.X/src/plugins, and is simple C++ classess that implements a virtual one.

There are various plugin implementing different attack, but two of them is the most characteristic. 

The fake closure of a session:-

In this example, the remote service has been ACKed thr 100th bytes received, our plugin (fake_close_fin) anticipate our real packet with a FIN. The flag FIN, in the TCP, mean the willing of a side to close the connection. 

In this analysis we don’t care about the scramble used: we suppose that the sniffer take a packet and the same packet is discarded by the remote host.

The FIN has the correct sequence number of (last segment) + 1, for this example is 101, if the sniffer check them, will consider the session closed from the client-session.

But fake_close_fin has a second usage inside the code:-

Because we don’t know if the sniffer wait the correctly sequence (of 101) or expect to see the FIN packet being ACKed before commit them into his routines, when a packets of 100 byte with a sequence of 200 will be sent, this plugin inject a FIN packet with the same sequence number. The remote server have to ACK 200, to confirm  data read. If the sniffer was expecting an ACK of 200, see them, and commit the FIN, closing the session.

Both way are possible, when I approached to develop a plugin usually avoid to read the code of the sniffers, because a lot of them are closed source. If an attack is applicable by theory, and by logic I feel that some check will be done, I try to anticipate them injecting the fake packets able to defeat that algorithm.

For closing a session, the flag FIN and the flag RST have different meaning but more or less effects. (trivia: injecting a packet with FIN+RST, not permitted by rfc, some sniffers consider the session closed and the remote service drop it because not permitted!)

The injection of a fake data:-

The previously image works with a concept more or less like the last FIN injection. 

We know that some sniffer commit a data only when they see the answers ACK, confirming that the packets was undoubtedly accepted by the server.

But when a sniffer see two packets with the same sequence number, could simple presume that one has been retransmitted. Independently from the reason of the duplication, his algorithm will be:

  1. I’ve the packet with seq 600
  2. I’ve another packet with seq 600, override the previously


  1. I’ve the packet with seq 600
  2. I’ve another packet with seq 600, drop this.

This cause, the saved packets will be the LAST receive in the first case, or the FIRST received in the second case. Fake_data, put two packets, large the same amount of the original one, before and after the covering packet. This will cause the sniffer to record an entirely fake data, this is how a wireshark will feel when an HTTP POST is treated in this way:

Every data send from the web client appears as “6”. Only for the sniffer!

Plugins are pretty simple, if you are skilled in TCP/IP and want to code some plugins, join the community! Mail to us, sniffjoke is growing.


Sniffjoke is powerful, but will result instable. For the most, because of the “malformed” packet, the packet using the IP/TCP options injection. If you detect some problem in navigation, you will try to edit plugins-enabled.conf of your location and remove every “MALFORMED” inclusions.

Sniffjoke has not a great impact also because lack of the intensive testing required for make a tool a famous one. For make those tests are required hackers with the skill of traffic analysis, mastering sniffjoke usage and with the patience of download a sniffer and check what happen inside it while following a sniffjoke session.

 If you would try in such research, publish your results online and signal to me, I will be very glad to link your research in the “sniffers autopsy” table:

Claudio Agosti, know as “vecna”, 31, is a free man, with skill in networking, kernel, hacking and security. His goal anyway stay in the “human right in digital environment”

Leave a Reply