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) 2020 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-RRP] Interface implementation 

11# 

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

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

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

15# 

16# Some calls have helper functions, which makes it even easier to use. 

17# They are located at the end of this file. 

18# Helper functions start with "h"<name of the call>. 

19# There are test cases for them too. 

20# 

21# Author: 

22# Alberto Solino (@agsolino) 

23# 

24 

25 

26from struct import unpack, pack 

27 

28from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantVaryingArray, NDRUniConformantArray 

29from impacket.dcerpc.v5.dtypes import DWORD, UUID, ULONG, LPULONG, BOOLEAN, SECURITY_INFORMATION, PFILETIME, \ 

30 RPC_UNICODE_STRING, FILETIME, NULL, MAXIMUM_ALLOWED, OWNER_SECURITY_INFORMATION, PWCHAR, PRPC_UNICODE_STRING 

31from impacket.dcerpc.v5.rpcrt import DCERPCException 

32from impacket import system_errors, LOG 

33from impacket.uuid import uuidtup_to_bin 

34 

35MSRPC_UUID_RRP = uuidtup_to_bin(('338CD001-2244-31F1-AAAA-900038001003', '1.0')) 

36 

37class DCERPCSessionError(DCERPCException): 

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

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

40 

41 def __str__( self ): 

42 key = self.error_code 

43 if key in system_errors.ERROR_MESSAGES: 43 ↛ 48line 43 didn't jump to line 48, because the condition on line 43 was never false

44 error_msg_short = system_errors.ERROR_MESSAGES[key][0] 

45 error_msg_verbose = system_errors.ERROR_MESSAGES[key][1] 

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

47 else: 

48 return 'RRP SessionError: unknown error code: 0x%x' % self.error_code 

49 

50################################################################################ 

51# CONSTANTS 

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

53# 2.2.2 PREGISTRY_SERVER_NAME 

54PREGISTRY_SERVER_NAME = PWCHAR 

55 

56# 2.2.3 error_status_t 

57error_status_t = ULONG 

58 

59# 2.2.5 RRP_UNICODE_STRING 

60RRP_UNICODE_STRING = RPC_UNICODE_STRING 

61PRRP_UNICODE_STRING = PRPC_UNICODE_STRING 

62 

63# 2.2.4 REGSAM 

64REGSAM = ULONG 

65 

66KEY_QUERY_VALUE = 0x00000001 

67KEY_SET_VALUE = 0x00000002 

68KEY_CREATE_SUB_KEY = 0x00000004 

69KEY_ENUMERATE_SUB_KEYS = 0x00000008 

70KEY_CREATE_LINK = 0x00000020 

71KEY_WOW64_64KEY = 0x00000100 

72KEY_WOW64_32KEY = 0x00000200 

73 

74REG_BINARY = 3 

75REG_DWORD = 4 

76REG_DWORD_LITTLE_ENDIAN = 4 

77REG_DWORD_BIG_ENDIAN = 5 

78REG_EXPAND_SZ = 2 

79REG_LINK = 6 

80REG_MULTI_SZ = 7 

81REG_NONE = 0 

82REG_QWORD = 11 

83REG_QWORD_LITTLE_ENDIAN = 11 

84REG_SZ = 1 

85 

86# 3.1.5.7 BaseRegCreateKey (Opnum 6) 

87REG_CREATED_NEW_KEY = 0x00000001 

88REG_OPENED_EXISTING_KEY = 0x00000002 

89 

90# 3.1.5.19 BaseRegRestoreKey (Opnum 19) 

91# Flags 

92REG_WHOLE_HIVE_VOLATILE = 0x00000001 

93REG_REFRESH_HIVE = 0x00000002 

94REG_NO_LAZY_FLUSH = 0x00000004 

95REG_FORCE_RESTORE = 0x00000008 

96 

97################################################################################ 

98# STRUCTURES 

99################################################################################ 

100# 2.2.1 RPC_HKEY 

101class RPC_HKEY(NDRSTRUCT): 

102 structure = ( 

103 ('context_handle_attributes',ULONG), 

104 ('context_handle_uuid',UUID), 

105 ) 

106 

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

108 NDRSTRUCT.__init__(self, data, isNDR64) 

109 self['context_handle_uuid'] = b'\x00'*16 

110 

111 def isNull(self): 

112 return self['context_handle_uuid'] == b'\x00'*16 

113 

114# 2.2.6 RVALENT 

115class RVALENT(NDRSTRUCT): 

116 structure = ( 

117 ('ve_valuename',PRRP_UNICODE_STRING), 

118 ('ve_valuelen',DWORD), 

119 ('ve_valueptr',DWORD), 

120 ('ve_type',DWORD), 

121 ) 

122 

123class RVALENT_ARRAY(NDRUniConformantVaryingArray): 

124 item = RVALENT 

125 

126# 2.2.9 RPC_SECURITY_DESCRIPTOR 

127class BYTE_ARRAY(NDRUniConformantVaryingArray): 

128 pass 

129 

130class PBYTE_ARRAY(NDRPOINTER): 

131 referent = ( 

132 ('Data', BYTE_ARRAY), 

133 ) 

134 

135class RPC_SECURITY_DESCRIPTOR(NDRSTRUCT): 

136 structure = ( 

137 ('lpSecurityDescriptor',PBYTE_ARRAY), 

138 ('cbInSecurityDescriptor',DWORD), 

139 ('cbOutSecurityDescriptor',DWORD), 

140 ) 

141 

142# 2.2.8 RPC_SECURITY_ATTRIBUTES 

