Hide keyboard shortcuts

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# 

25from __future__ import division 

26from __future__ import print_function 

27import random 

28from struct import pack, unpack 

29 

30from impacket import LOG 

31from impacket import hresult_errors 

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

33 MInterfacePointer, MInterfacePointer_ARRAY, BYTE_ARRAY, PPMInterfacePointer 

34from 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 

37from impacket.dcerpc.v5.enum import Enum 

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

39 NDRUniConformantVaryingArray, NDR 

40from impacket.dcerpc.v5.rpcrt import DCERPCException 

41from impacket.uuid import string_to_bin 

42 

43class 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 

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

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

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

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

63 

64error_status_t = ULONG 

65 

66LCID = DWORD 

67WORD = NDRUSHORT 

68 

69# 2.2.2 IID 

70IID = GUID 

71 

72# 2.2.3 LPOLESTR 

73LPOLESTR = LPWSTR 

74OLESTR = WSTR 

75 

76# 2.2.4 REFIID 

77REFIID = IID 

78 

79# 2.2.25 DATE 

80DATE = DOUBLE 

81class PDATE(NDRPOINTER): 

82 referent = ( 

83 ('Data', DATE), 

84 ) 

85 

86# 2.2.27 VARIANT_BOOL 

87VARIANT_BOOL = USHORT 

88 

89class PVARIANT_BOOL(NDRPOINTER): 

90 referent = ( 

91 ('Data', VARIANT_BOOL), 

92 ) 

93 

94# 3.1.4.4 IDispatch::Invoke (Opnum 6) 

95# dwFlags 

96DISPATCH_METHOD = 0x00000001 

97DISPATCH_PROPERTYGET = 0x00000002 

98DISPATCH_PROPERTYPUT = 0x00000004 

99DISPATCH_PROPERTYPUTREF = 0x00000008 

100DISPATCH_zeroVarResult = 0x00020000 

101DISPATCH_zeroExcepInfo = 0x00040000 

102DISPATCH_zeroArgErr = 0x00080000 

103 

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

105# STRUCTURES 

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

107# 2.2.26 DECIMAL 

108class DECIMAL(NDRSTRUCT): 

109 structure = ( 

110 ('wReserved',WORD), 

111 ('scale',BYTE), 

112 ('sign',BYTE), 

113 ('Hi32',ULONG), 

114 ('Lo64',ULONGLONG), 

115 ) 

116 

117class PDECIMAL(NDRPOINTER): 

118 referent = ( 

119 ('Data', DECIMAL), 

120 ) 

121 

122# 2.2.7 VARIANT Type Constants 

123class 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 

186class 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 

205class 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 

217class 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 

228class 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 

240class 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 

257class USHORT_ARRAY(NDRUniConformantArray): 

258 item = '<H' 

259 

260class 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 

298class BSTR(NDRPOINTER): 

299 referent = ( 

300 ('Data', FLAGGED_WORD_BLOB), 

301 ) 

302 

303class PBSTR(NDRPOINTER): 

304 referent = ( 

305 ('Data', BSTR), 

306 ) 

307 

308# 2.2.24 CURRENCY 

309class CURRENCY(NDRSTRUCT): 

310 structure = ( 

311 ('int64', LONGLONG), 

312 ) 

313 

314class PCURRENCY(NDRPOINTER): 

315 referent = ( 

316 ('Data', CURRENCY), 

317 ) 

318 

319# 2.2.28.2 BRECORD 

320# 2.2.28.2.1 _wireBRECORD 

321class _wireBRECORD(NDRSTRUCT): 

322 structure = ( 

323 ('fFlags', LONGLONG), 

324 ('clSize', LONGLONG), 

325 ('pRecInfo', MInterfacePointer), 

326 ('pRecord', BYTE_ARRAY), 

327 ) 

328 

329class BRECORD(NDRPOINTER): 

330 referent = ( 

331 ('Data', _wireBRECORD), 

332 ) 

333 

334# 2.2.30 SAFEARRAY 

335# 2.2.30.1 SAFEARRAYBOUND 

336class SAFEARRAYBOUND(NDRSTRUCT): 

337 structure = ( 

338 ('cElements', ULONG), 

339 ('lLbound', LONG), 

340 ) 

341 

342class PSAFEARRAYBOUND(NDRPOINTER): 

343 referent = ( 

344 ('Data', SAFEARRAYBOUND), 

345 ) 

346 

347# 2.2.30.2 SAFEARR_BSTR 

348class BSTR_ARRAY(NDRUniConformantArray): 

349 item = BSTR 

350 

351class PBSTR_ARRAY(NDRPOINTER): 

352 referent = ( 

353 ('Data', BSTR_ARRAY), 

354 ) 

355 

356class SAFEARR_BSTR(NDRSTRUCT): 

357 structure = ( 

358 ('Size', ULONG), 

359 ('aBstr', PBSTR_ARRAY), 

360 ) 

361 

362# 2.2.30.3 SAFEARR_UNKNOWN 

