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# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved.

2#

3# This software is provided under under a slightly modified version

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

5# for more information.

6#

7# Author: Alberto Solino (@agsolino)

8#

9# Description:

10# [MS-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 from __future__ import division

23 from __future__ import print_function

24 import random

25 from struct import pack, unpack

26

27 from impacket import LOG

28 from impacket import hresult_errors

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

30 MInterfacePointer, MInterfacePointer_ARRAY, BYTE_ARRAY, PPMInterfacePointer

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

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

33 PULONG, PULONGLONG, PINT, PUINT, NULL

34 from impacket.dcerpc.v5.enum import Enum

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

36 NDRUniConformantVaryingArray, NDR

37 from impacket.dcerpc.v5.rpcrt import DCERPCException

38 from impacket.uuid import string_to_bin

39

40 class DCERPCSessionError(DCERPCException):

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

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

43

44 def __str__( self ):

45 if self.error_code in hresult_errors.ERROR_MESSAGES:

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

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

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

49 else:

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

51

52################################################################################

53# CONSTANTS

54################################################################################

55# 1.9 Standards Assignments

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

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

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

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

60

61 error_status_t = ULONG

62

63 LCID = DWORD

64 WORD = NDRUSHORT

65

66# 2.2.2 IID

67 IID = GUID

68

69# 2.2.3 LPOLESTR

70 LPOLESTR = LPWSTR

71 OLESTR = WSTR

72

73# 2.2.4 REFIID

74 REFIID = IID

75

76# 2.2.25 DATE

77 DATE = DOUBLE

78 class PDATE(NDRPOINTER):

79 referent = (

80 ('Data', DATE),

81 )

82

83# 2.2.27 VARIANT_BOOL

84 VARIANT_BOOL = USHORT

85

86 class PVARIANT_BOOL(NDRPOINTER):

87 referent = (

88 ('Data', VARIANT_BOOL),

89 )

90

91# 3.1.4.4 IDispatch::Invoke (Opnum 6)

92# dwFlags

93 DISPATCH_METHOD = 0x00000001

94 DISPATCH_PROPERTYGET = 0x00000002

95 DISPATCH_PROPERTYPUT = 0x00000004

96 DISPATCH_PROPERTYPUTREF = 0x00000008

97 DISPATCH_zeroVarResult = 0x00020000

98 DISPATCH_zeroExcepInfo = 0x00040000

99 DISPATCH_zeroArgErr = 0x00080000

100

101################################################################################

102# STRUCTURES

103################################################################################

104# 2.2.26 DECIMAL

105 class DECIMAL(NDRSTRUCT):

106 structure = (

107 ('wReserved',WORD),

108 ('scale',BYTE),

109 ('sign',BYTE),

110 ('Hi32',ULONG),

111 ('Lo64',ULONGLONG),

112 )

113

114 class PDECIMAL(NDRPOINTER):

115 referent = (

116 ('Data', DECIMAL),

117 )

118

119# 2.2.7 VARIANT Type Constants

120 class VARENUM(NDRENUM):

121 class enumItems(Enum):

122 VT_EMPTY = 0

123 VT_NULL = 1

124 VT_I2 = 2

125 VT_I4 = 3

126 VT_R4 = 4

127 VT_R8 = 5

128 VT_CY = 6

129 VT_DATE = 7

130 VT_BSTR = 8

131 VT_DISPATCH = 9

132 VT_ERROR = 0xa

133 VT_BOOL = 0xb

134 VT_VARIANT = 0xc

135 VT_UNKNOWN = 0xd

136 VT_DECIMAL = 0xe

137 VT_I1 = 0x10

138 VT_UI1 = 0x11

139 VT_UI2 = 0x12

140 VT_UI4 = 0x13

141 VT_I8 = 0x14

142 VT_UI8 = 0x15

143 VT_INT = 0x16

144 VT_UINT = 0x17

145 VT_VOID = 0x18

146 VT_HRESULT = 0x19

147 VT_PTR = 0x1a

148 VT_SAFEARRAY = 0x1b

149 VT_CARRAY = 0x1c

150 VT_USERDEFINED = 0x1d

151 VT_LPSTR = 0x1e