143class RPC_SECURITY_ATTRIBUTES(NDRSTRUCT): 

144 structure = ( 

145 ('nLength',DWORD), 

146 ('RpcSecurityDescriptor',RPC_SECURITY_DESCRIPTOR), 

147 ('bInheritHandle',BOOLEAN), 

148 ) 

149 

150class PRPC_SECURITY_ATTRIBUTES(NDRPOINTER): 

151 referent = ( 

152 ('Data', RPC_SECURITY_ATTRIBUTES), 

153 ) 

154 

155################################################################################ 

156# RPC CALLS 

157################################################################################ 

158# 3.1.5.1 OpenClassesRoot (Opnum 0) 

159class OpenClassesRoot(NDRCALL): 

160 opnum = 0 

161 structure = ( 

162 ('ServerName', PREGISTRY_SERVER_NAME), 

163 ('samDesired', REGSAM), 

164 ) 

165 

166class OpenClassesRootResponse(NDRCALL): 

167 structure = ( 

168 ('phKey', RPC_HKEY), 

169 ('ErrorCode', error_status_t), 

170 ) 

171 

172# 3.1.5.2 OpenCurrentUser (Opnum 1) 

173class OpenCurrentUser(NDRCALL): 

174 opnum = 1 

175 structure = ( 

176 ('ServerName', PREGISTRY_SERVER_NAME), 

177 ('samDesired', REGSAM), 

178 ) 

179 

180class OpenCurrentUserResponse(NDRCALL): 

181 structure = ( 

182 ('phKey', RPC_HKEY), 

183 ('ErrorCode', error_status_t), 

184 ) 

185 

186# 3.1.5.3 OpenLocalMachine (Opnum 2) 

187class OpenLocalMachine(NDRCALL): 

188 opnum = 2 

189 structure = ( 

190 ('ServerName', PREGISTRY_SERVER_NAME), 

191 ('samDesired', REGSAM), 

192 ) 

193 

194class OpenLocalMachineResponse(NDRCALL): 

195 structure = ( 

196 ('phKey', RPC_HKEY), 

197 ('ErrorCode', error_status_t), 

198 ) 

199 

200# 3.1.5.4 OpenPerformanceData (Opnum 3) 

201class OpenPerformanceData(NDRCALL): 

202 opnum = 3 

203 structure = ( 

204 ('ServerName', PREGISTRY_SERVER_NAME), 

205 ('samDesired', REGSAM), 

206 ) 

207 

208class OpenPerformanceDataResponse(NDRCALL): 

209 structure = ( 

210 ('phKey', RPC_HKEY), 

211 ('ErrorCode', error_status_t), 

212 ) 

213 

214# 3.1.5.5 OpenUsers (Opnum 4) 

215class OpenUsers(NDRCALL): 

216 opnum = 4 

217 structure = ( 

218 ('ServerName', PREGISTRY_SERVER_NAME), 

219 ('samDesired', REGSAM), 

220 ) 

221 

222class OpenUsersResponse(NDRCALL): 

223 structure = ( 

224 ('phKey', RPC_HKEY), 

225 ('ErrorCode', error_status_t), 

226 ) 

227 

228# 3.1.5.6 BaseRegCloseKey (Opnum 5) 

229class BaseRegCloseKey(NDRCALL): 

230 opnum = 5 

231 structure = ( 

232 ('hKey', RPC_HKEY), 

233 ) 

234 

235class BaseRegCloseKeyResponse(NDRCALL): 

236 structure = ( 

237 ('hKey', RPC_HKEY), 

238 ('ErrorCode', error_status_t), 

239 ) 

240 

241# 3.1.5.7 BaseRegCreateKey (Opnum 6) 

242class BaseRegCreateKey(NDRCALL): 

243 opnum = 6 

244 structure = ( 

245 ('hKey', RPC_HKEY), 

246 ('lpSubKey', RRP_UNICODE_STRING), 

247 ('lpClass', RRP_UNICODE_STRING), 

248 ('dwOptions', DWORD), 

249 ('samDesired', REGSAM), 

250 ('lpSecurityAttributes', PRPC_SECURITY_ATTRIBUTES), 

251 ('lpdwDisposition', LPULONG), 

252 ) 

253 

254class BaseRegCreateKeyResponse(NDRCALL): 

255 structure = ( 

256 ('phkResult', RPC_HKEY), 

257 ('lpdwDisposition', LPULONG), 

258 ('ErrorCode', error_status_t), 

259 ) 

260 

261# 3.1.5.8 BaseRegDeleteKey (Opnum 7) 

262class BaseRegDeleteKey(NDRCALL): 

263 opnum = 7 

264 structure = ( 

265 ('hKey', RPC_HKEY), 

266 ('lpSubKey', RRP_UNICODE_STRING), 

267 ) 

268 

269class BaseRegDeleteKeyResponse(NDRCALL): 

270 structure = ( 

271 ('ErrorCode', error_status_t), 

272 ) 

273 

274# 3.1.5.9 BaseRegDeleteValue (Opnum 8) 

275class BaseRegDeleteValue(NDRCALL): 

276 opnum = 8 

277 structure = ( 

278 ('hKey', RPC_HKEY), 

279 ('lpValueName', RRP_UNICODE_STRING), 

280 ) 

281 

282class BaseRegDeleteValueResponse(NDRCALL): 

283 structure = ( 

284 ('ErrorCode', error_status_t), 

285 ) 

286 

287# 3.1.5.10 BaseRegEnumKey (Opnum 9) 

288class BaseRegEnumKey(NDRCALL): 

289 opnum = 9 

