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

22 

23from struct import unpack, pack 

24 

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

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

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

28from impacket.dcerpc.v5.rpcrt import DCERPCException 

29from impacket import system_errors, LOG 

30from impacket.uuid import uuidtup_to_bin 

31 

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

33 

34class DCERPCSessionError(DCERPCException): 

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

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

37 

38 def __str__( self ): 

39 key = self.error_code 

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

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

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

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

44 else: 

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

46 

47################################################################################ 

48# CONSTANTS 

49################################################################################ 

50# 2.2.2 PREGISTRY_SERVER_NAME 

51PREGISTRY_SERVER_NAME = PWCHAR 

52 

53# 2.2.3 error_status_t 

54error_status_t = ULONG 

55 

56# 2.2.5 RRP_UNICODE_STRING 

57RRP_UNICODE_STRING = RPC_UNICODE_STRING 

58PRRP_UNICODE_STRING = PRPC_UNICODE_STRING 

59 

60# 2.2.4 REGSAM 

61REGSAM = ULONG 

62 

63KEY_QUERY_VALUE = 0x00000001 

64KEY_SET_VALUE = 0x00000002 

65KEY_CREATE_SUB_KEY = 0x00000004 

66KEY_ENUMERATE_SUB_KEYS = 0x00000008 

67KEY_CREATE_LINK = 0x00000020 

68KEY_WOW64_64KEY = 0x00000100 

69KEY_WOW64_32KEY = 0x00000200 

70 

71REG_BINARY = 3 

72REG_DWORD = 4 

73REG_DWORD_LITTLE_ENDIAN = 4 

74REG_DWORD_BIG_ENDIAN = 5 

75REG_EXPAND_SZ = 2 

76REG_LINK = 6 

77REG_MULTI_SZ = 7 

78REG_NONE = 0 

79REG_QWORD = 11 

80REG_QWORD_LITTLE_ENDIAN = 11 

81REG_SZ = 1 

82 

83# 3.1.5.7 BaseRegCreateKey (Opnum 6) 

84REG_CREATED_NEW_KEY = 0x00000001 

85REG_OPENED_EXISTING_KEY = 0x00000002 

86 

87# 3.1.5.19 BaseRegRestoreKey (Opnum 19) 

88# Flags 

89REG_WHOLE_HIVE_VOLATILE = 0x00000001 

90REG_REFRESH_HIVE = 0x00000002 

91REG_NO_LAZY_FLUSH = 0x00000004 

92REG_FORCE_RESTORE = 0x00000008 

93 

94################################################################################ 

95# STRUCTURES 

96################################################################################ 

97# 2.2.1 RPC_HKEY 

98class RPC_HKEY(NDRSTRUCT): 

99 structure = ( 

100 ('context_handle_attributes',ULONG), 

101 ('context_handle_uuid',UUID), 

102 ) 

103 

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

105 NDRSTRUCT.__init__(self, data, isNDR64) 

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

107 

108 def isNull(self): 

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

110 

111# 2.2.6 RVALENT 

112class RVALENT(NDRSTRUCT): 

113 structure = ( 

114 ('ve_valuename',PRRP_UNICODE_STRING), 

115 ('ve_valuelen',DWORD), 

116 ('ve_valueptr',DWORD), 

117 ('ve_type',DWORD), 

118 ) 

119 

120class RVALENT_ARRAY(NDRUniConformantVaryingArray): 

121 item = RVALENT 

122 

123# 2.2.9 RPC_SECURITY_DESCRIPTOR 

124class BYTE_ARRAY(NDRUniConformantVaryingArray): 

125 pass 

126 

127class PBYTE_ARRAY(NDRPOINTER): 

128 referent = ( 

129 ('Data', BYTE_ARRAY), 

130 ) 

131 

132class RPC_SECURITY_DESCRIPTOR(NDRSTRUCT): 

133 structure = ( 

134 ('lpSecurityDescriptor',PBYTE_ARRAY), 

135 ('cbInSecurityDescriptor',DWORD), 

136 ('cbOutSecurityDescriptor',DWORD), 

137 ) 

138 

139# 2.2.8 RPC_SECURITY_ATTRIBUTES 

140class RPC_SECURITY_ATTRIBUTES(NDRSTRUCT): 

141 structure = ( 

142 ('nLength',DWORD), 

143 ('RpcSecurityDescriptor',RPC_SECURITY_DESCRIPTOR), 

144 ('bInheritHandle',BOOLEAN), 

145 ) 

