Coverage for /root/GitHubProjects/impacket/impacket/dcerpc/v5/dcomrt.py : 82%

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-DCOM] Interface implementation
11#
12# Best way to learn how to use these calls is to grab the protocol standard
13# so you understand what the call does, and then read the test case located
14# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC
15#
16# Some calls have helper functions, which makes it even easier to use.
17# They are located at the end of this file.
18# Helper functions start with "h"<name of the call>.
19# There are test cases for them too.
20#
21# ToDo:
22# [X] Use the same DCE connection for all the calls. Right now is connecting to the remote machine
23# for each call, making it slower.
24#
25# [X] Implement a ping mechanism, otherwise the garbage collector at the server shuts down the objects if
26# not used, returning RPC_E_DISCONNECTED
27#
28from __future__ import division
29from __future__ import print_function
30import socket
31from struct import pack
32from threading import Timer, currentThread
34from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray, NDRTLSTRUCT, UNKNOWNDATA
35from impacket.dcerpc.v5.dtypes import LPWSTR, ULONGLONG, HRESULT, GUID, USHORT, WSTR, DWORD, LPLONG, LONG, PGUID, ULONG, \
36 UUID, WIDESTR, NULL
37from impacket import hresult_errors, LOG
38from impacket.uuid import string_to_bin, uuidtup_to_bin, generate
39from impacket.dcerpc.v5.rpcrt import TypeSerialization1, RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_NONE, \
40 RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_WINNT, DCERPCException
41from impacket.dcerpc.v5 import transport
43CLSID_ActivationContextInfo = string_to_bin('000001a5-0000-0000-c000-000000000046')
44CLSID_ActivationPropertiesIn = string_to_bin('00000338-0000-0000-c000-000000000046')
45CLSID_ActivationPropertiesOut = string_to_bin('00000339-0000-0000-c000-000000000046')
46CLSID_CONTEXT_EXTENSION = string_to_bin('00000334-0000-0000-c000-000000000046')
47CLSID_ContextMarshaler = string_to_bin('0000033b-0000-0000-c000-000000000046')
48CLSID_ERROR_EXTENSION = string_to_bin('0000031c-0000-0000-c000-000000000046')
49CLSID_ErrorObject = string_to_bin('0000031b-0000-0000-c000-000000000046')
50CLSID_InstanceInfo = string_to_bin('000001ad-0000-0000-c000-000000000046')
51CLSID_InstantiationInfo = string_to_bin('000001ab-0000-0000-c000-000000000046')
52CLSID_PropsOutInfo = string_to_bin('00000339-0000-0000-c000-000000000046')
53CLSID_ScmReplyInfo = string_to_bin('000001b6-0000-0000-c000-000000000046')
54CLSID_ScmRequestInfo = string_to_bin('000001aa-0000-0000-c000-000000000046')
55CLSID_SecurityInfo = string_to_bin('000001a6-0000-0000-c000-000000000046')
56CLSID_ServerLocationInfo = string_to_bin('000001a4-0000-0000-c000-000000000046')
57CLSID_SpecialSystemProperties = string_to_bin('000001b9-0000-0000-c000-000000000046')
58IID_IActivation = uuidtup_to_bin(('4d9f4ab8-7d1c-11cf-861e-0020af6e7c57','0.0'))
59IID_IActivationPropertiesIn = uuidtup_to_bin(('000001A2-0000-0000-C000-000000000046','0.0'))
60IID_IActivationPropertiesOut = uuidtup_to_bin(('000001A3-0000-0000-C000-000000000046','0.0'))
61IID_IContext = uuidtup_to_bin(('000001c0-0000-0000-C000-000000000046','0.0'))
62IID_IObjectExporter = uuidtup_to_bin(('99fcfec4-5260-101b-bbcb-00aa0021347a','0.0'))
63IID_IRemoteSCMActivator = uuidtup_to_bin(('000001A0-0000-0000-C000-000000000046','0.0'))
64IID_IRemUnknown = uuidtup_to_bin(('00000131-0000-0000-C000-000000000046','0.0'))
65IID_IRemUnknown2 = uuidtup_to_bin(('00000143-0000-0000-C000-000000000046','0.0'))
66IID_IUnknown = uuidtup_to_bin(('00000000-0000-0000-C000-000000000046','0.0'))
67IID_IClassFactory = uuidtup_to_bin(('00000001-0000-0000-C000-000000000046','0.0'))
69class DCERPCSessionError(DCERPCException):
70 def __init__(self, error_string=None, error_code=None, packet=None):
71 DCERPCException.__init__(self, error_string, error_code, packet)
73 def __str__( self ):
74 if self.error_code in hresult_errors.ERROR_MESSAGES:
75 error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0]
76 error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1]
77 return 'DCOM SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
78 else:
79 return 'DCOM SessionError: unknown error code: 0x%x' % self.error_code
81################################################################################
82# CONSTANTS
83################################################################################
84# 2.2.1 OID
85OID = ULONGLONG
87class OID_ARRAY(NDRUniConformantArray):
88 item = OID
90class POID_ARRAY(NDRPOINTER):
91 referent = (
92 ('Data', OID_ARRAY),
93 )
95# 2.2.2 SETID
96SETID = ULONGLONG
98# 2.2.4 error_status_t
99error_status_t = ULONG
101# 2.2.6 CID
102CID = GUID
104# 2.2.7 CLSID
105CLSID = GUID
107# 2.2.8 IID
108IID = GUID
109PIID = PGUID
111# 2.2.9 IPID
112IPID = GUID
114# 2.2.10 OXID
115OXID = ULONGLONG
117# 2.2.18 OBJREF
118FLAGS_OBJREF_STANDARD = 0x00000001
119FLAGS_OBJREF_HANDLER = 0x00000002
120FLAGS_OBJREF_CUSTOM = 0x00000004
121FLAGS_OBJREF_EXTENDED = 0x00000008
123# 2.2.18.1 STDOBJREF
124SORF_NOPING = 0x00001000
126# 2.2.20 Context
127CTXMSHLFLAGS_BYVAL = 0x00000002
129# 2.2.20.1 PROPMARSHALHEADER
130CPFLAG_PROPAGATE = 0x00000001
131CPFLAG_EXPOSE = 0x00000002
132CPFLAG_ENVOY = 0x00000004
134# 2.2.22.2.1 InstantiationInfoData
135ACTVFLAGS_DISABLE_AAA = 0x00000002
136ACTVFLAGS_ACTIVATE_32_BIT_SERVER = 0x00000004
137ACTVFLAGS_ACTIVATE_64_BIT_SERVER = 0x00000008
138ACTVFLAGS_NO_FAILURE_LOG = 0x00000020
140# 2.2.22.2.2 SpecialPropertiesData
141SPD_FLAG_USE_CONSOLE_SESSION = 0x00000001
143# 2.2.28.1 IDL Range Constants
144MAX_REQUESTED_INTERFACES = 0x8000
145MAX_REQUESTED_PROTSEQS = 0x8000
146MIN_ACTPROP_LIMIT = 1
147MAX_ACTPROP_LIMIT = 10
149################################################################################
150# STRUCTURES
151################################################################################
152class handle_t(NDRSTRUCT):
153 structure = (
154 ('context_handle_attributes',ULONG),
155 ('context_handle_uuid',UUID),
156 )
158 def __init__(self, data=None, isNDR64=False):
159 NDRSTRUCT.__init__(self, data, isNDR64)
160 self['context_handle_uuid'] = b'\x00'*16
162 def isNull(self):
163 return self['context_handle_uuid'] == b'\x00'*16
165# 2.2.11 COMVERSION
166class COMVERSION(NDRSTRUCT):
167 default_major_version = 5
168 default_minor_version = 7
170 structure = (
171 ('MajorVersion',USHORT),
172 ('MinorVersion',USHORT),
173 )
175 @classmethod
176 def set_default_version(cls, major_version=None, minor_version=None):
177 # Set default dcom version for all new COMVERSION objects.
178 if major_version is not None:
179 cls.default_major_version = major_version
180 if minor_version is not None:
181 cls.default_minor_version = minor_version
183 def __init__(self, data = None,isNDR64 = False):
184 NDRSTRUCT.__init__(self, data, isNDR64)
185 if data is None: 185 ↛ exitline 185 didn't return from function '__init__', because the condition on line 185 was never false
186 self['MajorVersion'] = self.default_major_version
187 self['MinorVersion'] = self.default_minor_version
189class PCOMVERSION(NDRPOINTER):
190 referent = (
191 ('Data', COMVERSION),
192 )
194# 2.2.13.1 ORPC_EXTENT
195# This MUST contain an array of bytes that form the extent data.
196# The array size MUST be a multiple of 8 for alignment reasons.
197class BYTE_ARRAY(NDRUniConformantArray):
198 item = 'c'
200class ORPC_EXTENT(NDRSTRUCT):
201 structure = (
202 ('id',GUID),
203 ('size',ULONG),
204 ('data',BYTE_ARRAY),
205 )
207# 2.2.13.2 ORPC_EXTENT_ARRAY
208# ThisMUSTbeanarrayofORPC_EXTENTs.ThearraysizeMUSTbeamultipleof2for alignment reasons.
209class PORPC_EXTENT(NDRPOINTER):
210 referent = (
211 ('Data', ORPC_EXTENT),
212 )
214class EXTENT_ARRAY(NDRUniConformantArray):
215 item = PORPC_EXTENT
217class PEXTENT_ARRAY(NDRPOINTER):
218 referent = (
219 ('Data', EXTENT_ARRAY),
220 )
222class ORPC_EXTENT_ARRAY(NDRSTRUCT):
223 structure = (
224 ('size',ULONG),
225 ('reserved',ULONG),
226 ('extent',PEXTENT_ARRAY),
227 )
229class PORPC_EXTENT_ARRAY(NDRPOINTER):
230 referent = (
231 ('Data', ORPC_EXTENT_ARRAY),
232 )
234# 2.2.13.3 ORPCTHIS
235class ORPCTHIS(NDRSTRUCT):
236 structure = (
237 ('version',COMVERSION),
238 ('flags',ULONG),
239 ('reserved1',ULONG),
240 ('cid',CID),
241 ('extensions',PORPC_EXTENT_ARRAY),
242 )
244# 2.2.13.4 ORPCTHAT
245class ORPCTHAT(NDRSTRUCT):
246 structure = (
247 ('flags',ULONG),
248 ('extensions',PORPC_EXTENT_ARRAY),
249 )
251# 2.2.14 MInterfacePointer
252class MInterfacePointer(NDRSTRUCT):
253 structure = (
254 ('ulCntData',ULONG),
255 ('abData',BYTE_ARRAY),
256 )
258# 2.2.15 PMInterfacePointerInternal
259class PMInterfacePointerInternal(NDRPOINTER):
260 referent = (
261 ('Data', MInterfacePointer),
262 )
264# 2.2.16 PMInterfacePointer
265class PMInterfacePointer(NDRPOINTER):
266 referent = (
267 ('Data', MInterfacePointer),
268 )
270class PPMInterfacePointer(NDRPOINTER):
271 referent = (
272 ('Data', PMInterfacePointer),
273 )
275# 2.2.18 OBJREF
276class OBJREF(NDRSTRUCT):
277 commonHdr = (
278 ('signature',ULONG),
279 ('flags',ULONG),
280 ('iid',GUID),
281 )
282 def __init__(self, data = None,isNDR64 = False):
283 NDRSTRUCT.__init__(self, data, isNDR64)
284 if data is None:
285 self['signature'] = 0x574F454D
287# 2.2.18.1 STDOBJREF
288class STDOBJREF(NDRSTRUCT):
289 structure = (
290 ('flags',ULONG),
291 ('cPublicRefs',ULONG),
292 ('oxid',OXID),
293 ('oid',OID),
294 ('ipid',IPID),
295 )
297# 2.2.18.4 OBJREF_STANDARD
298class OBJREF_STANDARD(OBJREF):
299 structure = (
300 ('std',STDOBJREF),
301 ('saResAddr',':'),
302 )
303 def __init__(self, data = None,isNDR64 = False):
304 OBJREF.__init__(self, data, isNDR64)
305 if data is None: 305 ↛ 306line 305 didn't jump to line 306, because the condition on line 305 was never true
306 self['flags'] = FLAGS_OBJREF_STANDARD
308# 2.2.18.5 OBJREF_HANDLER
309class OBJREF_HANDLER(OBJREF):
310 structure = (
311 ('std',STDOBJREF),
312 ('clsid',CLSID),
313 ('saResAddr',':'),
314 )
315 def __init__(self, data = None,isNDR64 = False):
316 OBJREF.__init__(self, data, isNDR64)
317 if data is None:
318 self['flags'] = FLAGS_OBJREF_HANDLER
320# 2.2.18.6 OBJREF_CUSTOM
321class OBJREF_CUSTOM(OBJREF):
322 structure = (
323 ('clsid',CLSID),
324 ('cbExtension',ULONG),
325 ('ObjectReferenceSize',ULONG),
326 ('pObjectData',':'),
327 )
328 def __init__(self, data = None,isNDR64 = False):
329 OBJREF.__init__(self, data, isNDR64)
330 if data is None:
331 self['flags'] = FLAGS_OBJREF_CUSTOM
333# 2.2.18.8 DATAELEMENT
334class DATAELEMENT(NDRSTRUCT):
335 structure = (
336 ('dataID',GUID),
337 ('cbSize',ULONG),
338 ('cbRounded',ULONG),
339 ('Data',':'),
340 )
342class DUALSTRINGARRAYPACKED(NDRSTRUCT):
343 structure = (
344 ('wNumEntries',USHORT),
345 ('wSecurityOffset',USHORT),
346 ('aStringArray',':'),
347 )
348 def getDataLen(self, data, offset=0):
349 return self['wNumEntries']*2
351# 2.2.18.7 OBJREF_EXTENDED
352class OBJREF_EXTENDED(OBJREF):
353 structure = (
354 ('std',STDOBJREF),
355 ('Signature1',ULONG),
356 ('saResAddr',DUALSTRINGARRAYPACKED),
357 ('nElms',ULONG),
358 ('Signature2',ULONG),
359 ('ElmArray',DATAELEMENT),
360 )
361 def __init__(self, data = None, isNDR64 = False):
362 OBJREF.__init__(self, data, isNDR64)
363 if data is None:
364 self['flags'] = FLAGS_OBJREF_EXTENDED
365 self['Signature1'] = 0x4E535956
366 self['Signature1'] = 0x4E535956
367 self['nElms'] = 0x4E535956
369# 2.2.19 DUALSTRINGARRAY
370class USHORT_ARRAY(NDRUniConformantArray):
371 item = '<H'
373class PUSHORT_ARRAY(NDRPOINTER):
374 referent = (
375 ('Data', USHORT_ARRAY),
376 )
378class DUALSTRINGARRAY(NDRSTRUCT):
379 structure = (
380 ('wNumEntries',USHORT),
381 ('wSecurityOffset',USHORT),
382 ('aStringArray',USHORT_ARRAY),
383 )
385class PDUALSTRINGARRAY(NDRPOINTER):
386 referent = (
387 ('Data',DUALSTRINGARRAY),
388 )
390# 2.2.19.3 STRINGBINDING
391class STRINGBINDING(NDRSTRUCT):
392 structure = (
393 ('wTowerId',USHORT),
394 ('aNetworkAddr',WIDESTR),
395 )
397# 2.2.19.4 SECURITYBINDING
398class SECURITYBINDING(NDRSTRUCT):
399 structure = (
400 ('wAuthnSvc',USHORT),
401 ('Reserved',USHORT),
402 ('aPrincName',WIDESTR),
403 )
405# 2.2.20.1 PROPMARSHALHEADER
406class PROPMARSHALHEADER(NDRSTRUCT):
407 structure = (
408 ('clsid',CLSID),
409 ('policyId',GUID),
410 ('flags',ULONG),
411 ('cb',ULONG),
412 ('ctxProperty',':'),
413 )
415class PROPMARSHALHEADER_ARRAY(NDRUniConformantArray):
416 item = PROPMARSHALHEADER
418# 2.2.20 Context
419class Context(NDRSTRUCT):
420 structure = (
421 ('MajorVersion',USHORT),
422 ('MinVersion',USHORT),
423 ('ContextId',GUID),
424 ('Flags',ULONG),
425 ('Reserved',ULONG),
426 ('dwNumExtents',ULONG),
427 ('cbExtents',ULONG),
428 ('MshlFlags',ULONG),
429 ('Count',ULONG),
430 ('Frozen',ULONG),
431 ('PropMarshalHeader',PROPMARSHALHEADER_ARRAY),
432 )
434# 2.2.21.3 ErrorInfoString
435class ErrorInfoString(NDRSTRUCT):
436 structure = (
437 ('dwMax',ULONG),
438 ('dwOffSet',ULONG),
439 ('dwActual',IID),
440 ('Name',WSTR),
441 )
443# 2.2.21.2 Custom-Marshaled Error Information Format
444class ORPC_ERROR_INFORMATION(NDRSTRUCT):
445 structure = (
446 ('dwVersion',ULONG),
447 ('dwHelpContext',ULONG),
448 ('iid',IID),
449 ('dwSourceSignature',ULONG),
450 ('Source',ErrorInfoString),
451 ('dwDescriptionSignature',ULONG),
452 ('Description',ErrorInfoString),
453 ('dwHelpFileSignature',ULONG),
454 ('HelpFile',ErrorInfoString),
455 )
457# 2.2.21.5 EntryHeader
458class EntryHeader(NDRSTRUCT):
459 structure = (
460 ('Signature',ULONG),
461 ('cbEHBuffer',ULONG),
462 ('cbSize',ULONG),
463 ('reserved',ULONG),
464 ('policyID',GUID),
465 )
467class EntryHeader_ARRAY(NDRUniConformantArray):
468 item = EntryHeader
470# 2.2.21.4 Context ORPC Extension
471class ORPC_CONTEXT(NDRSTRUCT):
472 structure = (
473 ('SignatureVersion',ULONG),
474 ('Version',ULONG),
475 ('cPolicies',ULONG),
476 ('cbBuffer',ULONG),
477 ('cbSize',ULONG),
478 ('hr',ULONG),
479 ('hrServer',ULONG),
480 ('reserved',ULONG),
481 ('EntryHeader',EntryHeader_ARRAY),
482 ('PolicyData',':'),
483 )
484 def __init__(self, data = None, isNDR64 = False):
485 NDRSTRUCT.__init__(self, data, isNDR64)
486 if data is None:
487 self['SignatureVersion'] = 0x414E554B
489# 2.2.22.1 CustomHeader
490class CLSID_ARRAY(NDRUniConformantArray):
491 item = CLSID
493class PCLSID_ARRAY(NDRPOINTER):
494 referent = (
495 ('Data', CLSID_ARRAY),
496 )
498class DWORD_ARRAY(NDRUniConformantArray):
499 item = DWORD
501class PDWORD_ARRAY(NDRPOINTER):
502 referent = (
503 ('Data', DWORD_ARRAY),
504 )
506class CustomHeader(TypeSerialization1):
507 structure = (
508 ('totalSize',DWORD),
509 ('headerSize',DWORD),
510 ('dwReserved',DWORD),
511 ('destCtx',DWORD),
512 ('cIfs',DWORD),
513 ('classInfoClsid',CLSID),
514 ('pclsid',PCLSID_ARRAY),
515 ('pSizes',PDWORD_ARRAY),
516 ('pdwReserved',LPLONG),
517 #('pdwReserved',LONG),
518 )
519 def getData(self, soFar = 0):
520 self['headerSize'] = len(TypeSerialization1.getData(self, soFar)) + len(
521 TypeSerialization1.getDataReferents(self, soFar))
522 self['cIfs'] = len(self['pclsid'])
523 return TypeSerialization1.getData(self, soFar)
525# 2.2.22 Activation Properties BLOB
526class ACTIVATION_BLOB(NDRTLSTRUCT):
527 structure = (
528 ('dwSize',ULONG),
529 ('dwReserved',ULONG),
530 ('CustomHeader',CustomHeader),
531 ('Property',UNKNOWNDATA),
532 )
533 def getData(self, soFar = 0):
534 self['dwSize'] = len(self['CustomHeader'].getData(soFar)) + len(
535 self['CustomHeader'].getDataReferents(soFar)) + len(self['Property'])
536 self['CustomHeader']['totalSize'] = self['dwSize']
537 return NDRTLSTRUCT.getData(self)
539# 2.2.22.2.1 InstantiationInfoData
540class IID_ARRAY(NDRUniConformantArray):
541 item = IID
543class PIID_ARRAY(NDRPOINTER):
544 referent = (
545 ('Data', IID_ARRAY),
546 )
548class InstantiationInfoData(TypeSerialization1):
549 structure = (
550 ('classId',CLSID),
551 ('classCtx',DWORD),
552 ('actvflags',DWORD),
553 ('fIsSurrogate',LONG),
554 ('cIID',DWORD),
555 ('instFlag',DWORD),
556 ('pIID',PIID_ARRAY),
557 ('thisSize',DWORD),
558 ('clientCOMVersion',COMVERSION),
559 )
561# 2.2.22.2.2 SpecialPropertiesData
562class SpecialPropertiesData(TypeSerialization1):
563 structure = (
564 ('dwSessionId',ULONG),
565 ('fRemoteThisSessionId',LONG),
566 ('fClientImpersonating',LONG),
567 ('fPartitionIDPresent',LONG),
568 ('dwDefaultAuthnLvl',DWORD),
569 ('guidPartition',GUID),
570 ('dwPRTFlags',DWORD),
571 ('dwOrigClsctx',DWORD),
572 ('dwFlags',DWORD),
573 ('Reserved0',DWORD),
574 ('Reserved0',DWORD),
575 ('Reserved', '32s=""'),
576 #('Reserved1',DWORD),
577 #('Reserved2',ULONGLONG),
578 #('Reserved3_1',DWORD),
579 #('Reserved3_2',DWORD),
580 #('Reserved3_3',DWORD),
581 #('Reserved3_4',DWORD),
582 #('Reserved3_5',DWORD),
583 )
585# 2.2.22.2.3 InstanceInfoData
586class InstanceInfoData(TypeSerialization1):
587 structure = (
588 ('fileName',LPWSTR),
589 ('mode',DWORD),
590 ('ifdROT',PMInterfacePointer),
591 ('ifdStg',PMInterfacePointer),
592 )
594# 2.2.22.2.4.1 customREMOTE_REQUEST_SCM_INFO
595class customREMOTE_REQUEST_SCM_INFO(NDRSTRUCT):
596 structure = (
597 ('ClientImpLevel',DWORD),
598 ('cRequestedProtseqs',USHORT),
599 ('pRequestedProtseqs',PUSHORT_ARRAY),
600 )
602class PcustomREMOTE_REQUEST_SCM_INFO(NDRPOINTER):
603 referent = (
604 ('Data', customREMOTE_REQUEST_SCM_INFO),
605 )
607# 2.2.22.2.4 ScmRequestInfoData
608class ScmRequestInfoData(TypeSerialization1):
609 structure = (
610 ('pdwReserved',LPLONG),
611 ('remoteRequest',PcustomREMOTE_REQUEST_SCM_INFO),
612 )
614# 2.2.22.2.5 ActivationContextInfoData
615class ActivationContextInfoData(TypeSerialization1):
616 structure = (
617 ('clientOK',LONG),
618 ('bReserved1',LONG),
619 ('dwReserved1',DWORD),
620 ('dwReserved2',DWORD),
621 ('pIFDClientCtx',PMInterfacePointer),
622 ('pIFDPrototypeCtx',PMInterfacePointer),
623 )
625# 2.2.22.2.6 LocationInfoData
626class LocationInfoData(TypeSerialization1):
627 structure = (
628 ('machineName',LPWSTR),
629 ('processId',DWORD),
630 ('apartmentId',DWORD),
631 ('contextId',DWORD),
632 )
634# 2.2.22.2.7.1 COSERVERINFO
635class COSERVERINFO(NDRSTRUCT):
636 structure = (
637 ('dwReserved1',DWORD),
638 ('pwszName',LPWSTR),
639 ('pdwReserved',LPLONG),
640 ('dwReserved2',DWORD),
641 )
643class PCOSERVERINFO(NDRPOINTER):
644 referent = (
645 ('Data', COSERVERINFO),
646 )
648# 2.2.22.2.7 SecurityInfoData
649class SecurityInfoData(TypeSerialization1):
650 structure = (
651 ('dwAuthnFlags',DWORD),
652 ('pServerInfo',PCOSERVERINFO),
653 ('pdwReserved',LPLONG),
654 )
656# 2.2.22.2.8.1 customREMOTE_REPLY_SCM_INFO
657class customREMOTE_REPLY_SCM_INFO(NDRSTRUCT):
658 structure = (
659 ('Oxid',OXID),
660 ('pdsaOxidBindings',PDUALSTRINGARRAY),
661 ('ipidRemUnknown',IPID),
662 ('authnHint',DWORD),
663 ('serverVersion',COMVERSION),
664 )
666class PcustomREMOTE_REPLY_SCM_INFO(NDRPOINTER):
667 referent = (
668 ('Data', customREMOTE_REPLY_SCM_INFO),
669 )
671# 2.2.22.2.8 ScmReplyInfoData
672class ScmReplyInfoData(TypeSerialization1):
673 structure = (
674 ('pdwReserved',DWORD),
675 ('remoteReply',PcustomREMOTE_REPLY_SCM_INFO),
676 )
678# 2.2.22.2.9 PropsOutInfo
679class HRESULT_ARRAY(NDRUniConformantArray):
680 item = HRESULT
682class PHRESULT_ARRAY(NDRPOINTER):
683 referent = (
684 ('Data', HRESULT_ARRAY),
685 )
687class MInterfacePointer_ARRAY(NDRUniConformantArray):
688 item = MInterfacePointer
690class PMInterfacePointer_ARRAY(NDRUniConformantArray):
691 item = PMInterfacePointer
693class PPMInterfacePointer_ARRAY(NDRPOINTER):
694 referent = (
695 ('Data', PMInterfacePointer_ARRAY),
696 )
698class PropsOutInfo(TypeSerialization1):
699 structure = (
700 ('cIfs',DWORD),
701 ('piid',PIID_ARRAY),
702 ('phresults',PHRESULT_ARRAY),
703 ('ppIntfData',PPMInterfacePointer_ARRAY),
704 )
706# 2.2.23 REMINTERFACEREF
707class REMINTERFACEREF(NDRSTRUCT):
708 structure = (
709 ('ipid',IPID),
710 ('cPublicRefs',LONG),
711 ('cPrivateRefs',LONG),
712 )
714class REMINTERFACEREF_ARRAY(NDRUniConformantArray):
715 item = REMINTERFACEREF
717# 2.2.24 REMQIRESULT
718class REMQIRESULT(NDRSTRUCT):
719 structure = (
720 ('hResult',HRESULT),
721 ('std',STDOBJREF),
722 )
724# 2.2.25 PREMQIRESULT
725class PREMQIRESULT(NDRPOINTER):
726 referent = (
727 ('Data', REMQIRESULT),
728 )
730# 2.2.26 REFIPID
731REFIPID = GUID
733################################################################################
734# RPC CALLS
735################################################################################
736class DCOMCALL(NDRCALL):
737 commonHdr = (
738 ('ORPCthis', ORPCTHIS),
739 )
741class DCOMANSWER(NDRCALL):
742 commonHdr = (
743 ('ORPCthat', ORPCTHAT),
744 )
746# 3.1.2.5.1.1 IObjectExporter::ResolveOxid (Opnum 0)
747class ResolveOxid(NDRCALL):
748 opnum = 0
749 structure = (
750 ('pOxid', OXID),
751 ('cRequestedProtseqs', USHORT),
752 ('arRequestedProtseqs', USHORT_ARRAY),
753 )
755class ResolveOxidResponse(NDRCALL):
756 structure = (
757 ('ppdsaOxidBindings', PDUALSTRINGARRAY),
758 ('pipidRemUnknown', IPID),
759 ('pAuthnHint', DWORD),
760 ('ErrorCode', error_status_t),
761 )
763# 3.1.2.5.1.2 IObjectExporter::SimplePing (Opnum 1)
764class SimplePing(NDRCALL):
765 opnum = 1
766 structure = (
767 ('pSetId', SETID),
768 )
770class SimplePingResponse(NDRCALL):
771 structure = (
772 ('ErrorCode', error_status_t),
773 )
775# 3.1.2.5.1.3 IObjectExporter::ComplexPing (Opnum 2)
776class ComplexPing(NDRCALL):
777 opnum = 2
778 structure = (
779 ('pSetId', SETID),
780 ('SequenceNum', USHORT),
781 ('cAddToSet', USHORT),
782 ('cDelFromSet', USHORT),
783 ('AddToSet', POID_ARRAY),
784 ('DelFromSet', POID_ARRAY),
785 )
787class ComplexPingResponse(NDRCALL):
788 structure = (
789 ('pSetId', SETID),
790 ('pPingBackoffFactor', USHORT),
791 ('ErrorCode', error_status_t),
792 )
794# 3.1.2.5.1.4 IObjectExporter::ServerAlive (Opnum 3)
795class ServerAlive(NDRCALL):
796 opnum = 3
797 structure = (
798 )
800class ServerAliveResponse(NDRCALL):
801 structure = (
802 ('ErrorCode', error_status_t),
803 )
805# 3.1.2.5.1.5 IObjectExporter::ResolveOxid2 (Opnum 4)
806class ResolveOxid2(NDRCALL):
807 opnum = 4
808 structure = (
809 ('pOxid', OXID),
810 ('cRequestedProtseqs', USHORT),
811 ('arRequestedProtseqs', USHORT_ARRAY),
812 )
814class ResolveOxid2Response(NDRCALL):
815 structure = (
816 ('ppdsaOxidBindings', PDUALSTRINGARRAY),
817 ('pipidRemUnknown', IPID),
818 ('pAuthnHint', DWORD),
819 ('pComVersion', COMVERSION),
820 ('ErrorCode', error_status_t),
821 )
823# 3.1.2.5.1.6 IObjectExporter::ServerAlive2 (Opnum 5)
824class ServerAlive2(NDRCALL):
825 opnum = 5
826 structure = (
827 )
829class ServerAlive2Response(NDRCALL):
830 structure = (
831 ('pComVersion', COMVERSION),
832 ('ppdsaOrBindings', PDUALSTRINGARRAY),
833 ('pReserved', LPLONG),
834 ('ErrorCode', error_status_t),
835 )
837# 3.1.2.5.2.3.1 IActivation:: RemoteActivation (Opnum 0)
838class RemoteActivation(NDRCALL):
839 opnum = 0
840 structure = (
841 ('ORPCthis', ORPCTHIS),
842 ('Clsid', GUID),
843 ('pwszObjectName', LPWSTR),
844 ('pObjectStorage', PMInterfacePointer),
845 ('ClientImpLevel', DWORD),
846 ('Mode', DWORD),
847 ('Interfaces', DWORD),
848 ('pIIDs', PIID_ARRAY),
849 ('cRequestedProtseqs', USHORT),
850 ('aRequestedProtseqs', USHORT_ARRAY),
851 )
853class RemoteActivationResponse(NDRCALL):
854 structure = (
855 ('ORPCthat', ORPCTHAT),
856 ('pOxid', OXID),
857 ('ppdsaOxidBindings', PDUALSTRINGARRAY),
858 ('pipidRemUnknown', IPID),
859 ('pAuthnHint', DWORD),
860 ('pServerVersion', COMVERSION),
861 ('phr', HRESULT),
862 ('ppInterfaceData', PMInterfacePointer_ARRAY),
863 ('pResults', HRESULT_ARRAY),
864 ('ErrorCode', error_status_t),
865 )
867# 3.1.2.5.2.3.2 IRemoteSCMActivator:: RemoteGetClassObject (Opnum 3)
868class RemoteGetClassObject(NDRCALL):
869 opnum = 3
870 structure = (
871 ('ORPCthis', ORPCTHIS),
872 ('pActProperties', PMInterfacePointer),
873 )
875class RemoteGetClassObjectResponse(NDRCALL):
876 structure = (
877 ('ORPCthat', ORPCTHAT),
878 ('ppActProperties', PMInterfacePointer),
879 ('ErrorCode', error_status_t),
880 )
882# 3.1.2.5.2.3.3 IRemoteSCMActivator::RemoteCreateInstance (Opnum 4)
883class RemoteCreateInstance(NDRCALL):
884 opnum = 4
885 structure = (
886 ('ORPCthis', ORPCTHIS),
887 ('pUnkOuter', PMInterfacePointer),
888 ('pActProperties', PMInterfacePointer),
889 )
891class RemoteCreateInstanceResponse(NDRCALL):
892 structure = (
893 ('ORPCthat', ORPCTHAT),
894 ('ppActProperties', PMInterfacePointer),
895 ('ErrorCode', error_status_t),
896 )
898# 3.1.1.5.6.1.1 IRemUnknown::RemQueryInterface (Opnum 3)
899class RemQueryInterface(DCOMCALL):
900 opnum = 3
901 structure = (
902 ('ripid', REFIPID),
903 ('cRefs', ULONG),
904 ('cIids', USHORT),
905 ('iids', IID_ARRAY),
906 )
908class RemQueryInterfaceResponse(DCOMANSWER):
909 structure = (
910 ('ppQIResults', PREMQIRESULT),
911 ('ErrorCode', error_status_t),
912 )
914# 3.1.1.5.6.1.2 IRemUnknown::RemAddRef (Opnum 4 )
915class RemAddRef(DCOMCALL):
916 opnum = 4
917 structure = (
918 ('cInterfaceRefs', USHORT),
919 ('InterfaceRefs', REMINTERFACEREF_ARRAY),
920 )
922class RemAddRefResponse(DCOMANSWER):
923 structure = (
924 ('pResults', DWORD_ARRAY),
925 ('ErrorCode', error_status_t),
926 )
928# 3.1.1.5.6.1.3 IRemUnknown::RemRelease (Opnum 5)
929class RemRelease(DCOMCALL):
930 opnum = 5
931 structure = (
932 ('cInterfaceRefs', USHORT),
933 ('InterfaceRefs', REMINTERFACEREF_ARRAY),
934 )
936class RemReleaseResponse(DCOMANSWER):
937 structure = (
938 ('ErrorCode', error_status_t),
939 )
941################################################################################
942# OPNUMs and their corresponding structures
943################################################################################
944OPNUMS = {
945}
947################################################################################
948# HELPER FUNCTIONS
949################################################################################
950class DCOMConnection:
951 """
952 This class represents a DCOM Connection. It is in charge of establishing the
953 DCE connection against the portmap, and then launch a thread that will be
954 pinging the objects created against the target.
955 In theory, there should be a single instance of this class for every target
956 """
957 PINGTIMER = None
958 OID_ADD = {}
959 OID_DEL = {}
960 OID_SET = {}
961 PORTMAPS = {}
963 def __init__(self, target, username='', password='', domain='', lmhash='', nthash='', aesKey='', TGT=None, TGS=None,
964 authLevel=RPC_C_AUTHN_LEVEL_PKT_PRIVACY, oxidResolver=False, doKerberos=False, kdcHost=None):
965 self.__target = target
966 self.__userName = username
967 self.__password = password
968 self.__domain = domain
969 self.__lmhash = lmhash
970 self.__nthash = nthash
971 self.__aesKey = aesKey
972 self.__TGT = TGT
973 self.__TGS = TGS
974 self.__authLevel = authLevel
975 self.__portmap = None
976 self.__oxidResolver = oxidResolver
977 self.__doKerberos = doKerberos
978 self.__kdcHost = kdcHost
979 self.initConnection()
981 @classmethod
982 def addOid(cls, target, oid):
983 if (target in DCOMConnection.OID_ADD) is False:
984 DCOMConnection.OID_ADD[target] = set()
985 DCOMConnection.OID_ADD[target].add(oid)
986 if (target in DCOMConnection.OID_SET) is False:
987 DCOMConnection.OID_SET[target] = {}
988 DCOMConnection.OID_SET[target]['oids'] = set()
989 DCOMConnection.OID_SET[target]['setid'] = 0
991 @classmethod
992 def delOid(cls, target, oid):
993 if (target in DCOMConnection.OID_DEL) is False:
994 DCOMConnection.OID_DEL[target] = set()
995 DCOMConnection.OID_DEL[target].add(oid)
996 if (target in DCOMConnection.OID_SET) is False: 996 ↛ 997line 996 didn't jump to line 997, because the condition on line 996 was never true
997 DCOMConnection.OID_SET[target] = {}
998 DCOMConnection.OID_SET[target]['oids'] = set()
999 DCOMConnection.OID_SET[target]['setid'] = 0
1001 @classmethod
1002 def pingServer(cls):
1003 # Here we need to go through all the objects opened and ping them.
1004 # ToDo: locking for avoiding race conditions
1005 #print DCOMConnection.PORTMAPS
1006 #print DCOMConnection.OID_SET
1007 try:
1008 for target in DCOMConnection.OID_SET:
1009 addedOids = set()
1010 deletedOids = set()
1011 if target in DCOMConnection.OID_ADD:
1012 addedOids = DCOMConnection.OID_ADD[target]
1013 del(DCOMConnection.OID_ADD[target])
1015 if target in DCOMConnection.OID_DEL:
1016 deletedOids = DCOMConnection.OID_DEL[target]
1017 del(DCOMConnection.OID_DEL[target])
1019 objExporter = IObjectExporter(DCOMConnection.PORTMAPS[target])
1021 if len(addedOids) > 0 or len(deletedOids) > 0:
1022 if 'setid' in DCOMConnection.OID_SET[target]:
1023 setId = DCOMConnection.OID_SET[target]['setid']
1024 else:
1025 setId = 0
1026 resp = objExporter.ComplexPing(setId, 0, addedOids, deletedOids)
1027 DCOMConnection.OID_SET[target]['oids'] -= deletedOids
1028 DCOMConnection.OID_SET[target]['oids'] |= addedOids
1029 DCOMConnection.OID_SET[target]['setid'] = resp['pSetId']
1030 else:
1031 objExporter.SimplePing(DCOMConnection.OID_SET[target]['setid'])
1032 except Exception as e:
1033 # There might be exceptions when sending packets
1034 # We should try to continue tho.
1035 LOG.error(str(e))
1036 pass
1038 DCOMConnection.PINGTIMER = Timer(120,DCOMConnection.pingServer)
1039 try:
1040 DCOMConnection.PINGTIMER.start()
1041 except Exception as e:
1042 if str(e).find('threads can only be started once') < 0:
1043 raise e
1045 def initTimer(self):
1046 if self.__oxidResolver is True: 1046 ↛ 1047line 1046 didn't jump to line 1047, because the condition on line 1046 was never true
1047 if DCOMConnection.PINGTIMER is None:
1048 DCOMConnection.PINGTIMER = Timer(120, DCOMConnection.pingServer)
1049 try:
1050 DCOMConnection.PINGTIMER.start()
1051 except Exception as e:
1052 if str(e).find('threads can only be started once') < 0:
1053 raise e
1055 def initConnection(self):
1056 stringBinding = r'ncacn_ip_tcp:%s' % self.__target
1057 rpctransport = transport.DCERPCTransportFactory(stringBinding)
1059 if hasattr(rpctransport, 'set_credentials') and len(self.__userName) >=0: 1059 ↛ 1064line 1059 didn't jump to line 1064, because the condition on line 1059 was never false
1060 # This method exists only for selected protocol sequences.
1061 rpctransport.set_credentials(self.__userName, self.__password, self.__domain, self.__lmhash, self.__nthash,
1062 self.__aesKey, self.__TGT, self.__TGS)
1063 rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost)
1064 self.__portmap = rpctransport.get_dce_rpc()
1065 self.__portmap.set_auth_level(self.__authLevel)
1066 if self.__doKerberos is True: 1066 ↛ 1067line 1066 didn't jump to line 1067, because the condition on line 1066 was never true
1067 self.__portmap.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
1068 self.__portmap.connect()
1069 DCOMConnection.PORTMAPS[self.__target] = self.__portmap
1071 def CoCreateInstanceEx(self, clsid, iid):
1072 scm = IRemoteSCMActivator(self.__portmap)
1073 iInterface = scm.RemoteCreateInstance(clsid, iid)
1074 self.initTimer()
1075 return iInterface
1077 def get_dce_rpc(self):
1078 return DCOMConnection.PORTMAPS[self.__target]
1080 def disconnect(self):
1081 if DCOMConnection.PINGTIMER is not None: 1081 ↛ 1082line 1081 didn't jump to line 1082, because the condition on line 1081 was never true
1082 del(DCOMConnection.PORTMAPS[self.__target])
1083 del(DCOMConnection.OID_SET[self.__target])
1084 if len(DCOMConnection.PORTMAPS) == 0:
1085 # This means there are no more clients using this object, kill it
1086 DCOMConnection.PINGTIMER.cancel()
1087 DCOMConnection.PINGTIMER.join()
1088 DCOMConnection.PINGTIMER = None
1089 if self.__target in INTERFACE.CONNECTIONS: 1089 ↛ 1091line 1089 didn't jump to line 1091, because the condition on line 1089 was never false
1090 del(INTERFACE.CONNECTIONS[self.__target][currentThread().getName()])
1091 self.__portmap.disconnect()
1092 #print INTERFACE.CONNECTIONS
1094class CLASS_INSTANCE:
1095 def __init__(self, ORPCthis, stringBinding):
1096 self.__stringBindings = stringBinding
1097 self.__ORPCthis = ORPCthis
1098 self.__authType = RPC_C_AUTHN_WINNT
1099 self.__authLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY
1100 def get_ORPCthis(self):
1101 return self.__ORPCthis
1102 def get_string_bindings(self):
1103 return self.__stringBindings
1104 def get_auth_level(self):
1105 if RPC_C_AUTHN_LEVEL_NONE < self.__authLevel < RPC_C_AUTHN_LEVEL_PKT_PRIVACY: 1105 ↛ 1110line 1105 didn't jump to line 1110, because the condition on line 1105 was never false
1106 if self.__authType == RPC_C_AUTHN_WINNT: 1106 ↛ 1109line 1106 didn't jump to line 1109, because the condition on line 1106 was never false
1107 return RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
1108 else:
1109 return RPC_C_AUTHN_LEVEL_PKT_PRIVACY
1110 return self.__authLevel
1111 def set_auth_level(self, level):
1112 self.__authLevel = level
1113 def get_auth_type(self):
1114 return self.__authType
1115 def set_auth_type(self, authType):
1116 self.__authType = authType
1119class INTERFACE:
1120 # class variable holding the transport connections, organized by target IP
1121 CONNECTIONS = {}
1123 def __init__(self, cinstance=None, objRef=None, ipidRemUnknown=None, iPid=None, oxid=None, oid=None, target=None,
1124 interfaceInstance=None):
1125 if interfaceInstance is not None:
1126 self.__target = interfaceInstance.get_target()
1127 self.__iPid = interfaceInstance.get_iPid()
1128 self.__oid = interfaceInstance.get_oid()
1129 self.__oxid = interfaceInstance.get_oxid()
1130 self.__cinstance = interfaceInstance.get_cinstance()
1131 self.__objRef = interfaceInstance.get_objRef()
1132 self.__ipidRemUnknown = interfaceInstance.get_ipidRemUnknown()
1133 else:
1134 if target is None: 1134 ↛ 1135line 1134 didn't jump to line 1135, because the condition on line 1134 was never true
1135 raise Exception('No target')
1136 self.__target = target
1137 self.__iPid = iPid
1138 self.__oid = oid
1139 self.__oxid = oxid
1140 self.__cinstance = cinstance
1141 self.__objRef = objRef
1142 self.__ipidRemUnknown = ipidRemUnknown
1143 # We gotta check if we have a container inside our connection list, if not, create
1144 if (self.__target in INTERFACE.CONNECTIONS) is not True:
1145 INTERFACE.CONNECTIONS[self.__target] = {}
1146 INTERFACE.CONNECTIONS[self.__target][currentThread().getName()] = {}
1148 if objRef is not None:
1149 self.process_interface(objRef)
1151 def process_interface(self, data):
1152 objRefType = OBJREF(data)['flags']
1153 objRef = None
1154 if objRefType == FLAGS_OBJREF_CUSTOM:
1155 objRef = OBJREF_CUSTOM(data)
1156 elif objRefType == FLAGS_OBJREF_HANDLER: 1156 ↛ 1157line 1156 didn't jump to line 1157, because the condition on line 1156 was never true
1157 objRef = OBJREF_HANDLER(data)
1158 elif objRefType == FLAGS_OBJREF_STANDARD: 1158 ↛ 1160line 1158 didn't jump to line 1160, because the condition on line 1158 was never false
1159 objRef = OBJREF_STANDARD(data)
1160 elif objRefType == FLAGS_OBJREF_EXTENDED:
1161 objRef = OBJREF_EXTENDED(data)
1162 else:
1163 LOG.error("Unknown OBJREF Type! 0x%x" % objRefType)
1165 if objRefType != FLAGS_OBJREF_CUSTOM:
1166 if objRef['std']['flags'] & SORF_NOPING == 0: 1166 ↛ 1168line 1166 didn't jump to line 1168, because the condition on line 1166 was never false
1167 DCOMConnection.addOid(self.__target, objRef['std']['oid'])
1168 self.__iPid = objRef['std']['ipid']
1169 self.__oid = objRef['std']['oid']
1170 self.__oxid = objRef['std']['oxid']
1171 if self.__oxid is None: 1171 ↛ 1172line 1171 didn't jump to line 1172, because the condition on line 1171 was never true
1172 objRef.dump()
1173 raise Exception('OXID is None')
1175 def get_oxid(self):
1176 return self.__oxid
1178 def set_oxid(self, oxid):
1179 self.__oxid = oxid
1181 def get_oid(self):
1182 return self.__oid
1184 def set_oid(self, oid):
1185 self.__oid = oid
1187 def get_target(self):
1188 return self.__target
1190 def get_iPid(self):
1191 return self.__iPid
1193 def set_iPid(self, iPid):
1194 self.__iPid = iPid
1196 def get_objRef(self):
1197 return self.__objRef
1199 def set_objRef(self, objRef):
1200 self.__objRef = objRef
1202 def get_ipidRemUnknown(self):
1203 return self.__ipidRemUnknown
1205 def get_dce_rpc(self):
1206 return INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce']
1208 def get_cinstance(self):
1209 return self.__cinstance
1211 def set_cinstance(self, cinstance):
1212 self.__cinstance = cinstance
1214 def is_fdqn(self):
1215 # I will assume the following
1216 # If I can't socket.inet_aton() then it's not an IPv4 address
1217 # Same for ipv6, but since socket.inet_pton is not available in Windows, I'll look for ':'. There can't be
1218 # an FQDN with ':'
1219 # Is it isn't both, then it is a FDQN
1220 try:
1221 socket.inet_aton(self.__target)
1222 except:
1223 # Not an IPv4
1224 try:
1225 self.__target.index(':')
1226 except:
1227 # Not an IPv6, it's a FDQN
1228 return True
1229 return False
1232 def connect(self, iid = None):
1233 if (self.__target in INTERFACE.CONNECTIONS) is True: 1233 ↛ 1319line 1233 didn't jump to line 1319, because the condition on line 1233 was never false
1234 if currentThread().getName() in INTERFACE.CONNECTIONS[self.__target] and \
1235 (self.__oxid in INTERFACE.CONNECTIONS[self.__target][currentThread().getName()]) is True:
1236 dce = INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce']
1237 currentBinding = INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding']
1238 if currentBinding == iid:
1239 # We don't need to alter_ctx
1240 pass
1241 else:
1242 newDce = dce.alter_ctx(iid)
1243 INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'] = newDce
1244 INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding'] = iid
1245 else:
1246 stringBindings = self.get_cinstance().get_string_bindings()
1247 # No OXID present, we should create a new connection and store it
1248 stringBinding = None
1249 isTargetFDQN = self.is_fdqn()
1250 LOG.debug('Target system is %s and isFDQN is %s' % (self.get_target(), isTargetFDQN))
1251 for strBinding in stringBindings: 1251 ↛ 1281line 1251 didn't jump to line 1281, because the loop on line 1251 didn't complete
1252 # Here, depending on the get_target() value several things can happen
1253 # 1) it's an IPv4 address
1254 # 2) it's an IPv6 address
1255 # 3) it's a NetBios Name
1256 # we should handle all this cases accordingly
1257 # Does this match exactly what get_target() returns?
1258 LOG.debug('StringBinding: %s' % strBinding['aNetworkAddr'])
1259 if strBinding['wTowerId'] == 7:
1260 # If there's port information, let's strip it for now.
1261 if strBinding['aNetworkAddr'].find('[') >= 0: 1261 ↛ 1265line 1261 didn't jump to line 1265, because the condition on line 1261 was never false
1262 binding, _, bindingPort = strBinding['aNetworkAddr'].partition('[')
1263 bindingPort = '[' + bindingPort
1264 else:
1265 binding = strBinding['aNetworkAddr']
1266 bindingPort = ''
1268 if binding.upper().find(self.get_target().upper()) >= 0:
1269 stringBinding = 'ncacn_ip_tcp:' + strBinding['aNetworkAddr'][:-1]
1270 break
1271 # If get_target() is a FQDN, does it match the hostname?
1272 elif isTargetFDQN and binding.upper().find(self.get_target().upper().partition('.')[0]) >= 0: 1272 ↛ 1278line 1272 didn't jump to line 1278, because the condition on line 1272 was never true
1273 # Here we replace the aNetworkAddr with self.get_target()
1274 # This is to help resolving the target system name.
1275 # self.get_target() has been resolved already otherwise we wouldn't be here whereas
1276 # aNetworkAddr is usually the NetBIOS name and unless you have your DNS resolver
1277 # with the right suffixes it will probably not resolve right.
1278 stringBinding = 'ncacn_ip_tcp:%s%s' % (self.get_target(), bindingPort)
1279 break
1281 LOG.debug('StringBinding chosen: %s' % stringBinding)
1282 if stringBinding is None: 1282 ↛ 1284line 1282 didn't jump to line 1284, because the condition on line 1282 was never true
1283 # Something wen't wrong, let's just report it
1284 raise Exception('Can\'t find a valid stringBinding to connect')
1286 dcomInterface = transport.DCERPCTransportFactory(stringBinding)
1287 if hasattr(dcomInterface, 'set_credentials'): 1287 ↛ 1292line 1287 didn't jump to line 1292, because the condition on line 1287 was never false
1288 # This method exists only for selected protocol sequences.
1289 dcomInterface.set_credentials(*DCOMConnection.PORTMAPS[self.__target].get_credentials())
1290 dcomInterface.set_kerberos(DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().get_kerberos(),
1291 DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().get_kdcHost())
1292 dcomInterface.set_connect_timeout(300)
1293 dce = dcomInterface.get_dce_rpc()
1295 if iid is None: 1295 ↛ 1296line 1295 didn't jump to line 1296, because the condition on line 1295 was never true
1296 raise Exception('IID is None')
1297 else:
1298 dce.set_auth_level(self.__cinstance.get_auth_level())
1299 dce.set_auth_type(self.__cinstance.get_auth_type())
1301 dce.connect()
1303 if iid is None: 1303 ↛ 1304line 1303 didn't jump to line 1304, because the condition on line 1303 was never true
1304 raise Exception('IID is None')
1305 else:
1306 dce.bind(iid)
1308 if self.__oxid is None: 1308 ↛ 1311line 1308 didn't jump to line 1311, because the condition on line 1308 was never true
1309 #import traceback
1310 #traceback.print_stack()
1311 raise Exception("OXID NONE, something wrong!!!")
1313 INTERFACE.CONNECTIONS[self.__target][currentThread().getName()] = {}
1314 INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid] = {}
1315 INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'] = dce
1316 INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['currentBinding'] = iid
1317 else:
1318 # No connection created
1319 raise Exception('No connection created')
1321 def request(self, req, iid = None, uuid = None):
1322 req['ORPCthis'] = self.get_cinstance().get_ORPCthis()
1323 req['ORPCthis']['flags'] = 0
1324 self.connect(iid)
1325 dce = self.get_dce_rpc()
1326 try:
1327 resp = dce.request(req, uuid)
1328 except Exception as e:
1329 if str(e).find('RPC_E_DISCONNECTED') >= 0: 1329 ↛ 1330line 1329 didn't jump to line 1330, because the condition on line 1329 was never true
1330 msg = str(e) + '\n'
1331 msg += "DCOM keep-alive pinging it might not be working as expected. You can't be idle for more than 14 minutes!\n"
1332 msg += "You should exit the app and start again\n"
1333 raise DCERPCException(msg)
1334 else:
1335 raise
1336 return resp
1338 def disconnect(self):
1339 return INTERFACE.CONNECTIONS[self.__target][currentThread().getName()][self.__oxid]['dce'].disconnect()
1342# 3.1.1.5.6.1 IRemUnknown Methods
1343class IRemUnknown(INTERFACE):
1344 def __init__(self, interface):
1345 self._iid = IID_IRemUnknown
1346 #INTERFACE.__init__(self, interface.get_cinstance(), interface.get_objRef(), interface.get_ipidRemUnknown(),
1347 # interface.get_iPid(), target=interface.get_target())
1348 INTERFACE.__init__(self, interfaceInstance=interface)
1349 self.set_oxid(interface.get_oxid())
1351 def RemQueryInterface(self, cRefs, iids):
1352 # For now, it only supports a single IID
1353 request = RemQueryInterface()
1354 request['ORPCthis'] = self.get_cinstance().get_ORPCthis()
1355 request['ORPCthis']['flags'] = 0
1356 request['ripid'] = self.get_iPid()
1357 request['cRefs'] = cRefs
1358 request['cIids'] = len(iids)
1359 for iid in iids:
1360 _iid = IID()
1361 _iid['Data'] = iid
1362 request['iids'].append(_iid)
1363 resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown())
1364 #resp.dump()
1366 return IRemUnknown2(
1367 INTERFACE(self.get_cinstance(), None, self.get_ipidRemUnknown(), resp['ppQIResults']['std']['ipid'],
1368 oxid=resp['ppQIResults']['std']['oxid'], oid=resp['ppQIResults']['std']['oxid'],
1369 target=self.get_target()))
1371 def RemAddRef(self):
1372 request = RemAddRef()
1373 request['ORPCthis'] = self.get_cinstance().get_ORPCthis()
1374 request['ORPCthis']['flags'] = 0
1375 request['cInterfaceRefs'] = 1
1376 element = REMINTERFACEREF()
1377 element['ipid'] = self.get_iPid()
1378 element['cPublicRefs'] = 1
1379 request['InterfaceRefs'].append(element)
1380 resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown())
1381 return resp
1383 def RemRelease(self):
1384 request = RemRelease()
1385 request['ORPCthis'] = self.get_cinstance().get_ORPCthis()
1386 request['ORPCthis']['flags'] = 0
1387 request['cInterfaceRefs'] = 1
1388 element = REMINTERFACEREF()
1389 element['ipid'] = self.get_iPid()
1390 element['cPublicRefs'] = 1
1391 request['InterfaceRefs'].append(element)
1392 resp = self.request(request, IID_IRemUnknown, self.get_ipidRemUnknown())
1393 DCOMConnection.delOid(self.get_target(), self.get_oid())
1394 return resp
1396# 3.1.1.5.7 IRemUnknown2 Interface
1397class IRemUnknown2(IRemUnknown):
1398 def __init__(self, interface):
1399 IRemUnknown.__init__(self, interface)
1400 self._iid = IID_IRemUnknown2
1402# 3.1.2.5.1 IObjectExporter Methods
1403class IObjectExporter:
1404 def __init__(self, dce):
1405 self.__portmap = dce
1407 # 3.1.2.5.1.1 IObjectExporter::ResolveOxid (Opnum 0)
1408 def ResolveOxid(self, pOxid, arRequestedProtseqs):
1409 self.__portmap.connect()
1410 self.__portmap.bind(IID_IObjectExporter)
1411 request = ResolveOxid()
1412 request['pOxid'] = pOxid
1413 request['cRequestedProtseqs'] = len(arRequestedProtseqs)
1414 for protSeq in arRequestedProtseqs:
1415 request['arRequestedProtseqs'].append(protSeq)
1416 resp = self.__portmap.request(request)
1417 Oxids = b''.join(pack('<H', x) for x in resp['ppdsaOxidBindings']['aStringArray'])
1418 strBindings = Oxids[:resp['ppdsaOxidBindings']['wSecurityOffset']*2]
1420 done = False
1421 stringBindings = list()
1422 while not done:
1423 if strBindings[0:1] == b'\x00' and strBindings[1:2] == b'\x00':
1424 done = True
1425 else:
1426 binding = STRINGBINDING(strBindings)
1427 stringBindings.append(binding)
1428 strBindings = strBindings[len(binding):]
1430 return stringBindings
1432 # 3.1.2.5.1.2 IObjectExporter::SimplePing (Opnum 1)
1433 def SimplePing(self, setId):
1434 self.__portmap.connect()
1435 self.__portmap.bind(IID_IObjectExporter)
1436 request = SimplePing()
1437 request['pSetId'] = setId
1438 resp = self.__portmap.request(request)
1439 return resp
1441 # 3.1.2.5.1.3 IObjectExporter::ComplexPing (Opnum 2)
1442 def ComplexPing(self, setId = 0, sequenceNum = 0, addToSet = [], delFromSet = []):
1443 self.__portmap.connect()
1444 #self.__portmap.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
1445 self.__portmap.bind(IID_IObjectExporter)
1446 request = ComplexPing()
1447 request['pSetId'] = setId
1448 request['SequenceNum'] = setId
1449 request['cAddToSet'] = len(addToSet)
1450 request['cDelFromSet'] = len(delFromSet)
1451 if len(addToSet) > 0: 1451 ↛ 1452line 1451 didn't jump to line 1452, because the condition on line 1451 was never true
1452 for oid in addToSet:
1453 oidn = OID()
1454 oidn['Data'] = oid
1455 request['AddToSet'].append(oidn)
1456 else:
1457 request['AddToSet'] = NULL
1459 if len(delFromSet) > 0: 1459 ↛ 1460line 1459 didn't jump to line 1460, because the condition on line 1459 was never true
1460 for oid in delFromSet:
1461 oidn = OID()
1462 oidn['Data'] = oid
1463 request['DelFromSet'].append(oidn)
1464 else:
1465 request['DelFromSet'] = NULL
1466 resp = self.__portmap.request(request)
1467 return resp
1469 # 3.1.2.5.1.4 IObjectExporter::ServerAlive (Opnum 3)
1470 def ServerAlive(self):
1471 self.__portmap.connect()
1472 self.__portmap.bind(IID_IObjectExporter)
1473 request = ServerAlive()
1474 resp = self.__portmap.request(request)
1475 return resp
1477 # 3.1.2.5.1.5 IObjectExporter::ResolveOxid2 (Opnum 4)
1478 def ResolveOxid2(self,pOxid, arRequestedProtseqs):
1479 self.__portmap.connect()
1480 self.__portmap.bind(IID_IObjectExporter)
1481 request = ResolveOxid2()
1482 request['pOxid'] = pOxid
1483 request['cRequestedProtseqs'] = len(arRequestedProtseqs)
1484 for protSeq in arRequestedProtseqs:
1485 request['arRequestedProtseqs'].append(protSeq)
1486 resp = self.__portmap.request(request)
1487 Oxids = b''.join(pack('<H', x) for x in resp['ppdsaOxidBindings']['aStringArray'])
1488 strBindings = Oxids[:resp['ppdsaOxidBindings']['wSecurityOffset']*2]
1490 done = False
1491 stringBindings = list()
1492 while not done:
1493 if strBindings[0:1] == b'\x00' and strBindings[1:2] == b'\x00':
1494 done = True
1495 else:
1496 binding = STRINGBINDING(strBindings)
1497 stringBindings.append(binding)
1498 strBindings = strBindings[len(binding):]
1500 return stringBindings
1502 # 3.1.2.5.1.6 IObjectExporter::ServerAlive2 (Opnum 5)
1503 def ServerAlive2(self):
1504 self.__portmap.connect()
1505 self.__portmap.bind(IID_IObjectExporter)
1506 request = ServerAlive2()
1507 resp = self.__portmap.request(request)
1509 Oxids = b''.join(pack('<H', x) for x in resp['ppdsaOrBindings']['aStringArray'])
1510 strBindings = Oxids[:resp['ppdsaOrBindings']['wSecurityOffset']*2]
1512 done = False
1513 stringBindings = list()
1514 while not done:
1515 if strBindings[0:1] == b'\x00' and strBindings[1:2] == b'\x00':
1516 done = True
1517 else:
1518 binding = STRINGBINDING(strBindings)
1519 stringBindings.append(binding)
1520 strBindings = strBindings[len(binding):]
1522 return stringBindings
1524# 3.1.2.5.2.1 IActivation Methods
1525class IActivation:
1526 def __init__(self, dce):
1527 self.__portmap = dce
1529 # 3.1.2.5.2.3.1 IActivation:: RemoteActivation (Opnum 0)
1530 def RemoteActivation(self, clsId, iid):
1531 # Only supports one interface at a time
1532 self.__portmap.bind(IID_IActivation)
1533 ORPCthis = ORPCTHIS()
1534 ORPCthis['cid'] = generate()
1535 ORPCthis['extensions'] = NULL
1536 ORPCthis['flags'] = 1
1538 request = RemoteActivation()
1539 request['Clsid'] = clsId
1540 request['pwszObjectName'] = NULL
1541 request['pObjectStorage'] = NULL
1542 request['ClientImpLevel'] = 2
1543 request['Mode'] = 0
1544 request['Interfaces'] = 1
1546 _iid = IID()
1547 _iid['Data'] = iid
1549 request['pIIDs'].append(_iid)
1550 request['cRequestedProtseqs'] = 1
1551 request['aRequestedProtseqs'].append(7)
1553 resp = self.__portmap.request(request)
1555 # Now let's parse the answer and build an Interface instance
1557 ipidRemUnknown = resp['pipidRemUnknown']
1559 Oxids = b''.join(pack('<H', x) for x in resp['ppdsaOxidBindings']['aStringArray'])
1560 strBindings = Oxids[:resp['ppdsaOxidBindings']['wSecurityOffset']*2]
1561 securityBindings = Oxids[resp['ppdsaOxidBindings']['wSecurityOffset']*2:]
1563 done = False
1564 stringBindings = list()
1565 while not done:
1566 if strBindings[0:1] == b'\x00' and strBindings[1:2] == b'\x00':
1567 done = True
1568 else:
1569 binding = STRINGBINDING(strBindings)
1570 stringBindings.append(binding)
1571 strBindings = strBindings[len(binding):]
1573 done = False
1574 while not done:
1575 if len(securityBindings) < 2: 1575 ↛ 1576line 1575 didn't jump to line 1576, because the condition on line 1575 was never true
1576 done = True
1577 elif securityBindings[0:1] == b'\x00' and securityBindings[1:2 ]== b'\x00':
1578 done = True
1579 else:
1580 secBinding = SECURITYBINDING(securityBindings)
1581 securityBindings = securityBindings[len(secBinding):]
1583 classInstance = CLASS_INSTANCE(ORPCthis, stringBindings)
1584 return IRemUnknown2(INTERFACE(classInstance, b''.join(resp['ppInterfaceData'][0]['abData']), ipidRemUnknown,
1585 target=self.__portmap.get_rpc_transport().getRemoteHost()))
1588# 3.1.2.5.2.2 IRemoteSCMActivator Methods
1589class IRemoteSCMActivator:
1590 def __init__(self, dce):
1591 self.__portmap = dce
1593 def RemoteGetClassObject(self, clsId, iid):
1594 # iid should be IID_IClassFactory
1595 self.__portmap.bind(IID_IRemoteSCMActivator)
1596 ORPCthis = ORPCTHIS()
1597 ORPCthis['cid'] = generate()
1598 ORPCthis['extensions'] = NULL
1599 ORPCthis['flags'] = 1
1601 request = RemoteGetClassObject()
1602 request['ORPCthis'] = ORPCthis
1603 activationBLOB = ACTIVATION_BLOB()
1604 activationBLOB['CustomHeader']['destCtx'] = 2
1605 activationBLOB['CustomHeader']['pdwReserved'] = NULL
1606 clsid = CLSID()
1607 clsid['Data'] = CLSID_InstantiationInfo
1608 activationBLOB['CustomHeader']['pclsid'].append(clsid)
1609 clsid = CLSID()
1610 clsid['Data'] = CLSID_ActivationContextInfo
1611 activationBLOB['CustomHeader']['pclsid'].append(clsid)
1612 clsid = CLSID()
1613 clsid['Data'] = CLSID_ServerLocationInfo
1614 activationBLOB['CustomHeader']['pclsid'].append(clsid)
1615 clsid = CLSID()
1616 clsid['Data'] = CLSID_ScmRequestInfo
1617 activationBLOB['CustomHeader']['pclsid'].append(clsid)
1619 properties = b''
1620 # InstantiationInfo
1621 instantiationInfo = InstantiationInfoData()
1622 instantiationInfo['classId'] = clsId
1623 instantiationInfo['cIID'] = 1
1625 _iid = IID()
1626 _iid['Data'] = iid
1628 instantiationInfo['pIID'].append(_iid)
1630 dword = DWORD()
1631 marshaled = instantiationInfo.getData()+instantiationInfo.getDataReferents()
1632 pad = (8 - (len(marshaled) % 8)) % 8
1633 dword['Data'] = len(marshaled) + pad
1634 activationBLOB['CustomHeader']['pSizes'].append(dword)
1635 instantiationInfo['thisSize'] = dword['Data']
1637 properties += marshaled + b'\xFA'*pad
1639 # ActivationContextInfoData
1640 activationInfo = ActivationContextInfoData()
1641 activationInfo['pIFDClientCtx'] = NULL
1642 activationInfo['pIFDPrototypeCtx'] = NULL
1644 dword = DWORD()
1645 marshaled = activationInfo.getData()+activationInfo.getDataReferents()
1646 pad = (8 - (len(marshaled) % 8)) % 8
1647 dword['Data'] = len(marshaled) + pad
1648 activationBLOB['CustomHeader']['pSizes'].append(dword)
1650 properties += marshaled + b'\xFA'*pad
1652 # ServerLocation
1653 locationInfo = LocationInfoData()
1654 locationInfo['machineName'] = NULL
1656 dword = DWORD()
1657 dword['Data'] = len(locationInfo.getData())
1658 activationBLOB['CustomHeader']['pSizes'].append(dword)
1660 properties += locationInfo.getData()+locationInfo.getDataReferents()
1662 # ScmRequestInfo
1663 scmInfo = ScmRequestInfoData()
1664 scmInfo['pdwReserved'] = NULL
1665 #scmInfo['remoteRequest']['ClientImpLevel'] = 2
1666 scmInfo['remoteRequest']['cRequestedProtseqs'] = 1
1667 scmInfo['remoteRequest']['pRequestedProtseqs'].append(7)
1669 dword = DWORD()
1670 marshaled = scmInfo.getData()+scmInfo.getDataReferents()
1671 pad = (8 - (len(marshaled) % 8)) % 8
1672 dword['Data'] = len(marshaled) + pad
1673 activationBLOB['CustomHeader']['pSizes'].append(dword)
1675 properties += marshaled + b'\xFA'*pad
1677 activationBLOB['Property'] = properties
1680 objrefcustom = OBJREF_CUSTOM()
1681 objrefcustom['iid'] = IID_IActivationPropertiesIn[:-4]
1682 objrefcustom['clsid'] = CLSID_ActivationPropertiesIn
1684 objrefcustom['pObjectData'] = activationBLOB.getData()
1685 objrefcustom['ObjectReferenceSize'] = len(objrefcustom['pObjectData'])+8
1687 request['pActProperties']['ulCntData'] = len(objrefcustom.getData())
1688 request['pActProperties']['abData'] = list(objrefcustom.getData())
1689 resp = self.__portmap.request(request)
1690 # Now let's parse the answer and build an Interface instance
1692 objRefType = OBJREF(b''.join(resp['ppActProperties']['abData']))['flags']
1693 objRef = None
1694 if objRefType == FLAGS_OBJREF_CUSTOM: 1694 ↛ 1696line 1694 didn't jump to line 1696, because the condition on line 1694 was never false
1695 objRef = OBJREF_CUSTOM(b''.join(resp['ppActProperties']['abData']))
1696 elif objRefType == FLAGS_OBJREF_HANDLER:
1697 objRef = OBJREF_HANDLER(b''.join(resp['ppActProperties']['abData']))
1698 elif objRefType == FLAGS_OBJREF_STANDARD:
1699 objRef = OBJREF_STANDARD(b''.join(resp['ppActProperties']['abData']))
1700 elif objRefType == FLAGS_OBJREF_EXTENDED:
1701 objRef = OBJREF_EXTENDED(b''.join(resp['ppActProperties']['abData']))
1702 else:
1703 LOG.error("Unknown OBJREF Type! 0x%x" % objRefType)
1706 activationBlob = ACTIVATION_BLOB(objRef['pObjectData'])
1708 propOutput = activationBlob['Property'][:activationBlob['CustomHeader']['pSizes'][0]['Data']]
1709 scmReply = activationBlob['Property'][
1710 activationBlob['CustomHeader']['pSizes'][0]['Data']:activationBlob['CustomHeader']['pSizes'][0]['Data'] +
1711 activationBlob['CustomHeader']['pSizes'][1]['Data']]
1713 scmr = ScmReplyInfoData()
1714 size = scmr.fromString(scmReply)
1715 # Processing the scmReply
1716 scmr.fromStringReferents(scmReply[size:])
1717 ipidRemUnknown = scmr['remoteReply']['ipidRemUnknown']
1718 Oxids = b''.join(pack('<H', x) for x in scmr['remoteReply']['pdsaOxidBindings']['aStringArray'])
1719 strBindings = Oxids[:scmr['remoteReply']['pdsaOxidBindings']['wSecurityOffset']*2]
1720 securityBindings = Oxids[scmr['remoteReply']['pdsaOxidBindings']['wSecurityOffset']*2:]
1722 done = False
1723 stringBindings = list()
1724 while not done:
1725 if strBindings[0:1] == b'\x00' and strBindings[1:2] == b'\x00':
1726 done = True
1727 else:
1728 binding = STRINGBINDING(strBindings)
1729 stringBindings.append(binding)
1730 strBindings = strBindings[len(binding):]
1732 done = False
1733 while not done:
1734 if len(securityBindings) < 2: 1734 ↛ 1735line 1734 didn't jump to line 1735, because the condition on line 1734 was never true
1735 done = True
1736 elif securityBindings[0:1] == b'\x00' and securityBindings[1:2] == b'\x00':
1737 done = True
1738 else:
1739 secBinding = SECURITYBINDING(securityBindings)
1740 securityBindings = securityBindings[len(secBinding):]
1742 # Processing the Properties Output
1743 propsOut = PropsOutInfo()
1744 size = propsOut.fromString(propOutput)
1745 propsOut.fromStringReferents(propOutput[size:])
1747 classInstance = CLASS_INSTANCE(ORPCthis, stringBindings)
1748 classInstance.set_auth_level(scmr['remoteReply']['authnHint'])
1749 classInstance.set_auth_type(self.__portmap.get_auth_type())
1750 return IRemUnknown2(INTERFACE(classInstance, b''.join(propsOut['ppIntfData'][0]['abData']), ipidRemUnknown,
1751 target=self.__portmap.get_rpc_transport().getRemoteHost()))
1753 def RemoteCreateInstance(self, clsId, iid):
1754 # Only supports one interface at a time
1755 self.__portmap.bind(IID_IRemoteSCMActivator)
1757 ORPCthis = ORPCTHIS()
1758 ORPCthis['cid'] = generate()
1759 ORPCthis['extensions'] = NULL
1760 ORPCthis['flags'] = 1
1762 request = RemoteCreateInstance()
1763 request['ORPCthis'] = ORPCthis
1764 request['pUnkOuter'] = NULL
1766 activationBLOB = ACTIVATION_BLOB()
1767 activationBLOB['CustomHeader']['destCtx'] = 2
1768 activationBLOB['CustomHeader']['pdwReserved'] = NULL
1769 clsid = CLSID()
1770 clsid['Data'] = CLSID_InstantiationInfo
1771 activationBLOB['CustomHeader']['pclsid'].append(clsid)
1772 clsid = CLSID()
1773 clsid['Data'] = CLSID_ActivationContextInfo
1774 activationBLOB['CustomHeader']['pclsid'].append(clsid)
1775 clsid = CLSID()
1776 clsid['Data'] = CLSID_ServerLocationInfo
1777 activationBLOB['CustomHeader']['pclsid'].append(clsid)
1778 clsid = CLSID()
1779 clsid['Data'] = CLSID_ScmRequestInfo
1780 activationBLOB['CustomHeader']['pclsid'].append(clsid)
1782 properties = b''
1783 # InstantiationInfo
1784 instantiationInfo = InstantiationInfoData()
1785 instantiationInfo['classId'] = clsId
1786 instantiationInfo['cIID'] = 1
1788 _iid = IID()
1789 _iid['Data'] = iid
1791 instantiationInfo['pIID'].append(_iid)
1793 dword = DWORD()
1794 marshaled = instantiationInfo.getData()+instantiationInfo.getDataReferents()
1795 pad = (8 - (len(marshaled) % 8)) % 8
1796 dword['Data'] = len(marshaled) + pad
1797 activationBLOB['CustomHeader']['pSizes'].append(dword)
1798 instantiationInfo['thisSize'] = dword['Data']
1800 properties += marshaled + b'\xFA'*pad
1802 # ActivationContextInfoData
1803 activationInfo = ActivationContextInfoData()
1804 activationInfo['pIFDClientCtx'] = NULL
1805 activationInfo['pIFDPrototypeCtx'] = NULL
1807 dword = DWORD()
1808 marshaled = activationInfo.getData()+activationInfo.getDataReferents()
1809 pad = (8 - (len(marshaled) % 8)) % 8
1810 dword['Data'] = len(marshaled) + pad
1811 activationBLOB['CustomHeader']['pSizes'].append(dword)
1813 properties += marshaled + b'\xFA'*pad
1815 # ServerLocation
1816 locationInfo = LocationInfoData()
1817 locationInfo['machineName'] = NULL
1819 dword = DWORD()
1820 dword['Data'] = len(locationInfo.getData())
1821 activationBLOB['CustomHeader']['pSizes'].append(dword)
1823 properties += locationInfo.getData()+locationInfo.getDataReferents()
1825 # ScmRequestInfo
1826 scmInfo = ScmRequestInfoData()
1827 scmInfo['pdwReserved'] = NULL
1828 #scmInfo['remoteRequest']['ClientImpLevel'] = 2
1829 scmInfo['remoteRequest']['cRequestedProtseqs'] = 1
1830 scmInfo['remoteRequest']['pRequestedProtseqs'].append(7)
1832 dword = DWORD()
1833 marshaled = scmInfo.getData()+scmInfo.getDataReferents()
1834 pad = (8 - (len(marshaled) % 8)) % 8
1835 dword['Data'] = len(marshaled) + pad
1836 activationBLOB['CustomHeader']['pSizes'].append(dword)
1838 properties += marshaled + b'\xFA'*pad
1840 activationBLOB['Property'] = properties
1843 objrefcustom = OBJREF_CUSTOM()
1844 objrefcustom['iid'] = IID_IActivationPropertiesIn[:-4]
1845 objrefcustom['clsid'] = CLSID_ActivationPropertiesIn
1847 objrefcustom['pObjectData'] = activationBLOB.getData()
1848 objrefcustom['ObjectReferenceSize'] = len(objrefcustom['pObjectData'])+8
1850 request['pActProperties']['ulCntData'] = len(objrefcustom.getData())
1851 request['pActProperties']['abData'] = list(objrefcustom.getData())
1852 resp = self.__portmap.request(request)
1854 # Now let's parse the answer and build an Interface instance
1856 objRefType = OBJREF(b''.join(resp['ppActProperties']['abData']))['flags']
1857 objRef = None
1858 if objRefType == FLAGS_OBJREF_CUSTOM: 1858 ↛ 1860line 1858 didn't jump to line 1860, because the condition on line 1858 was never false
1859 objRef = OBJREF_CUSTOM(b''.join(resp['ppActProperties']['abData']))
1860 elif objRefType == FLAGS_OBJREF_HANDLER:
1861 objRef = OBJREF_HANDLER(b''.join(resp['ppActProperties']['abData']))
1862 elif objRefType == FLAGS_OBJREF_STANDARD:
1863 objRef = OBJREF_STANDARD(b''.join(resp['ppActProperties']['abData']))
1864 elif objRefType == FLAGS_OBJREF_EXTENDED:
1865 objRef = OBJREF_EXTENDED(b''.join(resp['ppActProperties']['abData']))
1866 else:
1867 LOG.error("Unknown OBJREF Type! 0x%x" % objRefType)
1870 activationBlob = ACTIVATION_BLOB(objRef['pObjectData'])
1872 propOutput = activationBlob['Property'][:activationBlob['CustomHeader']['pSizes'][0]['Data']]
1873 scmReply = activationBlob['Property'][
1874 activationBlob['CustomHeader']['pSizes'][0]['Data']:activationBlob['CustomHeader']['pSizes'][0]['Data'] +
1875 activationBlob['CustomHeader']['pSizes'][1]['Data']]
1877 scmr = ScmReplyInfoData()
1878 size = scmr.fromString(scmReply)
1879 # Processing the scmReply
1880 scmr.fromStringReferents(scmReply[size:])
1881 ipidRemUnknown = scmr['remoteReply']['ipidRemUnknown']
1882 Oxids = b''.join(pack('<H', x) for x in scmr['remoteReply']['pdsaOxidBindings']['aStringArray'])
1883 strBindings = Oxids[:scmr['remoteReply']['pdsaOxidBindings']['wSecurityOffset']*2]
1884 securityBindings = Oxids[scmr['remoteReply']['pdsaOxidBindings']['wSecurityOffset']*2:]
1886 done = False
1887 stringBindings = list()
1888 while not done:
1889 if strBindings[0:1] == b'\x00' and strBindings[1:2] == b'\x00':
1890 done = True
1891 else:
1892 binding = STRINGBINDING(strBindings)
1893 stringBindings.append(binding)
1894 strBindings = strBindings[len(binding):]
1896 done = False
1897 while not done:
1898 if len(securityBindings) < 2: 1898 ↛ 1899line 1898 didn't jump to line 1899, because the condition on line 1898 was never true
1899 done = True
1900 elif securityBindings[0:1] == b'\x00' and securityBindings[1:2] == b'\x00':
1901 done = True
1902 else:
1903 secBinding = SECURITYBINDING(securityBindings)
1904 securityBindings = securityBindings[len(secBinding):]
1906 # Processing the Properties Output
1907 propsOut = PropsOutInfo()
1908 size = propsOut.fromString(propOutput)
1909 propsOut.fromStringReferents(propOutput[size:])
1911 classInstance = CLASS_INSTANCE(ORPCthis, stringBindings)
1912 classInstance.set_auth_level(scmr['remoteReply']['authnHint'])
1913 classInstance.set_auth_type(self.__portmap.get_auth_type())
1914 return IRemUnknown2(INTERFACE(classInstance, b''.join(propsOut['ppIntfData'][0]['abData']), ipidRemUnknown,
1915 target=self.__portmap.get_rpc_transport().getRemoteHost()))