Skip to content

Commit 6ee4471

Browse files
Merge pull request #2 from secdev/master
Pull
2 parents 7692e5d + 08d6f4e commit 6ee4471

File tree

14 files changed

+552
-162
lines changed

14 files changed

+552
-162
lines changed

doc/scapy/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This document is under a `Creative Commons Attribution - Non-Commercial
2525

2626
usage
2727
advanced_usage
28+
routing
2829

2930
.. toctree::
3031
:maxdepth: 2

doc/scapy/routing.rst

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
*************
2+
Scapy routing
3+
*************
4+
5+
Scapy needs to know many things related to the network configuration of your machine, to be able to route packets properly. For instance, the interface list, the IPv4 and IPv6 routes...
6+
7+
This means that Scapy has implemented bindings to get this information. Those bindings are OS specific. This will show you how to use it for a different usage.
8+
9+
.. note::
10+
Scapy will have OS-specific functions underlying some high level functions. This page ONLY presents the cross platform ones
11+
12+
13+
List interfaces
14+
---------------
15+
16+
Use ``get_if_list()`` to get the interface list
17+
18+
.. code-block:: pycon
19+
20+
>>> get_if_list()
21+
['lo', 'eth0']
22+
23+
IPv4 routes
24+
-----------
25+
26+
.. note::
27+
If you want to change or edit the routes, have a look at `the "Routing" section in Usage <usage.html#routing>`_
28+
29+
The routes are stores in :py:attr:`conf.route <scapy.route.Route>`. You can use it to display the routes, or get specific routing
30+
31+
.. code-block:: pycon
32+
33+
>>> conf.route
34+
35+
Network Netmask Gateway Iface Output IP Metric
36+
0.0.0.0 0.0.0.0 10.0.0.1 eth0 10.0.0.5 100
37+
10.0.0.0 255.255.255.0 0.0.0.0 eth0 10.0.0.5 0
38+
127.0.0.0 255.0.0.0 0.0.0.0 lo 127.0.0.1 1
39+
168.63.129.16 255.255.255.255 10.0.0.1 eth0 10.0.0.5 100
40+
169.254.169.254 255.255.255.255 10.0.0.1 eth0 10.0.0.5 100
41+
42+
Get the route for a specific IP: :py:func:`conf.route.route() <scapy.route.Route.route>` will return ``(interface, outgoing_ip, gateway)``
43+
44+
.. code-block:: pycon
45+
46+
>>> conf.route.route("127.0.0.1")
47+
('lo', '127.0.0.1', '0.0.0.0')
48+
49+
IPv6 routes
50+
-----------
51+
52+
Same than IPv4 but with :py:attr:`conf.route6 <scapy.route6.Route6>`
53+
54+
Get router IP address
55+
---------------------
56+
57+
.. code-block:: pycon
58+
59+
>>> gw = conf.route.route("0.0.0.0")[2]
60+
>>> gw
61+
'10.0.0.1'
62+
63+
Get local IP / IP of an interface
64+
---------------------------------
65+
66+
Use ``conf.iface``
67+
68+
.. code-block:: pycon
69+
70+
>>> ip = get_if_addr(conf.iface) # default interface
71+
>>> ip = get_if_addr("eth0")
72+
>>> ip
73+
'10.0.0.5'
74+
75+
Get local MAC / MAC of an interface
76+
-----------------------------------
77+
78+
.. code-block:: pycon
79+
80+
>>> mac = get_if_hwaddr(conf.iface) # default interface
81+
>>> mac = get_if_hwaddr("eth0")
82+
>>> mac
83+
'54:3f:19:c9:38:6d'
84+
85+
Get MAC by IP
86+
-------------
87+
88+
.. code-block:: pycon
89+
90+
>>> mac = getmacbyip("10.0.0.1")
91+
>>> mac
92+
'f3:ae:5e:76:31:9b'
93+