290 structure = ( 

291 ('hKey', RPC_HKEY), 

292 ('dwIndex', DWORD), 

293 ('lpNameIn', RRP_UNICODE_STRING), 

294 ('lpClassIn', PRRP_UNICODE_STRING), 

295 ('lpftLastWriteTime', PFILETIME), 

296 ) 

297 

298class BaseRegEnumKeyResponse(NDRCALL): 

299 structure = ( 

300 ('lpNameOut', RRP_UNICODE_STRING), 

301 ('lplpClassOut', PRRP_UNICODE_STRING), 

302 ('lpftLastWriteTime', PFILETIME), 

303 ('ErrorCode', error_status_t), 

304 ) 

305 

306# 3.1.5.11 BaseRegEnumValue (Opnum 10) 

307class BaseRegEnumValue(NDRCALL): 

308 opnum = 10 

309 structure = ( 

310 ('hKey', RPC_HKEY), 

311 ('dwIndex', DWORD), 

312 ('lpValueNameIn', RRP_UNICODE_STRING), 

313 ('lpType', LPULONG), 

314 ('lpData', PBYTE_ARRAY), 

315 ('lpcbData', LPULONG), 

316 ('lpcbLen', LPULONG), 

317 ) 

318 

319class BaseRegEnumValueResponse(NDRCALL): 

320 structure = ( 

321 ('lpValueNameOut', RRP_UNICODE_STRING), 

322 ('lpType', LPULONG), 

323 ('lpData', PBYTE_ARRAY), 

324 ('lpcbData', LPULONG), 

325 ('lpcbLen', LPULONG), 

326 ('ErrorCode', error_status_t), 

327 ) 

328 

329# 3.1.5.12 BaseRegFlushKey (Opnum 11) 

330class BaseRegFlushKey(NDRCALL): 

331 opnum = 11 

332 structure = ( 

333 ('hKey', RPC_HKEY), 

334 ) 

335 

336class BaseRegFlushKeyResponse(NDRCALL): 

337 structure = ( 

338 ('ErrorCode', error_status_t), 

339 ) 

340 

341# 3.1.5.13 BaseRegGetKeySecurity (Opnum 12) 

342class BaseRegGetKeySecurity(NDRCALL): 

343 opnum = 12 

344 structure = ( 

345 ('hKey', RPC_HKEY), 

346 ('SecurityInformation', SECURITY_INFORMATION), 

347 ('pRpcSecurityDescriptorIn', RPC_SECURITY_DESCRIPTOR), 

348 ) 

349 

350class BaseRegGetKeySecurityResponse(NDRCALL): 

351 structure = ( 

352 ('pRpcSecurityDescriptorOut', RPC_SECURITY_DESCRIPTOR), 

353 ('ErrorCode', error_status_t), 

354 ) 

355 

356# 3.1.5.14 BaseRegLoadKey (Opnum 13) 

357class BaseRegLoadKey(NDRCALL): 

358 opnum = 13 

359 structure = ( 

360 ('hKey', RPC_HKEY), 

361 ('lpSubKey', RRP_UNICODE_STRING), 

362 ('lpFile', RRP_UNICODE_STRING), 

363 ) 

364 

365class BaseRegLoadKeyResponse(NDRCALL): 

366 structure = ( 

367 ('ErrorCode', error_status_t), 

368 ) 

369 

370# 3.1.5.15 BaseRegOpenKey (Opnum 15) 

371class BaseRegOpenKey(NDRCALL): 

372 opnum = 15 

373 structure = ( 

374 ('hKey', RPC_HKEY), 

375 ('lpSubKey', RRP_UNICODE_STRING), 

376 ('dwOptions', DWORD), 

377 ('samDesired', REGSAM), 

378 ) 

379 

380class BaseRegOpenKeyResponse(NDRCALL): 

381 structure = ( 

382 ('phkResult', RPC_HKEY), 

383 ('ErrorCode', error_status_t), 

384 ) 

385 

386# 3.1.5.16 BaseRegQueryInfoKey (Opnum 16) 

387class BaseRegQueryInfoKey(NDRCALL): 

388 opnum = 16 

389 structure = ( 

390 ('hKey', RPC_HKEY), 

391 ('lpClassIn', RRP_UNICODE_STRING), 

392 ) 

393 

394class BaseRegQueryInfoKeyResponse(NDRCALL): 

395 structure = ( 

396 ('lpClassOut', RPC_UNICODE_STRING), 

397 ('lpcSubKeys', DWORD), 

398 ('lpcbMaxSubKeyLen', DWORD), 

399 ('lpcbMaxClassLen', DWORD), 

400 ('lpcValues', DWORD), 

401 ('lpcbMaxValueNameLen', DWORD), 

402 ('lpcbMaxValueLen', DWORD), 

403 ('lpcbSecurityDescriptor', DWORD), 

404 ('lpftLastWriteTime', FILETIME), 

405 ('ErrorCode', error_status_t), 

406 ) 

407 

408# 3.1.5.17 BaseRegQueryValue (Opnum 17) 

409class BaseRegQueryValue(NDRCALL): 

410 opnum = 17 

411 structure = ( 

412 ('hKey', RPC_HKEY), 

413 ('lpValueName', RRP_UNICODE_STRING), 

414 ('lpType', LPULONG), 

415 ('lpData', PBYTE_ARRAY), 

416 ('lpcbData', LPULONG), 

417 ('lpcbLen', LPULONG), 

418 ) 

419 

420class BaseRegQueryValueResponse(NDRCALL): 