146 

147class PRPC_SECURITY_ATTRIBUTES(NDRPOINTER): 

148 referent = ( 

149 ('Data', RPC_SECURITY_ATTRIBUTES), 

150 ) 

151 

152################################################################################ 

153# RPC CALLS 

154################################################################################ 

155# 3.1.5.1 OpenClassesRoot (Opnum 0) 

156class OpenClassesRoot(NDRCALL): 

157 opnum = 0 

158 structure = ( 

159 ('ServerName', PREGISTRY_SERVER_NAME), 

160 ('samDesired', REGSAM), 

161 ) 

162 

163class OpenClassesRootResponse(NDRCALL): 

164 structure = ( 

165 ('phKey', RPC_HKEY), 

166 ('ErrorCode', error_status_t), 

167 ) 

168 

169# 3.1.5.2 OpenCurrentUser (Opnum 1) 

170class OpenCurrentUser(NDRCALL): 

171 opnum = 1 

172 structure = ( 

173 ('ServerName', PREGISTRY_SERVER_NAME), 

174 ('samDesired', REGSAM), 

175 ) 

176 

177class OpenCurrentUserResponse(NDRCALL): 

178 structure = ( 

179 ('phKey', RPC_HKEY), 

180 ('ErrorCode', error_status_t), 

181 ) 

182 

183# 3.1.5.3 OpenLocalMachine (Opnum 2) 

184class OpenLocalMachine(NDRCALL): 

185 opnum = 2 

186 structure = ( 

187 ('ServerName', PREGISTRY_SERVER_NAME), 

188 ('samDesired', REGSAM), 

189 ) 

190 

191class OpenLocalMachineResponse(NDRCALL): 

192 structure = ( 

193 ('phKey', RPC_HKEY), 

194 ('ErrorCode', error_status_t), 

195 ) 

196 

197# 3.1.5.4 OpenPerformanceData (Opnum 3) 

198class OpenPerformanceData(NDRCALL): 

199 opnum = 3 

200 structure = ( 

201 ('ServerName', PREGISTRY_SERVER_NAME), 

202 ('samDesired', REGSAM), 

203 ) 

204 

205class OpenPerformanceDataResponse(NDRCALL): 

206 structure = ( 

207 ('phKey', RPC_HKEY), 

208 ('ErrorCode', error_status_t), 

209 ) 

210 

211# 3.1.5.5 OpenUsers (Opnum 4) 

212class OpenUsers(NDRCALL): 

213 opnum = 4 

214 structure = ( 

215 ('ServerName', PREGISTRY_SERVER_NAME), 

216 ('samDesired', REGSAM), 

217 ) 

218 

219class OpenUsersResponse(NDRCALL): 

220 structure = ( 

221 ('phKey', RPC_HKEY), 

222 ('ErrorCode', error_status_t), 

223 ) 

224 

225# 3.1.5.6 BaseRegCloseKey (Opnum 5) 

226class BaseRegCloseKey(NDRCALL): 

227 opnum = 5 

228 structure = ( 

229 ('hKey', RPC_HKEY), 

230 ) 

231 

232class BaseRegCloseKeyResponse(NDRCALL): 

233 structure = ( 

234 ('hKey', RPC_HKEY), 

235 ('ErrorCode', error_status_t), 

236 ) 

237 

238# 3.1.5.7 BaseRegCreateKey (Opnum 6) 

239class BaseRegCreateKey(NDRCALL): 

240 opnum = 6 

241 structure = ( 

242 ('hKey', RPC_HKEY), 

243 ('lpSubKey', RRP_UNICODE_STRING), 

244 ('lpClass', RRP_UNICODE_STRING), 

245 ('dwOptions', DWORD), 

246 ('samDesired', REGSAM), 

247 ('lpSecurityAttributes', PRPC_SECURITY_ATTRIBUTES), 

248 ('lpdwDisposition', LPULONG), 

249 ) 

250 

251class BaseRegCreateKeyResponse(NDRCALL): 

252 structure = ( 

253 ('phkResult', RPC_HKEY), 

254 ('lpdwDisposition', LPULONG), 

255 ('ErrorCode', error_status_t), 

256 ) 

257 

258# 3.1.5.8 BaseRegDeleteKey (Opnum 7) 

259class BaseRegDeleteKey(NDRCALL): 