scapy/arch/linux.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
SO_TIMESTAMPNS
3232
from scapy.supersocket import SuperSocket
3333
from scapy.error import warning, Scapy_Exception, \
34-
ScapyInvalidPlatformException
34+
ScapyInvalidPlatformException, log_runtime
3535
from scapy.arch.common import get_if, compile_filter
3636
import scapy.modules.six as six
3737
from scapy.modules.six.moves import range
@@ -461,12 +461,19 @@ def __init__(self, iface=None, type=ETH_P_ALL, promisc=None, filter=None,
461461
)
462462
if not six.PY2:
463463
# Receive Auxiliary Data (VLAN tags)
464-
self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
465-
self.ins.setsockopt(
466-
socket.SOL_SOCKET,
467-
SO_TIMESTAMPNS,
468-
1
469-
)
464+
try:
465+
self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
466+
self.ins.setsockopt(
467+
socket.SOL_SOCKET,
468+
SO_TIMESTAMPNS,
469+
1
470+
)
471+
self.auxdata_available = True
472+
except OSError:
473+
# Note: Auxiliary Data is only supported since
474+
# Linux 2.6.21
475+
msg = "Your Linux Kernel does not support Auxiliary Data!"
476+
log_runtime.info(msg)
470477
if isinstance(self, L2ListenSocket):
471478
self.outs = None
472479
else:
@@ -494,7 +501,7 @@ def close(self):
494501
try:
495502
if self.promisc and self.ins:
496503
set_promisc(self.ins, self.iface, 0)
497-
except AttributeError:
504+
except (AttributeError, OSError):
498505
pass
499506
SuperSocket.close(self)
500507

scapy/contrib/automotive/bmw/definitions.py

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#! /usr/bin/env python
2-
31
# This file is part of Scapy
42
# See http://www.secdev.org/projects/scapy for more information
53
# Copyright (C) Nils Weiss <[email protected]>
@@ -11,9 +9,9 @@
119

1210
from scapy.packet import Packet, bind_layers
1311
from scapy.fields import ByteField, ShortField, ByteEnumField, X3BytesField, \
14-
StrField
12+
StrField, StrFixedLenField, LEIntField, LEThreeBytesField, PacketListField
1513
from scapy.contrib.automotive.uds import UDS, UDS_RDBI, UDS_DSC, UDS_IOCBI, \
16-
UDS_RC, UDS_RD, UDS_RSDBI
14+
UDS_RC, UDS_RD, UDS_RSDBI, UDS_RDBIPR
1715

1816

1917
BMW_specific_enum = {
@@ -245,6 +243,111 @@ class UDS2S_REQ(Packet):
245243
UDS.services[0xa5] = 'UnpackDS2Service'
246244

247245

246+
class SVK_DateField(LEThreeBytesField):
247+
def i2repr(self, pkt, x):
248+
x = self.addfield(pkt, b"", x)
249+
return "%02X.%02X.20%02X" % (x[0], x[1], x[2])
250+
251+
252+
class SVK_Entry(Packet):
253+
fields_desc = [
254+
ByteEnumField("processClass", 0, {1: "HWEL", 2: "HWAP", 4: "GWTB",
255+
5: "CAFD", 6: "BTLD", 7: "FLSL",
256+
8: "SWFL"}),
257+
StrFixedLenField("svk_id", b"", length=4),
258+
ByteField("mainVersion", 0),
259+
ByteField("subVersion", 0),
260+
ByteField("patchVersion", 0)]
261+
262+
def extract_padding(self, p):
263+
return b"", p
264+
265+
266+
class SVK(Packet):
267+
prog_status_enum = {
268+
1: "signature check and programming-dependencies check passed",
269+
2: "software entry invalid or programming-dependencies check failed",
270+
3: "software entry incompatible to hardware entry",
271+
4: "software entry incompatible with other software entry"}
272+
273+
fields_desc = [
274+
ByteEnumField("prog_status1", 0, prog_status_enum),
275+
ByteEnumField("prog_status2", 0, prog_status_enum),
276+
ShortField("entries_count", 0),
277+
SVK_DateField("prog_date", b'\x00\x00\x00'),
278+
ByteField("pad1", 0),
279+
LEIntField("prog_milage", 0),
280+
StrFixedLenField("pad2", 0, length=5),
281+
PacketListField("entries", [], cls=SVK_Entry,
282+
count_from=lambda x: x.entries_count)]
283+
284+
285+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf101)
286+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf102)
287+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf103)
288+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf104)
289+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf105)
290+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf106)
291+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf107)
292+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf108)
293+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf109)
294+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10a)
295+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10b)
296+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10c)
297+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10d)
298+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10e)
299+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10f)
300+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf110)
301+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf111)
302+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf112)
303+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf113)
304+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf114)
305+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf115)
306+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf116)
307+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf117)
308+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf118)
309+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf119)
310+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11a)
311+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11b)
312+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11c)
313+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11d)
314+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11e)
315+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11f)
316+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf120)
317+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf121)
318+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf122)
319+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf123)
320+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf124)
321+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf125)
322+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf126)
323+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf127)
324+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf128)
325+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf129)
326+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12a)
327+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12b)
328+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12c)
329+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12d)
330+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12e)
331+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12f)
332+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf130)
333+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf131)
334+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf132)
335+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf133)
336+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf134)
337+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf135)
338+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf136)
339+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf137)
340+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf138)
341+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf139)
342+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13a)
343+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13b)
344+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13c)
345+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13d)
346+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13e)
347+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13f)
348+
bind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf140)
349+
350+
248351
UDS_RDBI.dataIdentifiers[0x0014] = "RDBCI_IS_LESEN_DETAIL_REQ"
249352
UDS_RDBI.dataIdentifiers[0x0015] = "RDBCI_HS_LESEN_DETAIL_REQ"
250353
UDS_RDBI.dataIdentifiers[0x0e80] = "AirbagLock"

