o
    j                     @   s  d dl Z d dlZd dl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mZ d dlmZmZ d dlmZ d dlmZmZ d dlZG d	d
 d
ZG dd deZG dd deZG dd deZG dd deZG dd deZdd Zedkr^eej e Z e!e j"e j# eeeedZ$ze$e j% Z&W n e'y   e(de j%  e)d Y nw ee j*\Z+Z,Z-Z.e+se j%dv rdZ+ne.Z+e j/durz
e j/0d\Z1Z2W n e3y   eZ1e j/Z2Y nw dZ1dZ2e-dkre2dkre j4rn(e j5re6d nzed Z-W n e7y   e  e8d! e)d" Y nw e j9durFdZ:ze j90d\Z;Z<e;s5eZ;W nK e3yE   eZ;e j9Z<Y n=w dZ;dZ<e j=du rzed#Z:e:ed$krfe(d% e)d W n e7y~   e  e8d! e)d" Y nw e j=Z:e j>durz
e j>0d&\Z?Z@W n e3y   e+Z?e j>Z@Y nw e jAdurz
e jA0d\ZBZCW n e3y   dZBe jAZCY nw dZBdZCdZDe jEdure jEZDe jEdu re jAdu re j5se(d' e)d n
e+Z?e,Z@e-ZDe1ZBe2ZCe jFZGe j%d(kr	eGs	e#d) d*ZGe&e.e?e@eDeBeCeGe jHe jId+	ZJe j4r&eJKe,e+e:e;e<ZLn'e?e@fe+e,fkrAe8d,e+ d&e, d-e? d&e@ d.	 eJMe,e+e-e:e1e2e;e<ZLeLrWe)d  dS e)d dS dS )/    N)getpass)version)	transportsamrepm)
kerberosv5kpasswd)ldapldapasn1)logger)parse_targetEMPTY_LM_HASHc                   @   s^   e Zd ZdZ								dddZdd Z								dd	d
Zdd ZdddZdS )PasswordHandlerzIGeneric interface for all the password protocols supported by this script FNc
           
      C   s:   || _ || _|| _|| _|| _|| _|| _|| _|	| _dS )a  
        Instantiate password change or reset with the credentials of the account making the changes.
        It can be the target user, or a privileged account.

        :param string address:  IP address or hostname of the server or domain controller where the password will be changed
        :param string domain:   AD domain where the password will be changed
        :param string username: account that will attempt the password change or reset on the target(s)
        :param string password: password of the account that will attempt the password change
        :param string pwdHashLM: LM hash of the account that will attempt the password change
        :param string pwdHashNT: NT hash of the account that will attempt the password change
        :param bool doKerberos: use Kerberos authentication instead of NTLM
        :param string aesKey:   AES key for Kerberos authentication
        :param string kdcHost:  KDC host
        N)	addressdomainusernamepassword	pwdHashLM	pwdHashNT
doKerberosaesKeykdcHost)
selfr   r   authUsernameauthPasswordauthPwdHashLMauthPwdHashNTr   r   r    r   /root/aizidognhua/tmp/workspace/projects/ec89d86c-575f-41c9-af57-ac45cbdbf775/venv/lib/python3.10/site-packages/../../../bin/changepasswd.py__init__   s   
zPasswordHandler.__init__c	           	      C      t )z#Implementation of a password changeNotImplementedError	r   targetUsernametargetDomainoldPasswordnewPasswordoldPwdHashLMoldPwdHashNTnewPwdHashLMnewPwdHashNTr   r   r   _changePassword   s   zPasswordHandler._changePasswordc	           	   
   C   st   |du r#| j }|du r| j}|du r| j}|du r| j}|du r#| j}td| d|  | ||||||||S )a  
        Change the password of a target account, knowing the previous password.

        :param string targetUsername: account whose password will be changed, if different from the user performing the change
        :param string targetDomain:   domain of the account
        :param string oldPassword:    current password
        :param string newPassword:    new password
        :param string oldPwdHashLM:   current password, as LM hash
        :param string oldPwdHashMT:   current password, as NT hash
        :param string newPwdHashLM:   new password, as LM hash
        :param string newPwdHashMT:   new password, as NT hash

        :return bool success
        NzChanging the password of \)r   r   r   r   r   logginginfor-   r$   r   r   r   changePassword   s   zPasswordHandler.changePasswordc                 C   r!   )z Implementation of a password setr"   r   r%   r&   r(   r+   r,   r   r   r   _setPassword   s   zPasswordHandler._setPasswordc              
   C   sF   |du r| j }td| d| d| j  d| j  | |||||S )a  
        Set or Reset the password of a target account, with privileges.

        :param string targetUsername:   account whose password will be changed
        :param string targetDomain:     domain of the account
        :param string newPassword:      new password
        :param string newPwdHashLM:     new password, as LM hash
        :param string newPwdHashMT:     new password, as NT hash

        :return bool success
        NzSetting the password of r.    as )r   r/   r0   r   r3   r2   r   r   r   setPassword   s   &zPasswordHandler.setPassword)r   r   r   r   r   Fr   N)NNNr   NNr   r   )Nr   r   r   )	__name__
