|
46 | 46 | from impacket.dcerpc.v5.dcom import wmi |
47 | 47 | from impacket.dcerpc.v5.dcom.wmi import WBEMSTATUS |
48 | 48 | from impacket.dcerpc.v5.dcomrt import DCOMConnection, COMVERSION |
49 | | -from impacket.dcerpc.v5.dtypes import NULL |
| 49 | +from impacket.dcerpc.v5.dtypes import NULL, OWNER_SECURITY_INFORMATION, DACL_SECURITY_INFORMATION |
| 50 | +from impacket.dcerpc.v5 import transport, rrp |
| 51 | +from impacket.smbconnection import SMBConnection |
50 | 52 | from impacket.krb5.keytab import Keytab |
| 53 | +import struct |
51 | 54 |
|
52 | 55 | HIVE_MAP = { |
53 | 56 | 'HKLM': 0x80000002, 'HKEY_LOCAL_MACHINE': 0x80000002, |
@@ -277,6 +280,74 @@ def createkey(self, hive, subkey): |
277 | 280 | print('[-] CreateKey failed: %s' % e) |
278 | 281 | return False |
279 | 282 |
|
| 283 | + @staticmethod |
| 284 | + def takeown(address, username, password, domain, lmhash, nthash, |
| 285 | + aesKey, doKerberos, kdcHost, keypath): |
| 286 | + admin_sid = b'\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00' |
| 287 | + everyone_sid = b'\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00' |
| 288 | + system_sid = b'\x01\x01\x00\x00\x00\x00\x00\x05\x12\x00\x00\x00' |
| 289 | + |
| 290 | + smb = SMBConnection(address, address) |
| 291 | + if doKerberos: |
| 292 | + smb.kerberosLogin(username, password, domain, lmhash, nthash, |
| 293 | + aesKey, kdcHost=kdcHost) |
| 294 | + else: |
| 295 | + smb.login(username, password, domain, lmhash, nthash) |
| 296 | + |
| 297 | + rpctransport = transport.SMBTransport(address, filename=r'\winreg', |
| 298 | + smb_connection=smb) |
| 299 | + dce = rpctransport.get_dce_rpc() |
| 300 | + dce.connect() |
| 301 | + dce.bind(rrp.MSRPC_UUID_RRP) |
| 302 | + |
| 303 | + ans = rrp.hOpenLocalMachine(dce) |
| 304 | + hklm = ans['phKey'] |
| 305 | + |
| 306 | + try: |
| 307 | + print('[*] Opening key with WRITE_OWNER: %s' % keypath) |
| 308 | + ans = rrp.hBaseRegOpenKey(dce, hklm, keypath, samDesired=0x80000) |
| 309 | + hKey = ans['phkResult'] |
| 310 | + |
| 311 | + print('[*] Taking ownership (setting owner to Administrators)...') |
| 312 | + owner_sd = struct.pack('<BBHIIII', 1, 0, 0x8000, 20, 0, 0, 0) + admin_sid |
| 313 | + request = rrp.BaseRegSetKeySecurity() |
| 314 | + request['hKey'] = hKey |
| 315 | + request['SecurityInformation'] = OWNER_SECURITY_INFORMATION |
| 316 | + request['pRpcSecurityDescriptor']['lpSecurityDescriptor'] = list(owner_sd) |
| 317 | + request['pRpcSecurityDescriptor']['cbInSecurityDescriptor'] = len(owner_sd) |
| 318 | + request['pRpcSecurityDescriptor']['cbOutSecurityDescriptor'] = len(owner_sd) |
| 319 | + dce.request(request) |
| 320 | + print('[+] Ownership taken') |
| 321 | + |
| 322 | + rrp.hBaseRegCloseKey(dce, hKey) |
| 323 | + print('[*] Reopening with WRITE_DAC...') |
| 324 | + ans = rrp.hBaseRegOpenKey(dce, hklm, keypath, samDesired=0x40000) |
| 325 | + hKey = ans['phkResult'] |
| 326 | + |
| 327 | + print('[*] Setting DACL (Administrators + SYSTEM: full, Everyone: read)...') |
| 328 | + def _ace(mask, sid): |
| 329 | + body = struct.pack('<I', mask) + sid |
| 330 | + return struct.pack('<BBH', 0, 0x02, 4 + len(body)) + body |
| 331 | + |
| 332 | + aces = _ace(0xF003F, admin_sid) + _ace(0xF003F, system_sid) + _ace(0x20019, everyone_sid) |
| 333 | + acl = struct.pack('<BBHHH', 2, 0, 8 + len(aces), 3, 0) + aces |
| 334 | + dacl_sd = struct.pack('<BBHIIII', 1, 0, 0x8004, 0, 0, 0, 20) + acl |
| 335 | + |
| 336 | + request = rrp.BaseRegSetKeySecurity() |
| 337 | + request['hKey'] = hKey |
| 338 | + request['SecurityInformation'] = DACL_SECURITY_INFORMATION |
| 339 | + request['pRpcSecurityDescriptor']['lpSecurityDescriptor'] = list(dacl_sd) |
| 340 | + request['pRpcSecurityDescriptor']['cbInSecurityDescriptor'] = len(dacl_sd) |
| 341 | + request['pRpcSecurityDescriptor']['cbOutSecurityDescriptor'] = len(dacl_sd) |
| 342 | + dce.request(request) |
| 343 | + print('[+] DACL set — key is now writable') |
| 344 | + |
| 345 | + rrp.hBaseRegCloseKey(dce, hKey) |
| 346 | + finally: |
| 347 | + rrp.hBaseRegCloseKey(dce, hklm) |
| 348 | + dce.disconnect() |
| 349 | + smb.close() |
| 350 | + |
280 | 351 |
|
281 | 352 | # --------------------------------------------------------------------------- |
282 | 353 | # Service operations (Win32_Service, root/cimv2) |
@@ -990,6 +1061,14 @@ def _dispatch_reg(self, iWbemServices): |
990 | 1061 | logging.error('No registry action specified. Use -h for help.') |
991 | 1062 | return |
992 | 1063 |
|
| 1064 | + if opts.reg_action == 'takeown': |
| 1065 | + _, subkey = RegOps.parse_keyname(opts.keyName) |
| 1066 | + RegOps.takeown(self.__options.target_ip, self.__username, |
| 1067 | + self.__password, self.__domain, self.__lmhash, |
| 1068 | + self.__nthash, self.__aesKey, self.__doKerberos, |
| 1069 | + self.__kdcHost, subkey) |
| 1070 | + return |
| 1071 | + |
993 | 1072 | ops = RegOps(iWbemServices) |
994 | 1073 | hive, subkey = RegOps.parse_keyname(opts.keyName) |
995 | 1074 |
|
@@ -1201,6 +1280,11 @@ def _dispatch_share(self, iWbemServices): |
1201 | 1280 | p = reg_sub.add_parser('createkey', help='Create a registry key') |
1202 | 1281 | p.add_argument('-keyName', required=True, help='Registry key path') |
1203 | 1282 |
|
| 1283 | + p = reg_sub.add_parser('takeown', |
| 1284 | + help='Take ownership of a registry key via Remote Registry (requires RemoteRegistry service)') |
| 1285 | + p.add_argument('-keyName', required=True, |
| 1286 | + help='Registry key path (e.g. HKLM\\SOFTWARE\\Classes\\CLSID\\{...})') |
| 1287 | + |
1204 | 1288 | # ===================== service ===================== |
1205 | 1289 | svc_parser = subparsers.add_parser('service', |
1206 | 1290 | help='Service operations via WMI Win32_Service') |
|
0 commit comments