scapy/contrib/automotive/bmw/enet.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
from scapy.layers.inet import TCP
1414
from scapy.supersocket import StreamSocket
1515
from scapy.contrib.automotive.uds import UDS
16+
from scapy.contrib.isotp import ISOTP
17+
from scapy.error import Scapy_Exception
18+
from scapy.data import MTU
1619

1720

1821
"""
@@ -65,6 +68,28 @@ def post_build(self, pkt, pay):
6568

6669
class ENETSocket(StreamSocket):
6770
def __init__(self, ip='127.0.0.1', port=6801):
71+
self.ip = ip
72+
self.port = port
6873
s = socket.socket()
69-
s.connect((ip, port))
74+
s.connect((self.ip, self.port))
7075
StreamSocket.__init__(self, s, ENET)
76+
77+
78+
class ISOTP_ENETSocket(ENETSocket):
79+
def __init__(self, src, dst, ip='127.0.0.1', port=6801, basecls=ISOTP):
80+
super(ISOTP_ENETSocket, self).__init__(ip, port)
81+
self.src = src
82+
self.dst = dst
83+
self.basecls = ENET
84+
self.outputcls = basecls
85+
86+
def send(self, x):
87+
if not isinstance(x, ISOTP):
88+
raise Scapy_Exception("Please provide a packet class based on "
89+
"ISOTP")
90+
super(ISOTP_ENETSocket, self).send(
91+
ENET(src=self.src, dst=self.dst) / x)
92+
93+
def recv(self, x=MTU):
94+
pkt = super(ISOTP_ENETSocket, self).recv(x)
95+
return self.outputcls(bytes(pkt[1]))

scapy/contrib/http2.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,24 +2644,25 @@ def parse_txt_hdrs(self,
26442644
register=True, # type: bool
26452645
):
26462646
# type: (...) -> H2Seq
2647-
""" parse_txt_hdrs parses headers expressed in text and converts them
2648-
into a series of H2Frames with the "correct" flags. A body can be provided # noqa: E501
2649-
in which case, the data frames are added, bearing the End Stream flag,
2650-
instead of the H2HeadersFrame/H2ContinuationFrame. The generated frames
2651-
may respect max_frm_sz (SETTINGS_MAX_FRAME_SIZE) and
2652-
max_hdr_lst_sz (SETTINGS_MAX_HEADER_LIST_SIZE) if provided. The headers
2653-
are split into multiple headers fragment (and H2Frames) to respect
2654-
these limits. Also, a callback can be provided to tell if a header
2655-
should be never indexed (sensitive headers, such as cookies), and
2656-
another callback say if the header should be registered into the index
2657-
table at all.
2647+
"""
2648+
parse_txt_hdrs parses headers expressed in text and converts them
2649+
into a series of H2Frames with the "correct" flags. A body can be
2650+
provided in which case, the data frames are added, bearing the End
2651+
Stream flag, instead of the H2HeadersFrame/H2ContinuationFrame.
2652+
The generated frames may respect max_frm_sz (SETTINGS_MAX_FRAME_SIZE)
2653+
and max_hdr_lst_sz (SETTINGS_MAX_HEADER_LIST_SIZE) if provided.
2654+
The headers are split into multiple headers fragment (and H2Frames)
2655+
to respect these limits. Also, a callback can be provided to tell if
2656+
a header should be never indexed (sensitive headers, such as cookies),
2657+
and another callback say if the header should be registered into the
2658+
index table at all.
26582659
For an header to be registered, the is_sensitive callback must return
26592660
False AND the should_index callback should return True. This is the
26602661
default behavior.
26612662
26622663
:param str s: the string to parse for headers
26632664
:param int stream_id: the stream id to use in the generated H2Frames
2664-
:param str|None body: the eventual body of the request, that is added
2665+
:param str/None body: the eventual body of the request, that is added
26652666
to the generated frames
26662667
:param int max_frm_sz: the maximum frame size. This is used to split
26672668
the headers and data frames according to the maximum frame size

0 commit comments

Comments
 (0)