Answered PowerPoint Binary File Format Decryption

  • Tuesday, September 16, 2008 5:49 PM
     
     
     

    I am attempting to implement decryption of PowerPoint binary files that have been encrypted according to section 2.3.5 of

    [MS-OFFCRYPT] and section 2.37. of [MS-PPT] documentation. I have not been able to verifiy the password of a sample document

    and was hoping someone could review the following details for any incorrect assumptions. In particular I'm concerned that the

    PowerPoint documentation does not state exactly how a unicode password gets converted into a byte array to be input into the

    hash algorithm. I've tried the most obvious assumptions but fear that may be the missing detail.

    In my example the RC4 CryptoAPI Encryption Header described in [MS-OFFCRYPT]2.3.5.1 and pulled from the

    CryptSession10Container in my sample file has the following fields.

    EncryptionVersionInfo = 0x00020002
    EncryptionHeader.Flags = 0x00000004
    EncryptionHeaderSize = 0x0076
    EncryptionHeader (variable)
     Flags = 0x00000004
     SizeExtra = 0x00000000
     AlgID = 0x00006801 (RC4 encryption)
     AlgIDHash = 0x00008004 (SHA1 hashing)
     KeySize = 0x000038 (56 bit encryption key)
     ProviderType = 0x00000001
     Reserved1 = 0x0A680030
     Reserved2 = 0x00000000
     CSPName (variable) = Microsoft Base Cryptographic Provider v1.0
    EncryptionVerifier (variable)
     SaltSize = 0x00000010
     Salt (16 bytes) = 0x8 0xC2 0x8D 0x6A 0xDA 0x6C 0x7E 0x3D 0xD2 0x93 0x4A 0xE2 0xBC 0xD0 0xAB 0xDC
     EncryptedVerifier (16 bytes) = 0x7A 0x29 0xCC 0xF7 0x80 0x22 0x64 0x9D 0xC9 0x76 0x4E 0xF4 0x34 0xA2 0xF4 0xAB
     VerifierHashSize = 0x00000014
     EncryptedVerifierHash (variable) = 0xD9 0xC4 0xAC 0x44 0xE8 0xB3 0x5 0x9B 0x2 0xC8 0x55 0xFB 0x75 0x96 0x36 0xD1 0x82

    0x40 0xA5 0xA5


    The password used to generate this example was the single letter 'X' as the password to open the document.

    When executing the password verifier as outlined below from [MS-OFFCRYPT] 2.3.5.6 I get the following failed results ..

    1. Generate an encryption key as specified in section 2.3.5.2 utilizing a block number of 0x00000000.
            The password is the letter 'X' or 0x58 0x00 as a byte array
     H0 = H (Salt, Password) =
      SHA1 ( 08 C2 8D 6A DA 6C 7E 3D D2 93 4A E2 BC D0 AB DC 58 00) =
      17 0d f7 ab 28 69 6b ae 9f ee 92 1e bd a6 09 9c 36 60 65 cd
     HFinal = H (H0, blockNumber) =
      SHA1 ( 17 0d f7 ab 28 69 6b ae 9f ee 92 1e bd a6 09 9c 36 60 65 cd 00 00 00 00 ) =
      a9 65 10 37 b4 b1 91 90 c5 ba 44 54 57 1d 38 8f 67 ac c6 a8

     Encryption Key = First Seven bytes (56 bit key) of HFinal = a9 65 10 37 b4 b1 91


    2. Decrypt the EncryptedVerifier field of the EncryptionVerifier structure to obtain the Verifier value. The resultant

    Verifier value MUST be an array of 16 bytes.
     RC4 ( 7A 29 CC F7 80 22 64 9D C9 76 4E F4 34 A2 F4 AB ) =

     53 76 88 ba dc cf fe 10 43 4a 65 98 ba ed 5f 86


    3. Decrypt the EncryptedVerifierHash field of the EncryptionVerifier structure to obtain the hash of the Verifier value. The

    number of bytes used by the encrypted Verifier hash MUST be 20.
     RC4 ( D9 C4 AC 44 E8 B3 05 9B 02 C8 55 FB 75 96 36 D1 82 40 A5 A5 ) =

     f0 9b e8 09 b4 5e 9f 16 88 f4 7e 97 fb d9 9d fc b9 c4 74 23


    4. Calculate the SHA1 hash value of the Verifier value calculated in step 2.
     SHA1 ( 53 76 88 ba dc cf fe 10 43 4a 65 98 ba ed 5f 86) =

     e2 40 7d c2 5d d9 aa 65 cc cb e7 04 c3 8c 8f f0 75 e9 28 02


    5. Compare the results of step 3 and step 4. If the two hash values do not match the password is incorrect

     PASSWORD DOES NOT MATCH! SOMETHING IS WRONG WITH THE IMPLEMENTATION OR DOCS

    I suspect an issue with step1 when generating the encryption key. Any assistance with this issue would be greatly

    appreciated.

    Thanks!

    • Edited by Joe Keslin Friday, September 19, 2008 2:07 PM Fixed typo in step 4
    •  

