Skip to content

Commit db3e983

Browse files
committed
Merge branch 'master' into hdtn
2 parents f736de6 + 449142a commit db3e983

29 files changed

Lines changed: 6877 additions & 607 deletions

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
<!-- This is just a checklist to guide you. You can remove it safely. -->
1+
<!-- This is just a checklist to guide you. Please remove it if you check all items. -->
22

33
**Checklist:**
44

55
- [ ] If you are new to Scapy: I have checked [CONTRIBUTING.md](https://github.com/secdev/scapy/blob/master/CONTRIBUTING.md) (esp. section submitting-pull-requests)
66
- [ ] I squashed commits belonging together
77
- [ ] I added unit tests or explained why they are not relevant
8-
- [ ] I executed the regression tests (using `cd test && ./run_tests` or `tox`)
8+
- [ ] I executed the regression tests (using `tox`)
99
- [ ] If the PR is still not finished, please create a [Draft Pull Request](https://github.blog/2019-02-14-introducing-draft-pull-requests/)
1010

1111
<!-- brief description what this PR will do, e.g. fixes broken dissection of XXX -->

doc/scapy/build_dissect.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ look to its building process::
649649
def post_build(self, p, pay):
650650
if self.len is None and pay:
651651
l = len(pay)
652-
p = p[:1] + hex(l)[2:]+ p[2:]
652+
p = p[:1] + struct.pack("!B", l) + p[2:]
653653
return p+pay
654654

655655
When ``post_build()`` is called, ``p`` is the current layer, ``pay`` the payload,

doc/scapy/layers/dcerpc.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
DCE/RPC & [MS-RPCE]
22
===================
33

4-
.. note:: DCE/RPC per `DCE/RPC 1.1 <https://pubs.opengroup.org/onlinepubs/9629399/toc.pdf>`_ with the `[MS-RPCE] <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/290c38b1-92fe-4229-91e6-4fc376610c15>`_ additions
4+
.. note:: DCE/RPC per `DCE/RPC 1.1 <https://pubs.opengroup.org/onlinepubs/9629399/toc.pdf>`_ with the `[MS-RPCE] <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/290c38b1-92fe-4229-91e6-4fc376610c15>`_ additions.
55

66
Scapy provides support for dissecting and building Microsoft's Windows DCE/RPC calls.
77

doc/scapy/layers/dcom.rst

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
[MS-DCOM]
2+
=========
3+
4+
DCOM is a mechanism to manipulate COM objects remotely. It is in many ways just an extension over normal DCE/RPC, so understanding DCE/RPC concepts beforehand can be very useful.
5+
Before reading this, have a look at Scapy's `DCE/RPC <dcerpc.html>`_ documentation page.
6+
7+
Terminology
8+
-----------
9+
10+
- In DCOM one instantiates 'classes' to get 'object references'. A class implements one or several 'interfaces', each of which has methods.
11+
- ``CLSID``: the UIID of a **class**, used to instantiate it. This is typically chosen by whoever implements the COM object.
12+
- ``IID``: the UIID of an **interface**, used to request an IPID. This is chosen by whoever defines the COM interface (mostly Microsoft).
13+
- ``IPID``: a UIID that uniquely references an **interface on an object**. This allows to tell DCOM on which object to run the request we send.
14+
15+
There are other IDs such as the OID (a 64bit number that uniquely references each object), and the OXID (a 64bit number that uniquely references each object exporter), but we won't get into the details.
16+
17+
Per the spec, a DCOM client is supposed to keep track of the IPID, OID and OXID ids. In this regard, Scapy abstracts their usage.
18+
On the other hand, the calling application is supposed to know the ``CLSID`` of the class it wishes to instantiate, and the various ``IID`` of the interfaces it wishes to use.
19+
20+
General behavior of a DCOM client
21+
---------------------------------
22+
23+
1. Setup the DCOM client (endpoint, SSP, etc.)
24+
2. Get an object reference: Instantiate a class to get an object reference of the instance (``RemoteCreateInstance``), **OR**, get an object reference towards the class itself (``RemoteGetClassObject``).
25+
3. Acquire the IPID of an interface of the object.
26+
4. Call a method of that interface.
27+
5. Release the reference counts on the interface (delete the IPID).
28+
29+
Step 3 can be done manually through the ``AcquireInterface()`` method, but Scapy will also automatically call it if you try to use an interface that you haven't acquired on an object.
30+
31+
Using the DCOM client
32+
---------------------
33+
34+
General usage
35+
~~~~~~~~~~~~~
36+
37+
1. Setup the DCOM client and connect to the object resolver (which is by default on port 135).
38+
39+
.. code:: python
40+
41+
from scapy.layers.msrpce.msdcom import DCOM_Client
42+
from scapy.layers.ntlm import NTLMSSP
43+
44+
client = DCOM_Client(
45+
ssp=NTLMSSP(UPN="Administrator@domain.local", PASSWORD="Scapy1111@"),
46+
)
47+
client.connect("server1.domain.local")
48+
49+
.. note:: See the examples in `DCE/RPC <dcerpc.html>`_ to connect with SPNEGO/Kerberos.
50+
51+
2. Instantiate a class to get an object reference
52+
53+
.. code:: python
54+
55+
import uuid
56+
from scapy.layers.dcerpc import find_com_interface
57+
from scapy.layers.msrpce.raw.ms_pla import GetDataCollectorSets_Request
58+
59+
CLSID_TraceSessionCollection = uuid.UUID("03837530-098b-11d8-9414-505054503030")
60+
# The COM interface must have been compiled by scapy-rpc (midl-to-scapy)
61+
IDataCollectorSetCollection = find_com_interface("IDataCollectorSetCollection")
62+
63+
# Get new object reference
64+
objref = client.RemoteCreateInstance(
65+
# The CLSID we're instantiating
66+
clsid=CLSID_TraceSessionCollection,
67+
iids=[
68+
# An initial list of interfaces to ask for. There must be at least 1.
69+
IDataCollectorSetCollection,
70+
]
71+
)
72+
73+
3. Call a method on that object reference
74+
75+
.. code:: python
76+
77+
result = objref.sr1_req(
78+
# The request message (here from [MS-PLA])
79+
pkt=GetDataCollectorSets_Request(
80+
server=None,
81+
filter=NDRPointer(
82+
referent_id=0x72657355,
83+
value=FLAGGED_WORD_BLOB(
84+
cBytes=18,
85+
asData=r"session\*".encode("utf-16le"),
86+
)
87+
),
88+
),
89+
# The interface to send it on
90+
iface=IDataCollectorSetCollection,
91+
)
92+
93+
4. Release all the requested interfaces on the object reference
94+
95+
.. code:: python
96+
97+
objref.release()
98+
99+
5. Close the client
100+
101+
.. code:: python
102+
103+
client.close()
104+
105+
106+
Unmarshalling object references
107+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108+
109+
Some methods return a reference to an object that is created by the remote server. On the network,
110+
those are typically marshalled as a ``MInterfacePointer`` structure. Such a structure can be "unmarshalled" into a local object reference that can be used in Scapy to call methods on that object.
111+
112+
.. code:: python
113+
114+
# For instance, let's assume we're calling Next() of the IEnumVARIANT
115+
resp = enum.sr1_req(
116+
pkt=Next_Request(celt=1),
117+
iface=IEnumVARIANT,
118+
)
119+
120+
# Get the MInterfacePointer value
121+
value = resp.valueof("rgVar")[0].valueof("_varUnion")
122+
assert isinstance(value, MInterfacePointer)
123+
124+
# Unmarshall it and acquire an initial interface on it.
125+
objref = client.UnmarshallObjectReference(
126+
value,
127+
iid=IDataCollectorSet,
128+
)

scapy/arch/windows/native.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ def recv_raw(self, x=MTU):
222222

223223
def close(self):
224224
# type: () -> None
225-
if not self.closed and self.promisc:
225+
if not self.closed and self.promisc and hasattr(self, 'ins'):
226226
self.ins.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
227227
super(L3WinSocket, self).close()
228228

scapy/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,8 @@ class Conf(ConfClass):
11461146
)
11471147
#: Dictionary containing parsed NSS Keys
11481148
tls_nss_keys: Dict[str, bytes] = None
1149+
#: Whether to use NDR64 by default instead of NDR 32
1150+
ndr64: bool = True
11491151
#: When TCPSession is used, parse DCE/RPC sessions automatically.
11501152
#: This should be used for passive sniffing.
11511153
dcerpc_session_enable = False

scapy/fwdmachine.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ class ForwardMachine:
8686
Methods to override:
8787
8888
:func xfrmcs: a function to call when forwarding a packet from the 'client' to
89-
the server. If it returns True, the packet is forwarded as it. If it
90-
returns False or None, the packet is discarded. If it returns a
91-
packet, this packet is forwarded instead of the original packet.
89+
the server. If it raises a FORWARD exception, the packet is forwarded as it. If
90+
it raises a DROP Exception, the packet is discarded. If it raises a
91+
FORWARD_REPLACE(pkt) exception, then pkt is forwarded instead of the original
92+
packet.
9293
:func xfrmsc: same as xfrmcs for packets forwarded from the 'server' to the
9394
'client'.
9495
"""
@@ -372,7 +373,7 @@ def cb_sni(sock, server_name, _):
372373
# Load result certificate our SSL server
373374
# (this is dumb but we need to store them on disk)
374375
certfile = get_temp_file()
375-
with open(certfile, "wb") as fd:
376+
with open(certfile, "w") as fd:
376377
for c in certs:
377378
fd.write(c.pem)
378379
keyfile = get_temp_file()

0 commit comments

Comments
 (0)