260 opnum = 7 

261 structure = ( 

262 ('hKey', RPC_HKEY), 

263 ('lpSubKey', RRP_UNICODE_STRING), 

264 ) 

265 

266class BaseRegDeleteKeyResponse(NDRCALL): 

267 structure = ( 

268 ('ErrorCode', error_status_t), 

269 ) 

270 

271# 3.1.5.9 BaseRegDeleteValue (Opnum 8) 

272class BaseRegDeleteValue(NDRCALL): 

273 opnum = 8 

274 structure = ( 

275 ('hKey', RPC_HKEY), 

276 ('lpValueName', RRP_UNICODE_STRING), 

277 ) 

278 

279class BaseRegDeleteValueResponse(NDRCALL): 

280 structure = ( 

281 ('ErrorCode', error_status_t), 

282 ) 

283 

284# 3.1.5.10 BaseRegEnumKey (Opnum 9) 

285class BaseRegEnumKey(NDRCALL): 

286 opnum = 9 

287 structure = ( 

288 ('hKey', RPC_HKEY), 

289 ('dwIndex', DWORD), 

290 ('lpNameIn', RRP_UNICODE_STRING), 

291 ('lpClassIn', PRRP_UNICODE_STRING), 

292 ('lpftLastWriteTime', PFILETIME), 

293 ) 

294 

295class BaseRegEnumKeyResponse(NDRCALL): 

296 structure = ( 

297 ('lpNameOut', RRP_UNICODE_STRING), 

298 ('lplpClassOut', PRRP_UNICODE_STRING), 

299 ('lpftLastWriteTime', PFILETIME), 

300 ('ErrorCode', error_status_t), 

301 ) 

302 

303# 3.1.5.11 BaseRegEnumValue (Opnum 10) 

304class BaseRegEnumValue(NDRCALL): 

305 opnum = 10 

306 structure = ( 

307 ('hKey', RPC_HKEY), 

308 ('dwIndex', DWORD), 

309 ('lpValueNameIn', RRP_UNICODE_STRING), 

310 ('lpType', LPULONG), 

311 ('lpData', PBYTE_ARRAY), 

312 ('lpcbData', LPULONG), 

313 ('lpcbLen', LPULONG), 

314 ) 

315 

316class BaseRegEnumValueResponse(NDRCALL): 

317 structure = ( 

318 ('lpValueNameOut', RRP_UNICODE_STRING), 

319 ('lpType', LPULONG), 

320 ('lpData', PBYTE_ARRAY), 

321 ('lpcbData', LPULONG), 

322 ('lpcbLen', LPULONG), 

323 ('ErrorCode', error_status_t), 

324 ) 

325 

326# 3.1.5.12 BaseRegFlushKey (Opnum 11) 

327class BaseRegFlushKey(NDRCALL): 

328 opnum = 11 

329 structure = ( 

330 ('hKey', RPC_HKEY), 

331 ) 

332 

333class BaseRegFlushKeyResponse(NDRCALL): 

334 structure = ( 

335 ('ErrorCode', error_status_t), 

336 ) 

337 

338# 3.1.5.13 BaseRegGetKeySecurity (Opnum 12) 

339class BaseRegGetKeySecurity(NDRCALL): 

340 opnum = 12 

341 structure = ( 

342 ('hKey', RPC_HKEY), 

343 ('SecurityInformation', SECURITY_INFORMATION), 

344 ('pRpcSecurityDescriptorIn', RPC_SECURITY_DESCRIPTOR), 

345 ) 

346 

347class BaseRegGetKeySecurityResponse(NDRCALL): 

348 structure = ( 

349 ('pRpcSecurityDescriptorOut', RPC_SECURITY_DESCRIPTOR), 

350 ('ErrorCode', error_status_t), 

351 ) 

352 

353# 3.1.5.14 BaseRegLoadKey (Opnum 13) 

354class BaseRegLoadKey(NDRCALL): 

355 opnum = 13 

356 structure = ( 

357 ('hKey', RPC_HKEY), 

358 ('lpSubKey', RRP_UNICODE_STRING), 

359 ('lpFile', RRP_UNICODE_STRING), 

360 ) 

361 

362class BaseRegLoadKeyResponse(NDRCALL): 

363 structure = ( 

364 ('ErrorCode', error_status_t), 

365 ) 

366 

367# 3.1.5.15 BaseRegOpenKey (Opnum 15) 

