Exemplo n.º 1
0
        public static void Strip(string ebookPath, string outputDir, string name, string ccNumber)
        {
            if (string.IsNullOrEmpty(outputDir))
            {
                outputDir = Path.GetDirectoryName(ebookPath);
            }
            var ebook = new Pdb(ebookPath);

            var processor = new EReaderProcessor(ebook, name, ccNumber);

            outputDir = Path.Combine(outputDir, ebook.Filename);
            if (!Directory.Exists(outputDir))
            {
                Directory.CreateDirectory(outputDir);
            }
            string path;

            for (var i = 0; i < processor.numImagePages; i++)
            {
                var img = processor.GetImage(i);
                path = Path.Combine(outputDir, img.filename);
                using (var stream = File.Create(path))
                    stream.Write(img.content, 0, img.content.Length);
            }
            var pml = processor.GetText();

            path = Path.Combine(outputDir, ebook.Filename + ".pml");
            using (var stream = File.CreateText(path))
                stream.Write(pml);
        }
Exemplo n.º 2
0
        public EReaderPdb(Pdb pdbReader)
        {
            this.pdbReader = pdbReader;
            byte[] headerRawData = pdbReader.GetSection(0);
            if (headerRawData.Length != 132)
            {
                throw new FormatException("Unknown eReader header format.");
            }

            using (var stream = new MemoryStream(headerRawData))
            {
                var b = (byte)stream.ReadByte();
                if (b > 1)
                {
                    throw new FormatException(string.Format("Unknown DRM flag {0}", b));
                }
                haveDrm           = b == 1;
                b                 = (byte)stream.ReadByte();
                compressionMethod = (EReaderCompression)b;
                var buf = new byte[4];
                stream.Read(buf, 0, 4);                 //unknown, should be 0x00000000
                buf = new byte[2];
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                textEncoding = BitConverter.ToUInt16(buf, 0);                 //should be 2515 or 25152 for cp1251
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfSmallFontPages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfLargeFontPages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                nonTextFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfChapters = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfSmallFontIndexPages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfLargeFontIndexPages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfImages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfLinks = BitConverter.ToUInt16(buf, 0);
                b             = (byte)stream.ReadByte();
                if (b > 1)
                {
                    throw new FormatException(string.Format("Incorrect Metadata flag {0}", b));
                }
                haveMetadata = b == 1;
                buf          = new byte[3];
                stream.Read(buf, 0, 3);                 //unknown, should be 0
                buf = new byte[2];
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfFootnotes = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                numberOfSidebars = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                chapterIndexFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                magickValue = BitConverter.ToUInt16(buf, 0);
                //if (magickValue != 2560) throw new FormatException(string.Format("Unknown Magick Value {0}", magickValue));
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                smallFontPageIndexeFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                largeFontPageIndexeFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                imageDataFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                linksFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                metadataFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);                 //unknown, should be 0x0000
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                footnotesFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                sidebarFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian)
                {
                    buf = buf.Reverse();
                }
                lastRecord = BitConverter.ToUInt16(buf, 0);
            }
        }
