Snacktime: A Perl Solution
for Remote OS Fingerprinting

Tod Beardsley, Plan B Security
June, 2003
Austin, TX

Background

Franck Veysset, Olivier Courtay, and Olivier Heen of Intranode research noticed that one could fairly reliably detect a wide range of operating systems by timing the retransmission timeout lengths of the TCP handshake. Turns out, this is not only a surprisingly reliable, but has the potential to be extremely stealthy. Their proof-of-concept tool, RING, demonstrated this technique, and I reviewed their research for my GCIA Assignment #1, Ring out the old, RING in the new; see these papers for more in-depth analysis on how RTO timing works.

Being that I'm a chimp, I'm much better with Perl than I am with C, so I ported the concepts over, and added on some extra passive fingerprinting techniques. The result is Snacktime -- a half-open, half-passive OS Fingerprinting tool.

One of the drawbacks of RING is that when you're fingerprinting, there's not a lot else you can do, network-wise. Snacktime doesn't even try to shut up your stack, so you'll have to take care of that on your own. Two methods I've found work well:

The traditional method for dropping packets is using a firewall rule. There are a few ways to do this, depending on your existing firewall requirements, but either of these rules would work, presuming you have iptables installed:

Another way to avoid RSTing the connection is to spoof both your source IP address (using Snacktime's -s option) and your MAC address (using Dug Song's arpspoof (.deb)). This is more fun, and can have the added effect of reducing the number of packets sent to the target with identifying information about your machine from one to zero. To achieve this, get and install dsniff, and run (in another console):

arpspoof -t [your gateway] [your UNUSED, local fake IP]

A couple caveats: ARP spoofing can be dangerous (some network devices react badly when you start mucking around with their ARP tables), and illegal if you do it with a publicly-addressable Internet address (some states specifically outlaw this sort of spoofing activity through brain dead Super-DMCA legislature).

Syntax and Options

Snacktime has a short usage blurb, gotten at by supplying no options, or -h. Here are some more details:

This is the only required argument (everything else has default values), because you need to pick a target. This can be either an IP address or a DNS name. Note, however, if you use DNS, you may send some extra packets to your target's network, which could impact your stealth. Finally, only one host is allowed on the line -- Snacktime doesn't (yet) have the capability of taking a list of IPs, or a range, or anything like that. In the meantime, use a shell script wrapper.

-p [target port] (default: 80)

The target port. This port must be open and unfiltered, from your point of view. If you pick a closed port (one that sends you a RST), Snacktime will notice and exit.

-w [seconds] (default: 65)

The number of seconds to wait after the last SYN-ACK (this is not the total amount of time to wait). Lowering this value will speed things up, but too low, and you may time out before your target does. (most notably, the ridiculously persistent Sun stacks).

-m (no arguments)

Use more stuff to score results -- specifically, gauge the Time-to-Live (TTL) and TCP Window Size (WinSize) values. This can help break ties between two similar RTOs, but on the flip side, can throw off results if your target has customized these values, or is behind a device that rewrites header information, as some firewalls and load balancers are wont to do.

-v (no arguments)

Be verbose during testing and scoring. Its use is recommended to time new, unknown OSes.

-s [source address] (default: best guess)

A source IP address. Use this if your default Ethernet device is, for some reason, not reporting the "right" IP address. You'll also want to use this if you intend to spoof your source IP, and you have a method of hearing the replies (ie, through arp spoofing, discussed above).

Uncommon Options

-D [ethernet device] (default: best guess)

Your ethernet device, if you have many and Snacktime is guessing wrong. On Linux, this will tend to be eth0, eth1, etc.

-P [source port] (default: random > 1024)

A defined source port. This may be important for your own network's egress rules, or to defeat silly ingress rules on your target's network. For example, some administrators who haven't read a networking book in the last five years may still be allowing any traffic orgininating from ports 20 or 53, regardless of TCP flags.

-f [fingerprint file] (default: ./snack.fp)

Location of your fingerprint file.

-V (no options)

Be very verbose during testing and scoring. Its use implies -v, naturally, and its use is recommended if you don't mind a couple screens full of scoring information.

Reasons For Usage

So, why would you want to use Snacktime? I can think of a few reasons:

You're a network administrator, but you don't have login rights to one of your machines. Inexplicably, you're still responsible for keeping track of what all operating systems are running in your environment for auditing purposes. (I find myself in this situation a lot.)

