Coverage for /root/GitHubProjects/impacket/impacket/dcerpc/v5/dtypes.py : 87%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Impacket - Collection of Python classes for working with network protocols.
2#
3# SECUREAUTH LABS. Copyright (C) 2020 SecureAuth Corporation. All rights reserved.
4#
5# This software is provided under a slightly modified version
6# of the Apache Software License. See the accompanying LICENSE file
7# for more information.
8#
9# Description:
10# [MS-DTYP] Interface mini implementation
11#
12# Author:
13# Alberto Solino (@agsolino)
14#
16from __future__ import division
17from __future__ import print_function
18from struct import pack
19from six import binary_type
21from impacket.dcerpc.v5.ndr import NDRULONG, NDRUHYPER, NDRSHORT, NDRLONG, NDRPOINTER, NDRUniConformantArray, \
22 NDRUniFixedArray, NDR, NDRHYPER, NDRSMALL, NDRPOINTERNULL, NDRSTRUCT, \
23 NDRUSMALL, NDRBOOLEAN, NDRUSHORT, NDRFLOAT, NDRDOUBLEFLOAT, NULL
25DWORD = NDRULONG
26BOOL = NDRULONG
27UCHAR = NDRUSMALL
28SHORT = NDRSHORT
29NULL = NULL
31class LPDWORD(NDRPOINTER):
32 referent = (
33 ('Data', DWORD),
34 )
36class PSHORT(NDRPOINTER):
37 referent = (
38 ('Data', SHORT),
39 )
41class PBOOL(NDRPOINTER):
42 referent = (
43 ('Data', BOOL),
44 )
46class LPBYTE(NDRPOINTER):
47 referent = (
48 ('Data', NDRUniConformantArray),
49 )
50PBYTE = LPBYTE
52# 2.2.4 BOOLEAN
53BOOLEAN = NDRBOOLEAN
55# 2.2.6 BYTE
56BYTE = NDRUSMALL
58# 2.2.7 CHAR
59CHAR = NDRSMALL
60class PCHAR(NDRPOINTER):
61 referent = (
62 ('Data', CHAR),
63 )
65class WIDESTR(NDRUniFixedArray):
66 def getDataLen(self, data, offset=0):
67 return data.find(b'\x00\x00\x00', offset)+3-offset
69 def __setitem__(self, key, value):
70 if key == 'Data': 70 ↛ 79line 70 didn't jump to line 79, because the condition on line 70 was never false
71 try:
72 self.fields[key] = value.encode('utf-16le')
73 except UnicodeDecodeError:
74 import sys
75 self.fields[key] = value.decode(sys.getfilesystemencoding()).encode('utf-16le')
77 self.data = None # force recompute
78 else:
79 return NDR.__setitem__(self, key, value)
81 def __getitem__(self, key):
82 if key == 'Data': 82 ↛ 85line 82 didn't jump to line 85, because the condition on line 82 was never false
83 return self.fields[key].decode('utf-16le')
84 else:
85 return NDR.__getitem__(self,key)
87class STR(NDRSTRUCT):
88 commonHdr = (
89 ('MaximumCount', '<L=len(Data)'),
90 ('Offset','<L=0'),
91 ('ActualCount','<L=len(Data)'),
92 )
93 commonHdr64 = (
94 ('MaximumCount', '<Q=len(Data)'),
95 ('Offset','<Q=0'),
96 ('ActualCount','<Q=len(Data)'),
97 )
98 structure = (
99 ('Data',':'),
100 )
102 def dump(self, msg = None, indent = 0):
103 if msg is None:
104 msg = self.__class__.__name__
105 if msg != '':
106 print("%s" % msg, end=' ')
107 # Here just print the data
108 print(" %r" % (self['Data']), end=' ')
110 def __setitem__(self, key, value):
111 if key == 'Data': 111 ↛ 125line 111 didn't jump to line 125, because the condition on line 111 was never false
112 try:
113 if not isinstance(value, binary_type): 113 ↛ 117line 113 didn't jump to line 117, because the condition on line 113 was never false
114 self.fields[key] = value.encode('utf-8')
115 else:
116 # if it is a binary type (str in Python 2, bytes in Python 3), then we assume it is a raw buffer
117 self.fields[key] = value
118 except UnicodeDecodeError:
119 import sys
120 self.fields[key] = value.decode(sys.getfilesystemencoding()).encode('utf-8')
121 self.fields['MaximumCount'] = None
122 self.fields['ActualCount'] = None
123 self.data = None # force recompute
124 else:
125 return NDR.__setitem__(self, key, value)
127 def __getitem__(self, key):
128 if key == 'Data':
129 try:
130 return self.fields[key].decode('utf-8')
131 except UnicodeDecodeError:
132 # if we could't decode it, we assume it is a raw buffer
133 return self.fields[key]
134 else:
135 return NDR.__getitem__(self,key)
137 def getDataLen(self, data, offset=0):
138 return self["ActualCount"]
140class LPSTR(NDRPOINTER):
141 referent = (
142 ('Data', STR),
143 )
145class WSTR(NDRSTRUCT):
146 commonHdr = (
147 ('MaximumCount', '<L=len(Data)//2'),
148 ('Offset','<L=0'),
149 ('ActualCount','<L=len(Data)//2'),
150 )
151 commonHdr64 = (
152 ('MaximumCount', '<Q=len(Data)//2'),
153 ('Offset','<Q=0'),
154 ('ActualCount','<Q=len(Data)//2'),
155 )
156 structure = (
157 ('Data',':'),
158 )
160 def dump(self, msg = None, indent = 0):
161 if msg is None: 161 ↛ 162line 161 didn't jump to line 162, because the condition on line 161 was never true
162 msg = self.__class__.__name__
163 if msg != '':
164 print("%s" % msg, end=' ')
165 # Here just print the data
166 print(" %r" % (self['Data']), end=' ')
168 def getDataLen(self, data, offset=0):
169 return self["ActualCount"]*2
171 def __setitem__(self, key, value):
172 if key == 'Data': 172 ↛ 182line 172 didn't jump to line 182, because the condition on line 172 was never false
173 try:
174 self.fields[key] = value.encode('utf-16le')
175 except UnicodeDecodeError:
176 import sys
177 self.fields[key] = value.decode(sys.getfilesystemencoding()).encode('utf-16le')
178 self.fields['MaximumCount'] = None
179 self.fields['ActualCount'] = None
180 self.data = None # force recompute
181 else:
182 return NDR.__setitem__(self, key, value)
184 def __getitem__(self, key):
185 if key == 'Data':
186 return self.fields[key].decode('utf-16le')
187 else:
188 return NDR.__getitem__(self,key)
190class LPWSTR(NDRPOINTER):
191 referent = (
192 ('Data', WSTR),
193 )
195# 2.2.5 BSTR
196BSTR = LPWSTR
198# 2.2.8 DOUBLE
199DOUBLE = NDRDOUBLEFLOAT
200class PDOUBLE(NDRPOINTER):
201 referent = (
202 ('Data', DOUBLE),
203 )
205# 2.2.15 FLOAT
206FLOAT = NDRFLOAT
207class PFLOAT(NDRPOINTER):
208 referent = (
209 ('Data', FLOAT),
210 )
212# 2.2.18 HRESULT
213HRESULT = NDRLONG
214class PHRESULT(NDRPOINTER):
215 referent = (
216 ('Data', HRESULT),
217 )
219# 2.2.19 INT
220INT = NDRLONG
221class PINT(NDRPOINTER):
222 referent = (
223 ('Data', INT),
224 )
226# 2.2.26 LMSTR
227LMSTR = LPWSTR
229# 2.2.27 LONG
230LONG = NDRLONG
231class LPLONG(NDRPOINTER):
232 referent = (
233 ('Data', LONG),
234 )
236PLONG = LPLONG
238# 2.2.28 LONGLONG
239LONGLONG = NDRHYPER
241class PLONGLONG(NDRPOINTER):
242 referent = (
243 ('Data', LONGLONG),
244 )
246# 2.2.31 LONG64
247LONG64 = NDRUHYPER
248class PLONG64(NDRPOINTER):
249 referent = (
250 ('Data', LONG64),
251 )
253# 2.2.32 LPCSTR
254LPCSTR = LPSTR
256# 2.2.36 NET_API_STATUS
257NET_API_STATUS = DWORD
259# 2.2.52 ULONG_PTR
260ULONG_PTR = NDRULONG
261# 2.2.10 DWORD_PTR
262DWORD_PTR = ULONG_PTR
264# 2.3.2 GUID and UUID
265class GUID(NDRSTRUCT):
266 structure = (
267 ('Data','16s=b""'),
268 )
270 def getAlignment(self):
271 return 4
273class PGUID(NDRPOINTER):
274 referent = (
275 ('Data', GUID),
276 )
278UUID = GUID
279PUUID = PGUID
281# 2.2.37 NTSTATUS
282NTSTATUS = DWORD
284# 2.2.45 UINT
285UINT = NDRULONG
286class PUINT(NDRPOINTER):
287 referent = (
288 ('Data', UINT),
289 )
291# 2.2.50 ULONG
292ULONG = NDRULONG
293class PULONG(NDRPOINTER):
294 referent = (
295 ('Data', ULONG),
296 )
298LPULONG = PULONG
300# 2.2.54 ULONGLONG
301ULONGLONG = NDRUHYPER
302class PULONGLONG(NDRPOINTER):
303 referent = (
304 ('Data', ULONGLONG),
305 )
307# 2.2.57 USHORT
308USHORT = NDRUSHORT
309class PUSHORT(NDRPOINTER):
310 referent = (
311 ('Data', USHORT),
312 )
314# 2.2.59 WCHAR
315WCHAR = WSTR
316PWCHAR = LPWSTR
318# 2.2.61 WORD
319WORD = NDRUSHORT
320class PWORD(NDRPOINTER):
321 referent = (
322 ('Data', WORD),
323 )
324LPWORD = PWORD
326# 2.3.1 FILETIME
327class FILETIME(NDRSTRUCT):
328 structure = (
329 ('dwLowDateTime', DWORD),
330 ('dwHighDateTime', LONG),
331 )
333class PFILETIME(NDRPOINTER):
334 referent = (
335 ('Data', FILETIME),
336 )
338# 2.3.3 LARGE_INTEGER
339LARGE_INTEGER = NDRHYPER
340class PLARGE_INTEGER(NDRPOINTER):
341 referent = (
342 ('Data', LARGE_INTEGER),
343 )
345# 2.3.5 LUID
346class LUID(NDRSTRUCT):
347 structure = (
348 ('LowPart', DWORD),
349 ('HighPart', LONG),
350 )
352# 2.3.8 RPC_UNICODE_STRING
353class RPC_UNICODE_STRING(NDRSTRUCT):
354 # Here we're doing some tricks to make this data type
355 # easier to use. It's exactly the same as defined. I changed the
356 # Buffer name for Data, so users can write directly to the datatype
357 # instead of writing to datatype['Buffer'].
358 # The drawback is you cannot directly access the Length and
359 # MaximumLength fields.
360 # If you really need it, you will need to do it this way:
361 # class TT(NDRCALL):
362 # structure = (
363 # ('str1', RPC_UNICODE_STRING),
364 # )
365 #
366 # nn = TT()
367 # nn.fields['str1'].fields['MaximumLength'] = 30
368 structure = (
369 ('Length','<H=0'),
370 ('MaximumLength','<H=0'),
371 ('Data',LPWSTR),
372 )
374 def __setitem__(self, key, value):
375 if key == 'Data' and isinstance(value, NDR) is False:
376 try:
377 value.encode('utf-16le')
378 except UnicodeDecodeError:
379 import sys
380 value = value.decode(sys.getfilesystemencoding())
381 self['Length'] = len(value)*2
382 self['MaximumLength'] = len(value)*2
383 return NDRSTRUCT.__setitem__(self, key, value)
385 def dump(self, msg = None, indent = 0):
386 if msg is None: 386 ↛ 387line 386 didn't jump to line 387, because the condition on line 386 was never true
387 msg = self.__class__.__name__
388 if msg != '':
389 print("%s" % msg, end=' ')
391 if isinstance(self.fields['Data'] , NDRPOINTERNULL): 391 ↛ 392line 391 didn't jump to line 392, because the condition on line 391 was never true
392 print(" NULL", end=' ')
393 elif self.fields['Data']['ReferentID'] == 0:
394 print(" NULL", end=' ')
395 else:
396 return self.fields['Data'].dump('',indent)
398class PRPC_UNICODE_STRING(NDRPOINTER):
399 referent = (
400 ('Data', RPC_UNICODE_STRING ),
401 )
403# 2.3.9 OBJECT_TYPE_LIST
404ACCESS_MASK = DWORD
405class OBJECT_TYPE_LIST(NDRSTRUCT):
406 structure = (
407 ('Level', WORD),
408 ('Remaining',ACCESS_MASK),
409 ('ObjectType',PGUID),
410 )
412class POBJECT_TYPE_LIST(NDRPOINTER):
413 referent = (
414 ('Data', OBJECT_TYPE_LIST ),
415 )
417# 2.3.13 SYSTEMTIME
418class SYSTEMTIME(NDRSTRUCT):
419 structure = (
420 ('wYear', WORD),
421 ('wMonth', WORD),
422 ('wDayOfWeek', WORD),
423 ('wDay', WORD),
424 ('wHour', WORD),
425 ('wMinute', WORD),
426 ('wSecond', WORD),
427 ('wMilliseconds', WORD),
428 )
430class PSYSTEMTIME(NDRPOINTER):
431 referent = (
432 ('Data', SYSTEMTIME ),
433 )
435# 2.3.15 ULARGE_INTEGER
436class ULARGE_INTEGER(NDRSTRUCT):
437 structure = (
438 ('QuadPart', LONG64),
439 )
441class PULARGE_INTEGER(NDRPOINTER):
442 referent = (
443 ('Data', ULARGE_INTEGER),
444 )
446# 2.4.2.3 RPC_SID
447class DWORD_ARRAY(NDRUniConformantArray):
448 item = '<L'
450class RPC_SID_IDENTIFIER_AUTHORITY(NDRUniFixedArray):
451 align = 1
452 align64 = 1
453 def getDataLen(self, data, offset=0):
454 return 6
456class RPC_SID(NDRSTRUCT):
457 structure = (
458 ('Revision',NDRSMALL),
459 ('SubAuthorityCount',NDRSMALL),
460 ('IdentifierAuthority',RPC_SID_IDENTIFIER_AUTHORITY),
461 ('SubAuthority',DWORD_ARRAY),
462 )
463 def getData(self, soFar = 0):
464 self['SubAuthorityCount'] = len(self['SubAuthority'])
465 return NDRSTRUCT.getData(self, soFar)
467 def fromCanonical(self, canonical):
468 items = canonical.split('-')
469 self['Revision'] = int(items[1])
470 self['IdentifierAuthority'] = b'\x00\x00\x00\x00\x00' + pack('B',int(items[2]))
471 self['SubAuthorityCount'] = len(items) - 3
472 for i in range(self['SubAuthorityCount']):
473 self['SubAuthority'].append(int(items[i+3]))
475 def formatCanonical(self):
476 ans = 'S-%d-%d' % (self['Revision'], ord(self['IdentifierAuthority'][5:6]))
477 for i in range(self['SubAuthorityCount']):
478 ans += '-%d' % self['SubAuthority'][i]
479 return ans
481class PRPC_SID(NDRPOINTER):
482 referent = (
483 ('Data', RPC_SID),
484 )
486PSID = PRPC_SID
488# 2.4.3 ACCESS_MASK
489GENERIC_READ = 0x80000000
490GENERIC_WRITE = 0x40000000
491GENERIC_EXECUTE = 0x20000000
492GENERIC_ALL = 0x10000000
493MAXIMUM_ALLOWED = 0x02000000
494ACCESS_SYSTEM_SECURITY = 0x01000000
495SYNCHRONIZE = 0x00100000
496WRITE_OWNER = 0x00080000
497WRITE_DACL = 0x00040000
498READ_CONTROL = 0x00020000
499DELETE = 0x00010000
501# 2.4.5.1 ACL--RPC Representation
502class ACL(NDRSTRUCT):
503 structure = (
504 ('AclRevision',NDRSMALL),
505 ('Sbz1',NDRSMALL),
506 ('AclSize',NDRSHORT),
507 ('AceCount',NDRSHORT),
508 ('Sbz2',NDRSHORT),
509 )
511class PACL(NDRPOINTER):
512 referent = (
513 ('Data', ACL),
514 )
516# 2.4.6.1 SECURITY_DESCRIPTOR--RPC Representation
517class SECURITY_DESCRIPTOR(NDRSTRUCT):
518 structure = (
519 ('Revision',UCHAR),
520 ('Sbz1',UCHAR),
521 ('Control',USHORT),
522 ('Owner',PSID),
523 ('Group',PSID),
524 ('Sacl',PACL),
525 ('Dacl',PACL),
526 )
528# 2.4.7 SECURITY_INFORMATION
529OWNER_SECURITY_INFORMATION = 0x00000001
530GROUP_SECURITY_INFORMATION = 0x00000002
531DACL_SECURITY_INFORMATION = 0x00000004
532SACL_SECURITY_INFORMATION = 0x00000008
533LABEL_SECURITY_INFORMATION = 0x00000010
534UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000
535UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000
536PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000
537PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
538ATTRIBUTE_SECURITY_INFORMATION = 0x00000020
539SCOPE_SECURITY_INFORMATION = 0x00000040
540BACKUP_SECURITY_INFORMATION = 0x00010000
542SECURITY_INFORMATION = DWORD
543class PSECURITY_INFORMATION(NDRPOINTER):
544 referent = (
545 ('Data', SECURITY_INFORMATION),
546 )