152 VT_LPWSTR = 0x1f

153 VT_RECORD = 0x24

154 VT_INT_PTR = 0x25

155 VT_UINT_PTR = 0x26

156 VT_ARRAY = 0x2000

157 VT_BYREF = 0x4000

158 VT_RECORD_OR_VT_BYREF = VT_RECORD | VT_BYREF

159 VT_UI1_OR_VT_BYREF = VT_UI1 | VT_BYREF

160 VT_I2_OR_VT_BYREF = VT_I2 | VT_BYREF

161 VT_I4_OR_VT_BYREF = VT_I4 | VT_BYREF

162 VT_I8_OR_VT_BYREF = VT_I8 | VT_BYREF

163 VT_R4_OR_VT_BYREF = VT_R4 | VT_BYREF

164 VT_R8_OR_VT_BYREF = VT_R8 | VT_BYREF

165 VT_BOOL_OR_VT_BYREF = VT_BOOL | VT_BYREF

166 VT_ERROR_OR_VT_BYREF = VT_ERROR | VT_BYREF

167 VT_CY_OR_VT_BYREF = VT_CY | VT_BYREF

168 VT_DATE_OR_VT_BYREF = VT_DATE | VT_BYREF

169 VT_BSTR_OR_VT_BYREF = VT_BSTR | VT_BYREF

170 VT_UNKNOWN_OR_VT_BYREF = VT_UNKNOWN | VT_BYREF

171 VT_DISPATCH_OR_VT_BYREF = VT_DISPATCH | VT_BYREF

172 VT_ARRAY_OR_VT_BYREF = VT_ARRAY | VT_BYREF

173 VT_VARIANT_OR_VT_BYREF = VT_VARIANT| VT_BYREF

174 VT_I1_OR_VT_BYREF = VT_I1 | VT_BYREF

175 VT_UI2_OR_VT_BYREF = VT_UI2 | VT_BYREF

176 VT_UI4_OR_VT_BYREF = VT_UI4 | VT_BYREF

177 VT_UI8_OR_VT_BYREF = VT_UI8 | VT_BYREF

178 VT_INT_OR_VT_BYREF = VT_INT | VT_BYREF

179 VT_UINT_OR_VT_BYREF = VT_UINT | VT_BYREF

180 VT_DECIMAL_OR_VT_BYREF = VT_DECIMAL | VT_BYREF

181

182# 2.2.8 SAFEARRAY Feature Constants

183 class SF_TYPE(NDRENUM):

184 # [v1_enum] type

185 structure = (

186 ('Data', '<L'),

187 )

188 class enumItems(Enum):

189 SF_ERROR = VARENUM.VT_ERROR

190 SF_I1 = VARENUM.VT_I1

191 SF_I2 = VARENUM.VT_I2

192 SF_I4 = VARENUM.VT_I4

193 SF_I8 = VARENUM.VT_I8

194 SF_BSTR = VARENUM.VT_BSTR

195 SF_UNKNOWN = VARENUM.VT_UNKNOWN

196 SF_DISPATCH = VARENUM.VT_DISPATCH

197 SF_VARIANT = VARENUM.VT_VARIANT

198 SF_RECORD = VARENUM.VT_RECORD

199 SF_HAVEIID = VARENUM.VT_UNKNOWN | 0x8000

200

201# 2.2.10 CALLCONV Calling Convention Constants

202 class CALLCONV(NDRENUM):

203 # [v1_enum] type

204 structure = (

205 ('Data', '<L'),

206 )

207 class enumItems(Enum):

208 CC_CDECL = 1

209 CC_PASCAL = 2

210 CC_STDCALL = 4

211

212

213# 2.2.12 FUNCKIND Function Access Constants

214 class FUNCKIND(NDRENUM):

215 # [v1_enum] type

216 structure = (

217 ('Data', '<L'),

218 )

219 class enumItems(Enum):

220 FUNC_PUREVIRTUAL = 1

221 FUNC_STATIC = 3

222 FUNC_DISPATCH = 4

223

224# 2.2.14 INVOKEKIND Function Invocation Constants

225 class INVOKEKIND(NDRENUM):