__module____qualname____doc__r    r-   r1   r3   r5   r   r   r   r   r      s.    
%
,r   c                   @   s    e Zd ZdZdd Zdd ZdS )	KPasswordzTUse Kerberos Change-Password or Set-Password protocols (rfc3244) to change passwordsc	           
   
   C   s   || j krtd dS |std dS z t||||||| j| jf tj||||||| j| jd W n tj	tj
fyT }	 ztd|	  W Y d }	~	dS d }	~	ww td dS )NzZKPassword does not support changing the password of another user (try setPassword instead)F0KPassword requires the new password as plaintextr   r   zPassword not changed: "Password was changed successfully.T)r   r/   criticaldebugr   r   r   r1   r   KerberosErrorKPasswdErrorerrorr0   )
r   r%   r&   r'   r(   r)   r*   r+   r,   er   r   r   r-      sF   





zKPassword._changePasswordc                 C   s   |s	t d dS ztj| j| j|||| j| j| j| j	| j
d
 W n% tjtjfyF } zt d| d| d|  W Y d }~dS d }~ww t d| d| d d	S )
Nr;   Fr<   zPassword not changed for r.   : z"Password was set successfully for .T)r/   r>   r   r5   r   r   r   r   r   r   r   r   r@   rA   rB   r0   )r   r%   r&   r(   r+   r,   rC   r   r   r   r3   '  s.   

zKPassword._setPasswordN)r6   r7   r8   r9   r-   r3   r   r   r   r   r:      s    )r:   c                   @   sr   e Zd ZdZdZdZdd ZdddZddd	Zd
d Z	ddddZ
dd Zdd Zdd Zdd Zdd ZdS )SamrPasswordz>Use MS-SAMR protocol to change or reset the password of a userNFc                 C   r!   )zf
        Return a new transport for our RPC/DCE.

        :return rpc: RPC transport instance
        r"   r   r   r   r   rpctransportH  s   zSamrPassword.rpctransportc                 C   s   |   }t|dr(|r|jddddddd n|j| j| j| j| j| j| jd |r4d| _	|
dd nd| _	|
| j| j |rCdn| j d	| j }td
|  | }|  |tj td |S )z
        Instantiate a new transport and try to authenticate

        :param bool anonymous: Attempt a null binding
        :return dce: DCE/RPC, bound to SAMR
        set_credentialsr   )r   r   r   lmhashnthashr   )r   TFNznull sessionr.   zConnecting to DCE/RPC as zSuccessfully bound to SAMR)rH   hasattrrI   r   r   r   r   r   r   	anonymousset_kerberosr   r   r/   r0   get_dce_rpcconnectbindr   MSRPC_UUID_SAMRr?   )r   rM   rH   as_userdcer   r   r   authenticateP  s0   
	
zSamrPassword.authenticatec              
      s:  | j rdS z