368class BaseRegOpenKey(NDRCALL): 

369 opnum = 15 

370 structure = ( 

371 ('hKey', RPC_HKEY), 

372 ('lpSubKey', RRP_UNICODE_STRING), 

373 ('dwOptions', DWORD), 

374 ('samDesired', REGSAM), 

375 ) 

376 

377class BaseRegOpenKeyResponse(NDRCALL): 

378 structure = ( 

379 ('phkResult', RPC_HKEY), 

380 ('ErrorCode', error_status_t), 

381 ) 

382 

383# 3.1.5.16 BaseRegQueryInfoKey (Opnum 16) 

384class BaseRegQueryInfoKey(NDRCALL): 

385 opnum = 16 

386 structure = ( 

387 ('hKey', RPC_HKEY), 

388 ('lpClassIn', RRP_UNICODE_STRING), 

389 ) 

390 

391class BaseRegQueryInfoKeyResponse(NDRCALL): 

392 structure = ( 

393 ('lpClassOut', RPC_UNICODE_STRING), 

394 ('lpcSubKeys', DWORD), 

395 ('lpcbMaxSubKeyLen', DWORD), 

396 ('lpcbMaxClassLen', DWORD), 

397 ('lpcValues', DWORD), 

398 ('lpcbMaxValueNameLen', DWORD), 

399 ('lpcbMaxValueLen', DWORD), 

400 ('lpcbSecurityDescriptor', DWORD), 

401 ('lpftLastWriteTime', FILETIME), 

402 ('ErrorCode', error_status_t), 

403 ) 

404 

405# 3.1.5.17 BaseRegQueryValue (Opnum 17) 

406class BaseRegQueryValue(NDRCALL): 

407 opnum = 17 

408 structure = ( 

409 ('hKey', RPC_HKEY), 

410 ('lpValueName', RRP_UNICODE_STRING), 

411 ('lpType', LPULONG), 

412 ('lpData', PBYTE_ARRAY), 

413 ('lpcbData', LPULONG), 

414 ('lpcbLen', LPULONG), 

415 ) 

416 

417class BaseRegQueryValueResponse(NDRCALL): 

418 structure = ( 

419 ('lpType', LPULONG), 

420 ('lpData', PBYTE_ARRAY), 

421 ('lpcbData', LPULONG), 

422 ('lpcbLen', LPULONG), 

423 ('ErrorCode', error_status_t), 

424 ) 

425 

426# 3.1.5.18 BaseRegReplaceKey (Opnum 18) 

427class BaseRegReplaceKey(NDRCALL): 

428 opnum = 18 

429 structure = ( 

430 ('hKey', RPC_HKEY), 

431 ('lpSubKey', RRP_UNICODE_STRING), 

432 ('lpNewFile', RRP_UNICODE_STRING), 

433 ('lpOldFile', RRP_UNICODE_STRING), 

434 ) 

435 

436class BaseRegReplaceKeyResponse(NDRCALL): 

437 structure = ( 

438 ('ErrorCode', error_status_t), 

439 ) 

440 

441# 3.1.5.19 BaseRegRestoreKey (Opnum 19) 

442class BaseRegRestoreKey(NDRCALL): 

443 opnum = 19 

444 structure = ( 

445 ('hKey', RPC_HKEY), 

446 ('lpFile', RRP_UNICODE_STRING), 

447 ('Flags', DWORD), 

448 ) 

449 

450class BaseRegRestoreKeyResponse(NDRCALL): 

451 structure = ( 

452 ('ErrorCode', error_status_t), 

453 ) 

454 

455# 3.1.5.20 BaseRegSaveKey (Opnum 20) 

456class BaseRegSaveKey(NDRCALL): 

457 opnum = 20 

458 structure = ( 

459 ('hKey', RPC_HKEY), 

460 ('lpFile', RRP_UNICODE_STRING), 

461 ('pSecurityAttributes', PRPC_SECURITY_ATTRIBUTES), 

462 ) 

463 

464class BaseRegSaveKeyResponse(NDRCALL): 

465 structure = ( 

466 ('ErrorCode', error_status_t), 

467 ) 

468 

469# 3.1.5.21 BaseRegSetKeySecurity (Opnum 21) 

470class BaseRegSetKeySecurity(NDRCALL): 

471 opnum = 21 

