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

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

## 477 statements

Hot-keys on this page

r m x p toggle line displays

j k next/prev highlighted chunk

0 (zero) top of page

1 (one) first highlighted chunk

1# Impacket - Collection of Python classes for working with network protocols.

2#

3# SECUREAUTH LABS. Copyright (C) 2018 SecureAuth Corporation. All rights reserved.

4#

5# This software is provided under a slightly modified version

6# of the Apache Software License. See the accompanying LICENSE file

7# for more information.

8#

9# Description:

10# [MS-OAUT]: OLE Automation Protocol Implementation

11# This was used as a way to test the DCOM runtime. Further

12# testing is needed to verify it is working as expected

13#

14# Best way to learn how to use these calls is to grab the protocol standard

15# so you understand what the call does, and then read the test case located

16# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC

17#

18# Since DCOM is like an OO RPC, instead of helper functions you will see the

19# classes described in the standards developed.

20# There are test cases for them too.

21#

22# Author:

23# Alberto Solino (@agsolino)

24#

25 from __future__ import division

26 from __future__ import print_function

27 import random

28 from struct import pack, unpack

29

30 from impacket import LOG

31 from impacket import hresult_errors

32 from impacket.dcerpc.v5.dcomrt import DCOMCALL, DCOMANSWER, IRemUnknown2, PMInterfacePointer, INTERFACE, \

33 MInterfacePointer, MInterfacePointer_ARRAY, BYTE_ARRAY, PPMInterfacePointer

34 from impacket.dcerpc.v5.dtypes import LPWSTR, ULONG, DWORD, SHORT, GUID, USHORT, LONG, WSTR, BYTE, LONGLONG, FLOAT, \

35 DOUBLE, HRESULT, PSHORT, PLONG, PLONGLONG, PFLOAT, PDOUBLE, PHRESULT, CHAR, ULONGLONG, INT, UINT, PCHAR, PUSHORT, \

36 PULONG, PULONGLONG, PINT, PUINT, NULL

37 from impacket.dcerpc.v5.enum import Enum

38 from impacket.dcerpc.v5.ndr import NDRSTRUCT, NDRUniConformantArray, NDRPOINTER, NDRENUM, NDRUSHORT, NDRUNION, \

39 NDRUniConformantVaryingArray, NDR

40 from impacket.dcerpc.v5.rpcrt import DCERPCException

41 from impacket.uuid import string_to_bin

42

43 class DCERPCSessionError(DCERPCException):

44 def __init__(self, error_string=None, error_code=None, packet=None):

45 DCERPCException.__init__(self, error_string, error_code, packet)

46

47 def __str__( self ):

48 if self.error_code in hresult_errors.ERROR_MESSAGES:

49 error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0]

50 error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1]

51 return 'OAUT SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)

52 else:

53 return 'OAUT SessionError: unknown error code: 0x%x' % (self.error_code)

54

55################################################################################

56# CONSTANTS

57################################################################################

58# 1.9 Standards Assignments

59 IID_IDispatch = string_to_bin('00020400-0000-0000-C000-000000000046')

60 IID_ITypeInfo = string_to_bin('00020401-0000-0000-C000-000000000046')

61 IID_ITypeComp = string_to_bin('00020403-0000-0000-C000-000000000046')

62 IID_NULL = string_to_bin('00000000-0000-0000-0000-000000000000')

63

64 error_status_t = ULONG

65

66 LCID = DWORD

67 WORD = NDRUSHORT

68

69# 2.2.2 IID

70 IID = GUID

71

72# 2.2.3 LPOLESTR

73 LPOLESTR = LPWSTR

74 OLESTR = WSTR

75

76# 2.2.4 REFIID

77 REFIID = IID

78

79# 2.2.25 DATE

80 DATE = DOUBLE

81 class PDATE(NDRPOINTER):

82 referent = (

83 ('Data', DATE),

84 )

85

86# 2.2.27 VARIANT_BOOL

87 VARIANT_BOOL = USHORT

88

89 class PVARIANT_BOOL(NDRPOINTER):

90 referent = (

91 ('Data', VARIANT_BOOL),

92 )

93

94# 3.1.4.4 IDispatch::Invoke (Opnum 6)

95# dwFlags

96 DISPATCH_METHOD = 0x00000001

97 DISPATCH_PROPERTYGET = 0x00000002

98 DISPATCH_PROPERTYPUT = 0x00000004

99 DISPATCH_PROPERTYPUTREF = 0x00000008

100 DISPATCH_zeroVarResult = 0x00020000

101 DISPATCH_zeroExcepInfo = 0x00040000

102 DISPATCH_zeroArgErr = 0x00080000

103

104################################################################################

105# STRUCTURES

106################################################################################

107# 2.2.26 DECIMAL

108 class DECIMAL(NDRSTRUCT):

109 structure = (

110 ('wReserved',WORD),

111 ('scale',BYTE),

112 ('sign',BYTE),

113 ('Hi32',ULONG),

114 ('Lo64',ULONGLONG),

115 )

116

117 class PDECIMAL(NDRPOINTER):

118 referent = (

119 ('Data', DECIMAL),

120 )

121

122# 2.2.7 VARIANT Type Constants

123 class VARENUM(NDRENUM):

124 class enumItems(Enum):

125 VT_EMPTY = 0

126 VT_NULL = 1

127 VT_I2 = 2

128 VT_I4 = 3

129 VT_R4 = 4

130 VT_R8 = 5

131 VT_CY = 6

132 VT_DATE = 7

133 VT_BSTR = 8

134 VT_DISPATCH = 9

135 VT_ERROR = 0xa