| jdd| _ W dS  ty   zt fdddD rD|r1td | jdd| _ n`td tt  W Y d	  dS d
t v r]td tt  W Y d	  dS dt v rvtd tt  W Y d	  dS dt v rtd tt  W Y d	  dS  W Y d	  dS d	  ww )z
        Connect to SAMR using our transport protocol.

        This method must instantiate self.dce

        :param bool retry_if_expired: Retry as null binding if our password is expired
        :return bool: success
        TF)rM   c                 3   s    | ]	}|t  v V  qd S )N)str).0msgrC   r   r   	<genexpr>  s    z'SamrPassword.connect.<locals>.<genexpr>)STATUS_PASSWORD_MUST_CHANGESTATUS_PASSWORD_EXPIREDzKPassword is expired or must be changed, trying to bind with a null session.zlCannot set new NTLM hashes when current password is expired. Provide a plaintext value for the new password.NSTATUS_LOGON_FAILUREzAAuthentication failure when connecting to RPC: wrong credentials?STATUS_ACCOUNT_RESTRICTIONzAccount restriction: username and credentials are valid, but some other restriction preventsauthentication, like 'Protected Users' group or time-of-day restrictionSTATUS_ACCOUNT_DISABLEDz"The account is currently disabled.)	rT   rU   	Exceptionanyr/   warningr>   r?   rV   )r   retry_if_expiredr   rY   r   rP   y  sD   
 



zSamrPassword.connectc              
   C   s8  z?t | j| jd d }t | j|| jd }t j| j||dd }t | j||fd d d }t j| j||d	d
 }W |S  t	y } zPdt
|v r`td tt
| W Y d}~dS | jr|dt
|v r|td tt
| W Y d}~dS dt
|v rtd tt
| W Y d}~dS |d}~ww )z!Open an handle on the target user ServerHandleDomainId)domainIdDomainHandleRelativeIdsElementr   )userId
UserHandleSTATUS_NO_SUCH_DOMAINziWrong realm. Try to set the domain name for the target user account explicitly in format DOMAIN/username.NFSTATUS_ACCESS_DENIEDznOur anonymous session cannot get a handle to the target user. Retry with a user whose password is not expired.zAccess denied)r   hSamrConnectrT   r   hSamrLookupDomainInSamServerr   hSamrOpenDomainhSamrLookupNamesInDomainhSamrOpenUserr`   rV   r/   r>   r?   rM   )r   r   serverHandle	domainSIDdomainHandleuserRID
userHandlerC   r   r   r   rs     s6   
zSamrPassword.hSamrOpenUserT_changec             
   O   s   t d|j  z|| jg|R i |}W nP tyg } zDdt|v r8t d t t| W Y d}~dS dt|v ra|rFt d nt | j d| j d	 t t| W Y d}~dS |d}~ww |d
 dkrut 	d dS t 
d |  dS )a  
        Handles common errors when changing/resetting the password, regardless of the procedure

        :param callable samrProcedure: Function that will send the SAMR call
                                args and kwargs are passed verbatim
        :param bool _change:    Used for more precise error reporting,
                                True if it is a password change, False if it is a reset
        zSending SAMR call STATUS_PASSWORD_RESTRICTIONzSome password update rule has been violated. For example, the password history policy may prohibit the use of recent passwords or the password may not meet length criteria.NFrn   z7Target user is not allowed to change their own passwordr.   z6 user is not allowed to set the password of the target	ErrorCoder   r=   Tz/Non-zero return code, something weird happened.)r/   r?   r6   rT   r`   rV   r>   r   r   r0   rB   dump)r   samrProcedurerz   argskwargsresprC   r   r   r   _SamrWrapper  s2   	

zSamrPassword._SamrWrapperc              
   C   s   | j tjd|||||ddS )Nrd   Try   )r   r   hSamrUnicodeChangePasswordUser2)r   r   r'   r(   r)   r*   r+   r,   r   r   r   r     s   z,SamrPassword.hSamrUnicodeChangePasswordUser2c           	   
   C   s.   |  |}|s	dS | jtj||||||ddS )NFT)r'   r(   r*   r+   r,   rz   )rs   r   r   hSamrChangePasswordUser)	r   r   r'   r(   r)   r*   r+   r,   rx   r   r   r   r     s   
z$SamrPassword.hSamrChangePasswordUserc                 C   s(   |  |}|s	dS | jtj|||ddS )NFry   )rs   r   r   hSamrSetNTInternal1)r   r   r(   r+   r,   rx   r   r   r   hSamrSetInformationUser  s   
z$SamrPassword.hSamrSetInformationUserc	           
   	   C   sR   | j ddsdS |r| |||||ddS | ||d||||}	|	r'td |	S )NTrc   Fr   ztUser might need to change their password at next logon because we set hashes (unless password never expires is set).)rP   r   r   r/   rb   )
