def load_interfaces(reg_file):
    try:
        reg_handle = Registry(reg_file)
        int_keys = reg_handle.open('Microsoft\\WlanSvc\\Interfaces')
    except Exception as e:
        print(
            "I could not open the specified SOFTWARE registry key. It is usually located in \Windows\system32\config but is locked by the OS."
        )
        print("Error : ", str(e))
        return {}
    profile_lookup = {}
    for eachinterface in int_keys.subkeys():
        if len(eachinterface.subkeys()) == 0:
            continue
        for eachprofile in eachinterface.subkey("Profiles").subkeys():
            profileid = [
                x.value() for x in eachprofile.values()
                if x.name() == "ProfileIndex"
            ][0]
            metadata = eachprofile.subkey("MetaData").values()
            for eachvalue in metadata:
                if eachvalue.name() == "Channel Hints":
                    channelhintraw = eachvalue.value()
                    hintlength = struct.unpack("I", channelhintraw[0:4])[0]
                    name = channelhintraw[4:hintlength + 4]
                    profile_lookup[str(profileid)] = name
    return profile_lookup
Beispiel #2
0
 def load_reg_history(self, path_to_reg):
     reg_handle = Registry(path_to_reg)
     for eachsubkey in reg_handle.open(
             r"Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged"
     ).subkeys():
         reg_mac = eachsubkey.value("DefaultGatewayMac").value()
         if not reg_mac:
             continue
         BSSID = b':'.join(
             codecs.encode(reg_mac[i:i + 1], "hex")
             for i in range(0, 6)).decode().upper()
         SSID = eachsubkey.value("FirstNetwork").value()
         ProfileGuid = eachsubkey.value("ProfileGuid").value()
         nettype, first, last = resolver.get_profile_info(
             reg_handle, ProfileGuid)
         location = None
         if nettype == "Wireless":
             if SSID in self.Locations.ap_ssids:
                 location = self.Locations.best_ssid_location(SSID)
             elif BSSID in self.Locations.ap_bssids:
                 location = self.Locations.best_bssid_location(BSSID)
             assert not isinstance(location, list)
             if location:
                 self.data.append(
                     Event(first, location,
                           f"{SSID} {BSSID}-First-Connect"))
                 self.data.append(
                     Event(last, location, f"{SSID} {BSSID}-Last-Connect"))
     return
def main():

    args: Type[DumpWindowsSecretsFromRegDumpsArgumentParser.
               Namespace] = DumpWindowsSecretsFromRegDumpsArgumentParser(
               ).parse_args()

    boot_key: bytes = get_boot_key(lsa_registry=Registry(
        BytesIO(args.system_dump_path.read_bytes())),
                                   from_root=True)

    domain_cached_credentials, policy_secrets = (
        None, None) if not args.security_dump_path else dump_lsa_secrets(
            security_registry=Registry(
                BytesIO(args.security_dump_path.read_bytes())),
            boot_key=boot_key)

    sam_entries: Optional[list[SAMEntry]] = dump_sam_secrets(
        sam_dump=args.sam_dump_path.read_bytes(),
        boot_key=boot_key) if args.sam_dump_path else None

    print(
        get_secrets_output_string(
            sam_entries=sam_entries,
            domain_cached_credentials=domain_cached_credentials,
            policy_secrets=policy_secrets))
Beispiel #4
0
def registry_wifi_to_BSSID(wifi_name, reg_path = r"c:\Windows\system32\config\SOFTWARE"):
    reg_handle = Registry(reg_path)
    subkeys = reg_handle.open(r"Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged").subkeys()
    for eachkey in subkeys:
        if eachkey.value("FirstNetwork").value().lower() == wifi_name.lower():
            reg_mac = eachkey.value("DefaultGatewayMac").value()
            BSSID = b':'.join(codecs.encode(reg_mac[i:i+1],"hex") for i in range(0,6)).decode().upper()
            return BSSID