226 # [v1_enum] type

227 structure = (

228 ('Data', '<L'),

229 )

230 class enumItems(Enum):

231 INVOKE_FUNC = 1

232 INVOKE_PROPERTYGET = 2

233 INVOKE_PROPERTYPUT = 4

234 INVOKE_PROPERTYPUTREF = 8

235

236# 2.2.17 TYPEKIND Type Kind Constants

237 class TYPEKIND(NDRENUM):

238 # [v1_enum] type

239 structure = (

240 ('Data', '<L'),

241 )

242 class enumItems(Enum):

243 TKIND_ENUM = 0

244 TKIND_RECORD = 1

245 TKIND_MODULE = 2

246 TKIND_INTERFACE = 3

247 TKIND_DISPATCH = 4

248 TKIND_COCLASS = 5

249 TKIND_ALIAS = 6

250 TKIND_UNION = 7

251

252# 2.2.23 BSTR

253# 2.2.23.1 FLAGGED_WORD_BLOB

254 class USHORT_ARRAY(NDRUniConformantArray):

255 item = '<H'

256

257 class FLAGGED_WORD_BLOB(NDRSTRUCT):

258 structure = (

259 ('cBytes',ULONG),

260 ('clSize',ULONG),

261 ('asData',USHORT_ARRAY),

262 )

263 def __setitem__(self, key, value):

264 if key == 'asData':

265 value = value #+ '\x00'

266 array = list()

267 for letter in value:

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

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

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

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

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

273 self.data = None # force recompute

274 else:

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

276

277 def __getitem__(self, key):

278 if key == 'asData':

279 value = ''

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

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

282 return value

283 else:

284 return NDRSTRUCT.__getitem__(self,key)

285

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

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

288 ind = ' '*indent

289 if msg != '':

290 print("%s" % (msg))

291 value = ''

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

293

294# 2.2.23.2 BSTR Type Definition

295 class BSTR(NDRPOINTER):

296 referent = (

297 ('Data', FLAGGED_WORD_BLOB),

298 )

299

300 class PBSTR(NDRPOINTER):

301 referent = (

302 ('Data', BSTR),

303 )

304

305# 2.2.24 CURRENCY

306 class CURRENCY(NDRSTRUCT):

307 structure = (

308 ('int64', LONGLONG),

309 )

310

311 class PCURRENCY(NDRPOINTER):

312 referent = (

313 ('Data', CURRENCY),

314 )

315

316# 2.2.28.2 BRECORD

317# 2.2.28.2.1 _wireBRECORD

318 class _wireBRECORD(NDRSTRUCT):

319 structure = (

320 ('fFlags', LONGLONG),

321 ('clSize', LONGLONG),

322 ('pRecInfo', MInterfacePointer),

323 ('pRecord', BYTE_ARRAY),

324 )

325

326 class BRECORD(NDRPOINTER):

327 referent = (

328 ('Data', _wireBRECORD),

329 )

330

331# 2.2.30 SAFEARRAY

332# 2.2.30.1 SAFEARRAYBOUND

333 class SAFEARRAYBOUND(NDRSTRUCT):

334 structure = (

335 ('cElements', ULONG),

336 ('lLbound', LONG),

337 )

338

339 class PSAFEARRAYBOUND(NDRPOINTER):

340 referent = (

341 ('Data', SAFEARRAYBOUND),

342 )

343

344# 2.2.30.2 SAFEARR_BSTR

345 class BSTR_ARRAY(NDRUniConformantArray):

346 item = BSTR

347

348 class PBSTR_ARRAY(NDRPOINTER):

349 referent = (

350 ('Data', BSTR_ARRAY),

351 )

352

353 class SAFEARR_BSTR(NDRSTRUCT):

354 structure = (

355 ('Size', ULONG),

356 ('aBstr', PBSTR_ARRAY),

357 )

358

359# 2.2.30.3 SAFEARR_UNKNOWN

360 class SAFEARR_UNKNOWN(NDRSTRUCT):

361 structure = (

362 ('Size', ULONG),

363 ('apUnknown', MInterfacePointer_ARRAY),

364 )

365

366# 2.2.30.4 SAFEARR_DISPATCH