421 structure = ( 

422 ('lpType', LPULONG), 

423 ('lpData', PBYTE_ARRAY), 

424 ('lpcbData', LPULONG), 

425 ('lpcbLen', LPULONG), 

426 ('ErrorCode', error_status_t), 

427 ) 

428 

429# 3.1.5.18 BaseRegReplaceKey (Opnum 18) 

430class BaseRegReplaceKey(NDRCALL): 

431 opnum = 18 

432 structure = ( 

433 ('hKey', RPC_HKEY), 

434 ('lpSubKey', RRP_UNICODE_STRING), 

435 ('lpNewFile', RRP_UNICODE_STRING), 

436 ('lpOldFile', RRP_UNICODE_STRING), 

437 ) 

438 

439class BaseRegReplaceKeyResponse(NDRCALL): 

440 structure = ( 

441 ('ErrorCode', error_status_t), 

442 ) 

443 

444# 3.1.5.19 BaseRegRestoreKey (Opnum 19) 

445class BaseRegRestoreKey(NDRCALL): 

446 opnum = 19 

447 structure = ( 

448 ('hKey', RPC_HKEY), 

449 ('lpFile', RRP_UNICODE_STRING), 

450 ('Flags', DWORD), 

451 ) 

452 

453class BaseRegRestoreKeyResponse(NDRCALL): 

454 structure = ( 

455 ('ErrorCode', error_status_t), 

456 ) 

457 

458# 3.1.5.20 BaseRegSaveKey (Opnum 20) 

459class BaseRegSaveKey(NDRCALL): 

460 opnum = 20 

461 structure = ( 

462 ('hKey', RPC_HKEY), 

463 ('lpFile', RRP_UNICODE_STRING), 

464 ('pSecurityAttributes', PRPC_SECURITY_ATTRIBUTES), 

465 ) 

466 

467class BaseRegSaveKeyResponse(NDRCALL): 

468 structure = ( 

469 ('ErrorCode', error_status_t), 

470 ) 

471 

472# 3.1.5.21 BaseRegSetKeySecurity (Opnum 21) 

473class BaseRegSetKeySecurity(NDRCALL): 

474 opnum = 21 

475 structure = ( 

476 ('hKey', RPC_HKEY), 

477 ('SecurityInformation', SECURITY_INFORMATION), 

478 ('pRpcSecurityDescriptor', RPC_SECURITY_DESCRIPTOR), 

479 ) 

480 

481class BaseRegSetKeySecurityResponse(NDRCALL): 

482 structure = ( 

483 ('ErrorCode', error_status_t), 

484 ) 

485 

486# 3.1.5.22 BaseRegSetValue (Opnum 22) 

487class BaseRegSetValue(NDRCALL): 

488 opnum = 22 

489 structure = ( 

490 ('hKey', RPC_HKEY), 

491 ('lpValueName', RRP_UNICODE_STRING), 

492 ('dwType', DWORD), 

493 ('lpData', NDRUniConformantArray), 

494 ('cbData', DWORD), 

495 ) 

496 

497class BaseRegSetValueResponse(NDRCALL): 

498 structure = ( 

499 ('ErrorCode', error_status_t), 

500 ) 

501 

502# 3.1.5.23 BaseRegUnLoadKey (Opnum 23) 

503class BaseRegUnLoadKey(NDRCALL): 

504 opnum = 23 

505 structure = ( 

506 ('hKey', RPC_HKEY), 

507 ('lpSubKey', RRP_UNICODE_STRING), 

508 ) 

509 

510class BaseRegUnLoadKeyResponse(NDRCALL): 

511 structure = ( 

512 ('ErrorCode', error_status_t), 

513 ) 

514 

515# 3.1.5.24 BaseRegGetVersion (Opnum 26) 

516class BaseRegGetVersion(NDRCALL): 

517 opnum = 26 

518 structure = ( 

519 ('hKey', RPC_HKEY), 

520 ) 

521 

522class BaseRegGetVersionResponse(NDRCALL): 

523 structure = ( 

524 ('lpdwVersion', DWORD), 

525 ('ErrorCode', error_status_t), 

526 ) 

527 

528# 3.1.5.25 OpenCurrentConfig (Opnum 27) 

529class OpenCurrentConfig(NDRCALL): 

530 opnum = 27 

531 structure = ( 

532 ('ServerName', PREGISTRY_SERVER_NAME), 

533 ('samDesired', REGSAM), 

534 ) 

535 

536class OpenCurrentConfigResponse(NDRCALL): 

537 structure = ( 

538 ('phKey', RPC_HKEY), 

539 ('ErrorCode', error_status_t), 

540 ) 

541 

542# 3.1.5.26 BaseRegQueryMultipleValues (Opnum 29) 

543class BaseRegQueryMultipleValues(NDRCALL): 

544 opnum = 29 

545 structure = ( 

546 ('hKey', RPC_HKEY), 

547 ('val_listIn', RVALENT_ARRAY), 

548 ('num_vals', DWORD), 

549 ('lpvalueBuf', PBYTE_ARRAY), 

550 ('ldwTotsize', DWORD), 

551 ) 

552 

553class BaseRegQueryMultipleValuesResponse(NDRCALL): 

554 structure = ( 

555 ('val_listOut', RVALENT_ARRAY), 

556 ('lpvalueBuf', PBYTE_ARRAY), 

557 ('ldwTotsize', DWORD), 

558 ('ErrorCode', error_status_t), 

559 ) 

560 

561# 3.1.5.27 BaseRegSaveKeyEx (Opnum 31) 

562class BaseRegSaveKeyEx(NDRCALL): 

563 opnum = 31 