Beispiel #5
0
def getCryptUsername(sSoftware, sSID):
    with open(sSoftware, 'rb') as oFile:
        oReg = Registry(oFile)
        oRegKey = oReg.open(
            'Microsoft\\Windows\\CurrentVersion\\Authentication\\Credential Providers\\{D6886603-9D2F-4EB2-B667-1971041FA96B}'
        )
        for oKey in oRegKey.subkeys():
            if oKey.name() in sSID:
                return oKey.subkey('UserNames').subkeys()[0].name()
    return '<Unknown>'
Beispiel #6
0
def registry_all_wireless(reg_path = r"c:\Windows\system32\config\SOFTWARE"):
    reg_handle = Registry(reg_path)
    subkeys = reg_handle.open(r"Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged").subkeys()
    result = []
    for eachkey in subkeys:
        name = eachkey.value("FirstNetwork").value()
        reg_mac = eachkey.value("DefaultGatewayMac").value()
        if not int.from_bytes(reg_mac, "big"):
            continue
        BSSID = b':'.join(codecs.encode(reg_mac[i:i+1],"hex") for i in range(0,6)).decode().upper()
        result.append( (name,BSSID) )
    return result
def get_security_policy_secrets(
    security_registry: Registry,
    policy_secrets_decryption_key: bytes,
    use_new_style: bool = True
) -> Dict[str, bytes]:

    security_policy_secret_keys = (
        security_policy_key
        for security_policy_key in security_registry.open(r'Policy\Secrets').subkeys()
        if security_policy_key.name() != 'NL$Control'
    )

    secret_name_to_secret_data: Dict[str, bytes] = dict()

    for security_policy_secret_key in security_policy_secret_keys:
        for value_type in ('CurrVal', 'OldVal'):
            encrypted_secret_data = security_policy_secret_key.subkey(value_type).value('(default)').raw_data()
            if not encrypted_secret_data:
                continue

            if use_new_style:
                secret_data = LSASecret.from_bytes(
                    data=encrypted_secret_data
                ).blob(decryption_key=policy_secrets_decryption_key).secret
            else:
                raise NotImplementedError

            secret_name_to_secret_data[
                security_policy_secret_key.name() + ('_history' if value_type == 'OldVal' else '')
            ] = secret_data

    return secret_name_to_secret_data
def get_boot_key(lsa_registry: Registry, from_root: bool = False):

    return transform_untransformed_boot_key(
        untransformed_boot_key=bytes.fromhex(''.join(
            lsa_registry.open(boot_key_path.name if not from_root else str(
                boot_key_path))._nkrecord.classname()
            for boot_key_path in BOOT_KEY_PARTS_PATHS)))
def load_registry_sids(reg_file):
    """Given Software hive find SID usernames"""
    sids = {}
    profile_key = r"Microsoft\Windows NT\CurrentVersion\ProfileList"
    tgt_value = "ProfileImagePath"
    try:
        reg_handle = Registry(reg_file)
        key_handle = reg_handle.open(profile_key)
        for eachsid in key_handle.subkeys():
            sids_path = eachsid.value(tgt_value).value()
            sids[eachsid.name()] = sids_path.split("\\")[-1]
    except Exception as e:
        print(str(e))
        return {}
    print("Loaded SIDS", sids)
    return sids
def get_encrypted_policy_secrets_encryption_key(
        security_registry: Registry) -> tuple[bytes, bool]:
    """
    :param security_registry:
    :return:
    """

    try:
        return security_registry.open(r'Policy\PolEKList').value(
            '(default)').raw_data(), True
    except RegistryValueNotFoundException:
        pass

    try:
        return security_registry.open(r'Policy\PolSecretEncryptionKey').value(
            '(default)').raw_data(), False
    except RegistryValueNotFoundException:
        pass

    # TODO: Add a proper exception.
    raise Exception