363class SAFEARR_UNKNOWN(NDRSTRUCT): 

364 structure = ( 

365 ('Size', ULONG), 

366 ('apUnknown', MInterfacePointer_ARRAY), 

367 ) 

368 

369# 2.2.30.4 SAFEARR_DISPATCH 

370class SAFEARR_DISPATCH(NDRSTRUCT): 

371 structure = ( 

372 ('Size', ULONG), 

373 ('apDispatch', MInterfacePointer_ARRAY), 

374 ) 

375 

376# 2.2.30.6 SAFEARR_BRECORD 

377class BRECORD_ARRAY(NDRUniConformantArray): 

378 item = BRECORD 

379 

380class SAFEARR_BRECORD(NDRSTRUCT): 

381 structure = ( 

382 ('Size', ULONG), 

383 ('aRecord', BRECORD_ARRAY), 

384 ) 

385 

386# 2.2.30.7 SAFEARR_HAVEIID 

387class 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 

396class BYTE_SIZEDARR(NDRSTRUCT): 

397 structure = ( 

398 ('clSize', ULONG), 

399 ('pData', BYTE_ARRAY), 

400 ) 

401 

402# 2.2.30.8.2 WORD_SIZEDARR 

403class WORD_ARRAY(NDRUniConformantArray): 

404 item = '<H' 

405 

406class WORD_SIZEDARR(NDRSTRUCT): 

407 structure = ( 

408 ('clSize', ULONG), 

409 ('pData', WORD_ARRAY), 

410 ) 

411 

412# 2.2.30.8.3 DWORD_SIZEDARR 

413class DWORD_ARRAY(NDRUniConformantArray): 

414 item = '<L' 

415 

416class DWORD_SIZEDARR(NDRSTRUCT): 

417 structure = ( 

418 ('clSize', ULONG), 

419 ('pData', DWORD_ARRAY), 

420 ) 

421 

422# 2.2.30.8.4 HYPER_SIZEDARR 

423class HYPER_ARRAY(NDRUniConformantArray): 

424 item = '<Q' 

425 

426class HYPER_SIZEDARR(NDRSTRUCT): 

427 structure = ( 

428 ('clSize', ULONG), 

429 ('pData', HYPER_ARRAY), 

430 ) 

431 

432 

433# 2.2.36 HREFTYPE 

434HREFTYPE = DWORD 

435 

436# 2.2.30.5 SAFEARR_VARIANT 

437class 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 

445class PVARIANT_ARRAY(NDRPOINTER): 

446 referent = ( 

447 ('Data', VARIANT_ARRAY), 

448 ) 

449 

450class 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 

461class SAFEARR_VARIANT(NDRSTRUCT): 

462 structure = ( 

463 ('Size', ULONG), 

464 ('aVariant', VARIANT_ARRAY), 

465 ) 

466 

467# 2.2.30.9 SAFEARRAYUNION 

468class 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 

486class SAFEARRAYBOUND_ARRAY(NDRUniConformantArray): 

487 item = SAFEARRAYBOUND 

488 

489class PSAFEARRAYBOUND_ARRAY(NDRPOINTER): 

490 referent = ( 

491 ('Data', SAFEARRAYBOUND_ARRAY), 

492 ) 

493 

494class 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 

504class PSAFEARRAY(NDRPOINTER): 

505 referent = ( 

506 ('Data', SAFEARRAY), 

507 ) 

508 

509# 2.2.29 VARIANT 

510# 2.2.29.1 _wireVARIANT 

511class EMPTY(NDR): 

512 align = 0 

513 structure = ( 

514 ) 

515 

516class 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 

570class 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 

584class VARIANT(NDRPOINTER): 

585 referent = ( 

586 ('Data', wireVARIANTStr), 

587 ) 

588 

589class PVARIANT(NDRPOINTER): 

590 referent = ( 

591 ('Data', VARIANT), 

592 ) 

593 

594# 2.2.32 DISPID 

595DISPID = LONG 

596 

597# 2.2.33 DISPPARAMS 

598class DISPID_ARRAY(NDRUniConformantArray): 

599 item = '<L' 

600 

601class PDISPID_ARRAY(NDRPOINTER): 

602 referent = ( 

603 ('Data', DISPID_ARRAY), 

604 ) 

605 

606class 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 

615class 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 

629MEMBERID = DISPID 

630 

631# 2.2.38 ARRAYDESC 

632class 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 

649class 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 

672class TYPEDESC(NDRSTRUCT): 

673 structure = ( 

674 ('vtType',tdUnion), 

675 ('vt', VARENUM), 

676 ) 

677 

678 def getAlignment(self): 

679 return 4 

680 

681class 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 

695SCODE = LONG 

696 

697class SCODE_ARRAY(NDRUniConformantArray): 

698 item = SCODE 

699 

700class PSCODE_ARRAY(NDRPOINTER): 

701 referent = ( 

702 ('Data', SCODE_ARRAY), 

703 ) 

704 

705# 2.2.39 PARAMDESCEX 