136 VT_BOOL = 0xb

137 VT_VARIANT = 0xc

138 VT_UNKNOWN = 0xd

139 VT_DECIMAL = 0xe

140 VT_I1 = 0x10

141 VT_UI1 = 0x11

142 VT_UI2 = 0x12

143 VT_UI4 = 0x13

144 VT_I8 = 0x14

145 VT_UI8 = 0x15

146 VT_INT = 0x16

147 VT_UINT = 0x17

148 VT_VOID = 0x18

149 VT_HRESULT = 0x19

150 VT_PTR = 0x1a

151 VT_SAFEARRAY = 0x1b

152 VT_CARRAY = 0x1c

153 VT_USERDEFINED = 0x1d

154 VT_LPSTR = 0x1e

155 VT_LPWSTR = 0x1f

156 VT_RECORD = 0x24

157 VT_INT_PTR = 0x25

158 VT_UINT_PTR = 0x26

159 VT_ARRAY = 0x2000

160 VT_BYREF = 0x4000

161 VT_RECORD_OR_VT_BYREF = VT_RECORD | VT_BYREF

162 VT_UI1_OR_VT_BYREF = VT_UI1 | VT_BYREF

163 VT_I2_OR_VT_BYREF = VT_I2 | VT_BYREF

164 VT_I4_OR_VT_BYREF = VT_I4 | VT_BYREF

165 VT_I8_OR_VT_BYREF = VT_I8 | VT_BYREF

166 VT_R4_OR_VT_BYREF = VT_R4 | VT_BYREF

167 VT_R8_OR_VT_BYREF = VT_R8 | VT_BYREF

168 VT_BOOL_OR_VT_BYREF = VT_BOOL | VT_BYREF

169 VT_ERROR_OR_VT_BYREF = VT_ERROR | VT_BYREF

170 VT_CY_OR_VT_BYREF = VT_CY | VT_BYREF

171 VT_DATE_OR_VT_BYREF = VT_DATE | VT_BYREF

172 VT_BSTR_OR_VT_BYREF = VT_BSTR | VT_BYREF

173 VT_UNKNOWN_OR_VT_BYREF = VT_UNKNOWN | VT_BYREF

174 VT_DISPATCH_OR_VT_BYREF = VT_DISPATCH | VT_BYREF

175 VT_ARRAY_OR_VT_BYREF = VT_ARRAY | VT_BYREF

176 VT_VARIANT_OR_VT_BYREF = VT_VARIANT| VT_BYREF

177 VT_I1_OR_VT_BYREF = VT_I1 | VT_BYREF

178 VT_UI2_OR_VT_BYREF = VT_UI2 | VT_BYREF

179 VT_UI4_OR_VT_BYREF = VT_UI4 | VT_BYREF

180 VT_UI8_OR_VT_BYREF = VT_UI8 | VT_BYREF

181 VT_INT_OR_VT_BYREF = VT_INT | VT_BYREF

182 VT_UINT_OR_VT_BYREF = VT_UINT | VT_BYREF

183 VT_DECIMAL_OR_VT_BYREF = VT_DECIMAL | VT_BYREF

184

185# 2.2.8 SAFEARRAY Feature Constants

186 class SF_TYPE(NDRENUM):

187 # [v1_enum] type

188 structure = (

189 ('Data', '<L'),

190 )

191 class enumItems(Enum):

192 SF_ERROR = VARENUM.VT_ERROR

193 SF_I1 = VARENUM.VT_I1

194 SF_I2 = VARENUM.VT_I2

195 SF_I4 = VARENUM.VT_I4

196 SF_I8 = VARENUM.VT_I8

197 SF_BSTR = VARENUM.VT_BSTR

198 SF_UNKNOWN = VARENUM.VT_UNKNOWN

199 SF_DISPATCH = VARENUM.VT_DISPATCH

200 SF_VARIANT = VARENUM.VT_VARIANT

201 SF_RECORD = VARENUM.VT_RECORD

202 SF_HAVEIID = VARENUM.VT_UNKNOWN | 0x8000

203

204# 2.2.10 CALLCONV Calling Convention Constants

205 class CALLCONV(NDRENUM):

206 # [v1_enum] type

207 structure = (

208 ('Data', '<L'),

209 )

210 class enumItems(Enum):

211 CC_CDECL = 1

212 CC_PASCAL = 2

213 CC_STDCALL = 4

214

215

216# 2.2.12 FUNCKIND Function Access Constants

217 class FUNCKIND(NDRENUM):

218 # [v1_enum] type

219 structure = (

220 ('Data', '<L'),

221 )

222 class enumItems(Enum):

223 FUNC_PUREVIRTUAL = 1

224 FUNC_STATIC = 3

225 FUNC_DISPATCH = 4

226

227# 2.2.14 INVOKEKIND Function Invocation Constants

228 class INVOKEKIND(NDRENUM):

229 # [v1_enum] type

230 structure = (

231 ('Data', '<L'),

232 )

233 class enumItems(Enum):

234 INVOKE_FUNC = 1

235 INVOKE_PROPERTYGET = 2

236 INVOKE_PROPERTYPUT = 4

237 INVOKE_PROPERTYPUTREF = 8

238

239# 2.2.17 TYPEKIND Type Kind Constants

240 class TYPEKIND(NDRENUM):

241 # [v1_enum] type

242 structure = (

243 ('Data', '<L'),

244 )

245 class enumItems(Enum):

246 TKIND_ENUM = 0

247 TKIND_RECORD = 1

248 TKIND_MODULE = 2

249 TKIND_INTERFACE = 3

250 TKIND_DISPATCH = 4

251 TKIND_COCLASS = 5

252 TKIND_ALIAS = 6

253 TKIND_UNION = 7

254

255# 2.2.23 BSTR

256# 2.2.23.1 FLAGGED_WORD_BLOB

257 class USHORT_ARRAY(NDRUniConformantArray):

258 item = '<H'

259

260 class FLAGGED_WORD_BLOB(NDRSTRUCT):

261 structure = (

262 ('cBytes',ULONG),

263 ('clSize',ULONG),

264 ('asData',USHORT_ARRAY),

265 )

266 def __setitem__(self, key, value):

267 if key == 'asData':

268 value = value #+ '\x00'

269 array = list()

270 for letter in value:

271 encoded = letter.encode('utf-16le')

272 array.append(unpack('<H', encoded)[0])

273 self.fields[key]['Data'] = array

274 self['cBytes'] = len(value)*2

275 self['clSize'] = len(value)

276 self.data = None # force recompute

277 else:

278 return NDRSTRUCT.__setitem__(self, key, value)

279

280 def __getitem__(self, key):

281 if key == 'asData':

282 value = ''

283 for letter in self.fields['asData']['Data']:

284 value += pack('<H', letter).decode('utf-16le')

285 return value

286 else:

287 return NDRSTRUCT.__getitem__(self,key)

288

289 def dump(self, msg = None, indent = 0):

290 if msg is None: msg = self.__class__.__name__

291 ind = ' '*indent

292 if msg != '':

293 print("%s" % (msg))

294 value = ''

295 print('%sasData: %s' % (ind,self['asData']), end=' ')

296

297# 2.2.23.2 BSTR Type Definition

298 class BSTR(NDRPOINTER):

299 referent = (

300 ('Data', FLAGGED_WORD_BLOB),

301 )

302

303 class PBSTR(NDRPOINTER):

304 referent = (

305 ('Data', BSTR),

306 )

307

308# 2.2.24 CURRENCY

309 class CURRENCY(NDRSTRUCT):

310 structure = (

311 ('int64', LONGLONG),

312 )

313

314 class PCURRENCY(NDRPOINTER):

315 referent = (

316 ('Data', CURRENCY),

317 )

318

319# 2.2.28.2 BRECORD

320# 2.2.28.2.1 _wireBRECORD

321 class _wireBRECORD(NDRSTRUCT):

322 structure = (

323 ('fFlags', LONGLONG),

324 ('clSize', LONGLONG),

325 ('pRecInfo', MInterfacePointer),

326 ('pRecord', BYTE_ARRAY),

327 )

328

329 class BRECORD(NDRPOINTER):

330 referent = (

331 ('Data', _wireBRECORD),

332 )

333

334# 2.2.30 SAFEARRAY

335# 2.2.30.1 SAFEARRAYBOUND

336 class SAFEARRAYBOUND(NDRSTRUCT):

337 structure = (

338 ('cElements', ULONG),

339 ('lLbound', LONG),

340 )

341

342 class PSAFEARRAYBOUND(NDRPOINTER):

343 referent = (

344 ('Data', SAFEARRAYBOUND),

345 )

346

347# 2.2.30.2 SAFEARR_BSTR

348 class BSTR_ARRAY(NDRUniConformantArray):

349 item = BSTR

350

351 class PBSTR_ARRAY(NDRPOINTER):

352 referent = (

353 ('Data', BSTR_ARRAY),

354 )

355

356 class SAFEARR_BSTR(NDRSTRUCT):

357 structure = (

358 ('Size', ULONG),

359 ('aBstr', PBSTR_ARRAY),

360 )

361

362# 2.2.30.3 SAFEARR_UNKNOWN

363 class SAFEARR_UNKNOWN(NDRSTRUCT):

364 structure = (

365 ('Size', ULONG),

366 ('apUnknown', MInterfacePointer_ARRAY),

367 )

368

369# 2.2.30.4 SAFEARR_DISPATCH

370 class SAFEARR_DISPATCH(NDRSTRUCT):

371 structure = (

372 ('Size', ULONG),

373 ('apDispatch', MInterfacePointer_ARRAY),

374 )

375

376# 2.2.30.6 SAFEARR_BRECORD

377 class BRECORD_ARRAY(NDRUniConformantArray):

378 item = BRECORD

379

380 class SAFEARR_BRECORD(NDRSTRUCT):

381 structure = (

382 ('Size', ULONG),

383 ('aRecord', BRECORD_ARRAY),

384 )

385

386# 2.2.30.7 SAFEARR_HAVEIID

387 class SAFEARR_HAVEIID(NDRSTRUCT):

388 structure = (

389 ('Size', ULONG),

390 ('apUnknown', MInterfacePointer_ARRAY),

391 ('iid', IID),

392 )

393

394# 2.2.30.8 Scalar-Sized Arrays

395# 2.2.30.8.1 BYTE_SIZEDARR

396 class BYTE_SIZEDARR(NDRSTRUCT):

397 structure = (

398 ('clSize', ULONG),

399 ('pData', BYTE_ARRAY),

400 )

401

402# 2.2.30.8.2 WORD_SIZEDARR

403 class WORD_ARRAY(NDRUniConformantArray):

404 item = '<H'

405

406 class WORD_SIZEDARR(NDRSTRUCT):

407 structure = (

408 ('clSize', ULONG),

409 ('pData', WORD_ARRAY),

410 )

411

412# 2.2.30.8.3 DWORD_SIZEDARR

413 class DWORD_ARRAY(NDRUniConformantArray):

414 item = '<L'

415

416 class DWORD_SIZEDARR(NDRSTRUCT):

417 structure = (

418 ('clSize', ULONG),

419 ('pData', DWORD_ARRAY),

420 )

421

422# 2.2.30.8.4 HYPER_SIZEDARR

423 class HYPER_ARRAY(NDRUniConformantArray):

424 item = '<Q'

425

426 class HYPER_SIZEDARR(NDRSTRUCT):

427 structure = (

428 ('clSize', ULONG),

429 ('pData', HYPER_ARRAY),

430 )

431

432

433# 2.2.36 HREFTYPE

434 HREFTYPE = DWORD

435

436# 2.2.30.5 SAFEARR_VARIANT

437 class VARIANT_ARRAY(NDRUniConformantArray):

438 # In order to avoid the lack of forward declarations in Python

439 # I declare the item in the constructor

440 #item = VARIANT

441 def __init__(self, data = None, isNDR64 = False):

442 NDRUniConformantArray.__init__(self, data, isNDR64)

443 self.item = VARIANT

444

445 class PVARIANT_ARRAY(NDRPOINTER):

446 referent = (

447 ('Data', VARIANT_ARRAY),

448 )

449

450 class PVARIANT(NDRPOINTER):

451 # In order to avoid the lack of forward declarations in Python

452 # I declare the item in the constructor

453 #referent = (

454 # ('Data', VARIANT),

455 #)

456 def __init__(self, data = None, isNDR64 = False):

457 NDRPOINTER.__init__(self, data, isNDR64)

458 self.referent = ( ('Data', VARIANT),)

459

460

461 class SAFEARR_VARIANT(NDRSTRUCT):

462 structure = (

463 ('Size', ULONG),

464 ('aVariant', VARIANT_ARRAY),

465 )

466

467# 2.2.30.9 SAFEARRAYUNION

468 class SAFEARRAYUNION(NDRUNION):

469 commonHdr = (

470 ('tag', ULONG),

471 )

472 union = {

473 SF_TYPE.SF_BSTR : ('BstrStr', SAFEARR_BSTR),

474 SF_TYPE.SF_UNKNOWN : ('UnknownStr', SAFEARR_UNKNOWN),

475 SF_TYPE.SF_DISPATCH : ('DispatchStr', SAFEARR_DISPATCH),

476 SF_TYPE.SF_VARIANT : ('VariantStr', SAFEARR_VARIANT),

477 SF_TYPE.SF_RECORD : ('RecordStr', SAFEARR_BRECORD),

478 SF_TYPE.SF_HAVEIID : ('HaveIidStr', SAFEARR_HAVEIID),

479 SF_TYPE.SF_I1 : ('ByteStr', BYTE_SIZEDARR),

480 SF_TYPE.SF_I2 : ('WordStr', WORD_SIZEDARR),

481 SF_TYPE.SF_I4 : ('LongStr', DWORD_SIZEDARR),

482 SF_TYPE.SF_I8 : ('HyperStr', HYPER_SIZEDARR),

483 }

484

485# 2.2.30.10 SAFEARRAY

486 class SAFEARRAYBOUND_ARRAY(NDRUniConformantArray):

487 item = SAFEARRAYBOUND

488

489 class PSAFEARRAYBOUND_ARRAY(NDRPOINTER):

490 referent = (

491 ('Data', SAFEARRAYBOUND_ARRAY),

492 )

493

494 class SAFEARRAY(NDRSTRUCT):

495 structure = (

496 ('cDims', USHORT),

497 ('fFeatures', USHORT),

498 ('cbElements', ULONG),

499 ('cLocks', ULONG),

500 ('uArrayStructs', SAFEARRAYUNION),

501 ('rgsabound', SAFEARRAYBOUND_ARRAY),

502 )

503

504 class PSAFEARRAY(NDRPOINTER):

505 referent = (

506 ('Data', SAFEARRAY),

507 )

508

509# 2.2.29 VARIANT

510# 2.2.29.1 _wireVARIANT

511 class EMPTY(NDR):

512 align = 0

513 structure = (

514 )

515

516 class varUnion(NDRUNION):

517 commonHdr = (

518 ('tag', ULONG),

519 )

