Esempio n. 1
0
        public FilePass CreateFilePassFromPassword(string password)
        {
            ushort key    = CreateXorKey_Method1(password);
            ushort verify = CreatePasswordVerifier_Method1(password);

            return(FilePass.CreateXORObfuscationFilePass(key, verify));
        }
Esempio n. 2
0
        public byte[] TransformWorkbookBytes(byte[] bytes, ObfuscationMode mode, string password = XorObfuscation.DefaultPassword)
        {
            VirtualStreamReader vsr = new VirtualStreamReader(new MemoryStream(bytes));
            MemoryStream        ms  = new MemoryStream();
            BinaryWriter        bw  = new BinaryWriter(ms);

            while (vsr.BaseStream.Position < vsr.BaseStream.Length)
            {
                BiffHeader bh;
                bh.id = (RecordType)vsr.ReadUInt16();

                //Handle case where RecordId is empty
                if (bh.id == 0)
                {
                    break;
                }

                bh.length = vsr.ReadUInt16();

                //Taken from https://social.msdn.microsoft.com/Forums/en-US/3dadbed3-0e68-4f11-8b43-3a2328d9ebd5/xls-xor-data-transformation-method-1


                byte XorArrayIndex = (byte)((vsr.BaseStream.Position + bh.length) % 16);


                //We remove the FilePass Record for the decrypted document
                if (mode == ObfuscationMode.Decrypt && bh.id == RecordType.FilePass)
                {
                    //Skip the remaining FilePass bytes
                    ushort encryptionMode = vsr.ReadUInt16();

                    if (encryptionMode != 0)
                    {
                        throw new NotImplementedException("FilePass EncryptionMode of " + encryptionMode +
                                                          " is unsupported.");
                    }

                    ushort key    = vsr.ReadUInt16();
                    ushort verify = vsr.ReadUInt16();

                    ushort passwordVerify = CreatePasswordVerifier_Method1(password);

                    if (verify != passwordVerify)
                    {
                        throw new ArgumentException(
                                  "Incorrect decryption password. Try bruteforcing the password with another tool.");
                    }

                    continue;
                }
                ;

                bw.Write(Convert.ToUInt16(bh.id));
                bw.Write(Convert.ToUInt16(bh.length));

                //If we're encrypting, then use the byte writer for our current position rather than the read stream
                if (mode == ObfuscationMode.Encrypt)
                {
                    XorArrayIndex = (byte)((bw.BaseStream.Position + bh.length) % 16);
                }

                //Nothing to decrypt for 0 length
                if (bh.length == 0)
                {
                    continue;
                }

                switch (bh.id)
                {
                case RecordType.BOF:
                case RecordType.FilePass:
                case RecordType.UsrExcl:
                case RecordType.FileLock:
                case RecordType.InterfaceHdr:
                case RecordType.RRDInfo:
                case RecordType.RRDHead:
                    byte[] recordBytes = vsr.ReadBytes(bh.length);
                    bw.Write(recordBytes);

                    //If this is the first BOF record, we inject the appropriate FilePass record
                    if (mode == ObfuscationMode.Encrypt &&
                        bh.id == RecordType.BOF &&
                        vsr.BaseStream.Position == (bh.length + 4))
                    {
                        ushort   key           = CreateXorKey_Method1(password);
                        ushort   verify        = CreatePasswordVerifier_Method1(password);
                        FilePass filePass      = FilePass.CreateXORObfuscationFilePass(key, verify);
                        byte[]   filePassBytes = filePass.GetBytes();
                        bw.Write(filePassBytes);
                    }

                    continue;

                case RecordType.BoundSheet8:
                    //Special Case - don't encrypt/decrypt the lbPlyPos Field
                    uint lbPlyPos = vsr.ReadUInt32();

                    //For encryption we need to adjust this by the added FilePass record length
                    //Decryption we auto-fix afterwards, but encrypted entries don't auto-fix well
                    // if (mode == ObfuscationMode.Encrypt)
                    // {
                    //     lbPlyPos += 10;
                    // }

                    bw.Write(lbPlyPos);
                    //Since we are skipping lbPlyPos, we need to update the XorArrayIndex offset as well
                    XorArrayIndex = (byte)((XorArrayIndex + 4) % 16);
                    byte[] remainingBytes = vsr.ReadBytes(bh.length - 4);
                    if (mode == ObfuscationMode.Decrypt)
                    {
                        byte[] decryptedBytes = DecryptData_Method1(password, remainingBytes, XorArrayIndex);
                        bw.Write(decryptedBytes);
                    }
                    else
                    {
                        byte[] encryptedBytes = EncryptData_Method1(password, remainingBytes, XorArrayIndex);
                        bw.Write(encryptedBytes);
                    }
                    continue;

                default:
                    byte[] preTransformBytes = vsr.ReadBytes(bh.length);
                    if (mode == ObfuscationMode.Decrypt)
                    {
                        byte[] decBytes = DecryptData_Method1(password, preTransformBytes, XorArrayIndex);
                        bw.Write(decBytes);
                    }
                    else
                    {
                        byte[] encBytes = EncryptData_Method1(password, preTransformBytes, XorArrayIndex);
                        bw.Write(encBytes);
                    }
                    continue;
                }
            }

            return(bw.GetBytesWritten());
        }