367 class SAFEARR_DISPATCH(NDRSTRUCT):

368 structure = (

369 ('Size', ULONG),

370 ('apDispatch', MInterfacePointer_ARRAY),

371 )

372

373# 2.2.30.6 SAFEARR_BRECORD

374 class BRECORD_ARRAY(NDRUniConformantArray):

375 item = BRECORD

376

377 class SAFEARR_BRECORD(NDRSTRUCT):

378 structure = (

379 ('Size', ULONG),

380 ('aRecord', BRECORD_ARRAY),

381 )

382

383# 2.2.30.7 SAFEARR_HAVEIID

384 class SAFEARR_HAVEIID(NDRSTRUCT):

385 structure = (

386 ('Size', ULONG),

387 ('apUnknown', MInterfacePointer_ARRAY),

388 ('iid', IID),

389 )

390

391# 2.2.30.8 Scalar-Sized Arrays

392# 2.2.30.8.1 BYTE_SIZEDARR

393 class BYTE_SIZEDARR(NDRSTRUCT):

394 structure = (

395 ('clSize', ULONG),

396 ('pData', BYTE_ARRAY),

397 )

398

399# 2.2.30.8.2 WORD_SIZEDARR

400 class WORD_ARRAY(NDRUniConformantArray):

401 item = '<H'

402

403 class WORD_SIZEDARR(NDRSTRUCT):

404 structure = (

405 ('clSize', ULONG),

406 ('pData', WORD_ARRAY),

407 )

408

409# 2.2.30.8.3 DWORD_SIZEDARR

410 class DWORD_ARRAY(NDRUniConformantArray):

411 item = '<L'

412

413 class DWORD_SIZEDARR(NDRSTRUCT):

414 structure = (

415 ('clSize', ULONG),

416 ('pData', DWORD_ARRAY),

417 )

418

419# 2.2.30.8.4 HYPER_SIZEDARR

420 class HYPER_ARRAY(NDRUniConformantArray):

421 item = '<Q'

422

423 class HYPER_SIZEDARR(NDRSTRUCT):

424 structure = (

425 ('clSize', ULONG),

426 ('pData', HYPER_ARRAY),

427 )

428

429

430# 2.2.36 HREFTYPE

431 HREFTYPE = DWORD

432

433# 2.2.30.5 SAFEARR_VARIANT

434 class VARIANT_ARRAY(NDRUniConformantArray):

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

436 # I declare the item in the constructor

437 #item = VARIANT

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

439 NDRUniConformantArray.__init__(self, data, isNDR64)

440 self.item = VARIANT

441

442 class PVARIANT_ARRAY(NDRPOINTER):

443 referent = (

444 ('Data', VARIANT_ARRAY),

445 )

446

447 class PVARIANT(NDRPOINTER):

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

449 # I declare the item in the constructor

450 #referent = (

451 # ('Data', VARIANT),

452 #)

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

454 NDRPOINTER.__init__(self, data, isNDR64)

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

456

457

458 class SAFEARR_VARIANT(NDRSTRUCT):

459 structure = (

460 ('Size', ULONG),

461 ('aVariant', VARIANT_ARRAY),

462 )

463

464# 2.2.30.9 SAFEARRAYUNION

465 class SAFEARRAYUNION(NDRUNION):

466 commonHdr = (

467 ('tag', ULONG),

468 )

469 union = {

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

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

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

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

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

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

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

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

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

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

480 }

481

482# 2.2.30.10 SAFEARRAY

483 class SAFEARRAYBOUND_ARRAY(NDRUniConformantArray):

484 item = SAFEARRAYBOUND

485

486 class PSAFEARRAYBOUND_ARRAY(NDRPOINTER):

487 referent = (

488 ('Data', SAFEARRAYBOUND_ARRAY),

489 )

490

491 class SAFEARRAY(NDRSTRUCT):

492 structure = (

493 ('cDims', USHORT),

494 ('fFeatures', USHORT),

495 ('cbElements', ULONG),

496 ('cLocks', ULONG),

497 ('uArrayStructs', SAFEARRAYUNION),

498 ('rgsabound', SAFEARRAYBOUND_ARRAY),

499 )

