I am having a problem where I can't get the raw bytes in ascii format when using the sniff() function in scapy. Example, i have this function:
a = sniff(filter="tcp port 5900",iface="eth0", prn=lambda x: x.show(), count=20)
And the output of a.summary()
of one of the packets:
I would like the raw output to be in ascii format, since when I open the pcap file in Wireshark, it normally comes in ascii format. For example:
I would like the output of the sniff function to come in ascii format just like in wireshark. Is it possible?
I tried several parameters in the documentation but was unsuccessful. I was hoping to be able to extract this data in ASCII format like in wireshark using the sniff function.
You are trying to change the behavior of the show
method of the Packet
class (see source code). It boils down to patch _show_or_dump
. You should identify values of type bytes
and convert them to hex
with fvalue.hex()
:
from scapy.all import sniff
from scapy.packet import *
from unittest.mock import patch
def show_or_dump_hex(self,
dump=False, # type: bool
indent=3, # type: int
lvl="", # type: str
label_lvl="", # type: str
first_call=True # type: bool
):
# type: (...) -> Optional[str]
"""
Internal method that shows or dumps a hierarchical view of a packet.
Called by show.
:param dump: determine if it prints or returns the string value
:param int indent: the size of indentation for each layer
:param str lvl: additional information about the layer lvl
:param str label_lvl: additional information about the layer fields
:param first_call: determine if the current function is the first
:return: return a hierarchical view if dump, else print it
"""
if dump:
from scapy.themes import AnsiColorTheme
ct = AnsiColorTheme() # No color for dump output
else:
ct = conf.color_theme
s = "%s%s %s %s \n" % (label_lvl,
ct.punct("###["),
ct.layer_name(self.name),
ct.punct("]###"))
for f in self.fields_desc:
if isinstance(f, ConditionalField) and not f._evalcond(self):
continue
if isinstance(f, Emph) or f in conf.emph:
ncol = ct.emph_field_name
vcol = ct.emph_field_value
else:
ncol = ct.field_name
vcol = ct.field_value
fvalue = self.getfieldval(f.name)
if isinstance(fvalue, Packet) or (f.islist and f.holds_packets and isinstance(fvalue, list)): # noqa: E501
pad = max(0, 10 - len(f.name)) * " "
s += "%s \\%s%s\\\n" % (label_lvl + lvl, ncol(f.name), pad)
fvalue_gen = SetGen(
fvalue,
_iterpacket=0
) # type: SetGen[Packet]
for fvalue in fvalue_gen:
s += fvalue._show_or_dump(dump=dump, indent=indent, label_lvl=label_lvl + lvl + " |", first_call=False) # noqa: E501
else:
pad = max(0, 10 - len(f.name)) * " "
begn = "%s %s%s%s " % (label_lvl + lvl,
ncol(f.name),
pad,
ct.punct("="),)
if isinstance(fvalue, bytes): # this is where we check if the value is of type bytes
reprval = fvalue.hex()
else:
reprval = f.i2repr(self, fvalue)
if isinstance(reprval, str):
reprval = reprval.replace("\n", "\n" + " " * (len(label_lvl) + # noqa: E501
len(lvl) +
len(f.name) +
4))
s += "%s%s\n" % (begn, vcol(reprval))
if self.payload:
s += self.payload._show_or_dump( # type: ignore
dump=dump,
indent=indent,
lvl=lvl + (" " * indent * self.show_indent),
label_lvl=label_lvl,
first_call=False
)
if first_call and not dump:
print(s)
return None
else:
return s
with patch.object(Packet, '_show_or_dump', show_or_dump_hex):
a = sniff(iface="eth0", prn=lambda x: x.show(), count=20)
Output sample:
###[ TCP ]###
sport = 54346
dport = 8080
seq = 3963954686
ack = 1203731561
dataofs = 5
reserved = 0
flags = PA
window = 1026
chksum = 0x5518
urgptr = 0
options = []
###[ Raw ]###
load = 160303002510000021204b4a9d45e1716324cfe25d7535735aadec14fde479f6a238ac2aa83fb24e0b6614030300010116030300280000000000000000589efd0d4da6de55e816d04f0055e664628e1f11a43ad68a1fb8a45ff26af4ef
Edit: this can be done in a less verbose way by patching _StrField.i2repr()
(source code):
from scapy.all import sniff
from scapy.fields import _StrField
from unittest.mock import patch
def i2repr_hex(self, pkt, x):
# type: (Optional[Packet], I) -> str
if isinstance(x, bytes):
return x.hex()
return super(_StrField, self).i2repr(pkt, x)
with patch.object(_StrField, 'i2repr', i2repr_hex):
a = sniff(iface="eth0", prn=lambda x: x.show(), count=20)