564 structure = ( 

565 ('hKey', RPC_HKEY), 

566 ('lpFile', RRP_UNICODE_STRING), 

567 ('pSecurityAttributes', PRPC_SECURITY_ATTRIBUTES), 

568 ('Flags', DWORD), 

569 ) 

570 

571class BaseRegSaveKeyExResponse(NDRCALL): 

572 structure = ( 

573 ('ErrorCode', error_status_t), 

574 ) 

575 

576# 3.1.5.28 OpenPerformanceText (Opnum 32) 

577class OpenPerformanceText(NDRCALL): 

578 opnum = 32 

579 structure = ( 

580 ('ServerName', PREGISTRY_SERVER_NAME), 

581 ('samDesired', REGSAM), 

582 ) 

583 

584class OpenPerformanceTextResponse(NDRCALL): 

585 structure = ( 

586 ('phKey', RPC_HKEY), 

587 ('ErrorCode', error_status_t), 

588 ) 

589 

590# 3.1.5.29 OpenPerformanceNlsText (Opnum 33) 

591class OpenPerformanceNlsText(NDRCALL): 

592 opnum = 33 

593 structure = ( 

594 ('ServerName', PREGISTRY_SERVER_NAME), 

595 ('samDesired', REGSAM), 

596 ) 

597 

598class OpenPerformanceNlsTextResponse(NDRCALL): 

599 structure = ( 

600 ('phKey', RPC_HKEY), 

601 ('ErrorCode', error_status_t), 

602 ) 

603 

604# 3.1.5.30 BaseRegQueryMultipleValues2 (Opnum 34) 

605class BaseRegQueryMultipleValues2(NDRCALL): 

606 opnum = 34 

607 structure = ( 

608 ('hKey', RPC_HKEY), 

609 ('val_listIn', RVALENT_ARRAY), 

610 ('num_vals', DWORD), 

611 ('lpvalueBuf', PBYTE_ARRAY), 

612 ('ldwTotsize', DWORD), 

613 ) 

614 

615class BaseRegQueryMultipleValues2Response(NDRCALL): 

616 structure = ( 

617 ('val_listOut', RVALENT_ARRAY), 

618 ('lpvalueBuf', PBYTE_ARRAY), 

619 ('ldwRequiredSize', DWORD), 

620 ('ErrorCode', error_status_t), 

621 ) 

622 

623# 3.1.5.31 BaseRegDeleteKeyEx (Opnum 35) 

624class BaseRegDeleteKeyEx(NDRCALL): 

625 opnum = 35 

626 structure = ( 

627 ('hKey', RPC_HKEY), 

628 ('lpSubKey', RRP_UNICODE_STRING), 

629 ('AccessMask', REGSAM), 

630 ('Reserved', DWORD), 

631 ) 

632 

633class BaseRegDeleteKeyExResponse(NDRCALL): 

634 structure = ( 

635 ('ErrorCode', error_status_t), 

636 ) 

637 

638################################################################################ 

639# OPNUMs and their corresponding structures 

640################################################################################ 

641OPNUMS = { 

642 0 : (OpenClassesRoot, OpenClassesRootResponse), 

643 1 : (OpenCurrentUser, OpenCurrentUserResponse), 

644 2 : (OpenLocalMachine, OpenLocalMachineResponse), 

645 3 : (OpenPerformanceData, OpenPerformanceDataResponse), 

646 4 : (OpenUsers, OpenUsersResponse), 

647 5 : (BaseRegCloseKey, BaseRegCloseKeyResponse), 

648 6 : (BaseRegCreateKey, BaseRegCreateKeyResponse), 

649 7 : (BaseRegDeleteKey, BaseRegDeleteKeyResponse), 

650 8 : (BaseRegDeleteValue, BaseRegDeleteValueResponse), 

651 9 : (BaseRegEnumKey, BaseRegEnumKeyResponse), 

65210 : (BaseRegEnumValue, BaseRegEnumValueResponse), 

65311 : (BaseRegFlushKey, BaseRegFlushKeyResponse), 

65412 : (BaseRegGetKeySecurity, BaseRegGetKeySecurityResponse), 

65513 : (BaseRegLoadKey, BaseRegLoadKeyResponse), 

65615 : (BaseRegOpenKey, BaseRegOpenKeyResponse), 

65716 : (BaseRegQueryInfoKey, BaseRegQueryInfoKeyResponse), 

65817 : (BaseRegQueryValue, BaseRegQueryValueResponse), 

65918 : (BaseRegReplaceKey, BaseRegReplaceKeyResponse), 

66019 : (BaseRegRestoreKey, BaseRegRestoreKeyResponse), 

66120 : (BaseRegSaveKey, BaseRegSaveKeyResponse), 

66221 : (BaseRegSetKeySecurity, BaseRegSetKeySecurityResponse), 

66322 : (BaseRegSetValue, BaseRegSetValueResponse), 

66423 : (BaseRegUnLoadKey, BaseRegUnLoadKeyResponse), 

66526 : (BaseRegGetVersion, BaseRegGetVersionResponse), 

66627 : (OpenCurrentConfig, OpenCurrentConfigResponse), 

66729 : (BaseRegQueryMultipleValues, BaseRegQueryMultipleValuesResponse), 

66831 : (BaseRegSaveKeyEx, BaseRegSaveKeyExResponse), 

66932 : (OpenPerformanceText, OpenPerformanceTextResponse), 

67033 : (OpenPerformanceNlsText, OpenPerformanceNlsTextResponse), 

67134 : (BaseRegQueryMultipleValues2, BaseRegQueryMultipleValues2Response), 

67235 : (BaseRegDeleteKeyEx, BaseRegDeleteKeyExResponse), 

673} 