All Replies

  • Tuesday, September 16, 2008 7:05 PM
     
     
    Joe,
    Thanks for your post.

    We have a similar question in this forum. I am working on an answer to that one. When I have more details to post I will update this thread as well.

    Steve Smegner
    Application Development Consulting Group
  • Monday, September 29, 2008 8:06 PM
     
     
    Steve,

    I look forward to a response on this issue. Let me know if there is any other detail I can provide. We're kind of in a bind because we have numerous parsing technologies that operate on PPT files and have some large corporate customers requesting that we parse readonly PPT's and password protected PPT's.

    Thanks, Joe
  • Thursday, October 02, 2008 10:59 PM
     
     
    Joe,
    Thanks for keeping us updated. This has not fallen in the cracks. We are verifying our response for accuracy and will have an update here as soon as we are done. I hope to have this posted very soon.

    Thanks for your patience.

    Steve Smegner
    Application Development Consulting Group
  • Thursday, October 16, 2008 5:54 AM
     
     
    Greetings Joe,
    An updated version of MS-OFFCRYPTO has been posted here: http://msdn.microsoft.com/en-us/library/cc313071.aspx. This is version 1.01. This document contains the corrected password hash algorithm.

    Steve Smegner

    Application Development Consulting Group

  • Tuesday, March 17, 2009 2:09 PM
     
     

    Hi Steve,

    I recently downloaded the updated docs but have found that the specific encryption section I am dealing with has not been modified to address the issue I am having.

    Would it be possible to get a worked example that covers PowerPoint Binary password verification per the example in this thread that covers section 2.3.5 of [MS-OFFCRYPT] and  section 2.3.7 of [MS-PPT]?

    My primary concern is that there is some behavior difference in how the password is modified before being hashed. The documentation indicates behavior differences are documented for each format but there is nothing in the [MS-PPT] spec that indicates the unicode password should be adjusted in any way before supplying it to the hash function.

    In any case it would be really great to get an example that shows the expected values for each step when doing password verification for section 2.3.5.6 for a PowerPoint password example.


    Thanks, Joe

  • Thursday, March 19, 2009 7:52 PM
     
     

    Hi Joe,

    We have received your request and are investigating this issue. We will follow-up with any updates to this forum thread.

    Dominic Salemno
    Senior Support Escalation Engineer

  • Monday, March 30, 2009 2:52 PM
     
     

    Joe,

     

    How was the sample file and associated RC4 CryptoAPI Encryption Header created? If Microsoft Office, which version of Office was utilized?

    Dominic Salemno
    Senior Support Escalation Engineer

  • Monday, March 30, 2009 7:13 PM
     
     
    Dominic,

    I used PowerPoint 2002 SP3 for this sample though I've also used 2000 and 2003. The other use case I'm interested in involves decrypting read-only PPT's. Those should use the documented default password but I've also verified that won't validate either.

    - Joe
  • Monday, March 30, 2009 8:34 PM
     
     
    Joe,

    Could you send me a sample file to dochelp@microsoft.com for analysis?

    Dominic Salemno
    Senior Support Escalation Engineer
  • Tuesday, March 31, 2009 12:34 AM
     
     
    Dominic,
    I have emailed the sample file that matches this example per your request.
    - Joe
  • Friday, May 08, 2009 3:23 PM
     
     Answered

    Joe,

    The CryptoAPI RC4 Encryption mechanism does not implicitly reset. The equivalent in most RC4 implementations is combining both the EncryptedVerifier and EncryptedVerifierHash and sending them through the RC4 algoirthm as one byte-array at once like so:

    RC4 ( 7A 29 CC F7 80 22 64 9D C9 76 4E F4 34 A2 F4 AB D9 C4 AC 44 E8 B3 05 9B 02 C8 55 FB 75 96 36 D1 82 40 A5 A5 )

    Result: 0x53 0x76 0x88 0xBA 0xDC 0xCF 0xFE 0x10 0x43 0x4A 0x65 0x98 0xBA 0xED 0x5F 0x86 0xE2 0x40 0x7D 0xC2 0x5D 0xD9 0xAA 0x65 0xCC 0xCB 0xE7 0x04 0xC3 0x8C 0x8F 0xF0 0x75 0xE9 0x28 0x02

    The first 16 bytes are the decrypted EncryptedVerifier field: 0x53 0x76 0x88 0xBA 0xDC 0xCF 0xFE 0x10 0x43 0x4A 0x65 0x98 0xBA 0xED 0x5F 0x86

    The last 20 remaining bytes are for the decrypted EncryptedVerifierHash field: 0xE2 0x40 0x7D 0xC2 0x5D 0xD9 0xAA 0x65 0xCC 0xCB 0xE7 0x04 0xC3 0x8C 0x8F 0xF0 0x75 0xE9 0x28 0x02

    Performing an SHA-1 operation against the decrypted EncryptedVerifier field would result in the following: 0xE2 0x40 0x7D 0xC2 0x5D 0xD9 0xAA 0x65 0xCC 0xCB 0xE7 0x04 0xC3 0x8C 0x8F 0xF0 0x75 0xE9 0x28 0x02

    The result of which is a perfect match.

    Dominic Salemno
    Senior Support Escalation Engineer