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

22from __future__ import division 

23from __future__ import print_function 

24import random 

25from struct import pack, unpack 

26 

27from impacket import LOG 

28from impacket import hresult_errors 

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

30 MInterfacePointer, MInterfacePointer_ARRAY, BYTE_ARRAY, PPMInterfacePointer 

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

34from impacket.dcerpc.v5.enum import Enum 

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

36 NDRUniConformantVaryingArray, NDR 

37from impacket.dcerpc.v5.rpcrt import DCERPCException 

38from impacket.uuid import string_to_bin 

39 

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

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

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

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

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

60 

61error_status_t = ULONG 

62 

63LCID = DWORD 

64WORD = NDRUSHORT 

65 

66# 2.2.2 IID 

67IID = GUID 

68 

69# 2.2.3 LPOLESTR 

70LPOLESTR = LPWSTR 

71OLESTR = WSTR 

72 

73# 2.2.4 REFIID 

74REFIID = IID 

75 

76# 2.2.25 DATE 

77DATE = DOUBLE 

78class PDATE(NDRPOINTER): 

79 referent = ( 

80 ('Data', DATE), 

81 ) 

82 

83# 2.2.27 VARIANT_BOOL 

84VARIANT_BOOL = USHORT 

85 

86class PVARIANT_BOOL(NDRPOINTER): 

87 referent = ( 

88 ('Data', VARIANT_BOOL), 

89 ) 

90 

91# 3.1.4.4 IDispatch::Invoke (Opnum 6) 

92# dwFlags 

93DISPATCH_METHOD = 0x00000001 

94DISPATCH_PROPERTYGET = 0x00000002 

95DISPATCH_PROPERTYPUT = 0x00000004 

96DISPATCH_PROPERTYPUTREF = 0x00000008 

97DISPATCH_zeroVarResult = 0x00020000 

98DISPATCH_zeroExcepInfo = 0x00040000 

99DISPATCH_zeroArgErr = 0x00080000 

100 

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

102# STRUCTURES 

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

104# 2.2.26 DECIMAL 

105class DECIMAL(NDRSTRUCT): 

106 structure = ( 

107 ('wReserved',WORD), 

108 ('scale',BYTE), 

109 ('sign',BYTE), 

110 ('Hi32',ULONG), 

111 ('Lo64',ULONGLONG), 

112 ) 

113 

114class PDECIMAL(NDRPOINTER): 

115 referent = ( 

116 ('Data', DECIMAL), 

117 ) 

118 

119# 2.2.7 VARIANT Type Constants 

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

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

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

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

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

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

254class USHORT_ARRAY(NDRUniConformantArray): 

255 item = '<H' 

256 

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

295class BSTR(NDRPOINTER): 

296 referent = ( 

297 ('Data', FLAGGED_WORD_BLOB), 

298 ) 

299 

300class PBSTR(NDRPOINTER): 

301 referent = ( 

302 ('Data', BSTR), 

303 ) 

304 

305# 2.2.24 CURRENCY 

306class CURRENCY(NDRSTRUCT): 

307 structure = ( 

308 ('int64', LONGLONG), 

309 ) 

310 

311class PCURRENCY(NDRPOINTER): 

312 referent = ( 

313 ('Data', CURRENCY), 

314 ) 

315 

316# 2.2.28.2 BRECORD 

317# 2.2.28.2.1 _wireBRECORD 

318class _wireBRECORD(NDRSTRUCT): 

319 structure = ( 

320 ('fFlags', LONGLONG), 

321 ('clSize', LONGLONG), 

322 ('pRecInfo', MInterfacePointer), 

323 ('pRecord', BYTE_ARRAY), 

324 ) 

325 

326class BRECORD(NDRPOINTER): 

327 referent = ( 

328 ('Data', _wireBRECORD), 

329 ) 

330 

331# 2.2.30 SAFEARRAY 

332# 2.2.30.1 SAFEARRAYBOUND 

333class SAFEARRAYBOUND(NDRSTRUCT): 

334 structure = ( 

335 ('cElements', ULONG), 

336 ('lLbound', LONG), 

337 ) 

338 

339class PSAFEARRAYBOUND(NDRPOINTER): 

340 referent = ( 

341 ('Data', SAFEARRAYBOUND), 

342 ) 

343 

344# 2.2.30.2 SAFEARR_BSTR 

345class BSTR_ARRAY(NDRUniConformantArray): 

346 item = BSTR 

347 

348class PBSTR_ARRAY(NDRPOINTER): 

349 referent = ( 

350 ('Data', BSTR_ARRAY), 

351 ) 

352 

353class SAFEARR_BSTR(NDRSTRUCT): 

354 structure = ( 

355 ('Size', ULONG), 

356 ('aBstr', PBSTR_ARRAY), 

357 ) 

358 

359# 2.2.30.3 SAFEARR_UNKNOWN 