674 

675################################################################################ 

676# HELPER FUNCTIONS 

677################################################################################ 

678def checkNullString(string): 

679 if string == NULL: 

680 return string 

681 

682 if string[-1:] != '\x00': 682 ↛ 683line 682 didn't jump to line 683, because the condition on line 682 was never true

683 return string + '\x00' 

684 else: 

685 return string 

686 

687def packValue(valueType, value): 

688 if valueType == REG_DWORD: 688 ↛ 689line 688 didn't jump to line 689, because the condition on line 688 was never true

689 retData = pack('<L', value) 

690 elif valueType == REG_DWORD_BIG_ENDIAN: 690 ↛ 691line 690 didn't jump to line 691, because the condition on line 690 was never true

691 retData = pack('>L', value) 

692 elif valueType == REG_EXPAND_SZ: 692 ↛ 693line 692 didn't jump to line 693, because the condition on line 692 was never true

693 try: 

694 retData = value.encode('utf-16le') 

695 except UnicodeDecodeError: 

696 import sys 

697 retData = value.decode(sys.getfilesystemencoding()).encode('utf-16le') 

698 elif valueType == REG_MULTI_SZ: 698 ↛ 699line 698 didn't jump to line 699, because the condition on line 698 was never true

699 try: 

700 retData = value.encode('utf-16le') 

701 except UnicodeDecodeError: 

702 import sys 

703 retData = value.decode(sys.getfilesystemencoding()).encode('utf-16le') 

704 elif valueType == REG_QWORD: 704 ↛ 705line 704 didn't jump to line 705, because the condition on line 704 was never true

705 retData = pack('<Q', value) 

706 elif valueType == REG_QWORD_LITTLE_ENDIAN: 706 ↛ 707line 706 didn't jump to line 707, because the condition on line 706 was never true

707 retData = pack('>Q', value) 

708 elif valueType == REG_SZ: 708 ↛ 715line 708 didn't jump to line 715, because the condition on line 708 was never false

709 try: 

710 retData = value.encode('utf-16le') 

711 except UnicodeDecodeError: 

712 import sys 

713 retData = value.decode(sys.getfilesystemencoding()).encode('utf-16le') 

714 else: 

715 retData = value 

716 

717 return retData 

718 

719def unpackValue(valueType, value): 

720 if valueType == REG_DWORD: 

721 retData = unpack('<L', b''.join(value))[0] 

722 elif valueType == REG_DWORD_BIG_ENDIAN: 722 ↛ 723line 722 didn't jump to line 723, because the condition on line 722 was never true

723 retData = unpack('>L', b''.join(value))[0] 

724 elif valueType == REG_EXPAND_SZ: 724 ↛ 725line 724 didn't jump to line 725, because the condition on line 724 was never true

725 retData = b''.join(value).decode('utf-16le') 

726 elif valueType == REG_MULTI_SZ: 726 ↛ 727line 726 didn't jump to line 727, because the condition on line 726 was never true

727 retData = b''.join(value).decode('utf-16le') 

728 elif valueType == REG_QWORD: 728 ↛ 729line 728 didn't jump to line 729, because the condition on line 728 was never true

729 retData = unpack('<Q', b''.join(value))[0] 

730 elif valueType == REG_QWORD_LITTLE_ENDIAN: 730 ↛ 731line 730 didn't jump to line 731, because the condition on line 730 was never true

731 retData = unpack('>Q', b''.join(value))[0] 

732 elif valueType == REG_SZ: 732 ↛ 735line 732 didn't jump to line 735, because the condition on line 732 was never false

733 retData = b''.join(value).decode('utf-16le') 

734 else: 

735 retData = b''.join(value) 

736 

737 return retData 

738 

739def hOpenClassesRoot(dce, samDesired = MAXIMUM_ALLOWED): 

740 request = OpenClassesRoot() 

741 request['ServerName'] = NULL 

742 request['samDesired'] = samDesired 

743 return dce.request(request) 

744 

745def hOpenCurrentUser(dce, samDesired = MAXIMUM_ALLOWED): 

746 request = OpenCurrentUser() 

747 request['ServerName'] = NULL 

748 request['samDesired'] = samDesired 

749 return dce.request(request) 

750 

751def hOpenLocalMachine(dce, samDesired = MAXIMUM_ALLOWED): 

752 request = OpenLocalMachine() 

753 request['ServerName'] = NULL 

754 request['samDesired'] = samDesired 

755 return dce.request(request) 

756 

757def hOpenPerformanceData(dce, samDesired = MAXIMUM_ALLOWED): 

758 request = OpenPerformanceData() 

759 request['ServerName'] = NULL 

760 request['samDesired'] = samDesired 

761 return dce.request(request) 

762 

763def hOpenUsers(dce, samDesired = MAXIMUM_ALLOWED): 

764 request = OpenUsers() 

765 request['ServerName'] = NULL 

766 request['samDesired'] = samDesired 

767 return dce.request(request) 

768 

769def hBaseRegCloseKey(dce, hKey): 

770 request = BaseRegCloseKey() 

771 request['hKey'] = hKey 

772 return dce.request(request) 

773 

774def hBaseRegCreateKey(dce, hKey, lpSubKey, lpClass = NULL, dwOptions = 0x00000001, samDesired = MAXIMUM_ALLOWED, lpSecurityAttributes = NULL, lpdwDisposition = REG_CREATED_NEW_KEY): 

