From 4015e8ba4d1ea30d2f30535f18250ea58b96a6df Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Sat, 24 Jun 2017 15:46:38 +0300 Subject: [PATCH] PptFormatReader - decrypt ppt images --- .../DocDocxConverter/EncryptionHeader.cpp | 3 +- .../PPTFormatLib/Reader/PPTDocumentInfo.h | 4 +- .../PPTFormatLib/Reader/PPTFileReader.cpp | 21 +- .../PPTFormatLib/Reader/ReadStructures.cpp | 35 +- .../PPTFormatLib/Reader/ReadStructures.h | 6 +- .../Records/CryptSession10Container.h | 2 + .../PPTFormatLib/Records/Drawing/ArtBlip.cpp | 335 +++++++++--------- 7 files changed, 214 insertions(+), 192 deletions(-) diff --git a/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.cpp b/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.cpp index ebec59eb58..c1e44df349 100644 --- a/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.cpp +++ b/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.cpp @@ -147,10 +147,11 @@ namespace DocFileFormat 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; - break; 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; diff --git a/ASCOfficePPTFile/PPTFormatLib/Reader/PPTDocumentInfo.h b/ASCOfficePPTFile/PPTFormatLib/Reader/PPTDocumentInfo.h index 4635ca2d42..a4093fcd0a 100644 --- a/ASCOfficePPTFile/PPTFormatLib/Reader/PPTDocumentInfo.h +++ b/ASCOfficePPTFile/PPTFormatLib/Reader/PPTDocumentInfo.h @@ -96,7 +96,9 @@ public: if (bResult == false) { delete pInfo; - continue; + + if (pInfo->m_bEncrypt) return false; + else continue; } m_arUsers.push_back(pInfo); diff --git a/ASCOfficePPTFile/PPTFormatLib/Reader/PPTFileReader.cpp b/ASCOfficePPTFile/PPTFormatLib/Reader/PPTFileReader.cpp index 487d3ceb61..b7b56249bc 100644 --- a/ASCOfficePPTFile/PPTFormatLib/Reader/PPTFileReader.cpp +++ b/ASCOfficePPTFile/PPTFormatLib/Reader/PPTFileReader.cpp @@ -224,6 +224,7 @@ void CPPTFileReader::ReadDocumentSummary() void CPPTFileReader::ReadPictures() { + if (m_oDocumentInfo.m_arUsers.empty()) return; CFStreamPtr pStream = GetPictureStream(); if (!pStream) return; @@ -242,28 +243,22 @@ void CPPTFileReader::ReadPictures() POLE::Stream * pStreamTmp = pStream->stream_; if (pDecryptor) { - m_oDocumentInfo.m_arUsers[0]->DecryptStream(pStreamTmp, 0); + m_oDocumentInfo.m_arUsers[0]->DecryptStream(pStreamTmp, 0); pStreamTmp = m_oDocumentInfo.m_arUsers[0]->m_arStreamDecrypt.back()->stream_; } oHeader.ReadFromStream(pStreamTmp); - pStream->seekFromBegin(pos + 8); CRecordOfficeArtBlip art_blip; art_blip.m_strTmpDirectory = m_strTmpDirectory; art_blip.m_oDocumentInfo = &m_oDocumentInfo; - - pStreamTmp = pStream->stream_; - if (pDecryptor) - { - m_oDocumentInfo.m_arUsers[0]->DecryptStream(pStreamTmp, 1); - pStreamTmp = m_oDocumentInfo.m_arUsers[0]->m_arStreamDecrypt.back()->stream_; + // + pStream->seekFromBegin(pos + 8); + pStreamTmp = pStream->stream_; //каждое поле отдельно нужно - } - art_blip.ReadFromStream(oHeader, pStreamTmp); - - pStream->seekFromBegin(pos + oHeader.RecLen + 8); - + art_blip.ReadFromStream(oHeader, pStreamTmp); m_oDocumentInfo.m_mapStoreImageFile[ pos ] = art_blip.m_sFileName; + + pStream->seekFromBegin(pos + oHeader.RecLen + 8); } } diff --git a/ASCOfficePPTFile/PPTFormatLib/Reader/ReadStructures.cpp b/ASCOfficePPTFile/PPTFormatLib/Reader/ReadStructures.cpp index 56f6b84ced..934982df6f 100644 --- a/ASCOfficePPTFile/PPTFormatLib/Reader/ReadStructures.cpp +++ b/ASCOfficePPTFile/PPTFormatLib/Reader/ReadStructures.cpp @@ -33,8 +33,10 @@ #include "ReadStructures.h" -#include +#include "../../../ASCOfficeDocFile/DocDocxConverter/MemoryStream.h" +#include "../../../OfficeCryptReader/source/CryptTransform.h" +#include using namespace NSPresentationEditor; @@ -639,22 +641,31 @@ namespace NSPresentationEditor } } //------------------------------------------------------------------------------------ -void CMetaHeader::FromStream(POLE::Stream* pStream) +void CMetaHeader::FromStream(POLE::Stream* pStream, CRYPT::ECMADecryptor *pDecryptor) { - cbSize = StreamUtils::ReadDWORD(pStream); + int size = 34; + BYTE* pData = new BYTE[size]; + pStream->read(pData, size); + if (pDecryptor) + { + pDecryptor->Decrypt((char*)pData, size, 0); + } + MemoryStream memStream(pData, size, false); + + cbSize = memStream.ReadUInt32(); - rcBounds.left = StreamUtils::ReadLONG(pStream); - rcBounds.top = StreamUtils::ReadLONG(pStream); - rcBounds.right = StreamUtils::ReadLONG(pStream); - rcBounds.bottom = StreamUtils::ReadLONG(pStream); + rcBounds.left = memStream.ReadInt32(); + rcBounds.top = memStream.ReadInt32(); + rcBounds.right = memStream.ReadInt32(); + rcBounds.bottom = memStream.ReadInt32(); - ptSize.x = StreamUtils::ReadLONG(pStream); - ptSize.y = StreamUtils::ReadLONG(pStream); + ptSize.x = memStream.ReadInt32(); + ptSize.y = memStream.ReadInt32(); - cbSave = StreamUtils::ReadDWORD(pStream); + cbSave = memStream.ReadUInt32(); - compression = StreamUtils::ReadBYTE(pStream); - filter = StreamUtils::ReadBYTE(pStream); + compression = memStream.ReadByte(); + filter = memStream.ReadByte(); } void CMetaHeader::ToEMFHeader(Gdiplus::ENHMETAHEADER3* pHeader) diff --git a/ASCOfficePPTFile/PPTFormatLib/Reader/ReadStructures.h b/ASCOfficePPTFile/PPTFormatLib/Reader/ReadStructures.h index 489da916bf..5463a6eb9e 100644 --- a/ASCOfficePPTFile/PPTFormatLib/Reader/ReadStructures.h +++ b/ASCOfficePPTFile/PPTFormatLib/Reader/ReadStructures.h @@ -43,6 +43,10 @@ namespace NSZLib bool Decompress(const BYTE* pSrcBuffer, const ULONG& lSrcBufferLen, BYTE* pDstBuffer, ULONG& lDstBufferLen); } +namespace CRYPT +{ + class ECMADecryptor; +} /************************************************************** теперь все структуры... которые участвуют в записях @@ -170,7 +174,7 @@ public: CMetaHeader() { } - void FromStream(POLE::Stream* pStream); + void FromStream(POLE::Stream* pStream, CRYPT::ECMADecryptor *pDecryptor = NULL); void ToEMFHeader (Gdiplus::ENHMETAHEADER3* pHeader); void ToWMFHeader (Gdiplus::WmfPlaceableFileHeader* pHeader); diff --git a/ASCOfficePPTFile/PPTFormatLib/Records/CryptSession10Container.h b/ASCOfficePPTFile/PPTFormatLib/Records/CryptSession10Container.h index 4608704a65..b132813c33 100644 --- a/ASCOfficePPTFile/PPTFormatLib/Records/CryptSession10Container.h +++ b/ASCOfficePPTFile/PPTFormatLib/Records/CryptSession10Container.h @@ -165,6 +165,8 @@ public: 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; diff --git a/ASCOfficePPTFile/PPTFormatLib/Records/Drawing/ArtBlip.cpp b/ASCOfficePPTFile/PPTFormatLib/Records/Drawing/ArtBlip.cpp index 91aea8268a..258df5dde2 100644 --- a/ASCOfficePPTFile/PPTFormatLib/Records/Drawing/ArtBlip.cpp +++ b/ASCOfficePPTFile/PPTFormatLib/Records/Drawing/ArtBlip.cpp @@ -39,191 +39,198 @@ void CRecordOfficeArtBlip::ReadFromStream(SRecordHeader & oHeader, POLE::Stream* pStream) { - CMetaFileBuffer oMetaFile; + if ((oHeader.RecVersion == PSFLAG_CONTAINER) || ((oHeader.RecVersion & 0x0F) == 0x0F)) return; + + CRYPT::ECMADecryptor *pDecryptor = m_oDocumentInfo ? m_oDocumentInfo->m_arUsers[0]->m_pDecryptor : NULL; + CMetaFileBuffer oMetaFile; std::wstring sExt = L".jpg"; + int lOffset = 0; - int pos = pStream->tell(); - - if ((oHeader.RecVersion != PSFLAG_CONTAINER) && ((oHeader.RecVersion & 0x0F) != 0x0F)) + switch (oHeader.RecType) { - int lOffset = 0; - - switch (oHeader.RecType) + case RECORD_TYPE_ESCHER_BLIP_EMF: { - case RECORD_TYPE_ESCHER_BLIP_EMF: - { - if (0x03D4 == oHeader.RecInstance) lOffset = 16; - else if (0x03D5 == oHeader.RecInstance) lOffset = 32; + if (0x03D4 == oHeader.RecInstance) lOffset = 16; + else if (0x03D5 == oHeader.RecInstance) lOffset = 32; - StreamUtils::StreamSkip(lOffset, pStream); - lOffset += 34; + StreamUtils::StreamSkip(lOffset, pStream); + lOffset += 34; - oMetaFile.m_bIsValid = TRUE; - oMetaFile.m_sExtension = L".emf"; - - CMetaHeader oMetaHeader; - oMetaHeader.FromStream(pStream); - - Gdiplus::ENHMETAHEADER3 oEmfHeader; - oMetaHeader.ToEMFHeader(&oEmfHeader); - - oMetaFile.SetHeader(NULL, 0); - - BYTE* pData = new BYTE[oHeader.RecLen - lOffset]; - pStream->read(pData, oHeader.RecLen - lOffset); - - oMetaFile.SetData(pData, oMetaHeader.cbSave, oMetaHeader.cbSize, (bool)(oMetaHeader.compression != 0xFE) ); - - }break; - case RECORD_TYPE_ESCHER_BLIP_WMF: - { - if (0x0216 == oHeader.RecInstance) lOffset = 16; - else if (0x0217 == oHeader.RecInstance) lOffset = 32; - - StreamUtils::StreamSkip(lOffset, pStream); - - lOffset += 34; - - oMetaFile.m_bIsValid = TRUE; - oMetaFile.m_sExtension = L".wmf"; - - CMetaHeader oMetaHeader; - oMetaHeader.FromStream(pStream); - Gdiplus::WmfPlaceableFileHeader oWmfHeader; - oMetaHeader.ToWMFHeader(&oWmfHeader); - - LONG lLenHeader = 22; - BYTE* pMetaHeader = new BYTE[lLenHeader]; // удалится в oMetaFile - memcpy(pMetaHeader, (void*)(&oWmfHeader), lLenHeader); - - oMetaFile.SetHeader(pMetaHeader, lLenHeader); - - BYTE* pData = new BYTE[oHeader.RecLen - lOffset]; - pStream->read(pData, oHeader.RecLen - lOffset); - - oMetaFile.SetData(pData, oMetaHeader.cbSave, oMetaHeader.cbSize, (bool)(oMetaHeader.compression != 0xFE) ); - - }break; - case RECORD_TYPE_ESCHER_BLIP_PICT://Medwoche.ppt , (483) - { - if (0x0542 == oHeader.RecInstance) lOffset = 16; - else if (0x0543 == oHeader.RecInstance) lOffset = 32; - - StreamUtils::StreamSkip(lOffset, pStream); - - lOffset += 34; - - oMetaFile.m_bIsValid = TRUE; - oMetaFile.m_sExtension = L".wmf";//L".pct"; - ВРЕМЕННО пока не сделана конвертация pct(pic) хоть во что нито !!! - - CMetaHeader oMetaHeader; - oMetaHeader.FromStream(pStream); //отдельно вынесенный заголовок.. "форматный" находится в блоке данных - - BYTE* pData = new BYTE[oHeader.RecLen - lOffset]; - pStream->read(pData, oHeader.RecLen - lOffset); - - oMetaFile.SetData(pData, oMetaHeader.cbSave, oMetaHeader.cbSize, (bool)(oMetaHeader.compression != 0xFE) ); - }break; - case RECORD_TYPE_ESCHER_BLIP_JPEG: - { - if (0x046A == oHeader.RecInstance || 0x06E2 == oHeader.RecInstance) lOffset = 17; - else if (0x046B == oHeader.RecInstance || 0x06E3 == oHeader.RecInstance) lOffset = 33; - - //StreamUtils::StreamSkip(lOffset, pStream); - std::string str = StreamUtils::ReadStringA(pStream, lOffset); - - sExt = _T(".jpg"); - break; - } - case RECORD_TYPE_ESCHER_BLIP_PNG: - { - if (0x06E0 == oHeader.RecInstance) lOffset = 17; - else if (0x06E1 == oHeader.RecInstance) lOffset = 33; - - //StreamUtils::StreamSkip(lOffset, pStream); - std::string str = StreamUtils::ReadStringA(pStream, lOffset); - - sExt = _T(".png"); - break; - } - case RECORD_TYPE_ESCHER_BLIP_DIB: - { - if (0x07A8 == oHeader.RecInstance) lOffset = 17; - else if (0x07A9 == oHeader.RecInstance) lOffset = 33; - - StreamUtils::StreamSkip(lOffset, pStream); + oMetaFile.m_bIsValid = TRUE; + oMetaFile.m_sExtension = L".emf"; - sExt = _T(".bmp"); - break; - } - case RECORD_TYPE_ESCHER_BLIP_TIFF: + CMetaHeader oMetaHeader; + oMetaHeader.FromStream(pStream, pDecryptor); + + Gdiplus::ENHMETAHEADER3 oEmfHeader; + oMetaHeader.ToEMFHeader(&oEmfHeader); + + oMetaFile.SetHeader(NULL, 0); + + BYTE* pData = new BYTE[oHeader.RecLen - lOffset]; + pStream->read(pData, oHeader.RecLen - lOffset); + if (pDecryptor) { - if (0x06E4 == oHeader.RecInstance) lOffset = 17; - else if (0x06E5 == oHeader.RecInstance) lOffset = 33; - - StreamUtils::StreamSkip(lOffset, pStream); - - sExt = _T(".tif"); - break; + pDecryptor->Decrypt((char*)pData, oHeader.RecLen - lOffset, 0); } - default: + oMetaFile.SetData(pData, oMetaHeader.cbSave, oMetaHeader.cbSize, (bool)(oMetaHeader.compression != 0xFE) ); + + }break; + case RECORD_TYPE_ESCHER_BLIP_WMF: + { + if (0x0216 == oHeader.RecInstance) lOffset = 16; + else if (0x0217 == oHeader.RecInstance) lOffset = 32; + + StreamUtils::StreamSkip(lOffset, pStream); + + lOffset += 34; + + oMetaFile.m_bIsValid = TRUE; + oMetaFile.m_sExtension = L".wmf"; + + CMetaHeader oMetaHeader; + oMetaHeader.FromStream(pStream, pDecryptor); + + Gdiplus::WmfPlaceableFileHeader oWmfHeader; + oMetaHeader.ToWMFHeader(&oWmfHeader); + + LONG lLenHeader = 22; + BYTE* pMetaHeader = new BYTE[lLenHeader]; // удалится в oMetaFile + memcpy(pMetaHeader, (void*)(&oWmfHeader), lLenHeader); + + oMetaFile.SetHeader(pMetaHeader, lLenHeader); + + BYTE* pData = new BYTE[oHeader.RecLen - lOffset]; + pStream->read(pData, oHeader.RecLen - lOffset); + if (pDecryptor) { - break; + pDecryptor->Decrypt((char*)pData, oHeader.RecLen - lOffset, 0); } - } - int nImagesCount = 0; - if (m_oDocumentInfo) - { - nImagesCount = m_oDocumentInfo->m_mapStoreImageFile.size(); - } - //else nImagesCount = generate uniq name + oMetaFile.SetData(pData, oMetaHeader.cbSave, oMetaHeader.cbSize, (bool)(oMetaHeader.compression != 0xFE) ); - if (oMetaFile.m_bIsValid) + }break; + case RECORD_TYPE_ESCHER_BLIP_PICT://Medwoche.ppt , (483) { - std::wstring strFile = L"Image " +std::to_wstring(nImagesCount + 1) + oMetaFile.m_sExtension; + if (0x0542 == oHeader.RecInstance) lOffset = 16; + else if (0x0543 == oHeader.RecInstance) lOffset = 32; - CFile fileMeta; - HRESULT hr = fileMeta.CreateFile(m_strTmpDirectory + FILE_SEPARATOR_STR + strFile); + StreamUtils::StreamSkip(lOffset, pStream); + + lOffset += 34; + + oMetaFile.m_bIsValid = TRUE; + oMetaFile.m_sExtension = L".wmf";//L".pct"; - ВРЕМЕННО пока не сделана конвертация pct(pic) хоть во что нито !!! + + CMetaHeader oMetaHeader; + oMetaHeader.FromStream(pStream, pDecryptor); //отдельно вынесенный заголовок.. "форматный" находится в блоке данных + + BYTE* pData = new BYTE[oHeader.RecLen - lOffset]; + pStream->read(pData, oHeader.RecLen - lOffset); + if (pDecryptor) + { + pDecryptor->Decrypt((char*)pData, oHeader.RecLen - lOffset, 0); + } + oMetaFile.SetData(pData, oMetaHeader.cbSave, oMetaHeader.cbSize, (bool)(oMetaHeader.compression != 0xFE) ); + }break; + case RECORD_TYPE_ESCHER_BLIP_JPEG: + { + if (0x046A == oHeader.RecInstance || 0x06E2 == oHeader.RecInstance) lOffset = 17; + else if (0x046B == oHeader.RecInstance || 0x06E3 == oHeader.RecInstance) lOffset = 33; + + StreamUtils::StreamSkip(lOffset, pStream); + + sExt = _T(".jpg"); + break; + } + case RECORD_TYPE_ESCHER_BLIP_PNG: + { + if (0x06E0 == oHeader.RecInstance) lOffset = 17; + else if (0x06E1 == oHeader.RecInstance) lOffset = 33; + + StreamUtils::StreamSkip(lOffset, pStream); + + sExt = _T(".png"); + break; + } + case RECORD_TYPE_ESCHER_BLIP_DIB: + { + if (0x07A8 == oHeader.RecInstance) lOffset = 17; + else if (0x07A9 == oHeader.RecInstance) lOffset = 33; + + StreamUtils::StreamSkip(lOffset, pStream); - if (hr == S_OK) - { - oMetaFile.ToFile(&fileMeta); - fileMeta.CloseFile(); - } - m_sFileName = strFile; + sExt = _T(".bmp"); + break; } - else + case RECORD_TYPE_ESCHER_BLIP_TIFF: { - BYTE* pImage = new BYTE[oHeader.RecLen - lOffset]; + if (0x06E4 == oHeader.RecInstance) lOffset = 17; + else if (0x06E5 == oHeader.RecInstance) lOffset = 33; - pStream->read(pImage, oHeader.RecLen - lOffset); - - std::wstring strFile = L"Image " + std::to_wstring(nImagesCount + 1) + sExt; + StreamUtils::StreamSkip(lOffset, pStream); - CFile fileImage; - HRESULT hr = fileImage.CreateFile(m_strTmpDirectory + FILE_SEPARATOR_STR + strFile); - if (hr == S_OK) - { - if (RECORD_TYPE_ESCHER_BLIP_DIB == oHeader.RecType) - { - WORD vtType = 0x4D42; - fileImage.WriteFile((void*)&vtType, 2); - DWORD dwLen = oHeader.RecLen - lOffset; - fileImage.WriteFile((void*)&dwLen, 4); - DWORD dwRes = 0; - fileImage.WriteFile((void*)&dwRes, 4); - DWORD dwOffset = 2; - fileImage.WriteFile((void*)&dwOffset, 4); - } - fileImage.WriteFile((void*)pImage, oHeader.RecLen - lOffset); - fileImage.CloseFile(); - } - if (pImage)delete[] pImage; - pImage = NULL; - - m_sFileName = strFile; + sExt = _T(".tif"); + break; } + default: + { + break; + } + } + int nImagesCount = 0; + if (m_oDocumentInfo) + { + nImagesCount = m_oDocumentInfo->m_mapStoreImageFile.size(); + } + //else nImagesCount = generate uniq name + if (oMetaFile.m_bIsValid) + { + std::wstring strFile = L"Image " +std::to_wstring(nImagesCount + 1) + oMetaFile.m_sExtension; + + CFile fileMeta; + HRESULT hr = fileMeta.CreateFile(m_strTmpDirectory + FILE_SEPARATOR_STR + strFile); + + if (hr == S_OK) + { + oMetaFile.ToFile(&fileMeta); + fileMeta.CloseFile(); + } + m_sFileName = strFile; + } + else + { + BYTE* pImage = new BYTE[oHeader.RecLen - lOffset]; + + pStream->read(pImage, oHeader.RecLen - lOffset); + if (pDecryptor) + { + pDecryptor->Decrypt((char*)pImage, oHeader.RecLen - lOffset, 0); + } + std::wstring strFile = L"Image " + std::to_wstring(nImagesCount + 1) + sExt; + + CFile fileImage; + HRESULT hr = fileImage.CreateFile(m_strTmpDirectory + FILE_SEPARATOR_STR + strFile); + if (hr == S_OK) + { + if (RECORD_TYPE_ESCHER_BLIP_DIB == oHeader.RecType) + { + WORD vtType = 0x4D42; + fileImage.WriteFile((void*)&vtType, 2); + DWORD dwLen = oHeader.RecLen - lOffset; + fileImage.WriteFile((void*)&dwLen, 4); + DWORD dwRes = 0; + fileImage.WriteFile((void*)&dwRes, 4); + DWORD dwOffset = 2; + fileImage.WriteFile((void*)&dwOffset, 4); + } + fileImage.WriteFile((void*)pImage, oHeader.RecLen - lOffset); + fileImage.CloseFile(); + } + if (pImage)delete[] pImage; + pImage = NULL; + + m_sFileName = strFile; } }