520 union = {

521 VARENUM.VT_I8 : ('llVal', LONGLONG),

522 VARENUM.VT_I4 : ('lVal', LONG),

523 VARENUM.VT_UI1 : ('bVal', BYTE),

524 VARENUM.VT_I2 : ('iVal', SHORT),

525 VARENUM.VT_R4 : ('fltVal', FLOAT),

526 VARENUM.VT_R8 : ('dblVal', DOUBLE),

527 VARENUM.VT_BOOL : ('boolVal', VARIANT_BOOL),

528 VARENUM.VT_ERROR : ('scode', HRESULT),

529 VARENUM.VT_CY : ('cyVal', CURRENCY),

530 VARENUM.VT_DATE : ('date', DATE),

531 VARENUM.VT_BSTR : ('bstrVal', BSTR),

532 VARENUM.VT_UNKNOWN : ('punkVal', PMInterfacePointer),

533 VARENUM.VT_DISPATCH : ('pdispVal', PMInterfacePointer),

534 VARENUM.VT_ARRAY : ('parray', SAFEARRAY),

535 VARENUM.VT_RECORD : ('brecVal', BRECORD),

536 VARENUM.VT_RECORD_OR_VT_BYREF : ('brecVal', BRECORD),

537 VARENUM.VT_UI1_OR_VT_BYREF : ('pbVal', BYTE),

538 VARENUM.VT_I2_OR_VT_BYREF : ('piVal', PSHORT),

539 VARENUM.VT_I4_OR_VT_BYREF : ('plVal', PLONG),

540 VARENUM.VT_I8_OR_VT_BYREF : ('pllVal', PLONGLONG),

541 VARENUM.VT_R4_OR_VT_BYREF : ('pfltVal', PFLOAT),

542 VARENUM.VT_R8_OR_VT_BYREF : ('pdblVal', PDOUBLE),

543 VARENUM.VT_BOOL_OR_VT_BYREF : ('pboolVal', PVARIANT_BOOL),

544 VARENUM.VT_ERROR_OR_VT_BYREF : ('pscode', PHRESULT),

545 VARENUM.VT_CY_OR_VT_BYREF : ('pcyVal', PCURRENCY),

546 VARENUM.VT_DATE_OR_VT_BYREF : ('pdate', PDATE),

547 VARENUM.VT_BSTR_OR_VT_BYREF : ('pbstrVal', PBSTR),

548 VARENUM.VT_UNKNOWN_OR_VT_BYREF : ('ppunkVal', PPMInterfacePointer),

549 VARENUM.VT_DISPATCH_OR_VT_BYREF: ('ppdispVal', PPMInterfacePointer),

550 VARENUM.VT_ARRAY_OR_VT_BYREF : ('pparray', PSAFEARRAY),

551 VARENUM.VT_VARIANT_OR_VT_BYREF : ('pvarVal', PVARIANT),

552 VARENUM.VT_I1 : ('cVal', CHAR),

553 VARENUM.VT_UI2 : ('uiVal', USHORT),

554 VARENUM.VT_UI4 : ('ulVal', ULONG),

555 VARENUM.VT_UI8 : ('ullVal', ULONGLONG),

556 VARENUM.VT_INT : ('intVal', INT),

557 VARENUM.VT_UINT : ('uintVal', UINT),

558 VARENUM.VT_DECIMAL : ('decVal', DECIMAL),

559 VARENUM.VT_I1_OR_VT_BYREF : ('pcVal', PCHAR),

560 VARENUM.VT_UI2_OR_VT_BYREF : ('puiVal', PUSHORT),

561 VARENUM.VT_UI4_OR_VT_BYREF : ('pulVal', PULONG),

562 VARENUM.VT_UI8_OR_VT_BYREF : ('pullVal', PULONGLONG),

563 VARENUM.VT_INT_OR_VT_BYREF : ('pintVal', PINT),

564 VARENUM.VT_UINT_OR_VT_BYREF : ('puintVal', PUINT),

565 VARENUM.VT_DECIMAL_OR_VT_BYREF : ('pdecVal', PDECIMAL),

566 VARENUM.VT_EMPTY : ('empty', EMPTY),

567 VARENUM.VT_NULL : ('null', EMPTY),

568 }

569

570 class wireVARIANTStr(NDRSTRUCT):

571 structure = (

572 ('clSize',DWORD),

573 ('rpcReserved',DWORD),

574 ('vt',USHORT),

575 ('wReserved1',USHORT),

576 ('wReserved2',USHORT),

577 ('wReserved3',USHORT),

578 ('_varUnion',varUnion),

579 )

580

581 def getAlignment(self):

582 return 8

583

584 class VARIANT(NDRPOINTER):

585 referent = (

586 ('Data', wireVARIANTStr),

587 )

588

589 class PVARIANT(NDRPOINTER):

590 referent = (

591 ('Data', VARIANT),

592 )

593

594# 2.2.32 DISPID

595 DISPID = LONG

596

597# 2.2.33 DISPPARAMS

598 class DISPID_ARRAY(NDRUniConformantArray):

599 item = '<L'

600

601 class PDISPID_ARRAY(NDRPOINTER):

602 referent = (

603 ('Data', DISPID_ARRAY),

604 )

605

606 class DISPPARAMS(NDRSTRUCT):

607 structure = (

608 ('rgvarg',PVARIANT_ARRAY),

609 ('rgdispidNamedArgs', PDISPID_ARRAY),

610 ('cArgs', UINT),

611 ('cNamedArgs', UINT),

612 )

613

614# 2.2.34 EXCEPINFO

615 class EXCEPINFO(NDRSTRUCT):

616 structure = (

617 ('wCode',WORD),

618 ('wReserved', WORD),

619 ('bstrSource', BSTR),

620 ('bstrDescription', BSTR),

621 ('bstrHelpFile', BSTR),

622 ('dwHelpContext', DWORD),

623 ('pvReserved', ULONG),

624 ('pfnDeferredFillIn', ULONG),

625 ('scode', HRESULT),

626 )

627

628# 2.2.35 MEMBERID

629 MEMBERID = DISPID

630

631# 2.2.38 ARRAYDESC

632 class ARRAYDESC(NDRSTRUCT):

633 # In order to avoid the lack of forward declarations in Python

634 # I declare the item in the constructor

635 #structure = (

636 # ('tdescElem',TYPEDESC),

637 # ('cDims',USHORT),

638 # ('rgbounds',SAFEARRAYBOUND_ARRAY),

639 #)

640 def __init__(self, data = None, isNDR64 = False):

641 NDRSTRUCT.__init__(self, data, isNDR64)

642 self.structure = (

643 ('tdescElem',TYPEDESC),

644 ('cDims',USHORT),

645 ('rgbounds',SAFEARRAYBOUND_ARRAY),

646 )

647

648# 2.2.37 TYPEDESC

649 class tdUnion(NDRUNION):

650 notAlign = True

651 commonHdr = (

652 ('tag', USHORT),

653 )

654 # In order to avoid the lack of forward declarations in Python