500

501 class PSAFEARRAY(NDRPOINTER):

502 referent = (

503 ('Data', SAFEARRAY),

504 )

505

506# 2.2.29 VARIANT

507# 2.2.29.1 _wireVARIANT

508 class EMPTY(NDR):

509 align = 0

510 structure = (

511 )

512

513 class varUnion(NDRUNION):

514 commonHdr = (

515 ('tag', ULONG),

516 )

517 union = {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

565 }

566

567 class wireVARIANTStr(NDRSTRUCT):

568 structure = (

569 ('clSize',DWORD),

570 ('rpcReserved',DWORD),

571 ('vt',USHORT),

572 ('wReserved1',USHORT),

573 ('wReserved2',USHORT),

574 ('wReserved3',USHORT),

575 ('_varUnion',varUnion),

576 )

577

578 def getAlignment(self):

579 return 8

580

581 class VARIANT(NDRPOINTER):

582 referent = (

583 ('Data', wireVARIANTStr),

584 )

585

586 class PVARIANT(NDRPOINTER):

587 referent = (

588 ('Data', VARIANT),

589 )

590

591# 2.2.32 DISPID

592 DISPID = LONG

593

594# 2.2.33 DISPPARAMS

595 class DISPID_ARRAY(NDRUniConformantArray):

596 item = '<L'

597

598 class PDISPID_ARRAY(NDRPOINTER):

599 referent = (

600 ('Data', DISPID_ARRAY),

601 )

602

603 class DISPPARAMS(NDRSTRUCT):

604 structure = (

605 ('rgvarg',PVARIANT_ARRAY),

606 ('rgdispidNamedArgs', PDISPID_ARRAY),

607 ('cArgs', UINT),

608 ('cNamedArgs', UINT),

609 )

610

611# 2.2.34 EXCEPINFO

612 class EXCEPINFO(NDRSTRUCT):

613 structure = (

614 ('wCode',WORD),

615 ('wReserved', WORD),

616 ('bstrSource', BSTR),

617 ('bstrDescription', BSTR),

618 ('bstrHelpFile', BSTR),

619 ('dwHelpContext', DWORD),

620 ('pvReserved', ULONG),

621 ('pfnDeferredFillIn', ULONG),

622 ('scode', HRESULT),

623 )

624

625# 2.2.35 MEMBERID

626 MEMBERID = DISPID

627

628# 2.2.38 ARRAYDESC

629 class ARRAYDESC(NDRSTRUCT):

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

631 # I declare the item in the constructor

632 #structure = (

633 # ('tdescElem',TYPEDESC),

634 # ('cDims',USHORT),

635 # ('rgbounds',SAFEARRAYBOUND_ARRAY),

636 #)

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

638 NDRSTRUCT.__init__(self, data, isNDR64)

639 self.structure = (

640 ('tdescElem',TYPEDESC),

641 ('cDims',USHORT),

642 ('rgbounds',SAFEARRAYBOUND_ARRAY),

643 )

644

645# 2.2.37 TYPEDESC

646 class tdUnion(NDRUNION):

647 notAlign = True

648 commonHdr = (

649 ('tag', USHORT),

650 )

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

652 # I declare the item in the constructor

653 #union = {

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

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

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

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

658 #}

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

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

661 self.union = {

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

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

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

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

666 'default': None,

667 }

668

669 class TYPEDESC(NDRSTRUCT):

670 structure = (

671 ('vtType',tdUnion),

672 ('vt', VARENUM),

673 )

674

675 def getAlignment(self):

676 return 4

677

678 class PTYPEDESC(NDRPOINTER):

679 referent = (

680 ('Data', TYPEDESC),

681 )

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

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

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

685 if data is None:

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

687 else:

688 self.fromString(data)

689

690

691# 2.2.48 SCODE

692 SCODE = LONG

693

694 class SCODE_ARRAY(NDRUniConformantArray):

695 item = SCODE

696

697 class PSCODE_ARRAY(NDRPOINTER):

698 referent = (

699 ('Data', SCODE_ARRAY),

700 )

701

702# 2.2.39 PARAMDESCEX

703 class PARAMDESCEX(NDRSTRUCT):