Exemplo n.º 3
0
        private EReaderProcessor(Pdb pdb, string name, string ccNumber)
        {
            if (!(pdb.Filetype == "PNRd" && pdb.Creator == "PPrs"))
            {
                throw new FormatException("Invalid eReader file.");
            }

            pdbReader = pdb;
            var eReaderPdb = new EReaderPdb(pdbReader);

            if (!eReaderPdb.HaveDrm)
            {
                throw new InvalidOperationException("File doesn't have DRM or have unknown DRM version: {0}!");
            }

            if (!(eReaderPdb.CompressionMethod == EReaderCompression.Drm1 || eReaderPdb.CompressionMethod == EReaderCompression.Drm2))
            {
                throw new InvalidOperationException($"Unsupported compression method or DRM version: {eReaderPdb.CompressionMethod}!");
            }

            data = pdbReader.GetSection(1);
            var desEngine     = GetDesEngine(data.Copy(0, 8));
            var decryptedData = desEngine.TransformFinalBlock(data.Copy(-8), 0, 8);
            var cookieShuf    = decryptedData[0] << 24 | decryptedData[1] << 16 | decryptedData[2] << 8 | decryptedData[3];
            var cookieSize    = decryptedData[4] << 24 | decryptedData[5] << 16 | decryptedData[6] << 8 | decryptedData[7];

            if (cookieShuf < 0x03 || cookieShuf > 0x14 || cookieSize < 0xf0 || cookieSize > 0x200)
            {
                throw new InvalidOperationException("Unsupportd eReader format");
            }

            var input = desEngine.TransformFinalBlock(data.Copy(-cookieSize), 0, cookieSize);
            var r     = UnshuffleData(input.SubRange(0, -8), cookieShuf);
            //using (var stream = new FileStream(pdb.Filename+".eReaderSection1Dump", FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) stream.Write(r, 0, r.Length);
            var  userKeyPart1 = Encoding.ASCII.GetBytes(FixUserName(name));
            var  userKeyPart2 = Encoding.ASCII.GetBytes(ccNumber.ToCharArray().Copy(-8));
            long userKey;

            using (var stream1 = new MemoryStream(userKeyPart1))
                using (var stream2 = new MemoryStream(userKeyPart2))
                {
                    userKey = new CRC32().GetCrc32(stream1) & 0xffffffff;
                    userKey = userKey << 32 | new CRC32().GetCrc32(stream2) & 0xffffffff;
                }
            var drmSubVersion = (ushort)(r[0] << 8 | r[1]);

            numTextPages   = (ushort)(r[2] << 8 | r[3]) - 1;
            flags          = r[4] << 24 | r[5] << 16 | r[6] << 8 | r[7];
            firstImagePage = (ushort)(r[24] << 8 | r[25]);
            numImagePages  = (ushort)(r[26] << 8 | r[27]);
            if ((flags & ReqdFlags) != ReqdFlags)
            {
                throw new InvalidOperationException($"Unsupported flags combination: {flags:x8}");
            }

            var userKeyArray = BitConverter.GetBytes(userKey);

            if (BitConverter.IsLittleEndian)
            {
                userKeyArray = userKeyArray.Reverse();
            }
            desEngine = GetDesEngine(userKeyArray);
            var encryptedKey    = new byte[0];
            var encryptedKeySha = new byte[0];

            if (eReaderPdb.CompressionMethod == EReaderCompression.Drm1)
            {
                if (drmSubVersion != 13)
                {
                    throw new InvalidOperationException($"Unknown eReader DRM subversion ID: {drmSubVersion}");
                }

                encryptedKey    = r.Copy(44, 8);
                encryptedKeySha = r.Copy(52, 20);
            }
            else if (eReaderPdb.CompressionMethod == EReaderCompression.Drm2)
            {
                encryptedKey    = r.Copy(172, 8);
                encryptedKeySha = r.Copy(56, 20);
            }
            contentKey = desEngine.TransformFinalBlock(encryptedKey, 0, encryptedKey.Length);
            byte[] checkHash;
            using (var sha1 = SHA1.Create())
                checkHash = sha1.ComputeHash(contentKey);
            if (!encryptedKeySha.SequenceEqual(checkHash))
            {
                var s = new StringBuilder();
                for (var x = 0; x < r.Length - 8; x += 2)
                {
                    for (var y = 0; y < (x - 20); y += 2)
                    {
                        if (TestKeyDecryption(desEngine, r, x, y))
                        {
                            s.AppendFormat("keyOffset={0}, hashOffset={1}\n", x, y);
                        }
                    }
                    for (var y = x + 8; y < (r.Length - 20); y += 2)
                    {
                        if (TestKeyDecryption(desEngine, r, x, y))
                        {
                            s.AppendFormat("keyOffset={0}, hashOffset={1}\n", x, y);
                        }
                    }
                }
                if (s.Length > 0)
                {
                    throw new InvalidDataException("Key and/or KeyHash offset mismatch. Possible values:\n\n" + s);
                }
                throw new ArgumentException("Incorrect Name of Credit Card number.");
            }
            contentDecryptor = GetDesEngine(contentKey);
        }