472 structure = ( 

473 ('hKey', RPC_HKEY), 

474 ('SecurityInformation', SECURITY_INFORMATION), 

475 ('pRpcSecurityDescriptor', RPC_SECURITY_DESCRIPTOR), 

476 ) 

477 

478class BaseRegSetKeySecurityResponse(NDRCALL): 

479 structure = ( 

480 ('ErrorCode', error_status_t), 

481 ) 

482 

483# 3.1.5.22 BaseRegSetValue (Opnum 22) 

484class BaseRegSetValue(NDRCALL): 

485 opnum = 22 

486 structure = ( 

487 ('hKey', RPC_HKEY), 

488 ('lpValueName', RRP_UNICODE_STRING), 

489 ('dwType', DWORD), 

490 ('lpData', NDRUniConformantArray), 

491 ('cbData', DWORD), 

492 ) 

493 

494class BaseRegSetValueResponse(NDRCALL): 

495 structure = ( 

496 ('ErrorCode', error_status_t), 

497 ) 

498 

499# 3.1.5.23 BaseRegUnLoadKey (Opnum 23) 

500class BaseRegUnLoadKey(NDRCALL): 

501 opnum = 23 

502 structure = ( 

503 ('hKey', RPC_HKEY), 

504 ('lpSubKey', RRP_UNICODE_STRING), 

505 ) 

506 

507class BaseRegUnLoadKeyResponse(NDRCALL): 

508 structure = ( 

509 ('ErrorCode', error_status_t), 

510 ) 

511 

512# 3.1.5.24 BaseRegGetVersion (Opnum 26) 

513class BaseRegGetVersion(NDRCALL): 

514 opnum = 26 

515 structure = ( 

516 ('hKey', RPC_HKEY), 

517 ) 

518 

519class BaseRegGetVersionResponse(NDRCALL): 

520 structure = ( 

521 ('lpdwVersion', DWORD), 

522 ('ErrorCode', error_status_t), 

523 ) 

524 

525# 3.1.5.25 OpenCurrentConfig (Opnum 27) 

526class OpenCurrentConfig(NDRCALL): 

527 opnum = 27 

528 structure = ( 

529 ('ServerName', PREGISTRY_SERVER_NAME), 

530 ('samDesired', REGSAM), 

531 ) 

532 

533class OpenCurrentConfigResponse(NDRCALL): 

534 structure = ( 

535 ('phKey', RPC_HKEY), 

536 ('ErrorCode', error_status_t), 

537 ) 

538 

539# 3.1.5.26 BaseRegQueryMultipleValues (Opnum 29) 

540class BaseRegQueryMultipleValues(NDRCALL): 

541 opnum = 29 

542 structure = ( 

543 ('hKey', RPC_HKEY), 

544 ('val_listIn', RVALENT_ARRAY), 

545 ('num_vals', DWORD), 

546 ('lpvalueBuf', PBYTE_ARRAY), 

547 ('ldwTotsize', DWORD), 

548 ) 

549 

550class BaseRegQueryMultipleValuesResponse(NDRCALL): 

551 structure = ( 

552 ('val_listOut', RVALENT_ARRAY), 

553 ('lpvalueBuf', PBYTE_ARRAY), 

554 ('ldwTotsize', DWORD), 

555 ('ErrorCode', error_status_t), 

556 ) 

557 

558# 3.1.5.27 BaseRegSaveKeyEx (Opnum 31) 

559class BaseRegSaveKeyEx(NDRCALL): 

560 opnum = 31 

561 structure = ( 

562 ('hKey', RPC_HKEY), 

563 ('lpFile', RRP_UNICODE_STRING), 

564 ('pSecurityAttributes', PRPC_SECURITY_ATTRIBUTES), 

565 ('Flags', DWORD), 

566 ) 

567 

568class BaseRegSaveKeyExResponse(NDRCALL): 

569 structure = ( 

570 ('ErrorCode', error_status_t), 

571 ) 

572 

573# 3.1.5.28 OpenPerformanceText (Opnum 32) 

574class OpenPerformanceText(NDRCALL): 

575 opnum = 32 

576 structure = ( 

577 ('ServerName', PREGISTRY_SERVER_NAME), 

578 ('samDesired', REGSAM), 

579 ) 

580 

581class OpenPerformanceTextResponse(NDRCALL): 

582 structure = ( 

583 ('phKey', RPC_HKEY), 

584 ('ErrorCode', error_status_t), 

585 ) 

586 

587# 3.1.5.29 OpenPerformanceNlsText (Opnum 33) 

588class OpenPerformanceNlsText(NDRCALL): 

589 opnum = 33 

590 structure = ( 

591 ('ServerName', PREGISTRY_SERVER_NAME), 

592 ('samDesired', REGSAM), 

593 ) 

594 

595class OpenPerformanceNlsTextResponse(NDRCALL): 

596 structure = ( 

597 ('phKey', RPC_HKEY), 

598 ('ErrorCode', error_status_t), 

599 ) 

600 

601# 3.1.5.30 BaseRegQueryMultipleValues2 (Opnum 34) 

602class BaseRegQueryMultipleValues2(NDRCALL): 

603 opnum = 34 

604 structure = ( 

605 ('hKey', RPC_HKEY), 

606 ('val_listIn', RVALENT_ARRAY), 

607 ('num_vals', DWORD), 

608 ('lpvalueBuf', PBYTE_ARRAY), 

609 ('ldwTotsize', DWORD), 

610 ) 

611 

612class BaseRegQueryMultipleValues2Response(NDRCALL): 

613 structure = ( 

614 ('val_listOut', RVALENT_ARRAY), 

615 ('lpvalueBuf', PBYTE_ARRAY), 

616 ('ldwRequiredSize', DWORD), 

617 ('ErrorCode', error_status_t), 

618 ) 

619 

620# 3.1.5.31 BaseRegDeleteKeyEx (Opnum 35) 

621class BaseRegDeleteKeyEx(NDRCALL): 

622 opnum = 35 

623 structure = ( 

624 ('hKey', RPC_HKEY), 

625 ('lpSubKey', RRP_UNICODE_STRING), 

626 ('AccessMask', REGSAM), 

627 ('Reserved', DWORD), 

628 ) 

629 

630class BaseRegDeleteKeyExResponse(NDRCALL): 

631 structure = ( 

632 ('ErrorCode', error_status_t), 

633 ) 

634 

635################################################################################ 

636# OPNUMs and their corresponding structures 

637################################################################################ 

638OPNUMS = { 

639 0 : (OpenClassesRoot, OpenClassesRootResponse), 

640 1 : (OpenCurrentUser, OpenCurrentUserResponse), 

641 2 : (OpenLocalMachine, OpenLocalMachineResponse), 

642 3 : (OpenPerformanceData, OpenPerformanceDataResponse), 

643 4 : (OpenUsers, OpenUsersResponse), 

644 5 : (BaseRegCloseKey, BaseRegCloseKeyResponse), 

645 6 : (BaseRegCreateKey, BaseRegCreateKeyResponse), 

646 7 : (BaseRegDeleteKey, BaseRegDeleteKeyResponse), 

647 8 : (BaseRegDeleteValue, BaseRegDeleteValueResponse), 

648 9 : (BaseRegEnumKey, BaseRegEnumKeyResponse), 

64910 : (BaseRegEnumValue, BaseRegEnumValueResponse), 

65011 : (BaseRegFlushKey, BaseRegFlushKeyResponse), 

65112 : (BaseRegGetKeySecurity, BaseRegGetKeySecurityResponse), 

65213 : (BaseRegLoadKey, BaseRegLoadKeyResponse), 

65315 : (BaseRegOpenKey, BaseRegOpenKeyResponse), 

65416 : (BaseRegQueryInfoKey, BaseRegQueryInfoKeyResponse), 

65517 : (BaseRegQueryValue, BaseRegQueryValueResponse), 

65618 : (BaseRegReplaceKey, BaseRegReplaceKeyResponse), 

65719 : (BaseRegRestoreKey, BaseRegRestoreKeyResponse), 

65820 : (BaseRegSaveKey, BaseRegSaveKeyResponse), 

65921 : (BaseRegSetKeySecurity, BaseRegSetKeySecurityResponse), 

66022 : (BaseRegSetValue, BaseRegSetValueResponse), 

66123 : (BaseRegUnLoadKey, BaseRegUnLoadKeyResponse), 

66226 : (BaseRegGetVersion, BaseRegGetVersionResponse), 

66327 : (OpenCurrentConfig, OpenCurrentConfigResponse), 

66429 : (BaseRegQueryMultipleValues, BaseRegQueryMultipleValuesResponse), 

66531 : (BaseRegSaveKeyEx, BaseRegSaveKeyExResponse), 

66632 : (OpenPerformanceText, OpenPerformanceTextResponse), 

66733 : (OpenPerformanceNlsText, OpenPerformanceNlsTextResponse), 

66834 : (BaseRegQueryMultipleValues2, BaseRegQueryMultipleValues2Response), 

66935 : (BaseRegDeleteKeyEx, BaseRegDeleteKeyExResponse), 

670} 

671 

672################################################################################ 

673# HELPER FUNCTIONS 

674################################################################################ 

675def checkNullString(string): 

676 if string == NULL: 

677 return string 

678 

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

680 return string + '\x00' 

681 else: 

682 return string 

683 

684def packValue(valueType, value): 

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

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

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

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

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

690 try: 

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

692 except UnicodeDecodeError: 

693 import sys 

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

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

696 try: 

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

698 except UnicodeDecodeError: 

699 import sys 

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

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

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

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

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

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

706 try: 

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

708 except UnicodeDecodeError: 

709 import sys 

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

711 else: 

712 retData = value 

713 

714 return retData 

715 

716def unpackValue(valueType, value): 

717 if valueType == REG_DWORD: 

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

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

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

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

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

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

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

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

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

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

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

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

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

731 else: 

732 retData = b''.join(value) 

733 

734 return retData 

735 

736def hOpenClassesRoot(dce, samDesired = MAXIMUM_ALLOWED): 

737 request = OpenClassesRoot() 

738 request['ServerName'] = NULL 

739 request['samDesired'] = samDesired 

740 return dce.request(request) 

741 

742def hOpenCurrentUser(dce, samDesired = MAXIMUM_ALLOWED): 

743 request = OpenCurrentUser() 

744 request['ServerName'] = NULL 

745 request['samDesired'] = samDesired 

746 return dce.request(request) 

747 

748def hOpenLocalMachine(dce, samDesired = MAXIMUM_ALLOWED): 

749 request = OpenLocalMachine() 

750 request['ServerName'] = NULL 

751 request['samDesired'] = samDesired 

752 return dce.request(request) 

753 

754def hOpenPerformanceData(dce, samDesired = MAXIMUM_ALLOWED): 

755 request = OpenPerformanceData() 

756 request['ServerName'] = NULL 

757 request['samDesired'] = samDesired 

758 return dce.request(request) 

759 

760def hOpenUsers(dce, samDesired = MAXIMUM_ALLOWED): 

761 request = OpenUsers() 

762 request['ServerName'] = NULL 

763 request['samDesired'] = samDesired 

764 return dce.request(request) 

765 

766def hBaseRegCloseKey(dce, hKey): 

767 request = BaseRegCloseKey() 

768 request['hKey'] = hKey 

769 return dce.request(request) 

770 

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

772 request = BaseRegCreateKey() 

773 request['hKey'] = hKey 

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

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

776 request['dwOptions'] = dwOptions 

777 request['samDesired'] = samDesired 

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

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

780 else: 

781 request['lpSecurityAttributes'] = lpSecurityAttributes 

782 request['lpdwDisposition'] = lpdwDisposition 

783 

784 return dce.request(request) 

785 

786def hBaseRegDeleteKey(dce, hKey, lpSubKey): 

787 request = BaseRegDeleteKey() 

788 request['hKey'] = hKey 

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

790 return dce.request(request) 

791 

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

793 request = BaseRegEnumKey() 

794 request['hKey'] = hKey 

795 request['dwIndex'] = dwIndex 

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

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

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

799 request['lpftLastWriteTime'] = lpftLastWriteTime 

800 

801 return dce.request(request) 

802 

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

804 request = BaseRegEnumValue() 

805 request['hKey'] = hKey 

806 request['dwIndex'] = dwIndex 

807 retries = 1 

808 

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

810 while True: 

811 try: 

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

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

814 # needed to hold the value names. 

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

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

817 

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

819 request['lpcbData'] = dataLen 

820 request['lpcbLen'] = dataLen 

821 resp = dce.request(request) 

822 except DCERPCSessionError as e: 

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

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

825 raise 

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

827 # We need to adjust the size 

828 retries +=1 

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

830 continue 

831 else: 

832 raise 

833 else: 

834 break 

835 

836 return resp 

837 

838def hBaseRegFlushKey(dce, hKey): 

839 request = BaseRegFlushKey() 

840 request['hKey'] = hKey 

841 return dce.request(request) 

842 

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

