Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion scapy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,10 @@ def layers(self):
except ImportError:
import __builtin__ # noqa: F401
for lay in self.ldict:
doc = eval(lay).__doc__
try:
doc = eval(lay).__doc__
except AttributeError:
continue
result.append((lay, doc.strip().split("\n")[0] if doc else lay))
return result

Expand Down
34 changes: 21 additions & 13 deletions scapy/layers/msrpce/rpcclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ def connect(
transport=self.transport,
ndrendian=self.ndrendian,
verb=self.verb,
ssp=self.ssp,
smb_kwargs=smb_kwargs,
)
if endpoints:
Expand Down Expand Up @@ -234,14 +235,15 @@ def connect(
)

if self.transport == DCERPC_Transport.NCACN_NP: # SMB
# If the endpoint is provided, connect to it.
if endpoint is not None:
self.open_smbpipe(endpoint)

# We pack the socket into a SMB_RPC_SOCKET
sock = self.smbrpcsock = SMB_RPC_SOCKET.from_tcpsock(
sock, ssp=self.ssp, **smb_kwargs
)

# If the endpoint is provided, connect to it.
if endpoint is not None:
self.open_smbpipe(endpoint)

self.sock = DceRpcSocket(sock, DceRpc5, **self.dcesockargs)
elif self.transport == DCERPC_Transport.NCACN_IP_TCP:
self.sock = DceRpcSocket(
Expand Down Expand Up @@ -351,6 +353,9 @@ def sr1_req(self, pkt, **kwargs):
if "opnum" in kwargs:
opnum["opnum"] = kwargs.pop("opnum")

# Set NDR64
pkt.ndr64 = self.ndr64

# Send/receive
resp = self.sr1(
DceRpc5Request(
Expand Down Expand Up @@ -486,7 +491,10 @@ def _check_bind_context(self, interface, contexts) -> bool:
return False

def _bind(
self, interface: Union[DceRpcInterface, ComInterface], reqcls, respcls
self,
interface: Union[DceRpcInterface, ComInterface],
reqcls,
respcls,
) -> bool:
"""
Internal: used to send a bind/alter request
Expand Down Expand Up @@ -681,11 +689,10 @@ def _bind(
else:
print(conf.color_theme.fail("! Failure"))
resp.show()
if DceRpc5Fault in resp:
if resp[DceRpc5Fault].payload and not isinstance(
resp[DceRpc5Fault].payload, conf.raw_layer
):
resp[DceRpc5Fault].payload.show()
if resp[DceRpc5Fault].payload and not isinstance(
resp[DceRpc5Fault].payload, conf.raw_layer
):
resp[DceRpc5Fault].payload.show()
else:
print(conf.color_theme.fail("! Failure"))
resp.show()
Expand Down Expand Up @@ -900,7 +907,6 @@ def epm_map(self, interface):
return endpoints
elif status == 0x16C9A0D6:
if self.verb:
pkt.show()
print(
conf.color_theme.fail(
"! Server errored: 'There are no elements that satisfy"
Expand Down Expand Up @@ -953,7 +959,9 @@ def get_endpoint(
client.connect(ip, endpoint=endpoint, smb_kwargs=smb_kwargs)

client.bind(find_dcerpc_interface("ept"))
endpoints = client.epm_map(interface)
try:
endpoints = client.epm_map(interface)
finally:
client.close()

client.close()
return endpoints
22 changes: 17 additions & 5 deletions scapy/layers/ntlm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1416,7 +1416,15 @@ def __init__(
self.COMPUTER_NB_NAME.lower() + "." + self.DOMAIN_FQDN
)

self.IDENTITIES = IDENTITIES
if IDENTITIES:
self.IDENTITIES = {
# Windows usernames are case insensitive
user.upper(): hashnt
for user, hashnt in IDENTITIES.items()
}
else:
self.IDENTITIES = IDENTITIES

self.DO_NOT_CHECK_LOGIN = DO_NOT_CHECK_LOGIN
self.SERVER_CHALLENGE = SERVER_CHALLENGE
super(NTLMSSP, self).__init__(**kwargs)
Expand Down Expand Up @@ -1681,7 +1689,10 @@ def GSS_Init_sec_context(
+ [
AV_PAIR(
AvId="MsvAvSingleHost",
Value=Single_Host_Data(MachineID=os.urandom(32)),
Value=Single_Host_Data(
MachineID=os.urandom(32),
PermanentMachineID=os.urandom(32),
),
),
]
+ (
Expand Down Expand Up @@ -2048,7 +2059,8 @@ def _getSessionBaseKey(self, Context, auth_tok):
Function that returns the SessionBaseKey from the ntlm Authenticate.
"""
try:
username = auth_tok.UserName
# Windows usernames are case insensitive
username = auth_tok.UserName.upper()
except AttributeError:
username = None
try:
Expand Down Expand Up @@ -2076,9 +2088,9 @@ def _checkLogin(self, Context, auth_tok):

Overwrite and return True to bypass.
"""
# Create the NTLM AUTH
try:
username = auth_tok.UserName
# Windows usernames are case insensitive
username = auth_tok.UserName.upper()
except AttributeError:
username = None
try:
Expand Down
2 changes: 1 addition & 1 deletion scapy/layers/smbclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -1732,7 +1732,7 @@ def cat_complete(self, file):
return []
return self._fs_complete(file)

@CLIUtil.addcommand(spaces=True)
@CLIUtil.addcommand(spaces=True, globsupport=True)
def put(self, file):
"""
Upload a file
Expand Down
1 change: 1 addition & 0 deletions test/configs/bsd.utsc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"test/contrib/isotp_soft_socket.uts"
],
"onlyfailed": true,
"extensions": ["scapy-rpc"],
"preexec": {
"test/contrib/*.uts": "load_contrib(\"%name%\")",
"test/cert.uts": "load_layer(\"tls\")",
Expand Down
1 change: 1 addition & 0 deletions test/configs/linux.utsc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
],
"breakfailed": true,
"onlyfailed": true,
"extensions": ["scapy-rpc"],
"preexec": {
"test/contrib/*.uts": "load_contrib(\"%name%\")",
"test/scapy/layers/tls/*.uts": "load_layer(\"tls\")"
Expand Down
1 change: 1 addition & 0 deletions test/configs/windows.utsc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
],
"breakfailed": true,
"onlyfailed": true,
"extensions": ["scapy-rpc"],
"preexec": {
"test\\contrib\\*.uts": "load_contrib(\"%name%\")",
"test\\scapy\\layers\\tls\\*.uts": "load_layer(\"tls\")"
Expand Down
1 change: 1 addition & 0 deletions test/configs/windows2.utsc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
],
"breakfailed": true,
"onlyfailed": true,
"extensions": ["scapy-rpc"],
"preexec": {
"contrib\\*.uts": "load_contrib(\"%name%\")",
"scapy\\layers\\tls\\*.uts": "load_layer(\"tls\")"
Expand Down
3 changes: 0 additions & 3 deletions test/scapy/layers/msrpce/mslsad.uts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
* This files are stored in the scapy-rpc extension, but included as part of Scapy's main testing suite for consistency.

= [MS-LSAD] - Import [MS-LSAD]
~ disabled

from scapy.layers.msrpce.raw.ms_lsad import *

= [MS-LSAD] - Build LsarEnumerateAccountsWithUserRight_Request
~ disabled

policyHandle = NDRContextHandle(attributes=0, uuid=b'\x92\xa1*"\xc2\xc2\nJ\xaf\x0bL\xdd]C\x8c\x1a')
right = "SeAuditPrivilege"
Expand All @@ -25,7 +23,6 @@ pkt = LsarEnumerateAccountsWithUserRight_Request(
assert bytes(pkt) == b'\x00\x00\x00\x00\x92\xa1*"\xc2\xc2\nJ\xaf\x0bL\xdd]C\x8c\x1a\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00 \x00 \x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00S\x00e\x00A\x00u\x00d\x00i\x00t\x00P\x00r\x00i\x00v\x00i\x00l\x00e\x00g\x00e\x00'

= [MS-LSAD] - Dissect LsarEnumerateAccountsWithUserRight_Response
~ disabled

from scapy.layers.smb2 import WINNT_SID

Expand Down
121 changes: 121 additions & 0 deletions test/scapy/layers/msrpce/msscmr.uts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
% MS-SCMR tests

+ [MS-SCMR] build and dissection tests

* This files are stored in the scapy-rpc extension, but included as part of Scapy's main testing suite for consistency.

= [MS-SCMR] - Import [MS-SCMR]

from scapy.layers.msrpce.raw.ms_scmr import *

= [MS-SCMR] - Dissect ROpenServiceW_Request

DATA = bytes.fromhex('00000000053914c3f0543646af7317818dbee820160000000000000016000000530065006300750072006900740079004800650061006c00740068005300650072007600690063006500000005000000')

pkt = ROpenServiceW_Request(DATA, ndr64=False)
assert pkt.valueof("lpServiceName") == b"SecurityHealthService"
assert pkt.hSCManager.uuid == b'\x059\x14\xc3\xf0T6F\xafs\x17\x81\x8d\xbe\xe8 '

= [MS-SCMR] - Re-Build ROpenServiceW_Request

pkt = ROpenServiceW_Request(
hSCManager=NDRContextHandle(uuid=b'\x059\x14\xc3\xf0T6F\xafs\x17\x81\x8d\xbe\xe8 '),
lpServiceName=b"SecurityHealthService",
dwDesiredAccess=5,
ndr64=False,
)
assert bytes(pkt) == DATA

= [MS-SCMR] - Dissect RQueryServiceConfigW_Request

DATA = bytes.fromhex('00000000d76d93463d7e9047856bbc0839ef836910100000')

pkt = RQueryServiceConfigW_Request(DATA, ndr64=False)
assert pkt.cbBufSize == 4112

= [MS-SCMR] - Dissect RQueryServiceConfig2W_Request

DATA = bytes.fromhex('00000000d76d93463d7e9047856bbc0839ef83690100000010100000')

pkt = RQueryServiceConfig2W_Request(DATA, ndr64=False)
assert pkt.dwInfoLevel == 1
assert pkt.cbBufSize == 4112

= [MS-SCMR] - Dissect RQueryServiceConfig2W_Response

import zlib
DATA = zlib.decompress(bytes.fromhex('789ced8f4b0ec2300c05078903e408d9711d368875092d204a8b4805d7e7a5286c10127bde5876fc89ed240458026b6e8cdc39b1a72513e968488a7be924add9513723175507e941954136b261ab2951b9ab24cf5e9294be124deaacd5a87cf11a761f1b9ad93e14f5921a278eca24ceef7d657f9db7faba2fabdaceffe8a4e9871718638c31c618638c31ff4158bcce27d9e630e0'))

pkt = RQueryServiceConfig2W_Response(DATA, ndr64=False, request_packet=pkt)
assert pkt.lpBuffer.max_count == 4112
assert pkt.pcbBytesNeeded == 272
assert pkt.status == 0
assert pkt.lpBuffer.value[4:].decode("utf-16le").rstrip("\x00") == "Provides facilities for managing UWP apps access to app capabilities as well as checking an app's access to specific app capabilities"

= [MS-SCMR] - Dissect RQueryServiceConfigW_Response

DATA = bytes.fromhex('200000000200000001000000000002000400020000000000080002000c0002001000020030000000000000003000000043003a005c00570049004e0044004f00570053005c00730079007300740065006d00330032005c0073007600630068006f00730074002e0065007800650020002d006b0020006f007300700072006900760061006300790020002d0070000000010000000000000001000000000000002e000000000000002e000000720070006300730073002f00730074006100740065007200650070006f007300690074006f00720079002f0043006f00720065004d006500730073006100670069006e0067005200650067006900730074007200610072002f0000000c000000000000000c0000004c006f00630061006c00530079007300740065006d0000002200000000000000220000004300610070006100620069006c00690074007900200041006300630065007300730020004d0061006e0061006700650072002000530065007200760069006300650000007e01000000000000')
pkt = RQueryServiceConfigW_Response(DATA, ndr64=False)
assert pkt.status == 0
assert pkt.pcbBytesNeeded == 389
assert pkt.lpServiceConfig.dwServiceType == 32
assert pkt.lpServiceConfig.dwErrorControl == 1
assert pkt.lpServiceConfig.valueof("lpBinaryPathName") == b'C:\\WINDOWS\\system32\\svchost.exe -k osprivacy -p'
assert pkt.lpServiceConfig.valueof("lpDependencies") == b'rpcss/staterepository/CoreMessagingRegistrar/'
assert pkt.lpServiceConfig.valueof("lpDisplayName") == b'Capability Access Manager Service'

= [MS-SCMR] - Dissect RCreateServiceW_Request

DATA = bytes.fromhex('00000000dea1de2e22144844a5f5ea3948e8add905000000000000000500000074006500730074000000000000000000ff010f001000000003000000010000001c000000000000001c00000043003a005c00570069006e0064006f00770073005c00530079007300740065006d00330032005c0063006d0064002e00650078006500000000000000000000000000000000000000000000000000000000000000')
pkt = RCreateServiceW_Request(DATA, ndr64=False)
assert pkt.valueof("lpServiceName") == b"test"
assert pkt.dwDesiredAccess == 983551
assert pkt.dwStartType == 3
assert pkt.dwServiceType == 16
assert pkt.dwErrorControl == 1
assert pkt.valueof("lpBinaryPathName") == b"C:\\Windows\\System32\\cmd.exe"
assert pkt.lpDisplayName is None
assert pkt.dwPwSize == 0

= [MS-SCMR] - Re-Build RCreateServiceW_Request

pkt = RCreateServiceW_Request(
hSCManager=NDRContextHandle(uuid=b'\xde\xa1\xde."\x14HD\xa5\xf5\xea9H\xe8\xad\xd9'),
lpServiceName=b"test",
dwDesiredAccess=983551,
dwServiceType=16,
dwStartType=3,
dwErrorControl=1,
lpBinaryPathName=b"C:\\Windows\\System32\\cmd.exe",
ndr64=False,
)
assert bytes(pkt) == DATA

= [MS-SCMR] - Dissect RCreateServiceW_Request - with lpDisplayName

DATA = bytes.fromhex('00000000dcf903ed9e7b604ca9971ce8d0938b2405000000000000000500000074006500730074000000000000000200050000000000000005000000740065007300740000000000ff010f001000000003000000010000001c000000000000001c00000043003a005c00570069006e0064006f00770073005c00530079007300740065006d00330032005c0063006d0064002e00650078006500000000000000000000000000000000000000000000000000000000000000')
pkt = RCreateServiceW_Request(DATA, ndr64=False)
assert pkt.valueof("lpServiceName") == b"test"
assert pkt.dwDesiredAccess == 983551
assert pkt.dwStartType == 3
assert pkt.dwServiceType == 16
assert pkt.dwErrorControl == 1
assert pkt.valueof("lpBinaryPathName") == b"C:\\Windows\\System32\\cmd.exe"
assert pkt.lpDisplayName.referent_id == 0x20000
assert pkt.valueof("lpDisplayName") == b"test"
assert pkt.dwPwSize == 0

= [MS-SCMR] - Build RCreateServiceW_Request - with lpDisplayName

pkt = RCreateServiceW_Request(
hSCManager=NDRContextHandle(uuid=b'\xdc\xf9\x03\xed\x9e{`L\xa9\x97\x1c\xe8\xd0\x93\x8b$'),
lpServiceName=b"test",
lpDisplayName=b"test",
dwDesiredAccess=983551,
dwServiceType=16,
dwStartType=3,
dwErrorControl=1,
lpBinaryPathName=b"C:\\Windows\\System32\\cmd.exe",
ndr64=False,
)
assert bytes(pkt) == DATA
Loading