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