655 # I declare the item in the constructor

656 #union = {

657 # VARENUM.VT_PTR: ('lptdesc', tdUnion),

658 # VARENUM.VT_SAFEARRAY: ('lptdesc', tdUnion),

659 # VARENUM.VT_CARRAY: ('lpadesc', ARRAYDESC),

660 # VARENUM.VT_USERDEFINED: ('hreftype', HREFTYPE),

661 #}

662 def __init__(self, data = None, isNDR64=False, topLevel = False):

663 NDRUNION.__init__(self,None, isNDR64=isNDR64, topLevel=topLevel)

664 self.union = {

665 VARENUM.VT_PTR: ('lptdesc', PTYPEDESC),

666 VARENUM.VT_SAFEARRAY: ('lptdesc', PTYPEDESC),

667 VARENUM.VT_CARRAY: ('lpadesc', ARRAYDESC),

668 VARENUM.VT_USERDEFINED: ('hreftype', HREFTYPE),

669 'default': None,

670 }

671

672 class TYPEDESC(NDRSTRUCT):

673 structure = (

674 ('vtType',tdUnion),

675 ('vt', VARENUM),

676 )

677

678 def getAlignment(self):

679 return 4

680

681 class PTYPEDESC(NDRPOINTER):

682 referent = (

683 ('Data', TYPEDESC),

684 )

685 def __init__(self, data = None, isNDR64=False, topLevel = False):

686 ret = NDRPOINTER.__init__(self,None, isNDR64=isNDR64, topLevel = False)

687 # We're forcing the pointer not to be topLevel

688 if data is None:

689 self.fields['ReferentID'] = random.randint(1,65535)

690 else:

691 self.fromString(data)

692

693

694# 2.2.48 SCODE

695 SCODE = LONG

696

697 class SCODE_ARRAY(NDRUniConformantArray):

698 item = SCODE

699

700 class PSCODE_ARRAY(NDRPOINTER):

701 referent = (

702 ('Data', SCODE_ARRAY),

703 )

704

705# 2.2.39 PARAMDESCEX

706 class PARAMDESCEX(NDRSTRUCT):

707 structure = (

708 ('cBytes',ULONG),

709 ('varDefaultValue',VARIANT),

710 )

711

712 class PPARAMDESCEX(NDRPOINTER):

713 referent = (

714 ('Data', PARAMDESCEX),

715 )

716

717

718# 2.2.40 PARAMDESC

719 class PARAMDESC(NDRSTRUCT):

720 structure = (

721 ('pparamdescex',PPARAMDESCEX),

722 ('wParamFlags',USHORT),

723 )

724

725# 2.2.41 ELEMDESC

726 class ELEMDESC(NDRSTRUCT):

727 structure = (

728 ('tdesc',TYPEDESC),

729 ('paramdesc',PARAMDESC),

730 )

731

732 class ELEMDESC_ARRAY(NDRUniConformantArray):

733 item = ELEMDESC

734

735 class PELEMDESC_ARRAY(NDRPOINTER):

736 referent = (

737 ('Data', ELEMDESC_ARRAY),

738 )

739

740# 2.2.42 FUNCDESC

741 class FUNCDESC(NDRSTRUCT):

742 structure = (

743 ('memid',MEMBERID),

744 ('lReserved1',PSCODE_ARRAY),

745 ('lprgelemdescParam',PELEMDESC_ARRAY),

746 ('funckind',FUNCKIND),

747 ('invkind',INVOKEKIND),

748 ('callconv',CALLCONV),

749 ('cParams',SHORT),

750 ('cParamsOpt',SHORT),

751 ('oVft',SHORT),

752 ('cReserved2',SHORT),

753 ('elemdescFunc',ELEMDESC),

754 ('wFuncFlags',WORD),

755 )

756

757 class LPFUNCDESC(NDRPOINTER):

758 referent = (

759 ('Data', FUNCDESC),

760 )

761# 2.2.44 TYPEATTR

762 class TYPEATTR(NDRSTRUCT):

763 structure = (

764 ('guid',GUID),

765 ('lcid',LCID),

766 ('dwReserved1',DWORD),

767 ('dwReserved2',DWORD),

768 ('dwReserved3',DWORD),

769 ('lpstrReserved4',LPOLESTR),

770 ('cbSizeInstance',ULONG),

771 ('typeKind',TYPEKIND),

772 ('cFuncs',WORD),

773 ('cVars',WORD),

774 ('cImplTypes',WORD),

775 ('cbSizeVft',WORD),

776 ('cbAlignment',WORD),

777 ('wTypeFlags',WORD),

778 ('wMajorVerNum',WORD),

779 ('wMinorVerNum',WORD),

780 ('tdescAlias',TYPEDESC),

781 ('dwReserved5',DWORD),

782 ('dwReserved6',WORD),

783 )

784

785 class PTYPEATTR(NDRPOINTER):

786 referent = (

787 ('Data', TYPEATTR),

788 )

789

790 class BSTR_ARRAY_CV(NDRUniConformantVaryingArray):

791 item = BSTR

792

793 class UINT_ARRAY(NDRUniConformantArray):

794 item = '<L'

795

796 class OLESTR_ARRAY(NDRUniConformantArray):

797 item = LPOLESTR

798

799

800################################################################################

801# RPC CALLS

802################################################################################

803# 3.1.4.1 IDispatch::GetTypeInfoCount (Opnum 3)

804 class IDispatch_GetTypeInfoCount(DCOMCALL):

805 opnum = 3

806 structure = (

807 ('pwszMachineName', LPWSTR),

808 )

809

