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