x2t - ooxml - not strong encryption

This commit is contained in:
ElenaSubbotina
2018-10-03 20:01:57 +03:00
parent 8d664c2a4f
commit 9aad3d1adb
8 changed files with 606 additions and 189 deletions

View File

@ -46,7 +46,8 @@
using namespace CRYPT;
#define GETBIT(from, num) ((from & (1 << num)) != 0)
#define GETBIT(from, num) ((from & (1 << num)) != 0)
#define SETBIT(to, num, setorclear) {setorclear ? to |= (1 << num) : to &= ~(1 << num);}
#define WritingElement_ReadAttributes_Start(Reader) \
if ( Reader.GetAttributesCount() <= 0 )\
@ -288,15 +289,26 @@ bool ReadXmlEncryptionInfo(const std::string & xml_string, _ecmaCryptData & cryp
if (keyData.cipherAlgorithm == "AES")
{
if (keyData.cipherChaining == "ChainingModeCBC") cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CBC;
cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CBC;
//if (keyData.cipherChaining == "ChainingModeCBC") cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CBC;
if (keyData.cipherChaining == "ChainingModeCFB") cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CFB;
}
if (keyData.hashAlgorithm == "SHA1") cryptData.hashAlgorithm = CRYPT_METHOD::SHA1;
if (keyData.hashAlgorithm == "SHA224") cryptData.hashAlgorithm = CRYPT_METHOD::SHA224;
if (keyData.hashAlgorithm == "SHA256") cryptData.hashAlgorithm = CRYPT_METHOD::SHA256;
if (keyData.hashAlgorithm == "SHA384") cryptData.hashAlgorithm = CRYPT_METHOD::SHA384;
if (keyData.hashAlgorithm == "SHA512") cryptData.hashAlgorithm = CRYPT_METHOD::SHA512;
else if (keyData.cipherAlgorithm == "RC4")
{
cryptData.cipherAlgorithm = CRYPT_METHOD::RC4;
}
else if (keyData.cipherAlgorithm == "DES")
{
cryptData.cipherAlgorithm = CRYPT_METHOD::DES_CBC;
//if (keyData.cipherChaining == "ChainingModeCBC") cryptData.cipherAlgorithm = CRYPT_METHOD::DES_CBC;
if (keyData.cipherChaining == "ChainingModeECB") cryptData.cipherAlgorithm = CRYPT_METHOD::DES_ECB;
}
if (keyData.hashAlgorithm == "SHA1") cryptData.hashAlgorithm = CRYPT_METHOD::SHA1;
else if (keyData.hashAlgorithm == "SHA224") cryptData.hashAlgorithm = CRYPT_METHOD::SHA224;
else if (keyData.hashAlgorithm == "SHA256") cryptData.hashAlgorithm = CRYPT_METHOD::SHA256;
else if (keyData.hashAlgorithm == "SHA384") cryptData.hashAlgorithm = CRYPT_METHOD::SHA384;
else if (keyData.hashAlgorithm == "SHA512") cryptData.hashAlgorithm = CRYPT_METHOD::SHA512;
else if (keyData.hashAlgorithm == "MD5") cryptData.hashAlgorithm = CRYPT_METHOD::MD5;
return true;
}
@ -315,12 +327,33 @@ bool WriteXmlEncryptionInfo(const _ecmaCryptData & cryptData, std::string & xml_
keyData.keyBits = std::to_string(cryptData.keySize * 8);
keyData.saltValue = EncodeBase64(cryptData.dataSaltValue);
keyData.cipherAlgorithm = "AES";
if (keyData.cipherAlgorithm == "AES")
switch(cryptData.cipherAlgorithm)
{
if (cryptData.cipherAlgorithm == CRYPT_METHOD::AES_CBC) keyData.cipherChaining = "ChainingModeCBC";
if (cryptData.cipherAlgorithm == CRYPT_METHOD::AES_CFB) keyData.cipherChaining = "ChainingModeCFB";
case CRYPT_METHOD::RC4:
keyData.cipherAlgorithm = "RC4";
break;
case CRYPT_METHOD::AES_CBC:
keyData.cipherAlgorithm = "AES";
keyData.cipherChaining = "ChainingModeCBC";
break;
case CRYPT_METHOD::AES_ECB:
keyData.cipherAlgorithm = "AES";
keyData.cipherChaining = "ChainingModeECB";
break;
case CRYPT_METHOD::AES_CFB:
keyData.cipherAlgorithm = "AES";
keyData.cipherChaining = "ChainingModeCFB";
break;
case CRYPT_METHOD::DES_CBC:
keyData.cipherAlgorithm = "DES";
keyData.cipherChaining = "ChainingModeCBC";
break;
case CRYPT_METHOD::DES_ECB:
keyData.cipherAlgorithm = "DES";
keyData.cipherChaining = "ChainingModeECB";
break;
break;
}
switch(cryptData.hashAlgorithm)
@ -330,6 +363,7 @@ bool WriteXmlEncryptionInfo(const _ecmaCryptData & cryptData, std::string & xml_
case CRYPT_METHOD::SHA256: keyData.hashAlgorithm = "SHA256"; break;
case CRYPT_METHOD::SHA384: keyData.hashAlgorithm = "SHA384"; break;
case CRYPT_METHOD::SHA512: keyData.hashAlgorithm = "SHA512"; break;
case CRYPT_METHOD::MD5: keyData.hashAlgorithm = "MD5"; break;
}
std::vector<_keyEncryptor> keyEncryptors;
@ -360,7 +394,12 @@ bool WriteXmlEncryptionInfo(const _ecmaCryptData & cryptData, std::string & xml_
CP_XML_ATTR("keyBits", keyData.keyBits);
CP_XML_ATTR("hashSize", keyData.hashSize);
CP_XML_ATTR("cipherAlgorithm", keyData.cipherAlgorithm);
CP_XML_ATTR("cipherChaining", keyData.cipherChaining);
if (false == keyData.cipherChaining.empty())
{
CP_XML_ATTR("cipherChaining", keyData.cipherChaining);
}
CP_XML_ATTR("hashAlgorithm", keyData.hashAlgorithm);
CP_XML_ATTR("saltValue", keyData.saltValue);
}
@ -400,7 +439,105 @@ bool WriteXmlEncryptionInfo(const _ecmaCryptData & cryptData, std::string & xml_
return true;
}
bool WriteStandartEncryptionInfo(unsigned char* data, int &size, _ecmaCryptData & cryptData)
{
if (!data || size < 1) return false;
MemoryStream mem_stream(data, size, false);
_UINT32 SizeHeader = 0, Flags = 0, SizeExtra = 0, AlgID = 0, AlgIDHash = 0, KeySize = 0, ProviderType = 0, Reserved1 = 0, Reserved2 = 0;
bool fCryptoAPI = true, fDocProps = false, fExternal = false, fAES = cryptData.cipherAlgorithm != CRYPT_METHOD::RC4;
SETBIT(Flags, 2, fCryptoAPI);
SETBIT(Flags, 3, fDocProps);
SETBIT(Flags, 4, fExternal);
SETBIT(Flags, 5, fAES);
mem_stream.WriteUInt32(SizeHeader);
KeySize = (cryptData.keySize == 5) ? 0 : cryptData.keySize * 8;
std::string provider;// to utf16
switch(cryptData.cipherAlgorithm)
{
case CRYPT_METHOD::RC4:
{
ProviderType = 0x0001;
AlgID = 0x6801;
}break;
case CRYPT_METHOD::DES_ECB:
case CRYPT_METHOD::DES_CBC:
{
ProviderType = 0;//0x0018;
AlgID = 0x6601;
}break;
case CRYPT_METHOD::AES_ECB:
case CRYPT_METHOD::AES_CBC:
{
ProviderType = 0x0018;
switch(KeySize)
{
case 128: AlgID = 0x660E; break;
case 192: AlgID = 0x660F; break;
case 256: AlgID = 0x6610; break;
}
break;
}break;
}
//ProviderType = 0x0018;
switch(ProviderType)
{
case 0x0001: provider = "Microsoft Strong Cryptographic Provider"; break;
case 0x0018: provider = "Microsoft Enhanced RSA and AES Cryptographic Provider"; break;
}
switch(cryptData.hashAlgorithm)
{
case CRYPT_METHOD::MD5: AlgIDHash = 0x8003; break;
case CRYPT_METHOD::SHA1: AlgIDHash = 0x8004; break;
case CRYPT_METHOD::SHA256: AlgIDHash = 0x8004; break;
case CRYPT_METHOD::SHA384: AlgIDHash = 0x800D; break;
case CRYPT_METHOD::SHA512: AlgIDHash = 0x800E; break;
}
mem_stream.WriteUInt32(Flags);
mem_stream.WriteUInt32(SizeExtra);
mem_stream.WriteUInt32(AlgID);
mem_stream.WriteUInt32(AlgIDHash);
mem_stream.WriteUInt32(KeySize);
mem_stream.WriteUInt32(ProviderType);
mem_stream.WriteUInt32(Reserved1);
mem_stream.WriteUInt32(Reserved2);
for (size_t i = 0; i < provider.length(); ++i)
{
mem_stream.WriteByte((unsigned char)provider[i]);
mem_stream.WriteByte((unsigned char)0);
}
mem_stream.WriteByte((unsigned char)0); //null terminate
mem_stream.WriteByte((unsigned char)0);
SizeHeader = mem_stream.GetPosition() - 4;
//EncryptionVerifier
mem_stream.WriteUInt32((_UINT32)cryptData.saltSize);
mem_stream.WriteBytes((unsigned char*)cryptData.saltValue.c_str(), cryptData.saltSize);
mem_stream.WriteBytes((unsigned char*)cryptData.encryptedVerifierInput.c_str(), 0x10);
mem_stream.WriteUInt32((_UINT32)cryptData.hashSize);
//int szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20; //RC4 | AES(DES) .. md5?
mem_stream.WriteBytes((unsigned char*)cryptData.encryptedVerifierValue.c_str(), cryptData.encryptedVerifierValue.length()/*szEncryptedVerifierHash*/);
size = mem_stream.GetPosition();
mem_stream.Seek(0);
mem_stream.WriteUInt32(SizeHeader);
return true;
}
bool ReadStandartEncryptionInfo(unsigned char* data, int size, _ecmaCryptData & cryptData)
{
if (!data || size < 1) return false;
@ -445,21 +582,41 @@ bool ReadStandartEncryptionInfo(unsigned char* data, int size, _ecmaCryptData &
cryptData.hashSize = mem_stream.ReadUInt32();
int szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20;
cryptData.encryptedVerifierValue = std::string((char*)data + mem_stream.GetPosition(), szEncryptedVerifierHash);
unsigned long szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20; // RC4 | AES(DES)
unsigned long szEncryptedVerifierHashMax = mem_stream.GetSize() - mem_stream.GetPosition();
cryptData.encryptedVerifierValue = std::string((char*)data + mem_stream.GetPosition(), max(szEncryptedVerifierHash, szEncryptedVerifierHashMax));
mem_stream.ReadBytes(szEncryptedVerifierHash, false);
pos = mem_stream.GetPosition();
//------------------------------------------------------------------------------------------
cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; //by AlgIDHash -> 0x0000 || 0x8004
cryptData.spinCount = 50000;
switch(AlgIDHash)
{
case 0x8003:
cryptData.hashAlgorithm = CRYPT_METHOD::MD5; break;
case 0x0000:
case 0x8004:
cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; break;
case 0x800C:
cryptData.hashAlgorithm = CRYPT_METHOD::SHA256; break;
case 0x800D:
cryptData.hashAlgorithm = CRYPT_METHOD::SHA384; break;
case 0x800E:
cryptData.hashAlgorithm = CRYPT_METHOD::SHA512; break;
}
cryptData.spinCount = 50000;
switch(AlgID)
{
case 0x6801:
cryptData.cipherAlgorithm = CRYPT_METHOD::RC4;
cryptData.keySize = KeySize / 8;
if (KeySize == 0) cryptData.keySize = 5; //40 bit
else cryptData.keySize = KeySize / 8;
break;
case 0x6601:
cryptData.cipherAlgorithm = CRYPT_METHOD::DES_ECB;
cryptData.keySize = 8;
break;
case 0x660E:
cryptData.cipherAlgorithm = CRYPT_METHOD::AES_ECB;
@ -488,12 +645,53 @@ bool ECMACryptFile::EncryptOfficeFile(const std::wstring &file_name_inp, const s
{
_ecmaCryptData cryptData;
cryptData.bAgile = true;
cryptData.hashAlgorithm = CRYPT_METHOD::SHA512;
cryptData.keySize = 0x20;
cryptData.hashSize = 0x40;
cryptData.blockSize = 0x10;
cryptData.saltSize = 0x10;
//cryptData.bAgile = true;
//cryptData.cipherAlgorithm = CRYPT_METHOD::DES_CBC;
////cryptData.hashAlgorithm = CRYPT_METHOD::SHA512;
////cryptData.keySize = 0x08;
////cryptData.hashSize = 0x40;
////cryptData.blockSize = 0x10;
////cryptData.saltSize = 0x10;
//cryptData.hashAlgorithm = CRYPT_METHOD::SHA1;
//cryptData.keySize = 0x08;
//cryptData.hashSize = 0x14;
//cryptData.blockSize = 0x10;
//cryptData.saltSize = 0x10;
cryptData.bAgile = true;
cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CBC;
cryptData.hashAlgorithm = CRYPT_METHOD::SHA512;
cryptData.keySize = 0x20;
cryptData.hashSize = 0x40;
cryptData.blockSize = 0x10;
cryptData.saltSize = 0x10;
//cryptData.bAgile = false;
//cryptData.cipherAlgorithm = CRYPT_METHOD::AES_ECB;
//cryptData.hashAlgorithm = CRYPT_METHOD::SHA1;
//cryptData.keySize = 0x10;
//cryptData.hashSize = 0x14;
//cryptData.blockSize = 0x10;
//cryptData.saltSize = 0x10;
//cryptData.spinCount = 50000;
//cryptData.bAgile = false;
//cryptData.cipherAlgorithm = CRYPT_METHOD::RC4;
//cryptData.hashAlgorithm = CRYPT_METHOD::SHA1;
//cryptData.keySize = 7;
//cryptData.hashSize = 0x14;
//cryptData.blockSize = 0x10;
//cryptData.saltSize = 0x10;
//cryptData.spinCount = 50000;
//cryptData.bAgile = false;
//cryptData.cipherAlgorithm = CRYPT_METHOD::DES_ECB;
//cryptData.hashAlgorithm = CRYPT_METHOD::SHA1;
//cryptData.keySize = 0x08;
//cryptData.hashSize = 0x14;
//cryptData.blockSize = 0x10;
//cryptData.saltSize = 0x10;
//cryptData.spinCount = 50000;
ECMAEncryptor cryptor;
@ -539,22 +737,53 @@ bool ECMACryptFile::EncryptOfficeFile(const std::wstring &file_name_inp, const s
cryptor.GetCryptData(cryptData);
std::string strXml;
WriteXmlEncryptionInfo(cryptData, strXml);
if (cryptData.bAgile)
{
_UINT16 VersionInfoMajor = 0x0004, VersionInfoMinor = 0x0004; //agile
pStream->write((unsigned char*)&VersionInfoMajor, 2);
pStream->write((unsigned char*)&VersionInfoMinor, 2);
_UINT16 VersionInfoMajor = 0x0004, VersionInfoMinor = 0x0004; //agile standart
_UINT32 nEncryptionInfoFlags = 64;
pStream->write((unsigned char*)&nEncryptionInfoFlags, 4);
std::string strXml;
WriteXmlEncryptionInfo(cryptData, strXml);
pStream->write((unsigned char*)strXml.c_str(), strXml.length());
pStream->flush();
delete pStream;
}
else
{
_UINT16 VersionInfoMajor = 0x0004, VersionInfoMinor = 0x0002; // standart
pStream->write((unsigned char*)&VersionInfoMajor, 2);
pStream->write((unsigned char*)&VersionInfoMinor, 2);
pStream->write((unsigned char*)&VersionInfoMajor, 2);
pStream->write((unsigned char*)&VersionInfoMinor, 2);
_UINT32 nEncryptionInfoFlags = 64;
pStream->write((unsigned char*)&nEncryptionInfoFlags, 4);
pStream->write((unsigned char*)strXml.c_str(), strXml.length());
pStream->flush();
delete pStream;
//-------------------------------------------------------------------
_UINT32 nEncryptionInfoFlags = 0;
bool fCryptoAPI = true, fDocProps = false, fExternal = false, fAES = cryptData.cipherAlgorithm != CRYPT_METHOD::RC4;
SETBIT(nEncryptionInfoFlags, 2, fCryptoAPI);
SETBIT(nEncryptionInfoFlags, 3, fDocProps);
SETBIT(nEncryptionInfoFlags, 4, fExternal);
SETBIT(nEncryptionInfoFlags, 5, fAES);
pStream->write((unsigned char*)&nEncryptionInfoFlags, 4);
int nEncryptionInfoSize = 4096;
unsigned char* byteEncryptionInfo = new unsigned char[nEncryptionInfoSize];
WriteStandartEncryptionInfo(byteEncryptionInfo, nEncryptionInfoSize, cryptData);
pStream->write(byteEncryptionInfo, nEncryptionInfoSize);
delete []byteEncryptionInfo;
pStream->flush();
delete pStream;
}
//-------------------------------------------------------------------
pStream = new POLE::Stream(pStorage, L"EncryptedPackage", true, lengthData);
pStream->write(data_out, lengthData);
@ -651,10 +880,10 @@ bool ECMACryptFile::DecryptOfficeFile(const std::wstring &file_name_inp, const s
else
{
cryptData.bAgile = false;
bool fCryptoAPI = GETBIT(nEncryptionInfoFlags, 1);
bool fDocProps = GETBIT(nEncryptionInfoFlags, 2);
bool fExternal = GETBIT(nEncryptionInfoFlags, 3);
bool fAES = GETBIT(nEncryptionInfoFlags, 4);
bool fCryptoAPI = GETBIT(nEncryptionInfoFlags, 2);
bool fDocProps = GETBIT(nEncryptionInfoFlags, 3);
bool fExternal = GETBIT(nEncryptionInfoFlags, 4);
bool fAES = GETBIT(nEncryptionInfoFlags, 5);
if ((VersionInfoMajor == 0x0003 || VersionInfoMajor == 0x0004) && VersionInfoMinor == 0x0003) //extensible info
{
@ -676,28 +905,6 @@ bool ECMACryptFile::DecryptOfficeFile(const std::wstring &file_name_inp, const s
delete pStorage;
return false;
}
//------------------------------------------------------------------------------------------------------------
//pStream = new POLE::Stream(pStorage, "DataSpaces/DataSpaceMap");
//if (pStream)
//{
// delete pStream;
// pStorage->deleteByName("DataSpaces");
// //_UINT32 size = 0;
// //_UINT32 count = 0;
// //
// //pStream->read((unsigned char*)&size, 4);
// //pStream->read((unsigned char*)&count, 4);
// //for (int i = 0 ; i < count; i++)
// //{
// // _mapEntry m;
// // ReadMapEntry(pStream, m);
// // mapEntries.push_back(m);
// //}
// //delete pStream;
//}
//------------------------------------------------------------------------------------------------------------
ECMADecryptor decryptor;