844 request = BaseRegGetKeySecurity() 

845 request['hKey'] = hKey 

846 request['SecurityInformation'] = securityInformation 

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

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

849 

850 return dce.request(request) 

851 

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

853 request = BaseRegLoadKey() 

854 request['hKey'] = hKey 

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

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

857 return dce.request(request) 

858 

859def hBaseRegUnLoadKey(dce, hKey, lpSubKey): 

860 request = BaseRegUnLoadKey() 

861 request['hKey'] = hKey 

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

863 return dce.request(request) 

864 

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

866 request = BaseRegOpenKey() 

867 request['hKey'] = hKey 

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

869 request['dwOptions'] = dwOptions 

870 request['samDesired'] = samDesired 

871 return dce.request(request) 

872 

873def hBaseRegQueryInfoKey(dce, hKey): 

874 request = BaseRegQueryInfoKey() 

875 request['hKey'] = hKey 

876 # Not the cleanest way, but oh well 

877 # Plus, Windows XP needs MaximumCount also set 

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

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

880 return dce.request(request) 

881 

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

883 request = BaseRegQueryValue() 

884 request['hKey'] = hKey 

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

886 retries = 1 

887 

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

889 while True: 

890 try: 

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

892 request['lpcbData'] = dataLen 

893 request['lpcbLen'] = dataLen 

894 resp = dce.request(request) 

895 except DCERPCSessionError as e: 

896 if retries > 1: 

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

898 raise 

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

900 # We need to adjust the size 

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

902 continue 

903 else: 

904 raise 

905 else: 

906 break 

907 

908 # Returns 

909 # ( dataType, data ) 

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

911 

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

913 request = BaseRegReplaceKey() 

914 request['hKey'] = hKey 

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

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

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

918 return dce.request(request) 

919 

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

921 request = BaseRegRestoreKey() 

922 request['hKey'] = hKey 

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

924 request['Flags'] = flags 

925 return dce.request(request) 

926 

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

928 request = BaseRegSaveKey() 

929 request['hKey'] = hKey 

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

931 request['pSecurityAttributes'] = pSecurityAttributes 

932 return dce.request(request) 

933 

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

935 request = BaseRegSetValue() 

936 request['hKey'] = hKey 

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

938 request['dwType'] = dwType 

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

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

941 return dce.request(request) 

942 

943def hBaseRegGetVersion(dce, hKey): 

944 request = BaseRegGetVersion() 

945 request['hKey'] = hKey 

946 return dce.request(request) 

947 

948def hOpenCurrentConfig(dce, samDesired = MAXIMUM_ALLOWED): 

949 request = OpenCurrentConfig() 

950 request['ServerName'] = NULL 

951 request['samDesired'] = samDesired 

952 return dce.request(request) 

953 

954def hBaseRegQueryMultipleValues(dce, hKey, val_listIn): 

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

956 # have a bigger buffer for the data to receive 

957 request = BaseRegQueryMultipleValues() 

958 request['hKey'] = hKey 

959 

960 for item in val_listIn: 

961 itemn = RVALENT() 

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

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

964 itemn['ve_valueptr'] = NULL 

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

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

967 

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

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

970 request['ldwTotsize'] = 128 

971 

972 resp = dce.request(request) 

973 retVal = list() 

974 for item in resp['val_listOut']: 

975 itemn = dict() 

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

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

978 retVal.append(itemn) 

979 

980 return retVal 

981 

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

983 request = BaseRegSaveKeyEx() 

984 request['hKey'] = hKey 

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

986 request['pSecurityAttributes'] = pSecurityAttributes 

987 request['Flags'] = flags 

988 return dce.request(request) 

989 

990def hOpenPerformanceText(dce, samDesired = MAXIMUM_ALLOWED): 

991 request = OpenPerformanceText() 

992 request['ServerName'] = NULL 

993 request['samDesired'] = samDesired 

994 return dce.request(request) 

995 

996def hOpenPerformanceNlsText(dce, samDesired = MAXIMUM_ALLOWED): 

997 request = OpenPerformanceNlsText() 

998 request['ServerName'] = NULL 

999 request['samDesired'] = samDesired 

1000 return dce.request(request) 

1001 

1002def hBaseRegDeleteValue(dce, hKey, lpValueName): 

1003 request = BaseRegDeleteValue() 

1004 request['hKey'] = hKey 

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

1006 return dce.request(request)