704 structure = (

705 ('cBytes',ULONG),

706 ('varDefaultValue',VARIANT),

707 )

708

709 class PPARAMDESCEX(NDRPOINTER):

710 referent = (

711 ('Data', PARAMDESCEX),

712 )

713

714

715# 2.2.40 PARAMDESC

716 class PARAMDESC(NDRSTRUCT):

717 structure = (

718 ('pparamdescex',PPARAMDESCEX),

719 ('wParamFlags',USHORT),

720 )

721

722# 2.2.41 ELEMDESC

723 class ELEMDESC(NDRSTRUCT):

724 structure = (

725 ('tdesc',TYPEDESC),

726 ('paramdesc',PARAMDESC),

727 )

728

729 class ELEMDESC_ARRAY(NDRUniConformantArray):

730 item = ELEMDESC

731

732 class PELEMDESC_ARRAY(NDRPOINTER):

733 referent = (

734 ('Data', ELEMDESC_ARRAY),

735 )

736

737# 2.2.42 FUNCDESC

738 class FUNCDESC(NDRSTRUCT):

739 structure = (

740 ('memid',MEMBERID),

741 ('lReserved1',PSCODE_ARRAY),

742 ('lprgelemdescParam',PELEMDESC_ARRAY),

743 ('funckind',FUNCKIND),

744 ('invkind',INVOKEKIND),

745 ('callconv',CALLCONV),

746 ('cParams',SHORT),

747 ('cParamsOpt',SHORT),

748 ('oVft',SHORT),

749 ('cReserved2',SHORT),

750 ('elemdescFunc',ELEMDESC),

751 ('wFuncFlags',WORD),

752 )

753

754 class LPFUNCDESC(NDRPOINTER):

755 referent = (

756 ('Data', FUNCDESC),

757 )

758# 2.2.44 TYPEATTR

759 class TYPEATTR(NDRSTRUCT):

760 structure = (

761 ('guid',GUID),

762 ('lcid',LCID),

763 ('dwReserved1',DWORD),

764 ('dwReserved2',DWORD),

765 ('dwReserved3',DWORD),

766 ('lpstrReserved4',LPOLESTR),

767 ('cbSizeInstance',ULONG),

768 ('typeKind',TYPEKIND),

769 ('cFuncs',WORD),

770 ('cVars',WORD),

771 ('cImplTypes',WORD),

772 ('cbSizeVft',WORD),

773 ('cbAlignment',WORD),

774 ('wTypeFlags',WORD),

775 ('wMajorVerNum',WORD),

776 ('wMinorVerNum',WORD),

777 ('tdescAlias',TYPEDESC),

778 ('dwReserved5',DWORD),

779 ('dwReserved6',WORD),

780 )

781

782 class PTYPEATTR(NDRPOINTER):

783 referent = (

784 ('Data', TYPEATTR),

785 )

786

787 class BSTR_ARRAY_CV(NDRUniConformantVaryingArray):

788 item = BSTR

789

790 class UINT_ARRAY(NDRUniConformantArray):

791 item = '<L'

792

793 class OLESTR_ARRAY(NDRUniConformantArray):

794 item = LPOLESTR

795

796

797################################################################################

798# RPC CALLS

799################################################################################

800# 3.1.4.1 IDispatch::GetTypeInfoCount (Opnum 3)

801 class IDispatch_GetTypeInfoCount(DCOMCALL):

802 opnum = 3

803 structure = (

804 ('pwszMachineName', LPWSTR),

805 )

806

807 class IDispatch_GetTypeInfoCountResponse(DCOMANSWER):

808 structure = (

809 ('pctinfo', ULONG),

810 ('ErrorCode', error_status_t),

811 )

812

813# 3.1.4.2 IDispatch::GetTypeInfo (Opnum 4)

814 class IDispatch_GetTypeInfo(DCOMCALL):

815 opnum = 4

816 structure = (

817 ('iTInfo', ULONG),

818 ('lcid', DWORD),

819 )

820

821 class IDispatch_GetTypeInfoResponse(DCOMANSWER):

822 structure = (

823 ('ppTInfo', PMInterfacePointer),

824 ('ErrorCode', error_status_t),

825 )

826

827# 3.1.4.3 IDispatch::GetIDsOfNames (Opnum 5)

828 class IDispatch_GetIDsOfNames(DCOMCALL):

829 opnum = 5

830 structure = (

831 ('riid', REFIID),

832 ('rgszNames', OLESTR_ARRAY),

833 ('cNames', UINT),

834 ('lcid', LCID),

835 )

836

837 class IDispatch_GetIDsOfNamesResponse(DCOMANSWER):

838 structure = (

839 ('rgDispId', DISPID_ARRAY),

840 ('ErrorCode', error_status_t),

841 )

842

843# 3.1.4.4 IDispatch::Invoke (Opnum 6)

844 class IDispatch_Invoke(DCOMCALL):

845 opnum = 6

846 structure = (

847 ('dispIdMember', DISPID),

848 ('riid', REFIID),

849 ('lcid', LCID),

850 ('dwFlags', DWORD),

851 ('pDispParams', DISPPARAMS),

852 ('cVarRef', UINT),

853 ('rgVarRefIdx', UINT_ARRAY),

854 ('rgVarRef', VARIANT_ARRAY),

855 )

856

857 class IDispatch_InvokeResponse(DCOMANSWER):

858 structure = (

859 ('pVarResult', VARIANT),

860 ('pExcepInfo', EXCEPINFO),

861 ('pArgErr', UINT),

862 ('ErrorCode', error_status_t),

863 )

864

865# 3.7.4.1 ITypeInfo::GetTypeAttr (Opnum 3)

866 class ITypeInfo_GetTypeAttr(DCOMCALL):

867 opnum = 3

868 structure = (

869 )

870

871 class ITypeInfo_GetTypeAttrResponse(DCOMANSWER):

872 structure = (

873 ('ppTypeAttr', PTYPEATTR),

874 ('pReserved', DWORD),

875 ('ErrorCode', error_status_t),

876 )

877

878# 3.7.4.2 ITypeInfo::GetTypeComp (Opnum 4)

879 class ITypeInfo_GetTypeComp(DCOMCALL):

880 opnum = 4

881 structure = (

882 )

883

884 class ITypeInfo_GetTypeCompResponse(DCOMANSWER):

885 structure = (

886 ('ppTComp', PMInterfacePointer),

887 ('ErrorCode', error_status_t),

888 )

889

890# 3.7.4.3 ITypeInfo::GetFuncDesc (Opnum 5)

891 class ITypeInfo_GetFuncDesc(DCOMCALL):

892 opnum = 5

893 structure = (

894 ('index', UINT),

895 )

896

897 class ITypeInfo_GetFuncDescResponse(DCOMANSWER):

898 structure = (

899 ('ppFuncDesc', LPFUNCDESC),

900 ('pReserved', DWORD),

901 ('ErrorCode', error_status_t),

902 )

903

904# 3.7.4.5 ITypeInfo::GetNames (Opnum 7)

905 class ITypeInfo_GetNames(DCOMCALL):

906 opnum = 7

907 structure = (

908 ('memid', MEMBERID),

909 ('cMaxNames', UINT),

910 )

911

912 class ITypeInfo_GetNamesResponse(DCOMANSWER):

913 structure = (

914 ('rgBstrNames', BSTR_ARRAY_CV),

915 ('pcNames', UINT),

916 ('ErrorCode', error_status_t),

917 )

918

919# 3.7.4.8 ITypeInfo::GetDocumentation (Opnum 12)

920 class ITypeInfo_GetDocumentation(DCOMCALL):

921 opnum = 12

922 structure = (

923 ('memid', MEMBERID),

924 ('refPtrFlags', DWORD),

925 )

926

927 class ITypeInfo_GetDocumentationResponse(DCOMANSWER):

928 structure = (

929 ('pBstrName', BSTR),

930 ('pBstrDocString', BSTR),

931 ('pdwHelpContext', DWORD),

932 ('ErrorCode', error_status_t),

933 )

934

935

936################################################################################

937# OPNUMs and their corresponding structures

938################################################################################

939 OPNUMS = {

940}

941

942################################################################################