Beispiel #11
0
def load_interfaces(reg_file):
    try:
        reg_handle = Registry(reg_file)
    except Exception as e:
        log.info("I could not open the specified SOFTWARE registry key. It is usually located in \Windows\system32\config.  This is an optional value.  If you cant find it just dont provide one.")
        log.info(f"WARNING : {str(e)} ")
        return {}
    try:
        int_keys = reg_handle.open('Microsoft\\WlanSvc\\Interfaces')
    except Exception as e:
        log.info("There doesn't appear to be any wireless interfaces in this registry file.")
        log.info(f"WARNING : {str(e)} ")
        return {}
    ssid2bssid = {}
    for eachsubkey in reg_handle.open(r"Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged").subkeys():
        DefaultGatewayMac = eachsubkey.value("DefaultGatewayMac").value()
        BSSID =  b':'.join(codecs.encode(DefaultGatewayMac[i:i+1],"hex") for i in range(0,6)).decode().upper()
        if BSSID == "00:00:00:00:00:00":
            continue
        SSID = eachsubkey.value("FirstNetwork").value()
        ssid2bssid[SSID]=BSSID    
    profile_lookup = {}
    for eachinterface in int_keys.subkeys():
        if len(eachinterface.subkeys())==0:
            continue
        for eachprofile in eachinterface.subkey("Profiles").subkeys():
            profileid = eachprofile.value("ProfileIndex").value()
            try:
                channelhintraw = eachprofile.subkey("MetaData").value("Channel Hints").value()
            except:
                continue
            hintlength = struct.unpack("I", channelhintraw[0:4])[0]
            ssid = channelhintraw[4:hintlength+4].decode()
            bssid = ssid2bssid.get(ssid)
            if bssid:
                profile_lookup[str(profileid)] = (bssid,ssid)
    return profile_lookup
Beispiel #12
0
def main(sSOFTWARE, boolOutput = True):
    with open(sSOFTWARE, 'rb') as oFile:
        oReg = Registry(oFile)
        oKey = oReg.open('Microsoft\\Windows\\CurrentVersion\\Authentication\\LogonUI\\NgcPin\\Credentials')
        arrSIDs = []
        for oSubKey in oKey.subkeys():
            sSID = oSubKey.name()
            bData = oSubKey.value('EncryptedPassword').value()
            arrSIDs.append((sSID, bData))

        if boolOutput: print('[+] Found ' + str(len(arrSIDs)) + ' stored NgcPin Password(s) in the registry :\n')
        oKey = oReg.open('Microsoft\\Windows\\CurrentVersion\\Authentication\\Credential Providers\\{D6886603-9D2F-4EB2-B667-1971041FA96B}')
        arrUsers = []
        for oSubKey in oKey.subkeys():
            for oItem in arrSIDs:
                if oItem[0] == oSubKey.name():
                    sUsername = oSubKey.subkey('UserNames').subkeys()[0].name()
                    if boolOutput:
                        print('[+] SID         : ' + oItem[0])
                        print('[+] Username    : '******'=' * 20)
    return arrUsers
def dump_sam_secrets(sam_dump: bytes, boot_key: bytes) -> List[SAMEntry]:
    """
    Dump secrets from a SAM registry hive.
    The hashes are are stored in an double-encrypted format, and must first be decrypted.
    :param sam_dump: The SAM registry hive as a bytes.
    :param boot_key: The boot key as bytes.
    :return: A list of LM and NT hashes for each user in the SAM registry hive of the target host.
    """

    sam_registry = Registry(BytesIO(sam_dump))

    hashed_bootkey: bytes = obtain_hashed_bootkey(
        domain_account_f=DomainAccountF.from_bytes(
            data=sam_registry.open(r'SAM\Domains\Account').value('F').raw_data()
        ),
        bootkey=boot_key
    )

    sam_entries: List[SAMEntry] = []

    rid_strings = (
        value.name()
        for value in sam_registry.open(r'SAM\Domains\Account\Users').subkeys()
        if value.name() != 'Names'
    )

    for rid_string in rid_strings:
        user_account_v = UserAccountV.from_bytes(
            data=sam_registry.open(f'SAM\\Domains\\Account\\Users\\{rid_string}').value('V').raw_data()
        )

        lm_hash, nt_hash = obtain_hashes_for_rid(
            rid=int(rid_string, 16),
            double_encrypted_lm_hash=user_account_v.encrypted_lm_hash,
            double_encrypted_nt_hash=user_account_v.encrypted_nt_hash,
            hashed_bootkey=hashed_bootkey
        )

        password_hint = ''
        with suppress(RegistryValueNotFoundException):
            password_hint = sam_registry.open(
                path=f'SAM\\Domains\\Account\\Users\\{rid_string}'
            ).value('UserPasswordHint').raw_data().decode(encoding='utf-16le')

        sam_entries.append(
            SAMEntry(
                rid=int(rid_string, 16),
                account_name=user_account_v.name,
                password_hint=password_hint,
                lm_hash=lm_hash,
                nt_hash=nt_hash
            )
        )

    return sam_entries
