diff --git a/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.cpp b/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.cpp index c1e44df349..68ce51c2e9 100644 --- a/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.cpp +++ b/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.cpp @@ -35,143 +35,148 @@ namespace DocFileFormat { - EncryptionHeader::EncryptionHeader( FileInformationBlock* fib, POLE::Stream* tableStream ) + EncryptionHeader::EncryptionHeader( FileInformationBlock* fib, POLE::Stream* tableStream ) : bStandard(false), bXOR(false), bAES(false) { VirtualStreamReader tStream( tableStream, 0, fib->m_bOlderVersion); - if (fib->m_FibBase.fObfuscation) + if (fib->m_FibBase.fObfuscation || fib->m_bOlderVersion) { - //xor - return; - } - unsigned short vMajor = tStream.ReadUInt16(); - unsigned short vMinor = tStream.ReadUInt16(); - - if(0x0001 == vMajor) // RC4 encryption header structure - {// fib->m_FibBase.lKey == 52 - bStandard = true; - - crypt_data_rc4.Salt.b1 = tStream.ReadUInt32(); - crypt_data_rc4.Salt.b2 = tStream.ReadUInt32(); - crypt_data_rc4.Salt.b3 = tStream.ReadUInt32(); - crypt_data_rc4.Salt.b4 = tStream.ReadUInt32(); + bXOR = true; - crypt_data_rc4.EncryptedVerifier.b1 = tStream.ReadUInt32(); - crypt_data_rc4.EncryptedVerifier.b2 = tStream.ReadUInt32(); - crypt_data_rc4.EncryptedVerifier.b3 = tStream.ReadUInt32(); - crypt_data_rc4.EncryptedVerifier.b4 = tStream.ReadUInt32(); - - crypt_data_rc4.EncryptedVerifierHash.b1 = tStream.ReadUInt32(); - crypt_data_rc4.EncryptedVerifierHash.b2 = tStream.ReadUInt32(); - crypt_data_rc4.EncryptedVerifierHash.b3 = tStream.ReadUInt32(); - crypt_data_rc4.EncryptedVerifierHash.b4 = tStream.ReadUInt32(); + crypt_data_xor.key = fib->m_FibBase.lKey >> 16; + crypt_data_xor.hash = fib->m_FibBase.lKey - (crypt_data_xor.key << 16); } else { - bStandard = false; - crypt_data_aes.bAgile = false; + unsigned short vMajor = tStream.ReadUInt16(); + unsigned short vMinor = tStream.ReadUInt16(); - unsigned short flags = tStream.ReadUInt32(); - unsigned char *pDataRead = NULL; + if(0x0001 == vMajor) // RC4 encryption header structure + {// fib->m_FibBase.lKey == 52 + bStandard = true; - bool fCryptoAPI = GETBIT(flags, 1); - bool fDocProps = GETBIT(flags, 2); - bool fExternal = GETBIT(flags, 3); - bool fAES = GETBIT(flags, 4); - - //EncryptionHeader - int HeaderSize = tStream.ReadUInt32(); - int Flags = tStream.ReadUInt32(); - int SizeExtra = tStream.ReadUInt32(); - int AlgID = tStream.ReadUInt32(); - int AlgIDHash = tStream.ReadUInt32(); - int KeySize = tStream.ReadUInt32(); - int ProviderType= tStream.ReadUInt32(); - int Reserved1 = tStream.ReadUInt32(); - int Reserved2 = tStream.ReadUInt32(); - - int pos = tStream.GetPosition(); - int size = tStream.GetSize(); - - std::vector dataCSPName; - while(pos < size - 1) + crypt_data_rc4.Salt.b1 = tStream.ReadUInt32(); + crypt_data_rc4.Salt.b2 = tStream.ReadUInt32(); + crypt_data_rc4.Salt.b3 = tStream.ReadUInt32(); + crypt_data_rc4.Salt.b4 = tStream.ReadUInt32(); + + crypt_data_rc4.EncryptedVerifier.b1 = tStream.ReadUInt32(); + crypt_data_rc4.EncryptedVerifier.b2 = tStream.ReadUInt32(); + crypt_data_rc4.EncryptedVerifier.b3 = tStream.ReadUInt32(); + crypt_data_rc4.EncryptedVerifier.b4 = tStream.ReadUInt32(); + + crypt_data_rc4.EncryptedVerifierHash.b1 = tStream.ReadUInt32(); + crypt_data_rc4.EncryptedVerifierHash.b2 = tStream.ReadUInt32(); + crypt_data_rc4.EncryptedVerifierHash.b3 = tStream.ReadUInt32(); + crypt_data_rc4.EncryptedVerifierHash.b4 = tStream.ReadUInt32(); + } + else { - dataCSPName.push_back(tStream.ReadByte()); - dataCSPName.push_back(tStream.ReadByte()); - if (dataCSPName[dataCSPName.size() - 1] == 0 && dataCSPName[dataCSPName.size() - 2] == 0) + bAES = true; + crypt_data_aes.bAgile = false; + + unsigned short flags = tStream.ReadUInt32(); + unsigned char *pDataRead = NULL; + + bool fCryptoAPI = GETBIT(flags, 1); + crypt_data_aes.fDocProps = GETBIT(flags, 2); + bool fExternal = GETBIT(flags, 3); + bool fAES = GETBIT(flags, 4); + + //EncryptionHeader + int HeaderSize = tStream.ReadUInt32(); + int Flags = tStream.ReadUInt32(); + int SizeExtra = tStream.ReadUInt32(); + int AlgID = tStream.ReadUInt32(); + int AlgIDHash = tStream.ReadUInt32(); + int KeySize = tStream.ReadUInt32(); + int ProviderType= tStream.ReadUInt32(); + int Reserved1 = tStream.ReadUInt32(); + int Reserved2 = tStream.ReadUInt32(); + + int pos = tStream.GetPosition(); + int size = tStream.GetSize(); + + std::vector dataCSPName; + while(pos < size - 1) { + dataCSPName.push_back(tStream.ReadByte()); + dataCSPName.push_back(tStream.ReadByte()); + if (dataCSPName[dataCSPName.size() - 1] == 0 && dataCSPName[dataCSPName.size() - 2] == 0) + { + break; + } + pos+=2;//unicode null-terminate string + } + //EncryptionVerifier + crypt_data_aes.saltSize = tStream.ReadUInt32(); + pDataRead = tStream.ReadBytes(crypt_data_aes.saltSize, true); + if (pDataRead) + { + crypt_data_aes.saltValue = std::string((char*)pDataRead, crypt_data_aes.saltSize); + delete pDataRead; + } + + pDataRead = tStream.ReadBytes(0x10, true); + if (pDataRead) + { + crypt_data_aes.encryptedVerifierInput = std::string((char*)pDataRead, 0x10); + delete pDataRead; + } + + crypt_data_aes.hashSize = tStream.ReadUInt32(); + + int szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20; + pDataRead = tStream.ReadBytes(szEncryptedVerifierHash, true); + if (pDataRead) + { + crypt_data_aes.encryptedVerifierValue = std::string((char*)pDataRead, szEncryptedVerifierHash); + delete pDataRead; + } + + pos = tStream.GetPosition(); + + //------------------------------------------------------------------------------------------ + switch(AlgIDHash) + { + case 0x8003: crypt_data_aes.hashAlgorithm = CRYPT_METHOD::MD5; break; + case 0x0000: + case 0x8004: crypt_data_aes.hashAlgorithm = CRYPT_METHOD::SHA1; break; + } + crypt_data_aes.spinCount = 0; + + switch(AlgID) + { + case 0x0000: + if (fAES) crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; + if (fCryptoAPI) crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; + crypt_data_aes.keySize = KeySize / 8; + case 0x6801: + crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; + crypt_data_aes.keySize = KeySize / 8; + + if (crypt_data_aes.keySize == 0) crypt_data_aes.keySize = 5; // 40 bit + break; + case 0x660E: + crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; + crypt_data_aes.keySize = 128 /8; + break; + case 0x660F: + crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; + crypt_data_aes.keySize = 192 /8; + break; + case 0x6610: + crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; + crypt_data_aes.keySize = 256 /8; break; } - pos+=2;//unicode null-terminate string - } - //EncryptionVerifier - crypt_data_aes.saltSize = tStream.ReadUInt32(); - pDataRead = tStream.ReadBytes(crypt_data_aes.saltSize, true); - if (pDataRead) - { - crypt_data_aes.saltValue = std::string((char*)pDataRead, crypt_data_aes.saltSize); - delete pDataRead; - } - - pDataRead = tStream.ReadBytes(0x10, true); - if (pDataRead) - { - crypt_data_aes.encryptedVerifierInput = std::string((char*)pDataRead, 0x10); - delete pDataRead; - } - crypt_data_aes.hashSize = tStream.ReadUInt32(); - - int szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20; - pDataRead = tStream.ReadBytes(szEncryptedVerifierHash, true); - if (pDataRead) - { - crypt_data_aes.encryptedVerifierValue = std::string((char*)pDataRead, szEncryptedVerifierHash); - delete pDataRead; + //switch(ProviderType) + //{ + // case 0x0001: crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; break; + // case 0x0018: crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; break; + //} } - - pos = tStream.GetPosition(); - - //------------------------------------------------------------------------------------------ - switch(AlgIDHash) - { - case 0x8003: crypt_data_aes.hashAlgorithm = CRYPT_METHOD::MD5; break; - case 0x0000: - case 0x8004: crypt_data_aes.hashAlgorithm = CRYPT_METHOD::SHA1; break; - } - crypt_data_aes.spinCount = 0; - - switch(AlgID) - { - case 0x0000: - if (fAES) crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - if (fCryptoAPI) crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; - crypt_data_aes.keySize = KeySize / 8; - case 0x6801: - crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; - crypt_data_aes.keySize = KeySize / 8; - - if (crypt_data_aes.keySize == 0) crypt_data_aes.keySize = 5; // 40 bit - break; - case 0x660E: - crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - crypt_data_aes.keySize = 128 /8; - break; - case 0x660F: - crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - crypt_data_aes.keySize = 192 /8; - break; - case 0x6610: - crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - crypt_data_aes.keySize = 256 /8; - break; - } - - //switch(ProviderType) - //{ - // case 0x0001: crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; break; - // case 0x0018: crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; break; - //} } } } diff --git a/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.h b/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.h index 63766a64ab..9a8dca3c58 100644 --- a/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.h +++ b/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.h @@ -52,6 +52,10 @@ namespace DocFileFormat private: CRYPT::_rc4CryptData crypt_data_rc4; CRYPT::_ecmaCryptData crypt_data_aes; + CRYPT::_xorCryptData crypt_data_xor; + bool bStandard; + bool bXOR; + bool bAES; }; } diff --git a/ASCOfficeDocFile/DocDocxConverter/FileInformationBlock.h b/ASCOfficeDocFile/DocDocxConverter/FileInformationBlock.h index 56a281adc3..fd056fbeeb 100644 --- a/ASCOfficeDocFile/DocDocxConverter/FileInformationBlock.h +++ b/ASCOfficeDocFile/DocDocxConverter/FileInformationBlock.h @@ -531,7 +531,6 @@ namespace DocFileFormat { if (m_FibBase.nFib > 0 && m_FibBase.nFib <= Fib1995) { - m_RgLw97.cbMac = reader.ReadInt32();//32 /*m_FibWord97.fcSpare0 = */reader.ReadInt32(); /*m_FibWord97.fcSpare1 = */reader.ReadInt32(); /*m_FibWord97.fcSpare2 = */reader.ReadInt32(); @@ -1220,9 +1219,12 @@ namespace DocFileFormat if (m_FibBase.nFib > Fib1995) csw = reader.ReadUInt16(); //32 - if (m_FibBase.nFib > Fib1995 || m_FibBase.nFib == 0) - { - + if (m_FibBase.nFib > 0 && m_FibBase.nFib <= Fib1995) + { + m_RgLw97.cbMac = reader.ReadInt32();//32 + } + else if (m_FibBase.nFib > Fib1995 || m_FibBase.nFib == 0) + { //read the RgW97 reader.ReadBytes( 26, false ); //34 m_RgW97.lidFE = reader.ReadUInt16(); //60 @@ -1231,7 +1233,7 @@ namespace DocFileFormat //read the RgLW97 - m_RgLw97.cbMac = reader.ReadInt32(); //64 + m_RgLw97.cbMac = reader.ReadInt32(); //64 } reset(reader); } diff --git a/ASCOfficeDocFile/DocDocxConverter/WordDocument.cpp b/ASCOfficeDocFile/DocDocxConverter/WordDocument.cpp index b99ed61584..d44dde9627 100644 --- a/ASCOfficeDocFile/DocDocxConverter/WordDocument.cpp +++ b/ASCOfficeDocFile/DocDocxConverter/WordDocument.cpp @@ -174,11 +174,24 @@ namespace DocFileFormat } } - if (FIB->m_FibBase.fEncrypted && !FIB->m_bOlderVersion) + if (FIB->m_FibBase.fEncrypted) { - encryptionHeader = new EncryptionHeader (FIB, TableStream); + encryptionHeader = new EncryptionHeader (FIB, TableStream); - if (encryptionHeader->bStandard) + if (encryptionHeader->bXOR) + { + CRYPT::XORDecryptor Decryptor(1, encryptionHeader->crypt_data_xor.key, encryptionHeader->crypt_data_xor.hash, m_sPassword); + + if (Decryptor.IsVerify() == false) + { + Clear(); + + if (m_sPassword.empty() ) return AVS_ERROR_DRM; + else return AVS_ERROR_PASSWORD; + } + if (DecryptOfficeFile(&Decryptor) == false) return AVS_ERROR_DRM; + } + else if (encryptionHeader->bStandard) { CRYPT::RC4Decryptor Decryptor(encryptionHeader->crypt_data_rc4, m_sPassword); @@ -192,7 +205,7 @@ namespace DocFileFormat if (DecryptOfficeFile(&Decryptor) == false) return AVS_ERROR_DRM; } - else + else if (encryptionHeader->bAES) { CRYPT::ECMADecryptor Decryptor; @@ -208,9 +221,8 @@ namespace DocFileFormat if (DecryptOfficeFile(&Decryptor) == false) return AVS_ERROR_DRM; } - FIB->reset(VirtualStreamReader(WordDocumentStream, 68, false)); + FIB->reset(VirtualStreamReader(WordDocumentStream, bOlderVersion ? 36 : 68, false)); } - else if (FIB->m_FibBase.fEncrypted) return AVS_ERROR_DRM; //------------------------------------------------------------------------------------------------------------------ POLE::Stream * Summary = NULL; @@ -629,19 +641,37 @@ namespace DocFileFormat for( std::list::iterator it = entries_files.begin(); it != entries_files.end(); ++it ) { - std::wstring fullname = path + *it; - DecryptStream(fullname, storageIn, storageOut, Decryptor ); + std::wstring fullname_create = path + *it; + + if (it->at(0) < 32) + { + *it = it->substr(1); // without prefix + } + std::wstring fullname_open = path + *it; + + bool bDecrypt = false; + + if ( std::wstring::npos != fullname_open.find(L"WordDocument") || + std::wstring::npos != fullname_open.find(L"Data") || + std::wstring::npos != fullname_open.find(L"Table") || + (std::wstring::npos != fullname_open.find(L"SummaryInformation") && + encryptionHeader->bAES && encryptionHeader->crypt_data_aes.fDocProps) + ) + { + bDecrypt = true; + } + DecryptStream(fullname_open, storageIn, fullname_create, storageOut, Decryptor, bDecrypt); } } - bool WordDocument::DecryptStream(std::wstring streamName, POLE::Storage * storageIn, POLE::Storage * storageOut, CRYPT::Decryptor* Decryptor) + bool WordDocument::DecryptStream(std::wstring streamName_open, POLE::Storage * storageIn, std::wstring streamName_create, POLE::Storage * storageOut, CRYPT::Decryptor* Decryptor, bool bDecrypt) { - POLE::Stream *stream = new POLE::Stream(storageIn, streamName); + POLE::Stream *stream = new POLE::Stream(storageIn, streamName_open); if (!stream) return false; stream->seek(0); POLE::uint64 size_stream = stream->size(); - POLE::Stream *streamNew = new POLE::Stream(storageOut, streamName, true, size_stream); + POLE::Stream *streamNew = new POLE::Stream(storageOut, streamName_create, true, size_stream); if (!streamNew) return false; unsigned char* data_stream = new unsigned char[size_stream]; @@ -650,9 +680,9 @@ namespace DocFileFormat unsigned char* data_store = NULL; int size_data_store = 0; - if ( std::wstring::npos != streamName.find(L"WordDocument") ) + if ( std::wstring::npos != streamName_open.find(L"WordDocument") ) { - size_data_store = 68; + size_data_store = bOlderVersion ? 36 : 68; data_store = new unsigned char[size_data_store]; } @@ -662,14 +692,16 @@ namespace DocFileFormat size_t size_block = 0x200; unsigned long block = 0; - for (POLE::uint64 pos = 0; pos < size_stream; pos += size_block, block++) + for (POLE::uint64 pos = /*bOlderVersion ? size_data_store :*/ 0; pos < size_stream; pos += size_block, block++) { if (pos + size_block > size_stream) size_block = size_stream - pos; - Decryptor->Decrypt((char*)data_stream + pos, size_block, block); + if (bDecrypt) + { + Decryptor->Decrypt((char*)data_stream + pos, size_block, block); + } } - if (data_store) memcpy(data_stream, data_store, size_data_store); diff --git a/ASCOfficeDocFile/DocDocxConverter/WordDocument.h b/ASCOfficeDocFile/DocDocxConverter/WordDocument.h index 03fc3204ff..32198ec1d1 100644 --- a/ASCOfficeDocFile/DocDocxConverter/WordDocument.h +++ b/ASCOfficeDocFile/DocDocxConverter/WordDocument.h @@ -107,7 +107,7 @@ namespace DocFileFormat private: bool DecryptOfficeFile (CRYPT::Decryptor* Decryptor); - bool DecryptStream (std::wstring streamName, POLE::Storage * storageIn, POLE::Storage * storageOut, CRYPT::Decryptor* Decryptor); + bool DecryptStream (std::wstring streamName_open, POLE::Storage * storageIn, std::wstring streamName_create, POLE::Storage * storageOut, CRYPT::Decryptor* Decryptor, bool bDecrypt); void DecryptStream (int level, std::wstring streamName, POLE::Storage * storageIn, POLE::Storage * storageOut, CRYPT::Decryptor* Decryptor); inline OfficeArtContent* GetOfficeArt () diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Crypt.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Crypt.h index 2796d2ec0e..c6cd234634 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Crypt.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Crypt.h @@ -64,10 +64,18 @@ namespace CRYPT } EncryptedVerifierHash; }; + struct _xorCryptData + { + unsigned short key; + unsigned short hash; + }; + class Crypt { public: + virtual void Init(const unsigned long val) = 0; + virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) = 0; virtual void Decrypt(char* data, const size_t size, const unsigned long block_index) = 0; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.cpp index 237df20f1d..b91821faeb 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.cpp @@ -67,7 +67,7 @@ namespace CRYPT } //---------------------------------------------------------------------------------------- - XOR::XOR(int type, unsigned short key, unsigned short hash, std::wstring password) : + XORDecryptor::XORDecryptor(int type, unsigned short key, unsigned short hash, std::wstring password) : crypt(new XORCrypt(type, key, hash, password)) { nKey = key; @@ -75,20 +75,20 @@ namespace CRYPT nType = type; } - void XOR::Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) + void XORDecryptor::Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) { crypt->Decrypt(data, size, stream_pos, block_size); } - void XOR::Decrypt(char* data, const size_t size, const unsigned long block_index) + void XORDecryptor::Decrypt(char* data, const size_t size, const unsigned long block_index) { crypt->Decrypt(data, size, block_index); } - bool XOR::IsVerify() + bool XORDecryptor::IsVerify() { return crypt->IsVerify(); } - bool XOR::SetPassword(std::wstring password) + bool XORDecryptor::SetPassword(std::wstring password) { crypt.reset(); crypt = CryptPtr(new XORCrypt(nType, nKey, nHash, password)); @@ -97,6 +97,12 @@ namespace CRYPT else return false; } + void XORDecryptor::Init(const unsigned long val) + { + crypt->Init(val); + } + + }; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.h index c302939a6a..12b1c324ee 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.h @@ -37,10 +37,12 @@ namespace CRYPT { - class XOR : public Decryptor + class XORDecryptor : public Decryptor { public: - XOR(int type, unsigned short key, unsigned short hash, std::wstring password); + XORDecryptor(int type, unsigned short key, unsigned short hash, std::wstring password); + + virtual void Init(const unsigned long val); virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size); virtual void Decrypt(char* data, const size_t size, const unsigned long block_index); @@ -56,13 +58,15 @@ namespace CRYPT unsigned short nType; }; - typedef boost::shared_ptr XORPtr; + typedef boost::shared_ptr XORDecryptorPtr; class RC4Decryptor : public Decryptor { public: RC4Decryptor(_rc4CryptData & header, std::wstring password); + virtual void Init(const unsigned long val){} + virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size); virtual void Decrypt(char* data, const size_t size, const unsigned long block_index); diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.h index b366a9261d..370e4893ca 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.h @@ -43,6 +43,8 @@ class RC4Crypt : public Crypt public: RC4Crypt(CRYPT::_rc4CryptData & data, std::wstring password); + virtual void Init(const unsigned long val){} + virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size); virtual void Decrypt(char* data, const size_t size, const unsigned long block_index); diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/XORCrypt.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/XORCrypt.cpp index 03e549a08e..de244a316d 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/XORCrypt.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/XORCrypt.cpp @@ -166,14 +166,50 @@ bool XORCrypt::IsVerify() { return m_VerifyPassword; } - +void XORCrypt::Init(const unsigned long val) +{ + m_nOffset = val & 0x0F; +} void XORCrypt::Decrypt(char* data, const size_t size, const unsigned long block_index) { + unsigned char* pnData = (unsigned char*)data; + + const unsigned char* pnCurrKey = m_pnKey + m_nOffset; + const unsigned char* pnKeyLast = m_pnKey + 0x0F; + if (m_nRotateDistance == 7) + { + for( const unsigned char* pnDataEnd = pnData + size; pnData < pnDataEnd; ++pnData ) + { + const unsigned char cChar = *pnData ^ *pnCurrKey; + if (*pnData && cChar) + *pnData = cChar; + + if( pnCurrKey < pnKeyLast ) + ++pnCurrKey; + else + pnCurrKey = m_pnKey; + } + } + if (m_nRotateDistance == 2) + { + for( const unsigned char* pnDataEnd = pnData + size; pnData < pnDataEnd; ++pnData ) + { + lclRotateLeft( *pnData, 3 ); + *pnData ^= *pnCurrKey; + + if( pnCurrKey < pnKeyLast ) + ++pnCurrKey; + else + pnCurrKey = m_pnKey; + } + } + + Skip(size); } void XORCrypt::Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) { - m_nOffset = (stream_pos + size) & 0x0F; + Init(stream_pos + size); unsigned char* pnData = (unsigned char*)data; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/XORCrypt.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/XORCrypt.h index 57fa048737..ab3e6a8361 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/XORCrypt.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/XORCrypt.h @@ -43,6 +43,8 @@ class XORCrypt : public Crypt public: XORCrypt(int type, unsigned short key, unsigned short hash, std::wstring password); + virtual void Init(const unsigned long val); + virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size); virtual void Decrypt(char* data, const size_t size, const unsigned long block_index); diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/FilePass.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/FilePass.cpp index 72f23f1e7b..83d57a7f66 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/FilePass.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/FilePass.cpp @@ -59,7 +59,7 @@ void FilePass::readFields(CFRecord& record) record >> key.key >> key.verificationBytes; record.getGlobalWorkbookInfo()->decryptor = - CRYPT::DecryptorPtr(new CRYPT::XOR(2, key.key, key.verificationBytes, record.getGlobalWorkbookInfo()->password)); + CRYPT::DecryptorPtr(new CRYPT::XORDecryptor(2, key.key, key.verificationBytes, record.getGlobalWorkbookInfo()->password)); } else { @@ -70,7 +70,7 @@ void FilePass::readFields(CFRecord& record) record >> key; record.getGlobalWorkbookInfo()->decryptor = - CRYPT::DecryptorPtr(new CRYPT::XOR(2, key.key, key.verificationBytes, record.getGlobalWorkbookInfo()->password)); + CRYPT::DecryptorPtr(new CRYPT::XORDecryptor(2, key.key, key.verificationBytes, record.getGlobalWorkbookInfo()->password)); } else { diff --git a/OfficeCryptReader/source/CryptTransform.h b/OfficeCryptReader/source/CryptTransform.h index 3f62af2ccc..ac3d935822 100644 --- a/OfficeCryptReader/source/CryptTransform.h +++ b/OfficeCryptReader/source/CryptTransform.h @@ -65,6 +65,7 @@ class Decryptor virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) = 0; virtual void Decrypt(char* data, const size_t size, const unsigned long block_index) = 0; virtual bool SetPassword(std::wstring password) = 0; + virtual void Init(const unsigned long val) = 0; virtual bool IsVerify() = 0; }; @@ -73,21 +74,21 @@ typedef boost::shared_ptr DecryptorPtr; struct _ecmaCryptData { //default ms2010 - _ecmaCryptData() : cipherAlgorithm(CRYPT_METHOD::AES_CBC), hashAlgorithm(CRYPT_METHOD::SHA1), spinCount(100000), - keySize(0x10), hashSize(0x14), blockSize(0x10), saltSize(0x10), bAgile(true) + //_ecmaCryptData() : cipherAlgorithm(), hashAlgorithm(), spinCount(100000), + // keySize(0x10), hashSize(), blockSize(0x10), saltSize(0x10), bAgile(true) //default ms2013/ms2016 //_cryptData(): cipherAlgorithm(CRYPT_METHOD::AES_CBC), hashAlgorithm(CRYPT_METHOD::SHA256), spinCount(100000), // keySize(0x20), hashSize(0x40), blockSize(0x10), saltSize(0x10), bAgile(true) - { - } - CRYPT_METHOD::_cipherAlgorithm cipherAlgorithm; - CRYPT_METHOD::_hashAlgorithm hashAlgorithm; + //{ + //} + CRYPT_METHOD::_cipherAlgorithm cipherAlgorithm = CRYPT_METHOD::AES_CBC; + CRYPT_METHOD::_hashAlgorithm hashAlgorithm = CRYPT_METHOD::SHA1; - int spinCount; - int keySize; - int hashSize; - int blockSize; - int saltSize; + int spinCount = 100000; + int keySize = 0x10; + int hashSize = 0x14; + int blockSize = 0x10; + int saltSize = 0x10; std::string dataSaltValue; std::string saltValue; @@ -98,10 +99,12 @@ struct _ecmaCryptData std::string encryptedHmacKey; std::string encryptedHmacValue; - bool bAgile; + bool bAgile = true; //.......... + bool fDocProps = true; + }; class ECMAEncryptor { @@ -129,6 +132,7 @@ public: ECMADecryptor(); virtual ~ECMADecryptor(); + virtual void Init(const unsigned long val) {} virtual void Decrypt (char* data, const size_t size, const unsigned long stream_pos, const size_t block_size); virtual void Decrypt (char* data, const size_t size, const unsigned long start_iv_block);