943# HELPER FUNCTIONS AND INTERFACES

944################################################################################

945# 4.8.5 Enumerating All Methods in an Interface

946# INPUT: IDispatch pointer from the automation server

947# CALL IDispatch::GetTypeInfoCount and OBTAIN pcTInfo

948# COMMENT see Section 3.1.4.1 for information on pcTInfo i

949# IF pcTInfo = 0 THEN

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

951# ELSE

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

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

954# PRINT Name of the Interface is BstrName

955# CALL ITypeInfo::GetTypeAttr and OBTAIN TYPEATTR pointer

956#

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

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

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

960# rgBstrNames, cMaxNames and pcNames

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

962# to ITypeinfo::GetNames

963# IF pcNames > 0 THEN

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

965# PRINT Parameters to above method are following

966# FOR Y = 1 to pcNames -1

967# PRINT rgBstrNames[Y]

968# END FOR

969# END IF

970# END FOR i

971# ENDIF

972 def enumerateMethods(iInterface):

973 methods = dict()

974 typeInfoCount = iInterface.GetTypeInfoCount()

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

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

977 return {}

978 iTypeInfo = iInterface.GetTypeInfo()

979 iTypeAttr = iTypeInfo.GetTypeAttr()

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

981 funcDesc = iTypeInfo.GetFuncDesc(x)

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

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

984 funcDesc.dump()

985 print('='*80)

986 if names['pcNames'] > 0:

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

988 methods[name] = {}

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

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

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

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

993

994 return methods

995

996 def checkNullString(string):

997 if string == NULL:

998 return string

999

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

1001 return string + '\x00'

1002 else:

1003 return string

1004

1005 class ITypeComp(IRemUnknown2):

1006 def __init__(self, interface):

1007 IRemUnknown2.__init__(self,interface)

1008 self._iid = IID_ITypeComp

1009

1010 class ITypeInfo(IRemUnknown2):

1011 def __init__(self, interface):

1012 IRemUnknown2.__init__(self,interface)

1013 self._iid = IID_ITypeInfo

1014

1015 def GetTypeAttr(self):

1016 request = ITypeInfo_GetTypeAttr()

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

1018 return resp

1019

1020 def GetTypeComp(self):

1021 request = ITypeInfo_GetTypeComp()

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

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

1024

1025 def GetFuncDesc(self, index):

1026 request = ITypeInfo_GetFuncDesc()

1027 request['index'] = index

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

1029 return resp

1030

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

1032 request = ITypeInfo_GetNames()

1033 request['memid'] = memid

1034 request['cMaxNames'] = cMaxNames

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

1036 return resp

1037

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

1039 request = ITypeInfo_GetDocumentation()

1040 request['memid'] = memid

1041 request['refPtrFlags'] = refPtrFlags

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

1043 return resp

1044

1045

1046 class IDispatch(IRemUnknown2):

1047 def __init__(self, interface):

1048 IRemUnknown2.__init__(self,interface)

1049 self._iid = IID_IDispatch

1050

1051 def GetTypeInfoCount(self):

1052 request = IDispatch_GetTypeInfoCount()

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

1054 return resp

1055

1056 def GetTypeInfo(self):

1057 request = IDispatch_GetTypeInfo()

1058 request['iTInfo'] = 0

1059 request['lcid'] = 0

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

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

1062

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

1064 request = IDispatch_GetIDsOfNames()

1065 request['riid'] = IID_NULL

1066 for name in rgszNames:

1067 tmpName = LPOLESTR()

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

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

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

1071 request['lcid'] = lcid

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

1073 IDs = list()

1074 for id in resp['rgDispId']:

1075 IDs.append(id)

1076

1077 return IDs

1078

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

1080 request = IDispatch_Invoke()

1081 request['dispIdMember'] = dispIdMember

1082 request['riid'] = IID_NULL

1083 request['lcid'] = lcid

1084 request['dwFlags'] = dwFlags

1085 request['pDispParams'] = pDispParams

1086 request['cVarRef'] = cVarRef

1087 request['rgVarRefIdx'] = rgVarRefIdx

1088 request['rgVarRef'] = rgVarRefIdx

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

1090 return resp