Skip to content

Commit 662a27c

Browse files
committed
DCE/RPC: respect the association group for call_id
1 parent 9802dca commit 662a27c

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

scapy/layers/dcerpc.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@
180180
}
181181
DCE_RPC_INTERFACES_NAMES = {}
182182
DCE_RPC_INTERFACES_NAMES_rev = {}
183+
COM_INTERFACES_NAMES = {}
184+
COM_INTERFACES_NAMES_rev = {}
183185

184186

185187
class DCERPC_Transport(IntEnum):
@@ -1350,6 +1352,8 @@ def register_com_interface(name, uuid, opnums):
13501352
# bind for build
13511353
for opnum, operations in opnums.items():
13521354
bind_top_down(DceRpc5Request, operations.request, opnum=opnum)
1355+
COM_INTERFACES_NAMES[uuid] = name
1356+
COM_INTERFACES_NAMES_rev[name.lower()] = uuid
13531357

13541358

13551359
def find_com_interface(name) -> ComInterface:
@@ -2824,6 +2828,7 @@ def __init__(self, *args, **kwargs):
28242828
self.sent_cont_ids = []
28252829
self.cont_id = 0 # Currently selected context
28262830
self.auth_context_id = 0 # Currently selected authentication context
2831+
self.assoc_group_id = 0 # Currently selected association group
28272832
self.map_callid_opnum = {}
28282833
self.frags = collections.defaultdict(lambda: b"")
28292834
self.sniffsspcontexts = {} # Unfinished contexts for passive
@@ -2869,6 +2874,8 @@ def _up_pkt(self, pkt):
28692874
finally:
28702875
self.sent_cont_ids = []
28712876

2877+
self.assoc_group_id = pkt.assoc_group_id
2878+
28722879
# Endianness
28732880
self.ndrendian = {0: "big", 1: "little"}[pkt[DceRpc5].endian]
28742881

@@ -2878,18 +2885,20 @@ def _up_pkt(self, pkt):
28782885
elif DceRpc5Request in pkt:
28792886
# request => match opnum with callID
28802887
opnum = pkt.opnum
2888+
uid = (self.assoc_group_id, pkt.call_id)
28812889
if self.rpc_bind_is_com:
2882-
self.map_callid_opnum[pkt.call_id] = (
2890+
self.map_callid_opnum[uid] = (
28832891
opnum,
28842892
pkt[DceRpc5Request].payload.payload,
28852893
)
28862894
else:
2887-
self.map_callid_opnum[pkt.call_id] = opnum, pkt[DceRpc5Request].payload
2895+
self.map_callid_opnum[uid] = opnum, pkt[DceRpc5Request].payload
28882896
elif DceRpc5Response in pkt:
28892897
# response => get opnum from table
2898+
uid = (self.assoc_group_id, pkt.call_id)
28902899
try:
2891-
opnum, opts["request_packet"] = self.map_callid_opnum[pkt.call_id]
2892-
del self.map_callid_opnum[pkt.call_id]
2900+
opnum, opts["request_packet"] = self.map_callid_opnum[uid]
2901+
del self.map_callid_opnum[uid]
28932902
except KeyError:
28942903
log_runtime.info("Unknown call_id %s in DCE/RPC session" % pkt.call_id)
28952904
# Bind / Alter request/response specific
@@ -2912,7 +2921,7 @@ def _defragment(self, pkt, body=None):
29122921
"""
29132922
Function to defragment DCE/RPC packets.
29142923
"""
2915-
uid = pkt.call_id
2924+
uid = (self.assoc_group_id, pkt.call_id)
29162925
if pkt.pfc_flags.PFC_FIRST_FRAG and pkt.pfc_flags.PFC_LAST_FRAG:
29172926
# Not fragmented
29182927
return body

scapy/layers/msrpce/msdcom.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@
3030
PadField,
3131
StrLenField,
3232
StrNullFieldUtf16,
33+
UUIDEnumField,
3334
UUIDField,
3435
XShortField,
3536
XStrFixedLenField,
3637
)
3738
from scapy.volatile import RandUUID
3839

3940
from scapy.layers.dcerpc import (
41+
COM_INTERFACES_NAMES_rev,
42+
COM_INTERFACES_NAMES,
4043
ComInterface,
4144
DCE_C_AUTHN_LEVEL,
4245
DCE_RPC_PROTOCOL_IDENTIFIERS,
@@ -445,7 +448,15 @@ class OBJREF(Packet):
445448
fields_desc = [
446449
XStrFixedLenField("signature", b"MEOW", length=4), # :3
447450
LEIntField("flags", 0x04),
448-
UUIDField("iid", IID_IActivationPropertiesIn, uuid_fmt=UUIDField.FORMAT_LE),
451+
UUIDEnumField(
452+
"iid",
453+
IID_IActivationPropertiesIn,
454+
(
455+
COM_INTERFACES_NAMES.get,
456+
lambda x: COM_INTERFACES_NAMES_rev.get(x.lower()),
457+
),
458+
uuid_fmt=UUIDField.FORMAT_LE,
459+
),
449460
]
450461

451462

scapy/layers/msrpce/rpcclient.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
DCE/RPC client as per [MS-RPCE]
88
"""
99

10+
import collections
1011
import uuid
1112
import socket
1213

@@ -101,7 +102,7 @@ def __init__(
101102
), "transport must be from DCERPC_Transport"
102103

103104
# Counters
104-
self.call_id = 0
105+
self.call_ids = collections.defaultdict(lambda: 0) # by assoc_group_id
105106
self.next_cont_id = 0 # next available context id
106107
self.next_auth_contex_id = 0 # next available auth context id
107108

@@ -271,10 +272,10 @@ def sr1(self, pkt, **kwargs):
271272
272273
The DCE/RPC header is added automatically.
273274
"""
274-
self.call_id += 1
275+
self.call_ids[self.session.assoc_group_id] += 1
275276
pkt = (
276277
DceRpc5(
277-
call_id=self.call_id,
278+
call_id=self.call_ids[self.session.assoc_group_id],
278279
pfc_flags="PFC_FIRST_FRAG+PFC_LAST_FRAG",
279280
endian=self.ndrendian,
280281
auth_verifier=kwargs.pop("auth_verifier", None),
@@ -295,10 +296,10 @@ def send(self, pkt, **kwargs):
295296
296297
The DCE/RPC header is added automatically.
297298
"""
298-
self.call_id += 1
299+
self.call_ids[self.session.assoc_group_id] += 1
299300
pkt = (
300301
DceRpc5(
301-
call_id=self.call_id,
302+
call_id=self.call_ids[self.session.assoc_group_id],
302303
pfc_flags="PFC_FIRST_FRAG+PFC_LAST_FRAG",
303304
endian=self.ndrendian,
304305
auth_verifier=kwargs.pop("auth_verifier", None),
@@ -655,7 +656,6 @@ def _bind(
655656
and respcls in resp
656657
and self._check_bind_context(interface, resp.results)
657658
):
658-
self.call_id = 0 # reset call id
659659
port = resp.sec_addr.port_spec.decode()
660660
ndr = self.session.ndr64 and "NDR64" or "NDR32"
661661
self.ndr64 = self.session.ndr64

0 commit comments

Comments
 (0)