Commit 27c67d0a authored by ElenaSubbotina's avatar ElenaSubbotina Committed by Alexander Trofimov

DocFormatReader - анализ зашифрованности файла

XlsFormatReader - чтение зашифрованных файлов (введен параметр password на вход)
parent ea0ffa79
......@@ -457,37 +457,37 @@ namespace DocFileFormat
unsigned char flag8 = 0;
//read the FIB base
this->m_FibBase.wIdent = reader.ReadUInt16(); //0
this->m_FibBase.nFib = (FibVersion)reader.ReadUInt16(); //2
this->m_FibBase.wIdent = reader.ReadUInt16(); //0
this->m_FibBase.nFib = (FibVersion)reader.ReadUInt16(); //2
reader.ReadBytes( 2, false ); //4
this->m_FibBase.lid = reader.ReadUInt16(); //6
this->m_FibBase.pnNext = reader.ReadInt16(); //8
this->m_FibBase.lid = reader.ReadUInt16(); //6
this->m_FibBase.pnNext = reader.ReadInt16(); //8
flag16 = reader.ReadUInt16(); //10
this->m_FibBase.fDot = FormatUtils::BitmaskToBool((int)flag16, 0x0001);
this->m_FibBase.fGlsy = FormatUtils::BitmaskToBool((int)flag16, 0x0002);
this->m_FibBase.fComplex = FormatUtils::BitmaskToBool((int)flag16, 0x0002);
this->m_FibBase.fHasPic = FormatUtils::BitmaskToBool((int)flag16, 0x0008);
this->m_FibBase.cQuickSaves = (WORD)(((int)flag16 & 0x00F0) >> 4);
this->m_FibBase.fEncrypted = FormatUtils::BitmaskToBool((int)flag16, 0x0100);
this->m_FibBase.fWhichTblStm = FormatUtils::BitmaskToBool((int)flag16, 0x0200);
this->m_FibBase.fDot = FormatUtils::BitmaskToBool((int)flag16, 0x0001);
this->m_FibBase.fGlsy = FormatUtils::BitmaskToBool((int)flag16, 0x0002);
this->m_FibBase.fComplex = FormatUtils::BitmaskToBool((int)flag16, 0x0002);
this->m_FibBase.fHasPic = FormatUtils::BitmaskToBool((int)flag16, 0x0008);
this->m_FibBase.cQuickSaves = (WORD)(((int)flag16 & 0x00F0) >> 4);
this->m_FibBase.fEncrypted = FormatUtils::BitmaskToBool((int)flag16, 0x0100);
this->m_FibBase.fWhichTblStm = FormatUtils::BitmaskToBool((int)flag16, 0x0200);
this->m_FibBase.fReadOnlyRecommended = FormatUtils::BitmaskToBool((int)flag16, 0x0400);
this->m_FibBase.fWriteReservation = FormatUtils::BitmaskToBool((int)flag16, 0x0800);
this->m_FibBase.fExtChar = FormatUtils::BitmaskToBool((int)flag16, 0x1000);
this->m_FibBase.fLoadOverwrite = FormatUtils::BitmaskToBool((int)flag16, 0x2000);
this->m_FibBase.fFarEast = FormatUtils::BitmaskToBool((int)flag16, 0x4000);
this->m_FibBase.fCrypto = FormatUtils::BitmaskToBool((int)flag16, 0x8000);
this->m_FibBase.nFibBack = reader.ReadUInt16(); //12
this->m_FibBase.lKey = reader.ReadInt32(); //14
this->m_FibBase.envr = reader.ReadByte(); //18
this->m_FibBase.fExtChar = FormatUtils::BitmaskToBool((int)flag16, 0x1000);
this->m_FibBase.fLoadOverwrite = FormatUtils::BitmaskToBool((int)flag16, 0x2000);
this->m_FibBase.fFarEast = FormatUtils::BitmaskToBool((int)flag16, 0x4000);
this->m_FibBase.fCrypto = FormatUtils::BitmaskToBool((int)flag16, 0x8000);
this->m_FibBase.nFibBack = reader.ReadUInt16(); //12
this->m_FibBase.lKey = reader.ReadInt32(); //14
this->m_FibBase.envr = reader.ReadByte(); //18
flag8 = reader.ReadByte(); //19
this->m_FibBase.fMac = FormatUtils::BitmaskToBool((int)flag8, 0x01);
this->m_FibBase.fEmptySpecial = FormatUtils::BitmaskToBool((int)flag8, 0x02);
this->m_FibBase.fMac = FormatUtils::BitmaskToBool((int)flag8, 0x01);
this->m_FibBase.fEmptySpecial = FormatUtils::BitmaskToBool((int)flag8, 0x02);
this->m_FibBase.fLoadOverridePage = FormatUtils::BitmaskToBool((int)flag8, 0x04);
this->m_FibBase.fFutureSavedUndo = FormatUtils::BitmaskToBool((int)flag8, 0x08);
this->m_FibBase.fWord97Saved = FormatUtils::BitmaskToBool((int)flag8, 0x10);
this->m_FibBase.fWord97Saved = FormatUtils::BitmaskToBool((int)flag8, 0x10);
reader.ReadBytes( 4, false ); //20
this->m_FibBase.fcMin = reader.ReadInt32(); //24
this->m_FibBase.fcMac = reader.ReadInt32(); //28
this->m_FibBase.fcMin = reader.ReadInt32(); //24
this->m_FibBase.fcMac = reader.ReadInt32(); //28
this->csw = reader.ReadUInt16(); //32
......
......@@ -178,6 +178,9 @@ namespace DocFileFormat
}
}
if (FIB->m_FibBase.fEncrypted)
return AVS_ERROR_DRM;
// Get the streams
if (FIB->m_FibBase.fWhichTblStm)
{
......
......@@ -26,7 +26,7 @@ int _tmain(int argc, _TCHAR* argv[])
std::wstring dstTempPath = FileSystem::Directory::CreateDirectoryWithUniqueName(outputDir);
hr = ConvertXls2Xlsx(srcFileName, dstTempPath, L"C:\\Windows\\Fonts", NULL);
hr = ConvertXls2Xlsx(srcFileName, dstTempPath, L"password1", L"C:\\Windows\\Fonts", NULL);
if (hr != S_OK) return hr;
......
#pragma once
#include <string>
#include <boost/shared_ptr.hpp>
namespace CRYPT
......@@ -19,6 +20,8 @@ public:
XOR
} crypt_type;
virtual bool IsVerify() = 0;
};
typedef boost::shared_ptr<Crypt> CryptPtr;
......
......@@ -8,16 +8,31 @@
namespace CRYPT
{
Decryptor::Decryptor(const CRYPTO::RC4EncryptionHeader& header)
: crypt(new RC4Crypt(header)),
type(Crypt::RC4)
{
}
void Decryptor::Decrypt(char* data, const size_t size, const unsigned long stream_pos)
{
crypt->Decrypt(data, size, stream_pos);
}
Decryptor::Decryptor(CRYPTO::RC4EncryptionHeaderPtr & header, std::wstring password) :
crypt (new RC4Crypt(header, password)),
type (Crypt::RC4)
{
crypt_header = header;
}
void Decryptor::Decrypt(char* data, const size_t size, const unsigned long stream_pos)
{
crypt->Decrypt(data, size, stream_pos);
}
bool Decryptor::IsVerify()
{
return crypt->IsVerify();
}
bool Decryptor::SetPassword(std::wstring password)
{
crypt.reset();
crypt = CryptPtr(new RC4Crypt(crypt_header, password));
if (crypt) return crypt->IsVerify();
else return false;
}
};
......
......@@ -4,7 +4,9 @@
namespace CRYPTO
{
class RC4EncryptionHeader;
class RC4EncryptionHeader;
typedef boost::shared_ptr<RC4EncryptionHeader> RC4EncryptionHeaderPtr;
} // namespace CRYPTO
namespace CRYPT
......@@ -13,13 +15,18 @@ namespace CRYPT
class Decryptor
{
public:
Decryptor(const CRYPTO::RC4EncryptionHeader& header);
Decryptor(CRYPTO::RC4EncryptionHeaderPtr & header, std::wstring password);
void Decrypt(char* data, const size_t size, const unsigned long stream_pos);
bool IsVerify();
bool SetPassword(std::wstring password);
private:
CryptPtr crypt;
Crypt::crypt_type type;
CryptPtr crypt;
Crypt::crypt_type type;
CRYPTO::RC4EncryptionHeaderPtr crypt_header;
};
typedef boost::shared_ptr<Decryptor> DecryptorPtr;
......
......@@ -7,14 +7,19 @@
namespace CRYPT
{
RC4Crypt::RC4Crypt(const CRYPTO::RC4EncryptionHeader& header)
RC4Crypt::RC4Crypt(CRYPTO::RC4EncryptionHeaderPtr & header, std::wstring password)
{
CopyDWORDs2Bytes(header.Salt.b1, header.Salt.b2, header.Salt.b3, header.Salt.b4, pnSalt);
CopyDWORDs2Bytes(header.EncryptedVerifier.b1, header.EncryptedVerifier.b2, header.EncryptedVerifier.b3, header.EncryptedVerifier.b4, pnVerifier);
CopyDWORDs2Bytes(header.EncryptedVerifierHash.b1, header.EncryptedVerifierHash.b2, header.EncryptedVerifierHash.b3, header.EncryptedVerifierHash.b4, pnVerifierHash);
m_VerifyPassword = false;
if (!header) return;
CopyDWORDs2Bytes(header->Salt.b1, header->Salt.b2, header->Salt.b3, header->Salt.b4, pnSalt);
CopyDWORDs2Bytes(header->EncryptedVerifier.b1 , header->EncryptedVerifier.b2, header->EncryptedVerifier.b3, header->EncryptedVerifier.b4, pnVerifier);
CopyDWORDs2Bytes(header->EncryptedVerifierHash.b1, header->EncryptedVerifierHash.b2, header->EncryptedVerifierHash.b3, header->EncryptedVerifierHash.b4, pnVerifierHash);
mxDecoder.reset(new BiffDecoder_RCF(pnSalt, pnVerifier, pnVerifierHash));
mxDecoder->verifyPassword(L"VelvetSweatshop");
m_VerifyPassword = mxDecoder->verifyPassword(password);
}
void RC4Crypt::Encrypt(char* data, const size_t size)
......@@ -22,6 +27,11 @@ void RC4Crypt::Encrypt(char* data, const size_t size)
}
bool RC4Crypt::IsVerify()
{
return m_VerifyPassword;
}
void RC4Crypt::CopyDWORDs2Bytes(const unsigned int b1, const unsigned int b2, const unsigned int b3, const unsigned int b4, unsigned char* byte_array)
{
byte_array[0] = static_cast<unsigned char>((b1 & 0x000000ff) >> 0);
......
......@@ -10,20 +10,23 @@ namespace CRYPT
class RC4Crypt : public Crypt
{
public:
RC4Crypt(const CRYPTO::RC4EncryptionHeader& header);
RC4Crypt(CRYPTO::RC4EncryptionHeaderPtr & header, std::wstring password);
virtual void Encrypt(char* data, const size_t size);
virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos);
virtual bool IsVerify();
private:
void CopyDWORDs2Bytes(const unsigned int b1, const unsigned int b2, const unsigned int b3, const unsigned int b4, unsigned char* byte_array);
private:
unsigned char pnSalt[16];
unsigned char pnVerifier[16];
unsigned char pnVerifierHash[16];
BiffDecoderRef mxDecoder;
bool m_VerifyPassword;
};
......
......@@ -45,8 +45,13 @@ void FilePass::readFields(CFRecord& record)
majorVer = *record.getCurData<unsigned short>();
if(0x0001 == majorVer) // RC4 encryption header structure
{
record >> rc4Header;
record.getGlobalWorkbookInfo()->decryptor = CRYPT::DecryptorPtr(new CRYPT::Decryptor(rc4Header));
rc4HeaderPtr = CRYPTO::RC4EncryptionHeaderPtr(new CRYPTO::RC4EncryptionHeader());
rc4HeaderPtr->load (record);
record.getGlobalWorkbookInfo()->decryptor =
CRYPT::DecryptorPtr(new CRYPT::Decryptor(rc4HeaderPtr, record.getGlobalWorkbookInfo()->password));
Log::info("Encryption type: RC4 Standard");
}
else // RC4 CryptoAPI encryption header structuren
......
......@@ -28,10 +28,11 @@ public:
//-----------------------------
Boolean<unsigned short> wEncryptionType;
XORObfuscation key;
_UINT16 majorVer;
CRYPTO::RC4EncryptionHeader rc4Header;
CRYPTO::RC4CryptoAPIEncryptionHeader rc4CryptoAPIHeader;
XORObfuscation key;
_UINT16 majorVer;
CRYPTO::RC4EncryptionHeaderPtr rc4HeaderPtr;
CRYPTO::RC4CryptoAPIEncryptionHeader rc4CryptoAPIHeader;
};
......
......@@ -19,19 +19,25 @@ public:
static const XLS::ElementType type = XLS::typeRC4EncryptionHeader;
Version EncryptionVersionInfo;
struct SALT_TAG {
struct SALT_TAG
{
_UINT32 b1;
_UINT32 b2;
_UINT32 b3;
_UINT32 b4;
} Salt;
struct ENCRYPTED_VERIFIER_TAG {
struct ENCRYPTED_VERIFIER_TAG
{
_UINT32 b1;
_UINT32 b2;
_UINT32 b3;
_UINT32 b4;
} EncryptedVerifier;
struct ENCRYPTED_VERIFIER_HASH_TAG {
struct ENCRYPTED_VERIFIER_HASH_TAG
{
_UINT32 b1;
_UINT32 b2;
_UINT32 b3;
......@@ -39,5 +45,7 @@ public:
} EncryptedVerifierHash;
};
typedef boost::shared_ptr<RC4EncryptionHeader> RC4EncryptionHeaderPtr;
} // namespace CRYPTO
......@@ -106,6 +106,11 @@ const bool BinReaderProcessor::readChild(BaseObject& object, const bool is_manda
ret_val = object.read(reader_, parent_, is_mandatory /* log warning if mandatory tag absent*/);
if(!ret_val && is_mandatory)
{
if (global_info_->decryptor)
{
if (global_info_->decryptor->IsVerify() == false)
return false;
}
// We don't update ret_val here because we are reading to the copy of the object.
// And the real object will remain uninitialized
wanted_objects.push_back(object.clone()); // store the copy of the object that was not found (this line is here to take another chance to be read after some trash processed)
......
......@@ -47,6 +47,7 @@ public:
unsigned short CodePage;
CRYPT::DecryptorPtr decryptor;
std::wstring password;
std::vector<std::wstring> sheets_state;
std::vector<std::wstring> sheets_names;
......
......@@ -144,7 +144,17 @@ const bool GlobalsSubstream::loadContent(BinProcessor& proc)
}
}break;
case rt_WriteProtect: proc.optional<WriteProtect>(); break;
case rt_FilePass: proc.optional<FilePass>(); break;
case rt_FilePass:
{
if (proc.optional<FilePass>())
{
if (( proc.getGlobalWorkbookInfo()->decryptor) &&
( proc.getGlobalWorkbookInfo()->decryptor->IsVerify() == false))
{
return false;
}
}
}break;
case rt_Template:
{
if (proc.optional<Template>())
......
......@@ -5,14 +5,19 @@
#include "../../../Common/OfficeFileErrorDescription.h"
long ConvertXls2Xlsx(const std::wstring & srcFile, const std::wstring & dstPath, const std::wstring & fontsPath, const ProgressCallback* pCallBack)
long ConvertXls2Xlsx(const std::wstring & srcFile, const std::wstring & dstPath, const std::wstring & password, const std::wstring & fontsPath, const ProgressCallback* pCallBack)
{
XlsConverter converter(srcFile, dstPath, fontsPath, pCallBack);
XlsConverter converter(srcFile, dstPath, password, fontsPath, pCallBack);
if (converter.isError())
{
if (converter.is_older_version)
return AVS_MSFILE_ERROR_OLDER;
if (converter.is_encrypted)
{
if (password.empty()) return AVS_ERROR_DRM;
else return AVS_ERROR_PASSWORD;
}
else return AVS_ERROR_FILEFORMAT;
}
......
......@@ -2,4 +2,4 @@
struct ProgressCallback;
long ConvertXls2Xlsx(const std::wstring & srcFile, const std::wstring & dstPath, const std::wstring& fontsPath, const ProgressCallback* CallBack);
\ No newline at end of file
long ConvertXls2Xlsx(const std::wstring & srcFile, const std::wstring & dstPath, const std::wstring & password, const std::wstring& fontsPath, const ProgressCallback* CallBack);
\ No newline at end of file
......@@ -86,7 +86,7 @@ typedef struct tagBITMAPCOREHEADER {
} BITMAPCOREHEADER;
#endif
XlsConverter::XlsConverter(const std::wstring & xls_file, const std::wstring & _xlsx_path, const std::wstring & fontsPath, const ProgressCallback* CallBack)
XlsConverter::XlsConverter(const std::wstring & xls_file, const std::wstring & _xlsx_path, const std::wstring & password, const std::wstring & fontsPath, const ProgressCallback* CallBack)
{
xlsx_path = _xlsx_path;
output_document = NULL;
......@@ -95,6 +95,7 @@ XlsConverter::XlsConverter(const std::wstring & xls_file, const std::wstring & _
pCallBack = CallBack;
bUserStopConvert = false;
is_older_version = false;
is_encrypted = false;
try{
XLS::CompoundFile cfile(xls_file, XLS::CompoundFile::cf_ReadMode);
......@@ -138,15 +139,24 @@ XlsConverter::XlsConverter(const std::wstring & xls_file, const std::wstring & _
}
xls_global_info = boost::shared_ptr<XLS::GlobalWorkbookInfo>(new XLS::GlobalWorkbookInfo(workbook_code_page, this));
xls_global_info->fontsDirectory = fontsPath;
xls_global_info->password = password;
XLS::CFStreamCacheReader stream_reader(cfile.getWorkbookStream(), xls_global_info);
xls_document = boost::shared_ptr<XLS::WorkbookStreamObject>(new XLS::WorkbookStreamObject(workbook_code_page));
XLS::BinReaderProcessor proc(stream_reader , xls_document.get() , true);
proc.mandatory(*xls_document.get());
if (xls_global_info->decryptor)
{
is_encrypted = true;
if (xls_global_info->decryptor->IsVerify() == false) return;
}
}
catch(...)
{
......
......@@ -59,7 +59,7 @@ namespace ODRAW
class XlsConverter
{
public:
XlsConverter(const std::wstring & xls_file, const std::wstring & xlsx_path, const std::wstring & fontsPath, const ProgressCallback* ffCallBack);
XlsConverter(const std::wstring & xls_file, const std::wstring & xlsx_path, const std::wstring & password, const std::wstring & fontsPath, const ProgressCallback* ffCallBack);
~XlsConverter() ;
oox::xlsx_conversion_context * xlsx_context;
......@@ -95,6 +95,7 @@ public:
std::wstring GetTargetMoniker(XLS::BiffStructure *moniker);
bool isError();
bool is_encrypted;
bool is_older_version;
std::wstring WriteMediaFile (char *data, int size, std::wstring type_ext, int id = -1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment