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