r   r%   r&   r'   r(   r)   r*   r+   r,   resr   r   r   r-     s   
zSamrPassword._changePasswordc                 C   s2   | j ddsdS | ||||}|rtd |S )NFr   zWUser no longer has valid AES keys for Kerberos, until they change their password again.)rP   r   r/   rb   )r   r%   r&   r(   r+   r,   r   r   r   r   r3   +  s   
zSamrPassword._setPassword)F)r6   r7   r8   r9   rT   rM   rH   rU   rP   rs   r   r   r   r   r-   r3   r   r   r   r   rF   A  s    

)1 &rF   c                       s0   e Zd Zdd Z fddZ fddZ  ZS )RpcPasswordc                 C   s.   t j| jtjdd}t|}|| j |S )Nncacn_ip_tcp)protocol)r   hept_mapr   r   rR   r   DCERPCTransportFactorysetRemoteHost)r   stringBindingrH   r   r   r   rH   7  s   
zRpcPassword.rpctransportc	           	   
      s(   |st d t ||||||||S )NzmMS-RPC transport requires new password in plaintext in default Active Directory configuration. Trying anyway.)r/   rb   superr-   r$   	__class__r   r   r-   =  s   zRpcPassword._changePasswordc                    s   t d t |||||S )NzhMS-RPC transport does not allow password reset in default Active Directory configuration. Trying anyway.)r/   rb   r   r3   r2   r   r   r   r3   H  s   zRpcPassword._setPassword)r6   r7   r8   rH   r-   r3   __classcell__r   r   r   r   r   6  s    r   c                   @   s   e Zd Zdd ZdS )SmbPasswordc                 C   s   t j| jddS )Nz\samr)filename)r   SMBTransportr   rG   r   r   r   rH   P  s   zSmbPassword.rpctransportN)r6   r7   r8   rH   r   r   r   r   r   O  s    r   c                   @   sH   e Zd ZdZdZdZdd Zdd Zdd Zd	d
 Z	dd Z
dd ZdS )LdapPasswordz-Use LDAP to change or reset a user's passwordNc                 C   s  | j rdS d| j }dd|d | _td| d| j d| j  z0t	
|| j| j}| jsA|| j| j| j| j| j n|j| j| j| j| j| j| j| jd	 W n+ t	jtjjfy } ztd
| d| j d| j d|  W Y d}~dS d}~ww || _ dS )z:Connect to LDAPS with the credentials provided in __init__Tzldaps://zDC=z,DC=rE   zConnecting to r4   r.   r   zCannot connect to rD   NF)ldapConnectionr   joinsplitbaseDNr/   r?   r   r   r	   LDAPConnectionr   loginr   r   r   kerberosLoginr   r   LDAPSessionErrorOpenSSLSSLSysCallErrorrB   )r   r&   ldapURIr   rC   r   r   r   rP   Z  s4   
 	&zLdapPassword.connectc                 C   s   d| d dS )z
        Encode the password according to Microsoft's specifications

        Password must be surrounded by quotes and UTF-16 encoded
        "z	utf-16-le)encode)r   r   r   r   r   encodeLdapPasswordy  s   zLdapPassword.encodeLdapPasswordc                 C   sF   | j jd| d| jdd}|D ]}t|tjsqt|d   S dS )z Find the DN of the targeted userz(sAMAccountName=))distinguishedName)searchFilter
searchBase
attributes
objectNameN)r   searchr   
isinstancer
   SearchResultEntryrV   )r   r%   r&   answersitemr   r   r   findTargetDN  s   
zLdapPassword.findTargetDNc              	   C   s  |  |sdS | ||}|std dS td|  t }||d< |rktd|d d d< d	|d d d
 d< ||d d d
 d d< td|d d d< d	|d d d
 d< ||d d d
 d d< n!td|d d d< d	|d d d
 d< ||d d d
 d d< tdt|  | j	
|d }tdt|  t|d d d }	tt|	}
t|d d d }|
dkrtd|  dS |
dkrtd| d dS |
dkrtd| d| j d| j d  dS td| d!|
 d"|  dS )#NFz&Could not find the target user in LDAPz Found target distinguishedName: objectdeletechangesr   	operation
unicodePwdmodificationtypevalsadd   replacez	Sending: zReceiving: 
protocolOpmodifyResponse
resultCodediagnosticMessagesuccessz&Password was changed successfully for TconstraintViolationz!Could not change the password of z@, possibly due to the password policy or an invalid oldPassword.insufficientAccessRightszCould not set the password of z, r.   z has insufficient rightsz. rD   )rP   r   r/   r>   r?   r
   ModifyRequest	OperationrV   r   sendReceiveint