360class SAFEARR_UNKNOWN(NDRSTRUCT): 

361 structure = ( 

362 ('Size', ULONG), 

363 ('apUnknown', MInterfacePointer_ARRAY), 

364 ) 

365 

366# 2.2.30.4 SAFEARR_DISPATCH 

367class SAFEARR_DISPATCH(NDRSTRUCT): 

368 structure = ( 

369 ('Size', ULONG), 

370 ('apDispatch', MInterfacePointer_ARRAY), 

371 ) 

372 

373# 2.2.30.6 SAFEARR_BRECORD 

374class BRECORD_ARRAY(NDRUniConformantArray): 

375 item = BRECORD 

376 

377class SAFEARR_BRECORD(NDRSTRUCT): 

378 structure = ( 

379 ('Size', ULONG), 

380 ('aRecord', BRECORD_ARRAY), 

381 ) 

382 

383# 2.2.30.7 SAFEARR_HAVEIID 

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

393class BYTE_SIZEDARR(NDRSTRUCT): 

394 structure = ( 

395 ('clSize', ULONG), 

396 ('pData', BYTE_ARRAY), 

397 ) 

398 

399# 2.2.30.8.2 WORD_SIZEDARR 

400class WORD_ARRAY(NDRUniConformantArray): 

401 item = '<H' 

402 

403class WORD_SIZEDARR(NDRSTRUCT): 

404 structure = ( 

405 ('clSize', ULONG), 

406 ('pData', WORD_ARRAY), 

407 ) 

408 

409# 2.2.30.8.3 DWORD_SIZEDARR 

410class DWORD_ARRAY(NDRUniConformantArray): 

411 item = '<L' 

412 

413class DWORD_SIZEDARR(NDRSTRUCT): 

414 structure = ( 

415 ('clSize', ULONG), 

416 ('pData', DWORD_ARRAY), 

417 ) 

418 

419# 2.2.30.8.4 HYPER_SIZEDARR 

420class HYPER_ARRAY(NDRUniConformantArray): 

421 item = '<Q' 

422 

423class HYPER_SIZEDARR(NDRSTRUCT): 

424 structure = ( 

425 ('clSize', ULONG), 

426 ('pData', HYPER_ARRAY), 

427 ) 

428 

429 

430# 2.2.36 HREFTYPE 

431HREFTYPE = DWORD 

432 

433# 2.2.30.5 SAFEARR_VARIANT 

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

442class PVARIANT_ARRAY(NDRPOINTER): 

443 referent = ( 

444 ('Data', VARIANT_ARRAY), 

445 ) 

446 

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

458class SAFEARR_VARIANT(NDRSTRUCT): 

459 structure = ( 

460 ('Size', ULONG), 

461 ('aVariant', VARIANT_ARRAY), 

462 ) 

463 

464# 2.2.30.9 SAFEARRAYUNION 

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

483class SAFEARRAYBOUND_ARRAY(NDRUniConformantArray): 

484 item = SAFEARRAYBOUND 

485 

486class PSAFEARRAYBOUND_ARRAY(NDRPOINTER): 

487 referent = ( 

488 ('Data', SAFEARRAYBOUND_ARRAY), 

489 ) 

490 

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

501class PSAFEARRAY(NDRPOINTER): 

502 referent = ( 

503 ('Data', SAFEARRAY), 

504 ) 

505 

506# 2.2.29 VARIANT 

507# 2.2.29.1 _wireVARIANT 

508class EMPTY(NDR): 

509 align = 0 

510 structure = ( 

511 ) 

512 

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

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

581class VARIANT(NDRPOINTER): 

582 referent = ( 

583 ('Data', wireVARIANTStr), 

584 ) 

585 

586class PVARIANT(NDRPOINTER): 

587 referent = ( 

588 ('Data', VARIANT), 

589 ) 

590 

591# 2.2.32 DISPID 

592DISPID = LONG 

593 

594# 2.2.33 DISPPARAMS 

595class DISPID_ARRAY(NDRUniConformantArray): 

596 item = '<L' 

597 

598class PDISPID_ARRAY(NDRPOINTER): 

599 referent = ( 

600 ('Data', DISPID_ARRAY), 

601 ) 

602 

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

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

626MEMBERID = DISPID 

627 

628# 2.2.38 ARRAYDESC 

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

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

669class TYPEDESC(NDRSTRUCT): 

670 structure = ( 

671 ('vtType',tdUnion), 

672 ('vt', VARENUM), 

673 ) 

674 

675 def getAlignment(self): 

676 return 4 

677 

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

692SCODE = LONG 

693 

694class SCODE_ARRAY(NDRUniConformantArray): 

695 item = SCODE 

696 

697class PSCODE_ARRAY(NDRPOINTER): 

698 referent = ( 

699 ('Data', SCODE_ARRAY), 

700 ) 

701 

702# 2.2.39 PARAMDESCEX 