def get_domain_cached_credentials(
    security_registry: Registry,
    cached_credentials_decryption_key: bytes,
    use_new_style: bool = True
) -> List[DomainCachedCredentials2]:
    iteration_count = 10240
    with suppress(RegistryValueNotFoundException):
        reg_iteration_count = struct_unpack('<L', security_registry.open(r'Cache').value('NL$IterationCount'))[0]
        iteration_count = reg_iteration_count & 0xfffffc00 if reg_iteration_count > 10240 else reg_iteration_count * 1024

    registry_cache_entries = (
        RegistryCacheEntry.from_bytes(cache_key.raw_data())
        for cache_key in security_registry.open('Cache').values()
        if cache_key.name() not in {'NL$Control', 'NL$IterationCount'}
    )

    domain_cached_credentials: List[Union[DomainCachedCredentials, DomainCachedCredentials2]] = list()

    for registry_cache_entry in registry_cache_entries:
        if registry_cache_entry.initialization_vector == b'\x00' * 16:
            continue

        # TODO: Make nicer? (and parse flags in class)?
        if registry_cache_entry.flags & 1 == 1:
            if use_new_style:
                decrypted_cached_entry_data = decrypt_aes(
                    key=cached_credentials_decryption_key,
                    value=registry_cache_entry.encrypted_data,
                    initialization_vector=registry_cache_entry.initialization_vector
                )
            else:
                raise NotImplementedError
                # TODO: For some reason impacket uses `encrypt()`. Confirm that `decrypt()` is correct.
                # decrypted_cached_entry_data = ARC4.new(
                #     key=HMAC.new(
                #         key=nlkm_key,
                #         msg=registry_cache_entry.initialization_vector,
                #     ).digest()
                # ).decrypt(ciphertext=registry_cache_entry.encrypted_data)
        else:
            # "Plain! Until we figure out what this is, we skip it"
            raise NotImplementedError

        def calc_padded_length(length: int) -> int:
            return length + (length & 0x3) if (length & 0x3) > 0 else length

        padded_user_length = calc_padded_length(registry_cache_entry.user_length)
        padded_domain_length = calc_padded_length(registry_cache_entry.domain_name_length)

        encrypted_hash = decrypted_cached_entry_data[:16]
        username = decrypted_cached_entry_data[72:72+registry_cache_entry.user_length].decode(encoding='utf-16le')
        dns_domain_name = decrypted_cached_entry_data[
            72+padded_user_length+padded_domain_length
            :
            72+padded_user_length+padded_domain_length+registry_cache_entry.dns_domain_name_length
        ].decode(encoding='utf-16-le')

        if use_new_style:
            domain_cached_credentials.append(
                DomainCachedCredentials2(
                    iteration_count=iteration_count,
                    dns_domain_name=dns_domain_name,
                    username=username,
                    encrypted_hash=encrypted_hash
                )
            )
        else:
            domain_cached_credentials.append(
                DomainCachedCredentials(
                    dns_domain_name=dns_domain_name,
                    username=username,
                    encrypted_hash=encrypted_hash
                )
            )

    return domain_cached_credentials
Beispiel #15
0
 def unpack(self, data):
     with MemoryFile(data) as stream:
         root = Registry(stream).root()
         yield from self._walk(root, root.name())