Exemplo n.º 4
0
        private EReaderProcessor(Pdb pdb, string name, string ccNumber)
        {
            if (!(pdb.Filetype == "PNRd" && pdb.Creator == "PPrs")) throw new FormatException("Invalid eReader file.");
            pdbReader = pdb;
            var eReaderPdb = new EReaderPdb(pdbReader);
            if (!eReaderPdb.HaveDrm)
                throw new InvalidOperationException("File doesn't have DRM or have unknown DRM version: {0}!");
            if (!(eReaderPdb.CompressionMethod == EReaderCompression.Drm1 || eReaderPdb.CompressionMethod == EReaderCompression.Drm2))
                throw new InvalidOperationException(string.Format("Unsupported compression method or DRM version: {0}!", eReaderPdb.CompressionMethod));

            data = pdbReader.GetSection(1);
            ICryptoTransform desEngine = GetDesEngine(data.Copy(0, 8));
            byte[] decryptedData = desEngine.TransformFinalBlock(data.Copy(-8), 0, 8);
            int cookieShuf = decryptedData[0] << 24 | decryptedData[1] << 16 | decryptedData[2] << 8 | decryptedData[3];
            int cookieSize = decryptedData[4] << 24 | decryptedData[5] << 16 | decryptedData[6] << 8 | decryptedData[7];
            if (cookieShuf < 0x03 || cookieShuf > 0x14 || cookieSize < 0xf0 || cookieSize > 0x200) throw new InvalidOperationException("Unsupportd eReader format");
            byte[] input = desEngine.TransformFinalBlock(data.Copy(-cookieSize), 0, cookieSize);
            byte[] r = UnshuffData(input.SubRange(0, -8), cookieShuf);
            //using (var stream = new FileStream(pdb.Filename+".eReaderSection1Dump", FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) stream.Write(r, 0, r.Length);
            byte[] userKeyPart1 = Encoding.ASCII.GetBytes(FixUserName(name));
            byte[] userKeyPart2 = Encoding.ASCII.GetBytes(ccNumber.ToCharArray().Copy(-8));
            long userKey;
            using (var stream1 = new MemoryStream(userKeyPart1))
            using (var stream2 = new MemoryStream(userKeyPart2))
            {
                userKey = new CRC32().GetCrc32(stream1) & 0xffffffff;
                userKey = userKey << 32 | new CRC32().GetCrc32(stream2) & 0xffffffff;
            }
            var drmSubVersion = (ushort)(r[0] << 8 | r[1]);
            numTextPages = (ushort)(r[2] << 8 | r[3]) - 1;
            flags = r[4] << 24 | r[5] << 16 | r[6] << 8 | r[7];
            firstImagePage = (ushort)(r[24] << 8 | r[25]);
            numImagePages = (ushort)(r[26] << 8 | r[27]);
            if ((flags & ReqdFlags) != ReqdFlags) throw new InvalidOperationException(string.Format("Unsupported flags combination: {0:x8}", flags));
            byte[] userKeyArray = BitConverter.GetBytes(userKey);
            if (BitConverter.IsLittleEndian) userKeyArray = userKeyArray.Reverse();
            desEngine = GetDesEngine(userKeyArray);
            byte[] encryptedKey = new byte[0],
                   encryptedKeySha = new byte[0];
            if (eReaderPdb.CompressionMethod == EReaderCompression.Drm1)
            {
                if (drmSubVersion != 13) throw new InvalidOperationException(string.Format("Unknown eReader DRM subversion ID: {0}", drmSubVersion));
                encryptedKey = r.Copy(44, 8);
                encryptedKeySha = r.Copy(52, 20);
            }
            else if (eReaderPdb.CompressionMethod == EReaderCompression.Drm2)
            {
                encryptedKey = r.Copy(172, 8);
                encryptedKeySha = r.Copy(56, 20);
            }
            contentKey = desEngine.TransformFinalBlock(encryptedKey, 0, encryptedKey.Length);
            byte[] checkHash = SHA1.Create().ComputeHash(contentKey);
            if (!encryptedKeySha.IsEqualTo(checkHash))
            {
                var s = new StringBuilder();
                for (var x = 0; x < (r.Length - 8); x += 2)
                {
                    for (var y = 0; y < (x - 20); y += 2) if (TestKeyDecryption(desEngine, r, x, y)) s.AppendFormat("keyOffset={0}, hashOffset={1}\n", x, y);
                    for (var y = x + 8; y < (r.Length - 20); y += 2) if (TestKeyDecryption(desEngine, r, x, y)) s.AppendFormat("keyOffset={0}, hashOffset={1}\n", x, y);
                }
                if (s.Length > 0) throw new InvalidDataException("Key and/or KeyHash offset mismatch. Possible values:\n\n" + s);
                throw new ArgumentException("Incorrect Name of Credit Card number.");
            }
            contentDecryptor = GetDesEngine(contentKey);
        }
