0

In Scapy, I want to save to disk the output of sr for later analysis.

ans, unans = sr(somePackets)

While unans presents no problem with scapy's built-in function wrpcap, I can't seem to be able to save ans to disk.

>>> wrpcap(locationOnDisk, ans)
WARNING: PcapWriter: unknown LL type for tuple. Using type 1 (Ethernet)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/scapy/utils.py", line 470, in wrpcap
    PcapWriter(filename, *args, **kargs).write(pkt)
  File "/usr/lib/python2.7/dist-packages/scapy/utils.py", line 653, in write
    self._write_packet(p)
  File "/usr/lib/python2.7/dist-packages/scapy/utils.py", line 692, in _write_packet
    sec = int(packet.time)
AttributeError: 'tuple' object has no attribute 'time'

Indeed, it's the attribute time added by sr to each packet that I'm mostly interested in.

So I tried with pickle, but it went even worse:

>>> pickle.dump(ans, open(locationOnDisk, "w+"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/pickle.py", line 1370, in dump
    Pickler(file, protocol).dump(obj)
  File "/usr/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 725, in save_inst
    save(stuff)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/usr/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 600, in save_list
    self._batch_appends(iter(obj))
  File "/usr/lib/python2.7/pickle.py", line 615, in _batch_appends
    save(x)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 562, in save_tuple
    save(element)
  File "/usr/lib/python2.7/pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "/usr/lib/python2.7/pickle.py", line 419, in save_reduce
    save(state)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/usr/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/usr/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 725, in save_inst
    save(stuff)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/usr/lib/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 748, in save_global
    (obj, module, name))
pickle.PicklingError: Can't pickle <function <lambda> at 0x976c224>: it's not found as scapy.layers.inet.<lambda>

Any way to go around this?

Ricky Robinson
  • 21,798
  • 42
  • 129
  • 185
  • Are you sure `ans` is an iterable of packets? `scapy`'s first response tells you that it was expecting to see some sort of packets, but instead got an unexpected tuple. Reading the manual (http://goo.gl/XPB0V) has this quote: `The “send’n’receive” functions family is the heart of scapy. They return a couple of two lists. The first element is a list of couples (packet sent, answer), and the second element is the list of unanswered packets.`. So `ans` isn't what you think it is. – Asim Ihsan Jan 28 '13 at 12:16
  • Sorry, I didn't see your comment before. I am quite familiar with `ans`, but I didn't get what you said about it being or not an iterable of packets. I just wanted to save the content of `ans` to disk, not much else. :) – Ricky Robinson Feb 12 '13 at 18:30

1 Answers1

1
[13:44:49][root@box:~]$ scapy    
Welcome to Scapy (2.1.0)
>>> sr
<function sr at 0x8cc3614>
>>> ans, unans = sr(IP(dst="www.slashdot.org")/ICMP()/"XXXXXXXXXXX")
Begin emission:
.Finished to send 1 packets.
.*
Received 3 packets, got 1 answers, remaining 0 packets

>>> ans
<Results: TCP:0 UDP:0 ICMP:1 Other:0>
>>> type(ans)
<type 'instance'>
>>> dir(ans)
['__add__', '__doc__', '__getattr__', '__getitem__', '__getslice__', '__init__', '__module__', '__repr__', '_dump_document', '_elt2pkt', '_elt2show', '_elt2sum', 'afterglow', 'conversations', 'diffplot', 'display', 'filter', 'hexdump', 'hexraw', 'listname', 'make_lined_table', 'make_table', 'make_tex_table', 'multiplot', 'nsummary', 'nzpadding', 'padding', 'pdfdump', 'plot', 'psdump', 'rawhexdump', 'replace', 'res', 'sessions', 'show', 'sr', 'stats', 'summary', 'timeskew_graph']

So what do we know? We now know that ans is definitely not a list of packets, but is instead some other instance object that offers tuple semantics (__getitem__, etc.), and hence scapy will refuse to dump this to a capture file:

>>> wrpcap("test.cap", ans)
WARNING: PcapWriter: unknown LL type for tuple. Using type 1 (Ethernet)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/scapy/utils.py", line 466, in wrpcap
    PcapWriter(filename, *args, **kargs).write(pkt)
  File "/usr/local/lib/python2.7/site-packages/scapy/utils.py", line 649, in write
    self._write_packet(p)
  File "/usr/local/lib/python2.7/site-packages/scapy/utils.py", line 688, in _write_packet
    sec = int(packet.time)
AttributeError: 'tuple' object has no attribute 'time'

As I said in the comment above, the hint is in the error message. ans is not what you think it is:

>>> type(ans[0])
<type 'tuple'>
>>> len(ans[0])
2
>>> ans[0]
(<IP  frag=0 proto=icmp dst=216.34.181.48 |<ICMP  |<Raw  load='XXXXXXXXXXX' |>>>, <IP  version=4L ihl=5L tos=0x0 len=39 id=51902 flags=DF frag=0L ttl=235 proto=icmp chksum=0xbe0 src=216.34.181.48 dst=10.227.33.1 options=[] |<ICMP  type=echo-reply code=0 chksum=0xee45 id=0x0 seq=0x0 |<Raw  load='XXXXXXXXXXX' |<Padding  load='\x00\x00\x00\x00\x00\x00\x00' |>>>>)
>>> ans[0][0]
<IP  frag=0 proto=icmp dst=216.34.181.48 |<ICMP  |<Raw  load='XXXXXXXXXXX' |>>>
>>> ans[0][1]
<IP  version=4L ihl=5L tos=0x0 len=39 id=51902 flags=DF frag=0L ttl=235 proto=icmp chksum=0xbe0 src=216.34.181.48 dst=10.227.33.1 options=[] |<ICMP  type=echo-reply code=0 chksum=0xee45 id=0x0 seq=0x0 |<Raw  load='XXXXXXXXXXX' |<Padding  load='\x00\x00\x00\x00\x00\x00\x00' |>>>>

So what do we know now? Each element of ans is a two-tuple:

  • The first element of the tuple is the sent packet.
  • The second element of the tuple is the respective packet received

Hence, let's say you want both kinds of packets in your output:

>>> all_packets = [elem[0] for elem in ans] + [elem[1] for elem in ans]
>>> import operator
>>> all_packets.sort(key=operator.attrgetter("time"))
>>> wrpcap("test.cap", all_packets)
/usr/local/lib/python2.7/site-packages/scapy/utils.py:665: DeprecationWarning: 'I' format requires 0 <= number <= 4294967295
  self.f.write(struct.pack(self.endian+"IIII", sec, usec, caplen, wirelen))
>>> exit()

[14:03:09][root@box:~]$ ls -ltra | tail -1
-rw-r--r--  1 root root       141 2013-02-13 14:02 test.cap

I've confirmed that this file opens correctly in Wireshark, so you should be good to go; I'd suggest further testing to be sure. However, the conclusion stands: ans is not what you think it is.

Asim Ihsan
  • 1,501
  • 8
  • 18