Beispiel #16
0
 def process(self, data):
     with io.BytesIO(data) as stream:
         yield from self._walk(Registry(stream).root())
async def dump_remote_windows_secrets(
    smb_session: SMBv2Session,
    skip_lsa_secrets: bool = False,
    skip_sam_secrets: bool = False,
    dump_reg_share_name: str = 'C$',
    dump_reg_path: Optional[PureWindowsPath] = None
) -> tuple[Optional[list[SAMEntry]], Optional[list[DomainCachedCredentials2]], Optional[dict[str, bytes]]]:
    """
    Dump Windows secrets remotely over SMB.

    The secrets are obtained by reading and then processing data from the Windows registry. The MS-RRP protocol is used
    to do read this data remotely. The relevant registry values are saved to disk on the remote system with the
    `BaseRegSaveKey` RRP operation, and are then retrieved via the SMB READ command, after which the files on disk are
    deleted.

    :param smb_session: An SMB session with which to remotely dump the Windows secrets.
    :param skip_lsa_secrets: Whether to skip the extraction of LSA secrets.
    :param skip_sam_secrets: Whether to skip the extraction of SAM secrets.
    :param dump_reg_share_name: A name of an SMB share on the remote system in which the disk-saved registry values can
        be obtained.
    :param dump_reg_path: A path on the remote system where the relevant registry values are to be saved on disk.
    :return: Optionally, a list of SAM entries, domain cached credentials, and policy secrets.
    """

    if skip_lsa_secrets and skip_sam_secrets:
        return None, None, None

    async with smb_session.tree_connect(share_name=dump_reg_share_name) as (tree_id, _):
        async with smb_session.make_smbv2_transport(pipe=MS_RRP_PIPE_NAME) as (r, w):
            async with RPCConnection(reader=r, writer=w) as rpc_connection:
                await rpc_connection.bind(
                    presentation_context_list=ContextList([
                        ContextElement(context_id=0, abstract_syntax=MS_RRP_ABSTRACT_SYNTAX)
                    ])
                )

                open_local_machine_options = dict(
                    rpc_connection=rpc_connection,
                    request=OpenLocalMachineRequest(
                        sam_desired=Regsam(maximum_allowed=True)
                    )
                )
                async with open_local_machine(**open_local_machine_options) as local_machine_key_handle:
                    # TODO: `asyncio.gather` isn't working here for some reason...

                    lsa_data: bytes = await dump_reg(
                        rpc_connection=rpc_connection,
                        smb_session=smb_session,
                        root_key_handle=local_machine_key_handle,
                        tree_id=tree_id,
                        sub_key_name=r'SYSTEM\CurrentControlSet\Control\Lsa',
                        save_path=dump_reg_path
                    )

                    security_data: Optional[bytes] = await dump_reg(
                        rpc_connection=rpc_connection,
                        smb_session=smb_session,
                        root_key_handle=local_machine_key_handle,
                        tree_id=tree_id,
                        sub_key_name='SECURITY',
                        save_path=dump_reg_path
                    ) if not skip_lsa_secrets else None

                    sam_data: Optional[bytes] = await dump_reg(
                        rpc_connection=rpc_connection,
                        smb_session=smb_session,
                        root_key_handle=local_machine_key_handle,
                        tree_id=tree_id,
                        sub_key_name='SAM',
                        save_path=dump_reg_path
                    ) if not skip_sam_secrets else None

    boot_key = get_boot_key(lsa_registry=Registry(BytesIO(lsa_data)), from_root=False)

    if not skip_lsa_secrets:
        domain_cached_credentials, policy_secrets = dump_lsa_secrets(
            security_registry=Registry(BytesIO(security_data)),
            boot_key=boot_key
        )
    else:
        domain_cached_credentials, policy_secrets = None, None

    return (
        dump_sam_secrets(sam_dump=sam_data, boot_key=boot_key) if not skip_sam_secrets else None,
        domain_cached_credentials,
        policy_secrets
    )