Skip to content

Commit b564a13

Browse files
authored
Minor SMB/Kerberos improvements (#4749)
1 parent 8b002b6 commit b564a13

4 files changed

Lines changed: 106 additions & 6 deletions

File tree

scapy/fields.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,6 +2783,12 @@ def __init__(self, name, default, enum):
27832783
super(LEIntEnumField, self).__init__(name, default, enum, "<I")
27842784

27852785

2786+
class XLEIntEnumField(LEIntEnumField):
2787+
def _i2repr(self, pkt, x):
2788+
# type: (Optional[Packet], Any) -> str
2789+
return lhex(x)
2790+
2791+
27862792
class XShortEnumField(ShortEnumField):
27872793
def _i2repr(self, pkt, x):
27882794
# type: (Optional[Packet], Any) -> str

scapy/layers/kerberos.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
StrFixedLenEnumField,
112112
XByteField,
113113
XLEIntField,
114+
XLEIntEnumField,
114115
XLEShortField,
115116
XStrFixedLenField,
116117
XStrLenField,
@@ -139,6 +140,7 @@
139140
)
140141
from scapy.layers.inet import TCP, UDP
141142
from scapy.layers.smb import _NV_VERSION
143+
from scapy.layers.smb2 import STATUS_ERREF
142144
from scapy.layers.x509 import X509_AlgorithmIdentifier
143145

144146
# Typing imports
@@ -1874,7 +1876,7 @@ def m2i(self, pkt, s):
18741876
try:
18751877
return KERB_ERROR_DATA(val[0].val, _underlayer=pkt), val[1]
18761878
except BER_Decoding_Error:
1877-
if pkt.errorCode.val in [18]:
1879+
if pkt.errorCode.val in [18, 12]:
18781880
# Some types can also happen in FAST sessions
18791881
# 18: KDC_ERR_CLIENT_REVOKED
18801882
return MethodData(val[0].val, _underlayer=pkt), val[1]
@@ -2015,7 +2017,7 @@ def getSPN(self):
20152017

20162018
class KERB_EXT_ERROR(Packet):
20172019
fields_desc = [
2018-
XLEIntField("status", 0),
2020+
XLEIntEnumField("status", 0, STATUS_ERREF),
20192021
XLEIntField("reserved", 0),
20202022
XLEIntField("flags", 0x00000001),
20212023
]

scapy/layers/smb2.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
0xC0000064: "STATUS_NO_SUCH_USER",
121121
0xC000006D: "STATUS_LOGON_FAILURE",
122122
0xC000006E: "STATUS_ACCOUNT_RESTRICTION",
123+
0xC0000070: "STATUS_INVALID_WORKSTATION",
123124
0xC0000071: "STATUS_PASSWORD_EXPIRED",
124125
0xC0000072: "STATUS_ACCOUNT_DISABLED",
125126
0xC000009A: "STATUS_INSUFFICIENT_RESOURCES",

scapy/layers/smbclient.py

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@
7272
DirectTCP,
7373
FileAllInformation,
7474
FileIdBothDirectoryInformation,
75-
SMB_DIALECTS,
75+
SECURITY_DESCRIPTOR,
76+
SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2,
77+
SMB2_CREATE_REQUEST_LEASE,
78+
SMB2_CREATE_REQUEST_LEASE_V2,
7679
SMB2_Change_Notify_Request,
7780
SMB2_Change_Notify_Response,
7881
SMB2_Close_Request,
7982
SMB2_Close_Response,
8083
SMB2_Create_Context,
81-
SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2,
82-
SMB2_CREATE_REQUEST_LEASE_V2,
83-
SMB2_CREATE_REQUEST_LEASE,
8484
SMB2_Create_Request,
8585
SMB2_Create_Response,
8686
SMB2_ENCRYPTION_CIPHERS,
@@ -111,6 +111,7 @@
111111
SMB2_Write_Request,
112112
SMB2_Write_Response,
113113
SMBStreamSocket,
114+
SMB_DIALECTS,
114115
SRVSVC_SHARE_TYPES,
115116
STATUS_ERREF,
116117
)
@@ -1822,6 +1823,96 @@ def backup(self):
18221823
print("Backup Intent: On")
18231824
self.extra_create_options.append("FILE_OPEN_FOR_BACKUP_INTENT")
18241825

1826+
@CLIUtil.addcommand(spaces=True)
1827+
def watch(self, folder):
1828+
"""
1829+
Watch file changes in folder (recursively)
1830+
"""
1831+
if self._require_share():
1832+
return
1833+
# Get pwd of the ls
1834+
fpath = self.pwd / folder
1835+
self.smbsock.set_TID(self.current_tree)
1836+
# Open file
1837+
fileId = self.smbsock.create_request(
1838+
self.normalize_path(fpath),
1839+
type="folder",
1840+
extra_create_options=self.extra_create_options,
1841+
)
1842+
print("Watching '%s'" % fpath)
1843+
# Watch for changes
1844+
try:
1845+
while True:
1846+
changes = self.smbsock.changenotify(fileId)
1847+
for chg in changes:
1848+
print(chg.sprintf("%.time%: %Action% %FileName%"))
1849+
except KeyboardInterrupt:
1850+
pass
1851+
# Close the file
1852+
self.smbsock.close_request(fileId)
1853+
print("Cancelled.")
1854+
1855+
@CLIUtil.addcommand(spaces=True)
1856+
def getsd(self, file):
1857+
"""
1858+
Get the Security Descriptor
1859+
"""
1860+
if self._require_share():
1861+
return
1862+
fpath = self.pwd / file
1863+
self.smbsock.set_TID(self.current_tree)
1864+
# Open file
1865+
fileId = self.smbsock.create_request(
1866+
self.normalize_path(fpath),
1867+
type="",
1868+
mode="",
1869+
extra_desired_access=["READ_CONTROL", "ACCESS_SYSTEM_SECURITY"],
1870+
)
1871+
# Get the file size
1872+
info = self.smbsock.query_info(
1873+
FileId=fileId,
1874+
InfoType="SMB2_0_INFO_SECURITY",
1875+
FileInfoClass=0,
1876+
AdditionalInformation=(
1877+
0x00000001
1878+
| 0x00000002
1879+
| 0x00000004
1880+
| 0x00000008
1881+
| 0x00000010
1882+
| 0x00000020
1883+
| 0x00000040
1884+
| 0x00010000
1885+
),
1886+
)
1887+
self.smbsock.close_request(fileId)
1888+
return info
1889+
1890+
@CLIUtil.addcomplete(getsd)
1891+
def getsd_complete(self, file):
1892+
"""
1893+
Auto-complete getsd
1894+
"""
1895+
if self._require_share(silent=True):
1896+
return []
1897+
return self._fs_complete(file)
1898+
1899+
@CLIUtil.addoutput(getsd)
1900+
def getsd_output(self, results):
1901+
"""
1902+
Print the output of 'getsd'
1903+
"""
1904+
sd = SECURITY_DESCRIPTOR(results)
1905+
print("Owner:", sd.OwnerSid.summary())
1906+
print("Group:", sd.GroupSid.summary())
1907+
if getattr(sd, "DACL", None):
1908+
print("DACL:")
1909+
for ace in sd.DACL.Aces:
1910+
print(" - ", ace.toSDDL())
1911+
if getattr(sd, "SACL", None):
1912+
print("SACL:")
1913+
for ace in sd.SACL.Aces:
1914+
print(" - ", ace.toSDDL())
1915+
18251916

18261917
if __name__ == "__main__":
18271918
from scapy.utils import AutoArgparse

0 commit comments

Comments
 (0)