ResultCoder0   rB   r   r   )r   changer%   r&   oldPasswordEncodednewPasswordEncodedtargetDNrequestresponser   resultdiagMessager   r   r   _modifyPassword  sL   


	"zLdapPassword._modifyPasswordc	                 C   s<   |r|st d dS | |}	| |}
| d|||	|
S )z
        Change the password of a user.

        Must send a delete operation with the oldPassword and an add
        operation with the newPassword in the same modify request.
        z4LDAP requires the old and new passwords in plaintextFTr/   r>   r   r   )r   r%   r&   r'   r(   r)   r*   r+   r,   r   r   r   r   r   r-     s   



zLdapPassword._changePasswordc                 C   s.   |s	t d dS | |}| d||d|S )z
        Set the password of a user.

        Must send a modify operation with the newPassword (must have privileges).
        z+LDAP requires the new password in plaintextFNr   )r   r%   r&   r(   r+   r,   r   r   r   r   r3     s
   

zLdapPassword._setPassword)r6   r7   r8   r9   r   r   rP   r   r   r   r-   r3   r   r   r   r   r   T  s    5r   c                  C   s  t jdd} | jdddd | jddd	d | jd
ddd | d}| }|jddd dd |jddd ddd | d}|jddd ddd |jdddd | d}|jddd dd | }|jddd dd |jdddd d d | d!}|jd"d#dd$d%d&d' |jd(d)dd*d | jd+d,d}|jd-dd.d |jd/dd0d1d2 |jd3dd4d5d2 ttjd6kr|   t	d6 | 
 S )7Nz3Change or reset passwords over different protocols.)descriptiontargetstorez4[[domain/]username[:password]@]<hostname or address>)actionhelpz-ts
store_truez&adds timestamp to every logging outputz-debugzturn DEBUG output ONzNew credentials for targetz-newpassznew password)r   defaultr   z
-newhasheszLMHASH:NTHASHz2new NTLM hashes, format is NTHASH or LMHASH:NTHASH)r   r   metavarr   z6Authentication (target user whose password is changed)z-hashesz.NTLM hashes, format is NTHASH or LMHASH:NTHASHz-no-passz0Don't ask for password (useful for Kerberos, -k)z@Authentication (optional, privileged user performing the change)z-altuserzAlternative usernamez-altpasszAlternative passwordz-althashz
-althashesz6Alternative NT hash, format is NTHASH or LMHASH:NTHASHzMethod of operationsz	-protocolz-pz)Protocol to use for password change/resetsmb-samr)r   rpc-samrr   r	   )r   r   r   choicesz-resetz-adminzMTry to reset the password with privileges (may bypass some password policies)zKerberos authenticationzHApplicable to the authenticating user (-altuser if defined, else target)z-kzUse Kerberos authentication. Grabs credentials from ccache file (KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ones specified in the command linez-aesKeyzhex keyz<AES key to use for Kerberos Authentication (128 or 256 bits))r   r   r   z-dc-ipz
ip addresszIP Address of the domain controller, for Kerberos. If omitted it will use the domain part (FQDN) specified in the target parameterr   )argparseArgumentParseradd_argumentadd_argument_groupadd_mutually_exclusive_grouplensysargv
print_helpexit
parse_args)parsergroupexgroupr   r   r   r     s   







r   __main__)r   r   r   r	   zUnsupported password protocol r   )r   r   Builtin:r   z/Current password not given: will use KRB5CCNAMEzCurrent password: 	Cancelled   zNew password: zRetype new password: z"Passwords do not match, try again./zPlease, provide either alternative password (-altpass) or NT hash (-althash) for authentication, or specify -no-pass if you rely on Kerberos onlyr   zAUsing the KPassword protocol implies Kerberos authentication (-k)Tr   z'Attempting to *change* the password of r4   zE. You may want to use '-reset' to *reset* the password of the target.)Nr   r/   r   r   impacketr   impacket.dcerpc.v5r   r   r   impacket.krb5r   r   impacket.ldapr	   r
   impacket.examplesr   impacket.examples.utilsr   r   r   r   r:   rF   r   r   r   r   r6   printBANNERoptionsinittsr?   handlersr   PasswordProtocolKeyErrorr>   r   r   r&   r%   r'   r   hashesr   r)   r*   
ValueErrorresetno_passr0   KeyboardInterruptrb   	newhashesr(   r+   r,   newpassaltuser
authDomainr   althashr   r   r   altpasskr   r   dc_iphandlerr5   retr1   r   r   r   r   <module>   s$  xrF v 
V










 

 