810 class IDispatch_GetTypeInfoCountResponse(DCOMANSWER):

811 structure = (

812 ('pctinfo', ULONG),

813 ('ErrorCode', error_status_t),

814 )

815

816# 3.1.4.2 IDispatch::GetTypeInfo (Opnum 4)

817 class IDispatch_GetTypeInfo(DCOMCALL):

818 opnum = 4

819 structure = (

820 ('iTInfo', ULONG),

821 ('lcid', DWORD),

822 )

823

824 class IDispatch_GetTypeInfoResponse(DCOMANSWER):

825 structure = (

826 ('ppTInfo', PMInterfacePointer),

827 ('ErrorCode', error_status_t),

828 )

829

830# 3.1.4.3 IDispatch::GetIDsOfNames (Opnum 5)

831 class IDispatch_GetIDsOfNames(DCOMCALL):

832 opnum = 5

833 structure = (

834 ('riid', REFIID),

835 ('rgszNames', OLESTR_ARRAY),

836 ('cNames', UINT),

837 ('lcid', LCID),

838 )

839

840 class IDispatch_GetIDsOfNamesResponse(DCOMANSWER):

841 structure = (

842 ('rgDispId', DISPID_ARRAY),

843 ('ErrorCode', error_status_t),

844 )

845

846# 3.1.4.4 IDispatch::Invoke (Opnum 6)

847 class IDispatch_Invoke(DCOMCALL):

848 opnum = 6

849 structure = (

850 ('dispIdMember', DISPID),

851 ('riid', REFIID),

852 ('lcid', LCID),

853 ('dwFlags', DWORD),

854 ('pDispParams', DISPPARAMS),

855 ('cVarRef', UINT),

856 ('rgVarRefIdx', UINT_ARRAY),

857 ('rgVarRef', VARIANT_ARRAY),

858 )

859

860 class IDispatch_InvokeResponse(DCOMANSWER):

861 structure = (

862 ('pVarResult', VARIANT),

863 ('pExcepInfo', EXCEPINFO),

864 ('pArgErr', UINT),

865 ('ErrorCode', error_status_t),

866 )

867

868# 3.7.4.1 ITypeInfo::GetTypeAttr (Opnum 3)

869 class ITypeInfo_GetTypeAttr(DCOMCALL):

870 opnum = 3

871 structure = (

872 )

873

874 class ITypeInfo_GetTypeAttrResponse(DCOMANSWER):

875 structure = (

876 ('ppTypeAttr', PTYPEATTR),

877 ('pReserved', DWORD),

878 ('ErrorCode', error_status_t),

879 )

880

881# 3.7.4.2 ITypeInfo::GetTypeComp (Opnum 4)

882 class ITypeInfo_GetTypeComp(DCOMCALL):

883 opnum = 4

884 structure = (

885 )

886

887 class ITypeInfo_GetTypeCompResponse(DCOMANSWER):

888 structure = (

889 ('ppTComp', PMInterfacePointer),

890 ('ErrorCode', error_status_t),

891 )

892

893# 3.7.4.3 ITypeInfo::GetFuncDesc (Opnum 5)

894 class ITypeInfo_GetFuncDesc(DCOMCALL):

895 opnum = 5

896 structure = (

897 ('index', UINT),

898 )

899

900 class ITypeInfo_GetFuncDescResponse(DCOMANSWER):

901 structure = (

902 ('ppFuncDesc', LPFUNCDESC),

903 ('pReserved', DWORD),

904 ('ErrorCode', error_status_t),

905 )

906

907# 3.7.4.5 ITypeInfo::GetNames (Opnum 7)

908 class ITypeInfo_GetNames(DCOMCALL):

909 opnum = 7

910 structure = (

911 ('memid', MEMBERID),

912 ('cMaxNames', UINT),

913 )

914

915 class ITypeInfo_GetNamesResponse(DCOMANSWER):

916 structure = (

917 ('rgBstrNames', BSTR_ARRAY_CV),

918 ('pcNames', UINT),

919 ('ErrorCode', error_status_t),

920 )

921

922# 3.7.4.8 ITypeInfo::GetDocumentation (Opnum 12)

923 class ITypeInfo_GetDocumentation(DCOMCALL):

924 opnum = 12

925 structure = (

926 ('memid', MEMBERID),

927 ('refPtrFlags', DWORD),

928 )

929

930 class ITypeInfo_GetDocumentationResponse(DCOMANSWER):

931 structure = (

932 ('pBstrName', BSTR),

933 ('pBstrDocString', BSTR),

934 ('pdwHelpContext', DWORD),

935 ('ErrorCode', error_status_t),

936 )

937

938

939################################################################################

940# OPNUMs and their corresponding structures

941################################################################################

942 OPNUMS = {

943}

944

945################################################################################

946# HELPER FUNCTIONS AND INTERFACES

947################################################################################

948# 4.8.5 Enumerating All Methods in an Interface

949# INPUT: IDispatch pointer from the automation server

950# CALL IDispatch::GetTypeInfoCount and OBTAIN pcTInfo

951# COMMENT see Section 3.1.4.1 for information on pcTInfo i

952# IF pcTInfo = 0 THEN

953# PRINT Automation Server does not support type information for this object

954# ELSE

955# CALL IDispatch::GetTypeInfo with correct LocaleID and OBTAIN ITypeInfo pointer

956# CALL ITypeInfo::GetDocumentation(MEMBERID_NIL, 1, &BstrName, NULL, NULL, NULL)

957# PRINT Name of the Interface is BstrName

958# CALL ITypeInfo::GetTypeAttr and OBTAIN TYPEATTR pointer

959#