706class PARAMDESCEX(NDRSTRUCT): 

707 structure = ( 

708 ('cBytes',ULONG), 

709 ('varDefaultValue',VARIANT), 

710 ) 

711 

712class PPARAMDESCEX(NDRPOINTER): 

713 referent = ( 

714 ('Data', PARAMDESCEX), 

715 ) 

716 

717 

718# 2.2.40 PARAMDESC 

719class PARAMDESC(NDRSTRUCT): 

720 structure = ( 

721 ('pparamdescex',PPARAMDESCEX), 

722 ('wParamFlags',USHORT), 

723 ) 

724 

725# 2.2.41 ELEMDESC 

726class ELEMDESC(NDRSTRUCT): 

727 structure = ( 

728 ('tdesc',TYPEDESC), 

729 ('paramdesc',PARAMDESC), 

730 ) 

731 

732class ELEMDESC_ARRAY(NDRUniConformantArray): 

733 item = ELEMDESC 

734 

735class PELEMDESC_ARRAY(NDRPOINTER): 

736 referent = ( 

737 ('Data', ELEMDESC_ARRAY), 

738 ) 

739 

740# 2.2.42 FUNCDESC 

741class 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 

757class LPFUNCDESC(NDRPOINTER): 

758 referent = ( 

759 ('Data', FUNCDESC), 

760 ) 

761# 2.2.44 TYPEATTR 

762class 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 

785class PTYPEATTR(NDRPOINTER): 

786 referent = ( 

787 ('Data', TYPEATTR), 

788 ) 

789 

790class BSTR_ARRAY_CV(NDRUniConformantVaryingArray): 

791 item = BSTR 

792 

793class UINT_ARRAY(NDRUniConformantArray): 

794 item = '<L' 

795 

796class OLESTR_ARRAY(NDRUniConformantArray): 

797 item = LPOLESTR 

798 

799 

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

801# RPC CALLS 

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

803# 3.1.4.1 IDispatch::GetTypeInfoCount (Opnum 3) 

804class IDispatch_GetTypeInfoCount(DCOMCALL): 

805 opnum = 3 

806 structure = ( 

807 ('pwszMachineName', LPWSTR), 

808 ) 

809 

810class IDispatch_GetTypeInfoCountResponse(DCOMANSWER): 

811 structure = ( 

812 ('pctinfo', ULONG), 

813 ('ErrorCode', error_status_t), 

814 ) 

815 

816# 3.1.4.2 IDispatch::GetTypeInfo (Opnum 4) 

817class IDispatch_GetTypeInfo(DCOMCALL): 

818 opnum = 4 

819 structure = ( 

820 ('iTInfo', ULONG), 

821 ('lcid', DWORD), 

822 ) 

823 

824class IDispatch_GetTypeInfoResponse(DCOMANSWER): 

825 structure = ( 

826 ('ppTInfo', PMInterfacePointer), 

827 ('ErrorCode', error_status_t), 

828 ) 

829 

830# 3.1.4.3 IDispatch::GetIDsOfNames (Opnum 5) 

831class IDispatch_GetIDsOfNames(DCOMCALL): 

832 opnum = 5 

833 structure = ( 

834 ('riid', REFIID), 

835 ('rgszNames', OLESTR_ARRAY), 

836 ('cNames', UINT), 

837 ('lcid', LCID), 

838 ) 

839 

840class 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) 

847class 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 

860class 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) 

869class ITypeInfo_GetTypeAttr(DCOMCALL): 

870 opnum = 3 

871 structure = ( 

872 ) 

873 

874class 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) 

882class ITypeInfo_GetTypeComp(DCOMCALL): 

883 opnum = 4 

884 structure = ( 

885 ) 

886 

887class ITypeInfo_GetTypeCompResponse(DCOMANSWER): 

888 structure = ( 

889 ('ppTComp', PMInterfacePointer), 

890 ('ErrorCode', error_status_t), 

891 ) 

892 

893# 3.7.4.3 ITypeInfo::GetFuncDesc (Opnum 5) 

894class ITypeInfo_GetFuncDesc(DCOMCALL): 

895 opnum = 5 

896 structure = ( 

897 ('index', UINT), 

898 ) 

899 

900class 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) 

908class ITypeInfo_GetNames(DCOMCALL): 

909 opnum = 7 

910 structure = ( 

911 ('memid', MEMBERID), 

912 ('cMaxNames', UINT), 

913 ) 

914 

915class 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) 

923class ITypeInfo_GetDocumentation(DCOMCALL): 

924 opnum = 12 

925 structure = ( 

926 ('memid', MEMBERID), 

927 ('refPtrFlags', DWORD), 

928 ) 

929 

930class 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################################################################################ 

942OPNUMS = { 

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 

975def 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 

999def 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 

1008class ITypeComp(IRemUnknown2): 

1009 def __init__(self, interface): 

1010 IRemUnknown2.__init__(self,interface) 

1011 self._iid = IID_ITypeComp 

1012 

1013class 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 

1049class 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