Skip to content

Commit 57959ff

Browse files
committed
Add reg takeown subcommand and Remote Registry support to wmimultitool.py
Adds 'reg takeown' subcommand that takes ownership of TrustedInstaller-owned registry keys via Remote Registry (MS-RRP). Uses RegSetKeySecurity to change owner to Administrators, then sets a DACL granting Administrators + SYSTEM full control and Everyone read access. Required for COM CLSID TreatAs hijack technique where WbemLocator InprocServer32 key is TrustedInstaller-owned. Also adds imports for SMBConnection, transport, and rrp modules.
1 parent c6c74a7 commit 57959ff

1 file changed

Lines changed: 85 additions & 1 deletion

File tree

examples/wmimultitool.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@
4646
from impacket.dcerpc.v5.dcom import wmi
4747
from impacket.dcerpc.v5.dcom.wmi import WBEMSTATUS
4848
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
5052
from impacket.krb5.keytab import Keytab
53+
import struct
5154

5255
HIVE_MAP = {
5356
'HKLM': 0x80000002, 'HKEY_LOCAL_MACHINE': 0x80000002,
@@ -277,6 +280,74 @@ def createkey(self, hive, subkey):
277280
print('[-] CreateKey failed: %s' % e)
278281
return False
279282

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

281352
# ---------------------------------------------------------------------------
282353
# Service operations (Win32_Service, root/cimv2)
@@ -990,6 +1061,14 @@ def _dispatch_reg(self, iWbemServices):
9901061
logging.error('No registry action specified. Use -h for help.')
9911062
return
9921063

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+
9931072
ops = RegOps(iWbemServices)
9941073
hive, subkey = RegOps.parse_keyname(opts.keyName)
9951074

@@ -1201,6 +1280,11 @@ def _dispatch_share(self, iWbemServices):
12011280
p = reg_sub.add_parser('createkey', help='Create a registry key')
12021281
p.add_argument('-keyName', required=True, help='Registry key path')
12031282

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+
12041288
# ===================== service =====================
12051289
svc_parser = subparsers.add_parser('service',
12061290
help='Service operations via WMI Win32_Service')

0 commit comments

Comments
 (0)