You're Evil(tm), and you want to stealthily determine a machine's operating system so you can make sensible choices for which 0day exploit you want to launch against it. Yes, this is naughty, and maybe illegal, but before we start crying too much about this, let's remember: skiddies and worms won't generally have the patience or desire to perform this kind of reconnaissance, since stealth and sensible target selection aren't high priorities.

You've been the target of said evil person, and you want to find out what operating system the attack was sourced from. I, personally, use Snacktime for this purpose quite a bit.

You want to determine if a particular OS conforms to the relevant RFCs regarding retransmission timeouts and backoff times, because you care for some reason.

You want to correlate a guess from another OS fingerprinting tool, such as Nmap, Netcraft, or p0f.

As far as I can tell, measuring RTOs seems to be a pretty accurate and stealthy method for profiling networked devices, and Snacktime seems to be a pretty reasonable implementation. Furthermore, masking ones "normal" RTO can be difficult for some operating systems, and given this technique's relative newness, is much more uncommon than more traditional methods of defeating profiling (but see below).

Some comparisons to other fingerprinting techniques:

Nmap

Nmap is the de facto standard for OS profiling. It requires at least two ports on the target machine: one open and one closed. By measuring the ways the target responds to a handful of funny packets sent to each, Nmap makes its guess. However, the days of having machines sitting directly on the network without some kind of filtering device are receding, and Nmap's reliability drops dramatically when it's only given a single open port to work with.

p0f

p0f, by design, doesn't initiate communication, and only cares about initial SYNs. p0f doesn't generate any packets, so it is necessarily perfectly stealthy, but its use requires you to somehow get your target to talk to you.

However, these applications both have at their disposal comprehensive fingerprint databases. Snacktime has only been tested (and lightly, I might add) against a couple dozen different devices. So, if you have any new fingerprints, please feel free to mail them in to snacktime@planb-security.net.

Finally, there are other fingerprinting applications (QueSO, Internet Scanner, Ettercap, etc.), and while they all have their particular interface niceties, they tend make use of Nmap's fingerprint database and techniques (many funny packets to multiple dest ports).

This has been a major pain, and probably the biggest limitation of my weak Perl skillz. I used to control iptables directly, but the setting and removing of custom rules had an unfortunate side effect of wiping out any existing rules. However, I'm a fan of the ARP spoofery, and I'm liking that method more these days. Unfortunately, I haven't found a Perl module that lets me drop Ethernet packets directly on the wire, and my attempts at hacking up Net::RawIP have been ugly (they work, but it's really, really lame).

Ranges of targets.

Right now, I handle ranges through a shell script, but it's dumb not to do this internally. However, since my IPC sucks, this turns out to be a little harder than it sounds.

Logging

Once I get ranges down, I'll want to log the results. After these improvements, Snacktime can finally find use as an asset management tool (which was kind of the whole point at the beginning of this project).

Source OS Impersonation

It would be amusing to have the initial Syns conform to a number of different p0f-identifiable fingerprints.

Decoy Source IPs

Since Snacktime never completes the handshake, this could be useful -- Nmap uses decoys to great effect, but I'm having trouble coming up with legitimately, non-evil uses for such a feature.

I haven't made any particular effort to make Snacktime packets look more or less like any other normal SYN packets, but that said, I'd be very surprised if there's an IDS system out there that could reliably detect Snacktime traffic -- after all, little lost SYNs are not all that odd on the Internet.

As for defeating Snacktime (and other RTO profilers), changing the behavior of a device's SYN-ACK retries can range from trivial to impossible. For Linux, Toby Miller's recent paper on passive OS fingerprinting discusses the/proc/sys/net/ip4 directory -- therein, you can edit the tcp_synack_retriesto change the number (but not the timing) of SYN-ACKs sent back to Snacktime.

For Windows NT/2k, Microsoft's KB article 120642 discusses a number of TCP/IP behavioral defaults one could change, including default TTL and WinSize, but the RTO is not one of them. This is the same situation for the BSDs, as far as I can tell -- again, BSD administrators can edit the TTL and WinSize values using sysctl, but it appears the RTOs are off-limits. These measures will certainly muck up evaluating Snacktime scores using the -m (more stuff) option, but Snacktime's core functionality remains unaffected.