"Secrets" DPAPI or DPAPI for pentesters

    The second article on the results of the performance of our team on OFFZONE-2018. This time we will review the report with MainTrack “Windows DPAPI“ Sekretiki ”or DPAPI for pentesters”.

    Attention! A lot of beeches!

    When you run RedTeam campaigns, you want to give less reason for the BlueTeam reaction, but there may be a lot of them. For example, running mimikatz to get user passwords or certificates. Even if we managed to otmazat it from Kaspersky, BlueTeam has the ability to track using specialized tools such as Sysmon, Microsoft ATA, etc. At the same time, I would like to get as much information as possible from the compromised user's machine. In the course of the RedTeam campaigns that were held several times with opposition to the current BlueTeam teams, we came to the conclusion that it is necessary to avoid actions that can serve as indicators of the system being compromised as much as possible. It is possible to achieve this goal by using legal mechanisms and actions provided by the operating system for the user.

    One of these legal tools is the DPAPI (Windows Data Protection API) mechanism, which is used by the operating system and various applications to encrypt sensitive user data (primarily passwords, cryptographic keys, etc.) For the end user and his applications, DPAPI looks extremely simple : there are only 2 functions - “encrypt data” and “decrypt data”. In this article, I would like to consider how such a mechanism is useful for pentesters when conducting RedTeam campaigns.

    What is DPAPI? Only briefly and in Russian

    Since 2000, all Windows operating systems began to use the DPAPI mechanism to keep user data safe.

    If we skip all the cryptography we considered on the report, we need: master key, user SID, user password hash, and the DPAPI blob itself (DPAPI encrypted data) to decrypt the data encrypted via DPAPI.

    In general, the process looks like this:

    Inside our “cryptographic hat” there are many different crypto mechanisms that we will not discuss in this article, so as not to overload the reader. We only note that the main part of DPAPI is the so-called Masterkey (master key). To put it simply, the master key is 64 bytes of random data encrypted with prekey, which is generated from the user's password and his SID.

    Additional parameters also take part in the generation of prekey: the number of iterations (IterN), salt and HMAC, which may vary from case to case. The values ​​of these parameters are stored with the master key in one file.

    Thus, knowing the user's password, his SID and reading the generation parameters (HMAC, Salt, InterN) from the master key file, we can generate a prekey and decrypt the master key, i.e. get the same random 64 bytes that we will use to decrypt DPAPI blobs.

    And if I change my password?

    Usually, user passwords change at regular intervals. What happens if the user has changed the password? Where did the previous one go? After all, to decrypt the master key, you need to know the user's password, and to re-encrypt all the user's master keys each time is too expensive. In this case, with Windows, everything is thought out.

    There is a special file (CREDHIST) whose task is to store all previous user passwords. It is also encrypted with the user's current password and saved to the stack. If the system suddenly failed to decrypt the master key, then it proceeds as follows: using the current password, it decrypts the first entry in the CREDHIST. The received password tries to decrypt the master key again and so on until the passwords in the chain run out or the master key is decrypted.

    Some words about domain controller private keys

    As you may have guessed, DPAPI is used for all users, including domain users. In order to be able to reset the password to the user who successfully forgot it after some Friday party, you need a spare key that will be stored in a safe place. According to Microsoft, such a reliable place is a domain controller.

    The essence of the mechanism for decrypting the master key after resetting the user's password is as follows: a pair of RSA keys is created on the domain controller — a closed and an open one. The private key is stored on a domain controller in the NTDS database and is called BCKUPKEY_xxxx (see figure below), and the public key is distributed to all domain systems and is used to create a duplicate master key when it is generated.

    After the master key is created, a duplicate machine is created on the domain machine (or rather, the master key material is its 64 bytes), which is stored together with the main master key in one file and is called the Domain Key. If the master key is lost, i.e. When a user password is reset, the system sends a duplicate of it to the domain controller and asks for it to be decrypted. The controller, authorizing the user, decrypts the duplicate and returns to the system, after which the material of the master key is already re-encrypted with a new password.

    Having the appropriate privileges in the domain (most often admin ones), you can get these private RSA keys from the domain controller through the replication mechanism and use them to further decrypt the master keys created on the domain machines. This can be done using mimikatz or DSInternals. Read more about this in the mimikatz wiki or the DSInternals blog .

    Where are the master keys stored and what are they?

    The master key can be user and system, depending on whose secrets are encrypted. The user master key is stored in the user profile in the following way:


    In any case, the system stores all master keys ever used by the user. After all, she does not know in advance what master key will be necessary to decipher something. The GUID of the currently used key is stored in the Preferred file.

    The system master keys are stored in the following way:

    Similarly to the user, one master key is used, the name of which can be found in the Preferred file, where all ever used keys are stored.

    Well, what can your DPAPI do for a pentester?

    Since DPAPI is a legal and simple mechanism, various applications try to use it. Because it is convenient and safe. For the time being, of course.

    For example, DPAPI is used to encrypt private keys of client and system certificates, WIFI keys, Chrome (cookies, passwords), DropBox, Skype, RSA SecurID (a software application that generates one-time keys). And this is far from an exhaustive list.

    The task of the pentester is to decrypt the necessary blobs and get passwords, cookies, etc.

    This can be done in several ways. Anyway, they all boil down to two decoding - online and offline. Online decryption is when on the user's machine we simply call the system functions for decrypting data and transfer it to the input of the DPAPI blob, and the system already does everything by itself — looking for the master key with which the blob was encrypted, decrypts it using the user's SID and a password hash stored in LSASS memory.

    The figure below shows an example of calling DPAPI functions to encrypt and decrypt on powershell.

    First, we encrypt our secret (in this case, the word “Password”) by calling the function [Security.Cryptography.ProtectedData] :: Protect (). And we do it twice - in the first case using the user's master key (CurrentUser parameter), and in the second case - the system master key (LocalMachine parameter). Then we can decipher the received blobs through the call of the reverse function - [Security.Cryptography.ProtectedData] :: UnProtect ().

    In this case, the value of the CurrentUser or LocalMachine parameter is not important, since the system itself finds the master key suitable for decoding the blob, and does everything necessary. At the exit in both cases we get our initial secret - the word “Password” (its byte-by-word representation).

    When decoding online, it is important to understand the context in which you call the UnProtect () function. In order for decryption to succeed, it is necessary to be in a user session or to log in under a new session. It's all about the password hash, which is stored in the LSASS memory. If you make a call not in a user session (for example, you are logged in over the network via psexec or meterpreter), then you, respectively, do not have the password hash required to decrypt the master key. Of course, he is in the next session, but LSASS will not give it to you, because This is another session, even though it was created under the same user. For successful online decryption, you need to either migrate to any process started by the user logged in through the GUI, or fully log in, for example, via RDP.

    An alternative to powershell for decrypting DPAPI blobs online is to call mimiktaz :: blob with the / unprotect option. At the entrance, it is supplied with a binary file with a DPAPI blob, and at the output we get decrypted data. More cases using mimikatz are described in the HarmJ0y blog .

    The cue ball fell. Where to put my farm with vidyukhi?

    Due to the fact that the DPAPI master keys are encrypted on the user's password, it is possible to try the reverse process - brute force the user's password by its master key. For example, we received a reverse connection from our macro or DDE from the sent docx file. We can take the user's master key and recover the user's password without any escalation of privileges and mimikatz launches.

    For brute force password can you use Hashcat or JohnTheRipper? But before that, you need to get the parameters for bruteforce by the corresponding script from John:

    ./DPAPImk2john.py –S <sid> -mk <masterkey> -c <domain|local>

    Then we can send the result of the script to our farm with video cards and hope that the user has a weak password, because the master key bruteforce speed is approximately comparable to the WPA2 brute force, i.e. very really slow.

    It is worth noting here that, in the case where the master key is generated on a Windows 10 domain, then 10,000 rounds of PBKDF2 are added to the prekey generation. But even worse is that neither Hashcat nor JohnTheRipper know about it (at least at the time of this writing), which means that they will not be able to clear the password from such a master key.

    "Take away all that is bad, and then understand ..."

    As we noted earlier, the execution of suspicious actions on the user's machine can provoke additional interest to us from the Blueteam team, and this, accordingly, is fraught with the fact that the whole RedTeam will end there. An example is the launch of powershell on an accountant’s or secretary’s computer with subsequent investigation of the incident. In order not to cause undue suspicion, it is better to use offline ways to decrypt DPAPI blobs. To do this, you must first pick up everything you need from your car, namely:

    • User master keys;
    • Master keys of the system;
    • CREDHIST file (if it is not a domain machine);
    • User password (or its sha1 / ntlm hash);
    • User SID;
    • DPAPI blobs that we want to decrypt.

    To decrypt in offline mode, we can not do without specialized tools. Such tools can be:

    • Mimikatz;
    • Impacket (starting from the 18th version, it has DPAPI functionality);
    • Dpapick framework

    We’ll talk about the dpapick framework in more detail.

    The python dpapick framework itself was made by researcher Jean-Michel Piccode back in 2014 and represents the implementation of DPAPI mechanisms in Python crypto libraries. The use of python, as well as the structure of the framework, makes it quite easy to adapt it for various DPAPI mechanisms. In its original version, dpapick did not know how to use the domain backup key to decrypt master keys, and there were no mechanisms for decrypting master keys created on Windows 10 in the domain machine mode.

    After correcting these flaws and expanding the functionality for decoding DPAPI blobs, dpapick has become a fairly good tool for offline decoding of DPAPI. Below, as examples - we will show the options for using this framework to decrypt user-encrypted data through DPAPI.

    Chrome - pick up and decrypt cookies and passwords

    Chrome %localappdata%\Google\Chrome\User Data\Default\Cookies
    cookies are stored in a file. Login data is in a file. %localappdata%\Google\Chrome\User Data\Default\Login Data

    Both files are sqlite3 databases in which sensitive data is stored as DPAPI blobs. Dpapick contains a ready-made dissector (parser) of this data (examples / chrome.py). For successful decryption, it needs to specify the directory with master keys, the user's sid, his password or the location of the controller-domain's private key, as well as the sqlite3 file from Chrome (cookie or login data).

    Offline Chrome cookie decryption with user password

    ./chrome.py --cookie <cookiefile> --sid <SID> --password <..> --masterkey <masterkeydir>

    Offline Chrome cookie decryption using user password hash

    ./chrome.py --cookie <cookiefile> --sid <SID> --hash <..> --masterkey <masterkeydir>

    Offline decryption of Chrome passwords using a private key from a domain controller

    ./chrome.py --chrome <loginfile>  --pkey <rsa-priv.pem> --masterkey <masterkeydir>

    DPAPI for client certificates

    Client certificates are used a lot where - to generate OTP, EFS or authentication in VPN, Web-based applications, etc.

    The public key certificates themselves are stored in the user profile:
    And the private keys, with the help of which, in fact, a signature or other cryptographic operations are encrypted using DPAPI and located in the user profile along the way:


    In order to successfully decrypt the private keys of the certificates and the subsequent reconstruction of the PFX files, we also need the user's master keys, as well as his SID and password (or the RSA private key from the controller) in addition to the above files.

    With the help of Dpapick and the user's password, we decipher it:

    ./efs.py --certificates <certdir> --rsakyes <RSAdir> --sid <..> --password <..> --masterkey <masterkeydir>

    The optional rsaout parameter in the screenshot allows you to optionally export decrypted RSA keys in PEM format. The result of the script is a recreated PFX file without a password, which you can already import to yourself and use for its intended purpose. If there are several certificates and private keys in the above directories, then dpapick will try to decrypt each of them and make several pfx files.

    The same actions can be performed using the domain private key to decrypt the master key, specifying the appropriate parameter:

    ./efs.py --certificates <certdir> --rsakyes <RSAdir> --masterkey <masterkeydir> --pkey <domainbkpkey>

    A little more about the "phishing" domain

    Speaking of the Active Directory domain, it is worth mentioning such a wonderful piece as Credentials Roaming - the domain function, when master keys, encrypted passwords and certificates “travel” as a user throughout the Active Directory domain. They are not tied to a specific machine and will “arrive” on the computer on which the domain user logs in.

    When you enable this feature, all certificates that the user imports, as well as all his private keys and passwords, fly to AD and are stored in the corresponding account attributes: msPKIAccountCrdentailas and msPKIDPAPIMasterKeys.

    You can see how it looks inside AD, for example, via ldapsearch:

    ldapsearch -x -h dc1.lab.local -D “user1@lab.local" -s sub "samAccountname=user1"
    ldapsearch -x -h dc1.lab.local -D "admin@lab.local" -s sub "samAccountname=anyuser"

    By default, a user can get DPAPI attributes only for his account. But with elevated privileges, this can be done for any account, including a computer account.

    Credential Roaming is a very convenient technology not only for admins, but also for pentesters. Having gained access to the domain controller through ldap, you can merge all user certificates, his master keys and passwords encrypted with DPAPI (for example, passwords for connecting to network drives).

    And why not add such functionality to dpapick, we thought - and taught it to automatically extract certificates from a domain controller via ldap, decrypt them and generate pfx files.

    ./efs.py –ldap-server <..> --ldap-connect admin:Passw0rd@lab.local --ldap-user user1 --password Password1
    ./efs.py –ldap-server <..> --ldap-connect admin:Passw0rd@lab.local --ldap-user user1 --pkey <rsa-priv.pem>

    To execute the script, you need to specify the domain controller as an ldap server, connection details, the name of the account for which we receive certificates and a password to decrypt the master key (or a private backup controller key).

    Dropbox. Gone in 60 seconds ...

    Dropbox is another example of using DPAPI to store user secrets. Authorization tokens for dropbox are stored in files:


    These are encrypted sqlite3 databases containing data for connection. A symmetric key is used for encryption, which in turn is encrypted via DPAPI and is stored in the registry: Thus, the general order of the dropbox hijacking is as follows:


    1. pick up two database files from a computer;
    2. get the keys from the registry and decrypt them with dpapick;
    3. we encrypt the received keys using DPAPI already on our machine and put it into the registry;
    4. we replace the database files on our machine and launch Dropbox.

    You should be aware that special permissions are set for the above registry branches. Only the user can read them. Neither the administrator nor the system can read them. Thus, if you access the registry on behalf of another user (even the administrator), you must first set the appropriate permissions on the specified registry branches. For example, so (powershell):

    $acl = $key.GetAccessControl(); 
    $rule = New-Object System.Security.AccessControl.RegistryAccessRule ("administrator","FullControl","Allow");
    $key_path = "REGISTRY::HKEY_USERS\$Sid\SOFTWARE\Dropbox\ks"; 
    (Get-ItemProperty -Path $key_path -Name Client).Client;

    The keys ks and ks1 contain the header (8 bytes) of the dbx version before the DPAPI blob and md5 HMAC DPAPI blob (the last 16 bytes). The DPAPI blob itself starts with the 9th byte 0x01000000D0 ... These bytes need to be copied in base64 format to a file, which can then be decrypted using dpapick:

    ./filegeneric.py --sid <..> --password <..> --masterkey <..> --base64file <..>

    Then, on your machine, you need to encrypt the keys obtained at the last stage already by our master-key and put the result in the corresponding registry branches.

    For encryption, it is best to use powershell:

    [Byte[]] $dv0_entropy = 0xd1,0x14,0xa5,0x52,0x12,0x65,0x5f,0x74,0xbd,0x77,0x2e,0x37,0xe6,0x4a,0xee,0x9b; 
    $data = ($hdata -split "(?<=\G\w{2})(?=\w{2})" | %{ [Convert]::ToByte( $_, 16 ) }); 
    $dk1 = [system.security.cryptography.protecteddata]::Protect($data,$dv0_entropy,[System.Security.Cryptography.DataProtectionScope]::CurrentUser); 
    $OBJ_hmac = New-ObjectSystem.Security.Cryptography.HMACMD5
    $hmac = $OBJ_hmac.ComputeHash($dk1)

    In this case, hdata is the key that was obtained at the decryption stage. dv0_entropy is the entropy constant used by DBOX in DPAPI. To the resulting blob you need to attach the front header 8 bytes 0x00000000F6000000, and the rear - HMACMD5 + 0x00
    After that you can write data to the corresponding registry keys.

    DPAPI and RSA SecurID

    RSA SecurID is a client program that is used to generate a one-time password developed by RSA.

    It is quite a popular thing for large companies and also uses DPAPI, only a bit more complicated. In this case, RSA engineers decided to get bogged down and applied more complex DPAPI schemes.

    These tokens are stored in a file %LOCALAPPDATA%\RSA\SecurIDStoragethat is sqlite3 base. The base for each token is recorded its encrypted EnTokenSid (initial initialization parameters of the code generation algorithm). EnTokenSid is generated based on DBKey, the token SID and user SID, and DBKey is already generated by decoding DBKeyEnc in the following sequence by DPAPI:
    DBKeyEnc = DPAPI(CurrenUser, DPAPI(LocalSystem(DBKey))

    Those. First, the DB Key is encrypted with the system master key, and then the resulting DPAPI blob is once again encrypted with the user master key.

    CryptoCheckSum from CheckSum is also present in the database:
    CryptoCheckSum = DPAPI blob (CurrenUser)

    Thus, in order for the merged SecurIDStorage to work on your machine, you must:

    1. Due to the fact that the user's SID is involved in the formation of the EncTokenSid, it is necessary to set the current SID user in its virtual machine to the same value as the user SID from which the SecurIDStorage database is taken. The NewSid utility from SysInternals will help us with this;
    2. Decrypt DBKeyEnc using the user's master key and his password or domain private key (in the case of a domain machine);
    3. Decrypt the result of the previous decryption using the system master key and the value of the parameter DPAPI_SYSTEM;
    4. Decrypt CryptoCheckSum using the user's master key
    5. Encrypt the received DBKey and CheckSum values ​​in the reverse order already on their virtual machine;
    6. In some versions, SecurID will also need to set the HDD size of the virtual machine to be the same as the HDD size of the source machine, since the program compares it at startup.

    As already mentioned above, in order to decrypt DBKeyEnc, in addition to the user's master key, we will also need the system master key, as well as the DPAPI_SYSTEM value, which is used to decrypt the system master keys. DAPPI_SYSTEM is actually an already formed prekey involved in the generation of system master keys. You can get it from LSASS memory (via mimikatz or by analyzing the process dump) or from the corresponding registry branches (HKLM \ SYSTEM, HKLM \ SECURITY), dumping them and analyzing with the same Impacket.

    Then we can use the obtained DPAPI_SYSTEM to decrypt the necessary blobs using dpapick (parser - examples / filegeneric.py), as shown in the following screenshots:

    1) Obtaining DPAPI_SYSTEM via mimikatz offline

    2) Obtaining DPAPI_SYSTEM via Impacket offline

    3) Decryption of DPAPIck with user and system master keys


    So that you do not forget the places of specific data - we will put them in a separate section:

    User master keys


    System master keys



    LSASecrets – online
    SYSTEM, SECURITY (reg save …, system\backup, etc)

    User certificates


    System certificates



    %localappdata%\Google\Chrome\User Data\Default\Cookies
    %localappdata%\Google\Chrome\User Data\Default\Login Data


    %APPDATA%\Local\Dropbox\instance1\config.dbx %APPDATA%\Local\Dropbox\instance_db\instanse.dbx

    Rsa securid


    Small conclusion

    DPAPI is a smart thing - the main thing is to understand how it can be used during pentest and RedTeam research.

    In this article, we looked at just a few examples where DPAPI decryption can be applied. In fact, the scope of application is much broader. For example, we did not consider RDP (* .rdg), Icloud (pList file), Skype (*. Xml), keys for connecting to Wi-Fi. DPAPI is used everywhere and the corresponding parsers are included as part of the dpapick framework.

    A modified version of dpapick is posted on our GitHub . We urge you to use this tool to decrypt DPAPI and will be grateful for the further refinement of dpapick.

    And some interesting information can be found in our channel in telegrams . We are talking about security through the eyes of RedTeam.

    PS Thanks to the organizers of OFFZONE-2018 for a cool conference!

    PPS The second part of the article here

    Also popular now: