Scapy: using p0f

I’ve recently released a not-yet-applied patch for scapy which improves the use of p0f functionalities.

First, p0f now comes with databases designed for other TCP packets than only SYN packets (one database for SYN/ACK packets, one for RST and RST/ACK packets, and the last one for “stray” ACK packets). Those new databases are slightly different than the original one, and an effort was required to enable scapy’s p0f functions to use them.

Now, scapy is able to deal with any kind of TCP packets:

>>> sniff(prn=prnp0f, filter='tcp') - Linux 2.6 (newer, 2) (up: 128 hrs)
  -> (S) (distance 0) - UNKNOWN [49980:52:1:64:N,N,T,M1460,N,W0,N,N,S:AT:?:?] (up: 946 hrs)
  -> (SA)

The (S) and (SA) denote the database used (regular p0f.fp for S, and p0fa.fp for SA).

While working on this I’ve had two ideas of cool features to add, and I’ve added them.

The first one is a function to get signatures for the local system. This is done by sniffing packets generated by the use of socket functions, in a function I called p0f_getlocalsigs(). For now, I only use the loopback interface, which causes to generate different signatures than the one generated on regular network interfaces. I’m thinking to add other tests using other interfaces, but nothing is done for now.

Knowing that scapy is not only a sniffing tool, but is also great to forge, manipulate and send packets, the second one is a function that modifies a packet so that it matches a given signature. This work is done by a function called p0f_impersonate:

>>> pkt = p0f_impersonate(IP(dst='')/TCP(sport=12345, dport=80, flags='S'), osgenre='Linux')
>>> prnp0f(pkt) - Linux 2.4 (Google crawlbot) (up: 7326 hrs)
  -> Net(''):www (S) (distance 0)
>>> send(pkt)

A (real) p0f running in another window shows:

# p0f
p0f - passive os fingerprinting utility, version 2.0.8
(C) M. Zalewski , W. Stearns
p0f: listening (SYN) on 'eth1', 262 sigs (14 generic, cksum 0F1F5CA2), rule: 'all'. - Linux 2.4 (Google crawlbot) (up: 7326 hrs)
  -> (distance 0, link: (Google/AOL))