Coverage for /root/GitHubProjects/impacket/impacket/dcerpc/v5/dcom/oaut.py : 72%

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) 2018 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-OAUT]: OLE Automation Protocol Implementation
11# This was used as a way to test the DCOM runtime. Further
12# testing is needed to verify it is working as expected
13#
14# Best way to learn how to use these calls is to grab the protocol standard
15# so you understand what the call does, and then read the test case located
16# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC
17#
18# Since DCOM is like an OO RPC, instead of helper functions you will see the
19# classes described in the standards developed.
20# There are test cases for them too.
21#
22# Author:
23# Alberto Solino (@agsolino)
24#
25from __future__ import division
26from __future__ import print_function
27import random
28from struct import pack, unpack
30from impacket import LOG
31from impacket import hresult_errors
32from impacket.dcerpc.v5.dcomrt import DCOMCALL, DCOMANSWER, IRemUnknown2, PMInterfacePointer, INTERFACE, \
33 MInterfacePointer, MInterfacePointer_ARRAY, BYTE_ARRAY, PPMInterfacePointer
34from impacket.dcerpc.v5.dtypes import LPWSTR, ULONG, DWORD, SHORT, GUID, USHORT, LONG, WSTR, BYTE, LONGLONG, FLOAT, \
35 DOUBLE, HRESULT, PSHORT, PLONG, PLONGLONG, PFLOAT, PDOUBLE, PHRESULT, CHAR, ULONGLONG, INT, UINT, PCHAR, PUSHORT, \
36 PULONG, PULONGLONG, PINT, PUINT, NULL
37from impacket.dcerpc.v5.enum import Enum
38from impacket.dcerpc.v5.ndr import NDRSTRUCT, NDRUniConformantArray, NDRPOINTER, NDRENUM, NDRUSHORT, NDRUNION, \
39 NDRUniConformantVaryingArray, NDR
40from impacket.dcerpc.v5.rpcrt import DCERPCException
41from impacket.uuid import string_to_bin
43class DCERPCSessionError(DCERPCException):
44 def __init__(self, error_string=None, error_code=None, packet=None):
45 DCERPCException.__init__(self, error_string, error_code, packet)
47 def __str__( self ):
48 if self.error_code in hresult_errors.ERROR_MESSAGES:
49 error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0]
50 error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1]
51 return 'OAUT SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
52 else:
53 return 'OAUT SessionError: unknown error code: 0x%x' % (self.error_code)
55################################################################################
56# CONSTANTS
57################################################################################
58# 1.9 Standards Assignments
59IID_IDispatch = string_to_bin('00020400-0000-0000-C000-000000000046')
60IID_ITypeInfo = string_to_bin('00020401-0000-0000-C000-000000000046')
61IID_ITypeComp = string_to_bin('00020403-0000-0000-C000-000000000046')
62IID_NULL = string_to_bin('00000000-0000-0000-0000-000000000000')
64error_status_t = ULONG
66LCID = DWORD
67WORD = NDRUSHORT
69# 2.2.2 IID
70IID = GUID
72# 2.2.3 LPOLESTR
73LPOLESTR = LPWSTR
74OLESTR = WSTR
76# 2.2.4 REFIID
77REFIID = IID
79# 2.2.25 DATE
80DATE = DOUBLE
81class PDATE(NDRPOINTER):
82 referent = (
83 ('Data', DATE),
84 )
86# 2.2.27 VARIANT_BOOL
87VARIANT_BOOL = USHORT
89class PVARIANT_BOOL(NDRPOINTER):
90 referent = (
91 ('Data', VARIANT_BOOL),
92 )
94# 3.1.4.4 IDispatch::Invoke (Opnum 6)
95# dwFlags
96DISPATCH_METHOD = 0x00000001
97DISPATCH_PROPERTYGET = 0x00000002
98DISPATCH_PROPERTYPUT = 0x00000004
99DISPATCH_PROPERTYPUTREF = 0x00000008
100DISPATCH_zeroVarResult = 0x00020000
101DISPATCH_zeroExcepInfo = 0x00040000
102DISPATCH_zeroArgErr = 0x00080000
104################################################################################
105# STRUCTURES
106################################################################################
107# 2.2.26 DECIMAL
108class DECIMAL(NDRSTRUCT):
109 structure = (
110 ('wReserved',WORD),
111 ('scale',BYTE),
112 ('sign',BYTE),
113 ('Hi32',ULONG),
114 ('Lo64',ULONGLONG),
115 )
117class PDECIMAL(NDRPOINTER):
118 referent = (
119 ('Data', DECIMAL),
120 )
122# 2.2.7 VARIANT Type Constants
123class VARENUM(NDRENUM):
124 class enumItems(Enum):
125 VT_EMPTY = 0
126 VT_NULL = 1
127 VT_I2 = 2
128 VT_I4 = 3
129 VT_R4 = 4
130 VT_R8 = 5
131 VT_CY = 6
132 VT_DATE = 7
133 VT_BSTR = 8
134 VT_DISPATCH = 9
135 VT_ERROR = 0xa
136 VT_BOOL = 0xb
137 VT_VARIANT = 0xc
138 VT_UNKNOWN = 0xd
139 VT_DECIMAL = 0xe
140 VT_I1 = 0x10
141 VT_UI1 = 0x11
142 VT_UI2 = 0x12
143 VT_UI4 = 0x13
144 VT_I8 = 0x14
145 VT_UI8 = 0x15
146 VT_INT = 0x16
147 VT_UINT = 0x17
148 VT_VOID = 0x18
149 VT_HRESULT = 0x19
150 VT_PTR = 0x1a
151 VT_SAFEARRAY = 0x1b
152 VT_CARRAY = 0x1c
153 VT_USERDEFINED = 0x1d
154 VT_LPSTR = 0x1e
155 VT_LPWSTR = 0x1f
156 VT_RECORD = 0x24
157 VT_INT_PTR = 0x25
158 VT_UINT_PTR = 0x26
159 VT_ARRAY = 0x2000
160 VT_BYREF = 0x4000
161 VT_RECORD_OR_VT_BYREF = VT_RECORD | VT_BYREF
162 VT_UI1_OR_VT_BYREF = VT_UI1 | VT_BYREF
163 VT_I2_OR_VT_BYREF = VT_I2 | VT_BYREF
164 VT_I4_OR_VT_BYREF = VT_I4 | VT_BYREF
165 VT_I8_OR_VT_BYREF = VT_I8 | VT_BYREF
166 VT_R4_OR_VT_BYREF = VT_R4 | VT_BYREF
167 VT_R8_OR_VT_BYREF = VT_R8 | VT_BYREF
168 VT_BOOL_OR_VT_BYREF = VT_BOOL | VT_BYREF
169 VT_ERROR_OR_VT_BYREF = VT_ERROR | VT_BYREF
170 VT_CY_OR_VT_BYREF = VT_CY | VT_BYREF
171 VT_DATE_OR_VT_BYREF = VT_DATE | VT_BYREF
172 VT_BSTR_OR_VT_BYREF = VT_BSTR | VT_BYREF
173 VT_UNKNOWN_OR_VT_BYREF = VT_UNKNOWN | VT_BYREF
174 VT_DISPATCH_OR_VT_BYREF = VT_DISPATCH | VT_BYREF
175 VT_ARRAY_OR_VT_BYREF = VT_ARRAY | VT_BYREF
176 VT_VARIANT_OR_VT_BYREF = VT_VARIANT| VT_BYREF
177 VT_I1_OR_VT_BYREF = VT_I1 | VT_BYREF
178 VT_UI2_OR_VT_BYREF = VT_UI2 | VT_BYREF
179 VT_UI4_OR_VT_BYREF = VT_UI4 | VT_BYREF
180 VT_UI8_OR_VT_BYREF = VT_UI8 | VT_BYREF
181 VT_INT_OR_VT_BYREF = VT_INT | VT_BYREF
182 VT_UINT_OR_VT_BYREF = VT_UINT | VT_BYREF
183 VT_DECIMAL_OR_VT_BYREF = VT_DECIMAL | VT_BYREF
185# 2.2.8 SAFEARRAY Feature Constants
186class SF_TYPE(NDRENUM):
187 # [v1_enum] type
188 structure = (
189 ('Data', '<L'),
190 )
191 class enumItems(Enum):
192 SF_ERROR = VARENUM.VT_ERROR
193 SF_I1 = VARENUM.VT_I1
194 SF_I2 = VARENUM.VT_I2
195 SF_I4 = VARENUM.VT_I4
196 SF_I8 = VARENUM.VT_I8
197 SF_BSTR = VARENUM.VT_BSTR
198 SF_UNKNOWN = VARENUM.VT_UNKNOWN
199 SF_DISPATCH = VARENUM.VT_DISPATCH
200 SF_VARIANT = VARENUM.VT_VARIANT
201 SF_RECORD = VARENUM.VT_RECORD
202 SF_HAVEIID = VARENUM.VT_UNKNOWN | 0x8000
204# 2.2.10 CALLCONV Calling Convention Constants
205class CALLCONV(NDRENUM):
206 # [v1_enum] type
207 structure = (
208 ('Data', '<L'),
209 )
210 class enumItems(Enum):
211 CC_CDECL = 1
212 CC_PASCAL = 2
213 CC_STDCALL = 4
216# 2.2.12 FUNCKIND Function Access Constants
217class FUNCKIND(NDRENUM):
218 # [v1_enum] type
219 structure = (
220 ('Data', '<L'),
221 )
222 class enumItems(Enum):
223 FUNC_PUREVIRTUAL = 1
224 FUNC_STATIC = 3
225 FUNC_DISPATCH = 4
227# 2.2.14 INVOKEKIND Function Invocation Constants
228class INVOKEKIND(NDRENUM):
229 # [v1_enum] type
230 structure = (
231 ('Data', '<L'),
232 )
233 class enumItems(Enum):
234 INVOKE_FUNC = 1
235 INVOKE_PROPERTYGET = 2
236 INVOKE_PROPERTYPUT = 4
237 INVOKE_PROPERTYPUTREF = 8
239# 2.2.17 TYPEKIND Type Kind Constants
240class TYPEKIND(NDRENUM):
241 # [v1_enum] type
242 structure = (
243 ('Data', '<L'),
244 )
245 class enumItems(Enum):
246 TKIND_ENUM = 0
247 TKIND_RECORD = 1
248 TKIND_MODULE = 2
249 TKIND_INTERFACE = 3
250 TKIND_DISPATCH = 4
251 TKIND_COCLASS = 5
252 TKIND_ALIAS = 6
253 TKIND_UNION = 7
255# 2.2.23 BSTR
256# 2.2.23.1 FLAGGED_WORD_BLOB
257class USHORT_ARRAY(NDRUniConformantArray):
258 item = '<H'
260class FLAGGED_WORD_BLOB(NDRSTRUCT):
261 structure = (
262 ('cBytes',ULONG),
263 ('clSize',ULONG),
264 ('asData',USHORT_ARRAY),
265 )
266 def __setitem__(self, key, value):
267 if key == 'asData':
268 value = value #+ '\x00'
269 array = list()
270 for letter in value:
271 encoded = letter.encode('utf-16le')
272 array.append(unpack('<H', encoded)[0])
273 self.fields[key]['Data'] = array
274 self['cBytes'] = len(value)*2
275 self['clSize'] = len(value)
276 self.data = None # force recompute
277 else:
278 return NDRSTRUCT.__setitem__(self, key, value)
280 def __getitem__(self, key):
281 if key == 'asData':
282 value = ''
283 for letter in self.fields['asData']['Data']:
284 value += pack('<H', letter).decode('utf-16le')
285 return value
286 else:
287 return NDRSTRUCT.__getitem__(self,key)
289 def dump(self, msg = None, indent = 0):
290 if msg is None: msg = self.__class__.__name__
291 ind = ' '*indent
292 if msg != '':
293 print("%s" % (msg))
294 value = ''
295 print('%sasData: %s' % (ind,self['asData']), end=' ')
297# 2.2.23.2 BSTR Type Definition
298class BSTR(NDRPOINTER):
299 referent = (
300 ('Data', FLAGGED_WORD_BLOB),
301 )
303class PBSTR(NDRPOINTER):
304 referent = (
305 ('Data', BSTR),
306 )
308# 2.2.24 CURRENCY
309class CURRENCY(NDRSTRUCT):
310 structure = (
311 ('int64', LONGLONG),
312 )
314class PCURRENCY(NDRPOINTER):
315 referent = (
316 ('Data', CURRENCY),
317 )
319# 2.2.28.2 BRECORD
320# 2.2.28.2.1 _wireBRECORD
321class _wireBRECORD(NDRSTRUCT):
322 structure = (
323 ('fFlags', LONGLONG),
324 ('clSize', LONGLONG),
325 ('pRecInfo', MInterfacePointer),
326 ('pRecord', BYTE_ARRAY),
327 )
329class BRECORD(NDRPOINTER):
330 referent = (
331 ('Data', _wireBRECORD),
332 )
334# 2.2.30 SAFEARRAY
335# 2.2.30.1 SAFEARRAYBOUND
336class SAFEARRAYBOUND(NDRSTRUCT):
337 structure = (
338 ('cElements', ULONG),
339 ('lLbound', LONG),
340 )
342class PSAFEARRAYBOUND(NDRPOINTER):
343 referent = (
344 ('Data', SAFEARRAYBOUND),
345 )
347# 2.2.30.2 SAFEARR_BSTR
348class BSTR_ARRAY(NDRUniConformantArray):
349 item = BSTR
351class PBSTR_ARRAY(NDRPOINTER):
352 referent = (
353 ('Data', BSTR_ARRAY),
354 )
356class SAFEARR_BSTR(NDRSTRUCT):
357 structure = (
358 ('Size', ULONG),
359 ('aBstr', PBSTR_ARRAY),
360 )
362# 2.2.30.3 SAFEARR_UNKNOWN
363class SAFEARR_UNKNOWN(NDRSTRUCT):
364 structure = (
365 ('Size', ULONG),
366 ('apUnknown', MInterfacePointer_ARRAY),
367 )
369# 2.2.30.4 SAFEARR_DISPATCH
370class SAFEARR_DISPATCH(NDRSTRUCT):
371 structure = (
372 ('Size', ULONG),
373 ('apDispatch', MInterfacePointer_ARRAY),
374 )
376# 2.2.30.6 SAFEARR_BRECORD
377class BRECORD_ARRAY(NDRUniConformantArray):
378 item = BRECORD
380class SAFEARR_BRECORD(NDRSTRUCT):
381 structure = (
382 ('Size', ULONG),
383 ('aRecord', BRECORD_ARRAY),
384 )
386# 2.2.30.7 SAFEARR_HAVEIID
387class SAFEARR_HAVEIID(NDRSTRUCT):
388 structure = (
389 ('Size', ULONG),
390 ('apUnknown', MInterfacePointer_ARRAY),
391 ('iid', IID),
392 )
394# 2.2.30.8 Scalar-Sized Arrays
395# 2.2.30.8.1 BYTE_SIZEDARR
396class BYTE_SIZEDARR(NDRSTRUCT):
397 structure = (
398 ('clSize', ULONG),
399 ('pData', BYTE_ARRAY),
400 )
402# 2.2.30.8.2 WORD_SIZEDARR
403class WORD_ARRAY(NDRUniConformantArray):
404 item = '<H'
406class WORD_SIZEDARR(NDRSTRUCT):
407 structure = (
408 ('clSize', ULONG),
409 ('pData', WORD_ARRAY),
410 )
412# 2.2.30.8.3 DWORD_SIZEDARR
413class DWORD_ARRAY(NDRUniConformantArray):
414 item = '<L'
416class DWORD_SIZEDARR(NDRSTRUCT):
417 structure = (
418 ('clSize', ULONG),
419 ('pData', DWORD_ARRAY),
420 )
422# 2.2.30.8.4 HYPER_SIZEDARR
423class HYPER_ARRAY(NDRUniConformantArray):
424 item = '<Q'
426class HYPER_SIZEDARR(NDRSTRUCT):
427 structure = (
428 ('clSize', ULONG),
429 ('pData', HYPER_ARRAY),
430 )
433# 2.2.36 HREFTYPE
434HREFTYPE = DWORD
436# 2.2.30.5 SAFEARR_VARIANT
437class VARIANT_ARRAY(NDRUniConformantArray):
438 # In order to avoid the lack of forward declarations in Python
439 # I declare the item in the constructor
440 #item = VARIANT
441 def __init__(self, data = None, isNDR64 = False):
442 NDRUniConformantArray.__init__(self, data, isNDR64)
443 self.item = VARIANT
445class PVARIANT_ARRAY(NDRPOINTER):
446 referent = (
447 ('Data', VARIANT_ARRAY),
448 )
450class PVARIANT(NDRPOINTER):
451 # In order to avoid the lack of forward declarations in Python
452 # I declare the item in the constructor
453 #referent = (
454 # ('Data', VARIANT),
455 #)
456 def __init__(self, data = None, isNDR64 = False):
457 NDRPOINTER.__init__(self, data, isNDR64)
458 self.referent = ( ('Data', VARIANT),)
461class SAFEARR_VARIANT(NDRSTRUCT):
462 structure = (
463 ('Size', ULONG),
464 ('aVariant', VARIANT_ARRAY),
465 )
467# 2.2.30.9 SAFEARRAYUNION
468class SAFEARRAYUNION(NDRUNION):
469 commonHdr = (
470 ('tag', ULONG),
471 )
472 union = {
473 SF_TYPE.SF_BSTR : ('BstrStr', SAFEARR_BSTR),
474 SF_TYPE.SF_UNKNOWN : ('UnknownStr', SAFEARR_UNKNOWN),
475 SF_TYPE.SF_DISPATCH : ('DispatchStr', SAFEARR_DISPATCH),
476 SF_TYPE.SF_VARIANT : ('VariantStr', SAFEARR_VARIANT),
477 SF_TYPE.SF_RECORD : ('RecordStr', SAFEARR_BRECORD),
478 SF_TYPE.SF_HAVEIID : ('HaveIidStr', SAFEARR_HAVEIID),
479 SF_TYPE.SF_I1 : ('ByteStr', BYTE_SIZEDARR),
480 SF_TYPE.SF_I2 : ('WordStr', WORD_SIZEDARR),
481 SF_TYPE.SF_I4 : ('LongStr', DWORD_SIZEDARR),
482 SF_TYPE.SF_I8 : ('HyperStr', HYPER_SIZEDARR),
483 }
485# 2.2.30.10 SAFEARRAY
486class SAFEARRAYBOUND_ARRAY(NDRUniConformantArray):
487 item = SAFEARRAYBOUND
489class PSAFEARRAYBOUND_ARRAY(NDRPOINTER):
490 referent = (
491 ('Data', SAFEARRAYBOUND_ARRAY),
492 )
494class SAFEARRAY(NDRSTRUCT):
495 structure = (
496 ('cDims', USHORT),
497 ('fFeatures', USHORT),
498 ('cbElements', ULONG),
499 ('cLocks', ULONG),
500 ('uArrayStructs', SAFEARRAYUNION),
501 ('rgsabound', SAFEARRAYBOUND_ARRAY),
502 )
504class PSAFEARRAY(NDRPOINTER):
505 referent = (
506 ('Data', SAFEARRAY),
507 )
509# 2.2.29 VARIANT
510# 2.2.29.1 _wireVARIANT
511class EMPTY(NDR):
512 align = 0
513 structure = (
514 )
516class varUnion(NDRUNION):
517 commonHdr = (
518 ('tag', ULONG),
519 )
520 union = {
521 VARENUM.VT_I8 : ('llVal', LONGLONG),
522 VARENUM.VT_I4 : ('lVal', LONG),
523 VARENUM.VT_UI1 : ('bVal', BYTE),
524 VARENUM.VT_I2 : ('iVal', SHORT),
525 VARENUM.VT_R4 : ('fltVal', FLOAT),
526 VARENUM.VT_R8 : ('dblVal', DOUBLE),
527 VARENUM.VT_BOOL : ('boolVal', VARIANT_BOOL),
528 VARENUM.VT_ERROR : ('scode', HRESULT),
529 VARENUM.VT_CY : ('cyVal', CURRENCY),
530 VARENUM.VT_DATE : ('date', DATE),
531 VARENUM.VT_BSTR : ('bstrVal', BSTR),
532 VARENUM.VT_UNKNOWN : ('punkVal', PMInterfacePointer),
533 VARENUM.VT_DISPATCH : ('pdispVal', PMInterfacePointer),
534 VARENUM.VT_ARRAY : ('parray', SAFEARRAY),
535 VARENUM.VT_RECORD : ('brecVal', BRECORD),
536 VARENUM.VT_RECORD_OR_VT_BYREF : ('brecVal', BRECORD),
537 VARENUM.VT_UI1_OR_VT_BYREF : ('pbVal', BYTE),
538 VARENUM.VT_I2_OR_VT_BYREF : ('piVal', PSHORT),
539 VARENUM.VT_I4_OR_VT_BYREF : ('plVal', PLONG),
540 VARENUM.VT_I8_OR_VT_BYREF : ('pllVal', PLONGLONG),
541 VARENUM.VT_R4_OR_VT_BYREF : ('pfltVal', PFLOAT),
542 VARENUM.VT_R8_OR_VT_BYREF : ('pdblVal', PDOUBLE),
543 VARENUM.VT_BOOL_OR_VT_BYREF : ('pboolVal', PVARIANT_BOOL),
544 VARENUM.VT_ERROR_OR_VT_BYREF : ('pscode', PHRESULT),
545 VARENUM.VT_CY_OR_VT_BYREF : ('pcyVal', PCURRENCY),
546 VARENUM.VT_DATE_OR_VT_BYREF : ('pdate', PDATE),
547 VARENUM.VT_BSTR_OR_VT_BYREF : ('pbstrVal', PBSTR),
548 VARENUM.VT_UNKNOWN_OR_VT_BYREF : ('ppunkVal', PPMInterfacePointer),
549 VARENUM.VT_DISPATCH_OR_VT_BYREF: ('ppdispVal', PPMInterfacePointer),
550 VARENUM.VT_ARRAY_OR_VT_BYREF : ('pparray', PSAFEARRAY),
551 VARENUM.VT_VARIANT_OR_VT_BYREF : ('pvarVal', PVARIANT),
552 VARENUM.VT_I1 : ('cVal', CHAR),
553 VARENUM.VT_UI2 : ('uiVal', USHORT),
554 VARENUM.VT_UI4 : ('ulVal', ULONG),
555 VARENUM.VT_UI8 : ('ullVal', ULONGLONG),
556 VARENUM.VT_INT : ('intVal', INT),
557 VARENUM.VT_UINT : ('uintVal', UINT),
558 VARENUM.VT_DECIMAL : ('decVal', DECIMAL),
559 VARENUM.VT_I1_OR_VT_BYREF : ('pcVal', PCHAR),
560 VARENUM.VT_UI2_OR_VT_BYREF : ('puiVal', PUSHORT),
561 VARENUM.VT_UI4_OR_VT_BYREF : ('pulVal', PULONG),
562 VARENUM.VT_UI8_OR_VT_BYREF : ('pullVal', PULONGLONG),
563 VARENUM.VT_INT_OR_VT_BYREF : ('pintVal', PINT),
564 VARENUM.VT_UINT_OR_VT_BYREF : ('puintVal', PUINT),
565 VARENUM.VT_DECIMAL_OR_VT_BYREF : ('pdecVal', PDECIMAL),
566 VARENUM.VT_EMPTY : ('empty', EMPTY),
567 VARENUM.VT_NULL : ('null', EMPTY),
568 }
570class wireVARIANTStr(NDRSTRUCT):
571 structure = (
572 ('clSize',DWORD),
573 ('rpcReserved',DWORD),
574 ('vt',USHORT),
575 ('wReserved1',USHORT),
576 ('wReserved2',USHORT),
577 ('wReserved3',USHORT),
578 ('_varUnion',varUnion),
579 )
581 def getAlignment(self):
582 return 8
584class VARIANT(NDRPOINTER):
585 referent = (
586 ('Data', wireVARIANTStr),
587 )
589class PVARIANT(NDRPOINTER):
590 referent = (
591 ('Data', VARIANT),
592 )
594# 2.2.32 DISPID
595DISPID = LONG
597# 2.2.33 DISPPARAMS
598class DISPID_ARRAY(NDRUniConformantArray):
599 item = '<L'
601class PDISPID_ARRAY(NDRPOINTER):
602 referent = (
603 ('Data', DISPID_ARRAY),
604 )
606class DISPPARAMS(NDRSTRUCT):
607 structure = (
608 ('rgvarg',PVARIANT_ARRAY),
609 ('rgdispidNamedArgs', PDISPID_ARRAY),
610 ('cArgs', UINT),
611 ('cNamedArgs', UINT),
612 )
614# 2.2.34 EXCEPINFO
615class EXCEPINFO(NDRSTRUCT):
616 structure = (
617 ('wCode',WORD),
618 ('wReserved', WORD),
619 ('bstrSource', BSTR),
620 ('bstrDescription', BSTR),
621 ('bstrHelpFile', BSTR),
622 ('dwHelpContext', DWORD),
623 ('pvReserved', ULONG),
624 ('pfnDeferredFillIn', ULONG),
625 ('scode', HRESULT),
626 )
628# 2.2.35 MEMBERID
629MEMBERID = DISPID
631# 2.2.38 ARRAYDESC
632class ARRAYDESC(NDRSTRUCT):
633 # In order to avoid the lack of forward declarations in Python
634 # I declare the item in the constructor
635 #structure = (
636 # ('tdescElem',TYPEDESC),
637 # ('cDims',USHORT),
638 # ('rgbounds',SAFEARRAYBOUND_ARRAY),
639 #)
640 def __init__(self, data = None, isNDR64 = False):
641 NDRSTRUCT.__init__(self, data, isNDR64)
642 self.structure = (
643 ('tdescElem',TYPEDESC),
644 ('cDims',USHORT),
645 ('rgbounds',SAFEARRAYBOUND_ARRAY),
646 )
648# 2.2.37 TYPEDESC
649class tdUnion(NDRUNION):
650 notAlign = True
651 commonHdr = (
652 ('tag', USHORT),
653 )
654 # In order to avoid the lack of forward declarations in Python
655 # I declare the item in the constructor
656 #union = {
657 # VARENUM.VT_PTR: ('lptdesc', tdUnion),
658 # VARENUM.VT_SAFEARRAY: ('lptdesc', tdUnion),
659 # VARENUM.VT_CARRAY: ('lpadesc', ARRAYDESC),
660 # VARENUM.VT_USERDEFINED: ('hreftype', HREFTYPE),
661 #}
662 def __init__(self, data = None, isNDR64=False, topLevel = False):
663 NDRUNION.__init__(self,None, isNDR64=isNDR64, topLevel=topLevel)
664 self.union = {
665 VARENUM.VT_PTR: ('lptdesc', PTYPEDESC),
666 VARENUM.VT_SAFEARRAY: ('lptdesc', PTYPEDESC),
667 VARENUM.VT_CARRAY: ('lpadesc', ARRAYDESC),
668 VARENUM.VT_USERDEFINED: ('hreftype', HREFTYPE),
669 'default': None,
670 }
672class TYPEDESC(NDRSTRUCT):
673 structure = (
674 ('vtType',tdUnion),
675 ('vt', VARENUM),
676 )
678 def getAlignment(self):
679 return 4
681class PTYPEDESC(NDRPOINTER):
682 referent = (
683 ('Data', TYPEDESC),
684 )
685 def __init__(self, data = None, isNDR64=False, topLevel = False):
686 ret = NDRPOINTER.__init__(self,None, isNDR64=isNDR64, topLevel = False)
687 # We're forcing the pointer not to be topLevel
688 if data is None:
689 self.fields['ReferentID'] = random.randint(1,65535)
690 else:
691 self.fromString(data)
694# 2.2.48 SCODE
695SCODE = LONG
697class SCODE_ARRAY(NDRUniConformantArray):
698 item = SCODE
700class PSCODE_ARRAY(NDRPOINTER):
701 referent = (
702 ('Data', SCODE_ARRAY),
703 )
705# 2.2.39 PARAMDESCEX
706class PARAMDESCEX(NDRSTRUCT):
707 structure = (
708 ('cBytes',ULONG),
709 ('varDefaultValue',VARIANT),
710 )
712class PPARAMDESCEX(NDRPOINTER):
713 referent = (
714 ('Data', PARAMDESCEX),
715 )
718# 2.2.40 PARAMDESC
719class PARAMDESC(NDRSTRUCT):
720 structure = (
721 ('pparamdescex',PPARAMDESCEX),
722 ('wParamFlags',USHORT),
723 )
725# 2.2.41 ELEMDESC
726class ELEMDESC(NDRSTRUCT):
727 structure = (
728 ('tdesc',TYPEDESC),
729 ('paramdesc',PARAMDESC),
730 )
732class ELEMDESC_ARRAY(NDRUniConformantArray):
733 item = ELEMDESC
735class PELEMDESC_ARRAY(NDRPOINTER):
736 referent = (
737 ('Data', ELEMDESC_ARRAY),
738 )
740# 2.2.42 FUNCDESC
741class FUNCDESC(NDRSTRUCT):
742 structure = (
743 ('memid',MEMBERID),
744 ('lReserved1',PSCODE_ARRAY),
745 ('lprgelemdescParam',PELEMDESC_ARRAY),
746 ('funckind',FUNCKIND),
747 ('invkind',INVOKEKIND),
748 ('callconv',CALLCONV),
749 ('cParams',SHORT),
750 ('cParamsOpt',SHORT),
751 ('oVft',SHORT),
752 ('cReserved2',SHORT),
753 ('elemdescFunc',ELEMDESC),
754 ('wFuncFlags',WORD),
755 )
757class LPFUNCDESC(NDRPOINTER):
758 referent = (
759 ('Data', FUNCDESC),
760 )
761# 2.2.44 TYPEATTR
762class TYPEATTR(NDRSTRUCT):
763 structure = (
764 ('guid',GUID),
765 ('lcid',LCID),
766 ('dwReserved1',DWORD),
767 ('dwReserved2',DWORD),
768 ('dwReserved3',DWORD),
769 ('lpstrReserved4',LPOLESTR),
770 ('cbSizeInstance',ULONG),
771 ('typeKind',TYPEKIND),
772 ('cFuncs',WORD),
773 ('cVars',WORD),
774 ('cImplTypes',WORD),
775 ('cbSizeVft',WORD),
776 ('cbAlignment',WORD),
777 ('wTypeFlags',WORD),
778 ('wMajorVerNum',WORD),
779 ('wMinorVerNum',WORD),
780 ('tdescAlias',TYPEDESC),
781 ('dwReserved5',DWORD),
782 ('dwReserved6',WORD),
783 )
785class PTYPEATTR(NDRPOINTER):
786 referent = (
787 ('Data', TYPEATTR),
788 )
790class BSTR_ARRAY_CV(NDRUniConformantVaryingArray):
791 item = BSTR
793class UINT_ARRAY(NDRUniConformantArray):
794 item = '<L'
796class OLESTR_ARRAY(NDRUniConformantArray):
797 item = LPOLESTR
800################################################################################
801# RPC CALLS
802################################################################################
803# 3.1.4.1 IDispatch::GetTypeInfoCount (Opnum 3)
804class IDispatch_GetTypeInfoCount(DCOMCALL):
805 opnum = 3
806 structure = (
807 ('pwszMachineName', LPWSTR),
808 )
810class IDispatch_GetTypeInfoCountResponse(DCOMANSWER):
811 structure = (
812 ('pctinfo', ULONG),
813 ('ErrorCode', error_status_t),
814 )
816# 3.1.4.2 IDispatch::GetTypeInfo (Opnum 4)
817class IDispatch_GetTypeInfo(DCOMCALL):
818 opnum = 4
819 structure = (
820 ('iTInfo', ULONG),
821 ('lcid', DWORD),
822 )
824class IDispatch_GetTypeInfoResponse(DCOMANSWER):
825 structure = (
826 ('ppTInfo', PMInterfacePointer),
827 ('ErrorCode', error_status_t),
828 )
830# 3.1.4.3 IDispatch::GetIDsOfNames (Opnum 5)
831class IDispatch_GetIDsOfNames(DCOMCALL):
832 opnum = 5
833 structure = (
834 ('riid', REFIID),
835 ('rgszNames', OLESTR_ARRAY),
836 ('cNames', UINT),
837 ('lcid', LCID),
838 )
840class IDispatch_GetIDsOfNamesResponse(DCOMANSWER):
841 structure = (
842 ('rgDispId', DISPID_ARRAY),
843 ('ErrorCode', error_status_t),
844 )
846# 3.1.4.4 IDispatch::Invoke (Opnum 6)
847class IDispatch_Invoke(DCOMCALL):
848 opnum = 6
849 structure = (
850 ('dispIdMember', DISPID),
851 ('riid', REFIID),
852 ('lcid', LCID),
853 ('dwFlags', DWORD),
854 ('pDispParams', DISPPARAMS),
855 ('cVarRef', UINT),
856 ('rgVarRefIdx', UINT_ARRAY),
857 ('rgVarRef', VARIANT_ARRAY),
858 )
860class IDispatch_InvokeResponse(DCOMANSWER):
861 structure = (
862 ('pVarResult', VARIANT),
863 ('pExcepInfo', EXCEPINFO),
864 ('pArgErr', UINT),
865 ('ErrorCode', error_status_t),
866 )
868# 3.7.4.1 ITypeInfo::GetTypeAttr (Opnum 3)
869class ITypeInfo_GetTypeAttr(DCOMCALL):
870 opnum = 3
871 structure = (
872 )
874class ITypeInfo_GetTypeAttrResponse(DCOMANSWER):
875 structure = (
876 ('ppTypeAttr', PTYPEATTR),
877 ('pReserved', DWORD),
878 ('ErrorCode', error_status_t),
879 )
881# 3.7.4.2 ITypeInfo::GetTypeComp (Opnum 4)
882class ITypeInfo_GetTypeComp(DCOMCALL):
883 opnum = 4
884 structure = (
885 )
887class ITypeInfo_GetTypeCompResponse(DCOMANSWER):
888 structure = (
889 ('ppTComp', PMInterfacePointer),
890 ('ErrorCode', error_status_t),
891 )
893# 3.7.4.3 ITypeInfo::GetFuncDesc (Opnum 5)
894class ITypeInfo_GetFuncDesc(DCOMCALL):
895 opnum = 5
896 structure = (
897 ('index', UINT),
898 )
900class ITypeInfo_GetFuncDescResponse(DCOMANSWER):
901 structure = (
902 ('ppFuncDesc', LPFUNCDESC),
903 ('pReserved', DWORD),
904 ('ErrorCode', error_status_t),
905 )
907# 3.7.4.5 ITypeInfo::GetNames (Opnum 7)
908class ITypeInfo_GetNames(DCOMCALL):
909 opnum = 7
910 structure = (
911 ('memid', MEMBERID),
912 ('cMaxNames', UINT),
913 )
915class ITypeInfo_GetNamesResponse(DCOMANSWER):
916 structure = (
917 ('rgBstrNames', BSTR_ARRAY_CV),
918 ('pcNames', UINT),
919 ('ErrorCode', error_status_t),
920 )
922# 3.7.4.8 ITypeInfo::GetDocumentation (Opnum 12)
923class ITypeInfo_GetDocumentation(DCOMCALL):
924 opnum = 12
925 structure = (
926 ('memid', MEMBERID),
927 ('refPtrFlags', DWORD),
928 )
930class ITypeInfo_GetDocumentationResponse(DCOMANSWER):
931 structure = (
932 ('pBstrName', BSTR),
933 ('pBstrDocString', BSTR),
934 ('pdwHelpContext', DWORD),
935 ('ErrorCode', error_status_t),
936 )
939################################################################################
940# OPNUMs and their corresponding structures
941################################################################################
942OPNUMS = {
943}
945################################################################################
946# HELPER FUNCTIONS AND INTERFACES
947################################################################################
948# 4.8.5 Enumerating All Methods in an Interface
949# INPUT: IDispatch pointer from the automation server
950# CALL IDispatch::GetTypeInfoCount and OBTAIN pcTInfo
951# COMMENT see Section 3.1.4.1 for information on pcTInfo i
952# IF pcTInfo = 0 THEN
953# PRINT Automation Server does not support type information for this object
954# ELSE
955# CALL IDispatch::GetTypeInfo with correct LocaleID and OBTAIN ITypeInfo pointer
956# CALL ITypeInfo::GetDocumentation(MEMBERID_NIL, 1, &BstrName, NULL, NULL, NULL)
957# PRINT Name of the Interface is BstrName
958# CALL ITypeInfo::GetTypeAttr and OBTAIN TYPEATTR pointer
959#
960# FOR X = 0 to TYPEATTR:: cFuncs -1
961# CALL ITypeInfo::GetFuncDesc with X and OBTAIN FUNCDESC pointer
962# CALL ITypeInfo::GetNames with FUNCDESC::memid and appropriate values for
963# rgBstrNames, cMaxNames and pcNames
964# COMMENT see Section 3.7.4.5 for more information regarding the parameters
965# to ITypeinfo::GetNames
966# IF pcNames > 0 THEN
967# PRINT Name of the method is rgBstrNames[0]
968# PRINT Parameters to above method are following
969# FOR Y = 1 to pcNames -1
970# PRINT rgBstrNames[Y]
971# END FOR
972# END IF
973# END FOR i
974# ENDIF
975def enumerateMethods(iInterface):
976 methods = dict()
977 typeInfoCount = iInterface.GetTypeInfoCount()
978 if typeInfoCount['pctinfo'] == 0:
979 LOG.error('Automation Server does not support type information for this object')
980 return {}
981 iTypeInfo = iInterface.GetTypeInfo()
982 iTypeAttr = iTypeInfo.GetTypeAttr()
983 for x in range(iTypeAttr['ppTypeAttr']['cFuncs']):
984 funcDesc = iTypeInfo.GetFuncDesc(x)
985 names = iTypeInfo.GetNames(funcDesc['ppFuncDesc']['memid'], 255)
986 print(names['rgBstrNames'][0]['asData'])
987 funcDesc.dump()
988 print('='*80)
989 if names['pcNames'] > 0:
990 name = names['rgBstrNames'][0]['asData']
991 methods[name] = {}
992 for param in range(1, names['pcNames']):
993 methods[name][names['rgBstrNames'][param]['asData']] = ''
994 if funcDesc['ppFuncDesc']['elemdescFunc'] != NULL:
995 methods[name]['ret'] = funcDesc['ppFuncDesc']['elemdescFunc']['tdesc']['vt']
997 return methods
999def checkNullString(string):
1000 if string == NULL:
1001 return string
1003 if string[-1:] != '\x00':
1004 return string + '\x00'
1005 else:
1006 return string
1008class ITypeComp(IRemUnknown2):
1009 def __init__(self, interface):
1010 IRemUnknown2.__init__(self,interface)
1011 self._iid = IID_ITypeComp
1013class ITypeInfo(IRemUnknown2):
1014 def __init__(self, interface):
1015 IRemUnknown2.__init__(self,interface)
1016 self._iid = IID_ITypeInfo
1018 def GetTypeAttr(self):
1019 request = ITypeInfo_GetTypeAttr()
1020 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1021 return resp
1023 def GetTypeComp(self):
1024 request = ITypeInfo_GetTypeComp()
1025 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1026 return ITypeComp(INTERFACE(self.get_cinstance(), ''.join(resp['ppTComp']['abData']), self.get_ipidRemUnknown(), target = self.get_target()))
1028 def GetFuncDesc(self, index):
1029 request = ITypeInfo_GetFuncDesc()
1030 request['index'] = index
1031 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1032 return resp
1034 def GetNames(self, memid, cMaxNames=10):
1035 request = ITypeInfo_GetNames()
1036 request['memid'] = memid
1037 request['cMaxNames'] = cMaxNames
1038 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1039 return resp
1041 def GetDocumentation(self, memid, refPtrFlags=15):
1042 request = ITypeInfo_GetDocumentation()
1043 request['memid'] = memid
1044 request['refPtrFlags'] = refPtrFlags
1045 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1046 return resp
1049class IDispatch(IRemUnknown2):
1050 def __init__(self, interface):
1051 IRemUnknown2.__init__(self,interface)
1052 self._iid = IID_IDispatch
1054 def GetTypeInfoCount(self):
1055 request = IDispatch_GetTypeInfoCount()
1056 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1057 return resp
1059 def GetTypeInfo(self):
1060 request = IDispatch_GetTypeInfo()
1061 request['iTInfo'] = 0
1062 request['lcid'] = 0
1063 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1064 return ITypeInfo(INTERFACE(self.get_cinstance(), ''.join(resp['ppTInfo']['abData']), self.get_ipidRemUnknown(), target = self.get_target()))
1066 def GetIDsOfNames(self, rgszNames, lcid = 0):
1067 request = IDispatch_GetIDsOfNames()
1068 request['riid'] = IID_NULL
1069 for name in rgszNames:
1070 tmpName = LPOLESTR()
1071 tmpName['Data'] = checkNullString(name)
1072 request['rgszNames'].append(tmpName)
1073 request['cNames'] = len(rgszNames)
1074 request['lcid'] = lcid
1075 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1076 IDs = list()
1077 for id in resp['rgDispId']:
1078 IDs.append(id)
1080 return IDs
1082 def Invoke(self, dispIdMember, lcid, dwFlags, pDispParams, cVarRef, rgVarRefIdx, rgVarRef):
1083 request = IDispatch_Invoke()
1084 request['dispIdMember'] = dispIdMember
1085 request['riid'] = IID_NULL
1086 request['lcid'] = lcid
1087 request['dwFlags'] = dwFlags
1088 request['pDispParams'] = pDispParams
1089 request['cVarRef'] = cVarRef
1090 request['rgVarRefIdx'] = rgVarRefIdx
1091 request['rgVarRef'] = rgVarRefIdx
1092 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())
1093 return resp