775 request = BaseRegCreateKey() 

776 request['hKey'] = hKey 

777 request['lpSubKey'] = checkNullString(lpSubKey) 

778 request['lpClass'] = checkNullString(lpClass) 

779 request['dwOptions'] = dwOptions 

780 request['samDesired'] = samDesired 

781 if lpSecurityAttributes == NULL: 781 ↛ 784line 781 didn't jump to line 784, because the condition on line 781 was never false

782 request['lpSecurityAttributes']['RpcSecurityDescriptor']['lpSecurityDescriptor'] = NULL 

783 else: 

784 request['lpSecurityAttributes'] = lpSecurityAttributes 

785 request['lpdwDisposition'] = lpdwDisposition 

786 

787 return dce.request(request) 

788 

789def hBaseRegDeleteKey(dce, hKey, lpSubKey): 

790 request = BaseRegDeleteKey() 

791 request['hKey'] = hKey 

792 request['lpSubKey'] = checkNullString(lpSubKey) 

793 return dce.request(request) 

794 

795def hBaseRegEnumKey(dce, hKey, dwIndex, lpftLastWriteTime = NULL): 

796 request = BaseRegEnumKey() 

797 request['hKey'] = hKey 

798 request['dwIndex'] = dwIndex 

799 request.fields['lpNameIn'].fields['MaximumLength'] = 1024 

800 request.fields['lpNameIn'].fields['Data'].fields['Data'].fields['MaximumCount'] = 1024//2 

801 request['lpClassIn'] = ' '* 64 

802 request['lpftLastWriteTime'] = lpftLastWriteTime 

803 

804 return dce.request(request) 

805 

806def hBaseRegEnumValue(dce, hKey, dwIndex, dataLen=256): 

807 request = BaseRegEnumValue() 

808 request['hKey'] = hKey 

809 request['dwIndex'] = dwIndex 

810 retries = 1 

811 

812 # We need to be aware the size might not be enough, so let's catch ERROR_MORE_DATA exception 

813 while True: 

814 try: 

815 # Only the maximum length field of the lpValueNameIn is used to determine the buffer length to be allocated 

816 # by the service. Specify a string with a zero length but maximum length set to the largest buffer size 

817 # needed to hold the value names. 

818 request.fields['lpValueNameIn'].fields['MaximumLength'] = dataLen*2 

819 request.fields['lpValueNameIn'].fields['Data'].fields['Data'].fields['MaximumCount'] = dataLen 

820 

821 request['lpData'] = b' ' * dataLen 

822 request['lpcbData'] = dataLen 

823 request['lpcbLen'] = dataLen 

824 resp = dce.request(request) 

825 except DCERPCSessionError as e: 

826 if retries > 1: 826 ↛ 827line 826 didn't jump to line 827, because the condition on line 826 was never true

827 LOG.debug('Too many retries when calling hBaseRegEnumValue, aborting') 

828 raise 

829 if e.get_error_code() == system_errors.ERROR_MORE_DATA: 829 ↛ 835line 829 didn't jump to line 835, because the condition on line 829 was never false

830 # We need to adjust the size 

831 retries +=1 

832 dataLen = e.get_packet()['lpcbData'] 

833 continue 

834 else: 

835 raise 

836 else: 

837 break 

838 

839 return resp 

840 

841def hBaseRegFlushKey(dce, hKey): 

842 request = BaseRegFlushKey() 

843 request['hKey'] = hKey 

844 return dce.request(request) 

845 

846def hBaseRegGetKeySecurity(dce, hKey, securityInformation = OWNER_SECURITY_INFORMATION ): 

847 request = BaseRegGetKeySecurity() 

848 request['hKey'] = hKey 

849 request['SecurityInformation'] = securityInformation 

850 request['pRpcSecurityDescriptorIn']['lpSecurityDescriptor'] = NULL 

851 request['pRpcSecurityDescriptorIn']['cbInSecurityDescriptor'] = 1024 

852 

853 return dce.request(request) 

854 

855def hBaseRegLoadKey(dce, hKey, lpSubKey, lpFile): 

856 request = BaseRegLoadKey() 

857 request['hKey'] = hKey 

858 request['lpSubKey'] = checkNullString(lpSubKey) 

859 request['lpFile'] = checkNullString(lpFile) 

860 return dce.request(request) 

861 

862def hBaseRegUnLoadKey(dce, hKey, lpSubKey): 

863 request = BaseRegUnLoadKey() 

864 request['hKey'] = hKey 

865 request['lpSubKey'] = checkNullString(lpSubKey) 

866 return dce.request(request) 

867 

868def hBaseRegOpenKey(dce, hKey, lpSubKey, dwOptions=0x00000001, samDesired = MAXIMUM_ALLOWED): 

869 request = BaseRegOpenKey() 

870 request['hKey'] = hKey 

871 request['lpSubKey'] = checkNullString(lpSubKey) 

872 request['dwOptions'] = dwOptions 

873 request['samDesired'] = samDesired 

874 return dce.request(request) 

875 

876def hBaseRegQueryInfoKey(dce, hKey): 

877 request = BaseRegQueryInfoKey() 

878 request['hKey'] = hKey 

879 # Not the cleanest way, but oh well 

880 # Plus, Windows XP needs MaximumCount also set 

881 request.fields['lpClassIn'].fields['MaximumLength'] = 1024 

882 request.fields['lpClassIn'].fields['Data'].fields['Data'].fields['MaximumCount'] = 1024//2 

883 return dce.request(request) 

884 

885def hBaseRegQueryValue(dce, hKey, lpValueName, dataLen=512): 