703class PARAMDESCEX(NDRSTRUCT): 

704 structure = ( 

705 ('cBytes',ULONG), 

706 ('varDefaultValue',VARIANT), 

707 ) 

708 

709class PPARAMDESCEX(NDRPOINTER): 

710 referent = ( 

711 ('Data', PARAMDESCEX), 

712 ) 

713 

714 

715# 2.2.40 PARAMDESC 

716class PARAMDESC(NDRSTRUCT): 

717 structure = ( 

718 ('pparamdescex',PPARAMDESCEX), 

719 ('wParamFlags',USHORT), 

720 ) 

721 

722# 2.2.41 ELEMDESC 

723class ELEMDESC(NDRSTRUCT): 

724 structure = ( 

725 ('tdesc',TYPEDESC), 

726 ('paramdesc',PARAMDESC), 

727 ) 

728 

729class ELEMDESC_ARRAY(NDRUniConformantArray): 

730 item = ELEMDESC 

731 

732class PELEMDESC_ARRAY(NDRPOINTER): 

733 referent = ( 

734 ('Data', ELEMDESC_ARRAY), 

735 ) 

736 

737# 2.2.42 FUNCDESC 

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

754class LPFUNCDESC(NDRPOINTER): 

755 referent = ( 

756 ('Data', FUNCDESC), 

757 ) 

758# 2.2.44 TYPEATTR 

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

782class PTYPEATTR(NDRPOINTER): 

783 referent = ( 

784 ('Data', TYPEATTR), 

785 ) 

786 

787class BSTR_ARRAY_CV(NDRUniConformantVaryingArray): 

788 item = BSTR 

789 

790class UINT_ARRAY(NDRUniConformantArray): 

791 item = '<L' 

792 

793class OLESTR_ARRAY(NDRUniConformantArray): 

794 item = LPOLESTR 

795 

796 

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

798# RPC CALLS 

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

800# 3.1.4.1 IDispatch::GetTypeInfoCount (Opnum 3) 

801class IDispatch_GetTypeInfoCount(DCOMCALL): 

802 opnum = 3 

803 structure = ( 

804 ('pwszMachineName', LPWSTR), 

805 ) 

806 

807class IDispatch_GetTypeInfoCountResponse(DCOMANSWER): 

808 structure = ( 

809 ('pctinfo', ULONG), 

810 ('ErrorCode', error_status_t), 

811 ) 

812 

813# 3.1.4.2 IDispatch::GetTypeInfo (Opnum 4) 

814class IDispatch_GetTypeInfo(DCOMCALL): 

815 opnum = 4 

816 structure = ( 

817 ('iTInfo', ULONG), 

818 ('lcid', DWORD), 

819 ) 

820 

821class IDispatch_GetTypeInfoResponse(DCOMANSWER): 

822 structure = ( 

823 ('ppTInfo', PMInterfacePointer), 

824 ('ErrorCode', error_status_t), 

825 ) 

826 

827# 3.1.4.3 IDispatch::GetIDsOfNames (Opnum 5) 

828class IDispatch_GetIDsOfNames(DCOMCALL): 

829 opnum = 5 

830 structure = ( 

831 ('riid', REFIID), 

832 ('rgszNames', OLESTR_ARRAY), 

833 ('cNames', UINT), 

834 ('lcid', LCID), 

835 ) 

836 

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

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

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

866class ITypeInfo_GetTypeAttr(DCOMCALL): 

867 opnum = 3 

868 structure = ( 

869 ) 

870 

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

879class ITypeInfo_GetTypeComp(DCOMCALL): 

880 opnum = 4 

881 structure = ( 

882 ) 

883 

884class ITypeInfo_GetTypeCompResponse(DCOMANSWER): 

885 structure = ( 

886 ('ppTComp', PMInterfacePointer), 

887 ('ErrorCode', error_status_t), 

888 ) 

889 

890# 3.7.4.3 ITypeInfo::GetFuncDesc (Opnum 5) 

891class ITypeInfo_GetFuncDesc(DCOMCALL): 

892 opnum = 5 

893 structure = ( 

894 ('index', UINT), 

895 ) 

896 

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

905class ITypeInfo_GetNames(DCOMCALL): 

906 opnum = 7 

907 structure = ( 

908 ('memid', MEMBERID), 

909 ('cMaxNames', UINT), 

910 ) 

911 

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

920class ITypeInfo_GetDocumentation(DCOMCALL): 

921 opnum = 12 

922 structure = ( 

923 ('memid', MEMBERID), 

924 ('refPtrFlags', DWORD), 

925 ) 

926 

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

939OPNUMS = { 

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 

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

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

1005class ITypeComp(IRemUnknown2): 

1006 def __init__(self, interface): 

1007 IRemUnknown2.__init__(self,interface) 

1008 self._iid = IID_ITypeComp 

1009 

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

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