960# FOR X = 0 to TYPEATTR:: cFuncs -1

961# CALL ITypeInfo::GetFuncDesc with X and OBTAIN FUNCDESC pointer

962# CALL ITypeInfo::GetNames with FUNCDESC::memid and appropriate values for

963# rgBstrNames, cMaxNames and pcNames

964# COMMENT see Section 3.7.4.5 for more information regarding the parameters

965# to ITypeinfo::GetNames

966# IF pcNames > 0 THEN

967# PRINT Name of the method is rgBstrNames[0]

968# PRINT Parameters to above method are following

969# FOR Y = 1 to pcNames -1

970# PRINT rgBstrNames[Y]

971# END FOR

972# END IF

973# END FOR i

974# ENDIF

975 def enumerateMethods(iInterface):

976 methods = dict()

977 typeInfoCount = iInterface.GetTypeInfoCount()

978 if typeInfoCount['pctinfo'] == 0:

979 LOG.error('Automation Server does not support type information for this object')

980 return {}

981 iTypeInfo = iInterface.GetTypeInfo()

982 iTypeAttr = iTypeInfo.GetTypeAttr()

983 for x in range(iTypeAttr['ppTypeAttr']['cFuncs']):

984 funcDesc = iTypeInfo.GetFuncDesc(x)

985 names = iTypeInfo.GetNames(funcDesc['ppFuncDesc']['memid'], 255)

986 print(names['rgBstrNames'][0]['asData'])

987 funcDesc.dump()

988 print('='*80)

989 if names['pcNames'] > 0:

990 name = names['rgBstrNames'][0]['asData']

991 methods[name] = {}

992 for param in range(1, names['pcNames']):

993 methods[name][names['rgBstrNames'][param]['asData']] = ''

994 if funcDesc['ppFuncDesc']['elemdescFunc'] != NULL:

995 methods[name]['ret'] = funcDesc['ppFuncDesc']['elemdescFunc']['tdesc']['vt']

996

997 return methods

998

999 def checkNullString(string):

1000 if string == NULL:

1001 return string

1002

1003 if string[-1:] != '\x00':

1004 return string + '\x00'

1005 else:

1006 return string

1007

1008 class ITypeComp(IRemUnknown2):

1009 def __init__(self, interface):

1010 IRemUnknown2.__init__(self,interface)

1011 self._iid = IID_ITypeComp

1012

1013 class ITypeInfo(IRemUnknown2):

1014 def __init__(self, interface):

1015 IRemUnknown2.__init__(self,interface)

1016 self._iid = IID_ITypeInfo

1017

1018 def GetTypeAttr(self):

1019 request = ITypeInfo_GetTypeAttr()

1020 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1021 return resp

1022

1023 def GetTypeComp(self):

1024 request = ITypeInfo_GetTypeComp()

1025 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1026 return ITypeComp(INTERFACE(self.get_cinstance(), ''.join(resp['ppTComp']['abData']), self.get_ipidRemUnknown(), target = self.get_target()))

1027

1028 def GetFuncDesc(self, index):

1029 request = ITypeInfo_GetFuncDesc()

1030 request['index'] = index

1031 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1032 return resp

1033

1034 def GetNames(self, memid, cMaxNames=10):

1035 request = ITypeInfo_GetNames()

1036 request['memid'] = memid

1037 request['cMaxNames'] = cMaxNames

1038 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1039 return resp

1040

1041 def GetDocumentation(self, memid, refPtrFlags=15):

1042 request = ITypeInfo_GetDocumentation()

1043 request['memid'] = memid

1044 request['refPtrFlags'] = refPtrFlags

1045 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1046 return resp

1047

1048

1049 class IDispatch(IRemUnknown2):

1050 def __init__(self, interface):

1051 IRemUnknown2.__init__(self,interface)

1052 self._iid = IID_IDispatch

1053

1054 def GetTypeInfoCount(self):

1055 request = IDispatch_GetTypeInfoCount()

1056 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1057 return resp

1058

1059 def GetTypeInfo(self):

1060 request = IDispatch_GetTypeInfo()

1061 request['iTInfo'] = 0

1062 request['lcid'] = 0

1063 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1064 return ITypeInfo(INTERFACE(self.get_cinstance(), ''.join(resp['ppTInfo']['abData']), self.get_ipidRemUnknown(), target = self.get_target()))

1065

1066 def GetIDsOfNames(self, rgszNames, lcid = 0):

1067 request = IDispatch_GetIDsOfNames()

1068 request['riid'] = IID_NULL

1069 for name in rgszNames:

1070 tmpName = LPOLESTR()

1071 tmpName['Data'] = checkNullString(name)

1072 request['rgszNames'].append(tmpName)

1073 request['cNames'] = len(rgszNames)

1074 request['lcid'] = lcid

1075 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1076 IDs = list()

1077 for id in resp['rgDispId']:

1078 IDs.append(id)

1079

1080 return IDs

1081

1082 def Invoke(self, dispIdMember, lcid, dwFlags, pDispParams, cVarRef, rgVarRefIdx, rgVarRef):

1083 request = IDispatch_Invoke()

1084 request['dispIdMember'] = dispIdMember

1085 request['riid'] = IID_NULL

1086 request['lcid'] = lcid

1087 request['dwFlags'] = dwFlags

1088 request['pDispParams'] = pDispParams

1089 request['cVarRef'] = cVarRef

1090 request['rgVarRefIdx'] = rgVarRefIdx

1091 request['rgVarRef'] = rgVarRefIdx

1092 resp = self.request(request, iid = self._iid, uuid = self.get_iPid())

1093 return resp