886 request = BaseRegQueryValue() 

887 request['hKey'] = hKey 

888 request['lpValueName'] = checkNullString(lpValueName) 

889 retries = 1 

890 

891 # We need to be aware the size might not be enough, so let's catch ERROR_MORE_DATA exception 

892 while True: 

893 try: 

894 request['lpData'] =b' ' * dataLen 

895 request['lpcbData'] = dataLen 

896 request['lpcbLen'] = dataLen 

897 resp = dce.request(request) 

898 except DCERPCSessionError as e: 

899 if retries > 1: 

900 LOG.debug('Too many retries when calling hBaseRegQueryValue, aborting') 

901 raise 

902 if e.get_error_code() == system_errors.ERROR_MORE_DATA: 

903 # We need to adjust the size 

904 dataLen = e.get_packet()['lpcbData'] 

905 continue 

906 else: 

907 raise 

908 else: 

909 break 

910 

911 # Returns 

912 # ( dataType, data ) 

913 return resp['lpType'], unpackValue(resp['lpType'], resp['lpData']) 

914 

915def hBaseRegReplaceKey(dce, hKey, lpSubKey, lpNewFile, lpOldFile): 

916 request = BaseRegReplaceKey() 

917 request['hKey'] = hKey 

918 request['lpSubKey'] = checkNullString(lpSubKey) 

919 request['lpNewFile'] = checkNullString(lpNewFile) 

920 request['lpOldFile'] = checkNullString(lpOldFile) 

921 return dce.request(request) 

922 

923def hBaseRegRestoreKey(dce, hKey, lpFile, flags=REG_REFRESH_HIVE): 

924 request = BaseRegRestoreKey() 

925 request['hKey'] = hKey 

926 request['lpFile'] = checkNullString(lpFile) 

927 request['Flags'] = flags 

928 return dce.request(request) 

929 

930def hBaseRegSaveKey(dce, hKey, lpFile, pSecurityAttributes = NULL): 

931 request = BaseRegSaveKey() 

932 request['hKey'] = hKey 

933 request['lpFile'] = checkNullString(lpFile) 

934 request['pSecurityAttributes'] = pSecurityAttributes 

935 return dce.request(request) 

936 

937def hBaseRegSetValue(dce, hKey, lpValueName, dwType, lpData): 

938 request = BaseRegSetValue() 

939 request['hKey'] = hKey 

940 request['lpValueName'] = checkNullString(lpValueName) 

941 request['dwType'] = dwType 

942 request['lpData'] = packValue(dwType,lpData) 

943 request['cbData'] = len(request['lpData']) 

944 return dce.request(request) 

945 

946def hBaseRegGetVersion(dce, hKey): 

947 request = BaseRegGetVersion() 

948 request['hKey'] = hKey 

949 return dce.request(request) 

950 

951def hOpenCurrentConfig(dce, samDesired = MAXIMUM_ALLOWED): 

952 request = OpenCurrentConfig() 

953 request['ServerName'] = NULL 

954 request['samDesired'] = samDesired 

955 return dce.request(request) 

956 

957def hBaseRegQueryMultipleValues(dce, hKey, val_listIn): 

958 # ToDo, check the result to see whether we need to 

959 # have a bigger buffer for the data to receive 

960 request = BaseRegQueryMultipleValues() 

961 request['hKey'] = hKey 

962 

963 for item in val_listIn: 

964 itemn = RVALENT() 

965 itemn['ve_valuename'] = checkNullString(item['ValueName']) 

966 itemn['ve_valuelen'] = len(itemn['ve_valuename']) 

967 itemn['ve_valueptr'] = NULL 

968 itemn['ve_type'] = item['ValueType'] 

969 request['val_listIn'].append(itemn) 

970 

971 request['num_vals'] = len(request['val_listIn']) 

972 request['lpvalueBuf'] = list(b' '*128) 

973 request['ldwTotsize'] = 128 

974 

975 resp = dce.request(request) 

976 retVal = list() 

977 for item in resp['val_listOut']: 

978 itemn = dict() 

979 itemn['ValueName'] = item['ve_valuename'] 

980 itemn['ValueData'] = unpackValue(item['ve_type'], resp['lpvalueBuf'][item['ve_valueptr'] : item['ve_valueptr']+item['ve_valuelen']]) 

981 retVal.append(itemn) 

982 

983 return retVal 

984 

985def hBaseRegSaveKeyEx(dce, hKey, lpFile, pSecurityAttributes = NULL, flags=1): 

986 request = BaseRegSaveKeyEx() 

987 request['hKey'] = hKey 

988 request['lpFile'] = checkNullString(lpFile) 

989 request['pSecurityAttributes'] = pSecurityAttributes 

990 request['Flags'] = flags 

991 return dce.request(request) 

992 

993def hOpenPerformanceText(dce, samDesired = MAXIMUM_ALLOWED): 

994 request = OpenPerformanceText() 

995 request['ServerName'] = NULL 

996 request['samDesired'] = samDesired 

997 return dce.request(request) 

998 

999def hOpenPerformanceNlsText(dce, samDesired = MAXIMUM_ALLOWED): 

1000 request = OpenPerformanceNlsText() 

1001 request['ServerName'] = NULL 

1002 request['samDesired'] = samDesired 

1003 return dce.request(request) 

1004 

1005def hBaseRegDeleteValue(dce, hKey, lpValueName): 

1006 request = BaseRegDeleteValue() 

1007 request['hKey'] = hKey 

1008 request['lpValueName'] = checkNullString(lpValueName) 

1009 return dce.request(request)