Exemplo n.º 5
0
        public static void Strip(string ebookPath, string outputDir, string name, string ccNumber)
        {
            if (string.IsNullOrEmpty(outputDir)) outputDir = Path.GetDirectoryName(ebookPath);
            var ebook = new Pdb(ebookPath);

            var processor = new EReaderProcessor(ebook, name, ccNumber);
            outputDir = Path.Combine(outputDir, ebook.Filename);
            if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir);
            string path;
            for (int i = 0; i < processor.numImagePages; i++)
            {
                EReaderImageInfo img = processor.GetImage(i);
                path = Path.Combine(outputDir, img.filename);
                using (FileStream stream = File.Create(path)) stream.Write(img.content, 0, img.content.Length);
            }
            string pml = processor.GetText();
            path = Path.Combine(outputDir, ebook.Filename + ".pml");
            using (StreamWriter stream = File.CreateText(path)) stream.Write(pml);
        }
Exemplo n.º 6
0
        public EReaderPdb(Pdb pdbReader)
        {
            this.pdbReader = pdbReader;
            byte[] headerRawData = pdbReader.GetSection(0);
            if (headerRawData.Length != 132)
                throw new FormatException("Unknown eReader header format.");

            using (var stream = new MemoryStream(headerRawData))
            {
                var b = (byte)stream.ReadByte();
                if (b > 1) throw new FormatException(string.Format("Unknown DRM flag {0}", b));
                haveDrm = b == 1;
                b = (byte)stream.ReadByte();
                compressionMethod = (EReaderCompression)b;
                var buf = new byte[4];
                stream.Read(buf, 0, 4); //unknown, should be 0x00000000
                buf = new byte[2];
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                textEncoding = BitConverter.ToUInt16(buf, 0); //should be 2515 or 25152 for cp1251
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfSmallFontPages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfLargeFontPages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                nonTextFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfChapters = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfSmallFontIndexPages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfLargeFontIndexPages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfImages = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfLinks = BitConverter.ToUInt16(buf, 0);
                b = (byte)stream.ReadByte();
                if (b > 1) throw new FormatException(string.Format("Incorrect Metadata flag {0}", b));
                haveMetadata = b == 1;
                buf = new byte[3];
                stream.Read(buf, 0, 3); //unknown, should be 0
                buf = new byte[2];
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfFootnotes = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                numberOfSidebars = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                chapterIndexFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                magickValue = BitConverter.ToUInt16(buf, 0);
                //if (magickValue != 2560) throw new FormatException(string.Format("Unknown Magick Value {0}", magickValue));
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                smallFontPageIndexeFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                largeFontPageIndexeFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                imageDataFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                linksFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                metadataFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2); //unknown, should be 0x0000
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                footnotesFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                sidebarFirstRecord = BitConverter.ToUInt16(buf, 0);
                stream.Read(buf, 0, 2);
                if (BitConverter.IsLittleEndian) buf = buf.Reverse();
                lastRecord = BitConverter.ToUInt16(buf, 0);
            }
        }