public void parseDRM(byte[] byteData, int drmCount, List <byte[]> pidList) { byte[] keyVec1 = new byte[] { 0x72, 0x38, 0x33, (byte)0xB0, (byte)0xB4, (byte)0xF2, (byte)0xE3, (byte)0xCA, (byte)0xDF, 0x09, 0x01, (byte)0xD6, (byte)0xE2, (byte)0xE0, 0x3F, (byte)0x96 }; foreach (byte[] pid in pidList) { byte[] bigpid = new byte[16]; for (int i = 0; i < 16; i++) { bigpid[i] = 0x00; } for (int i = 0; i < pid.Count(); i++) { bigpid[i] = pid[i]; } byte[] tempKey = PK1Enc(bigpid, keyVec1); int tempKeySum = 0; for (int i = 0; i < tempKey.Count(); i++) { tempKeySum += tempKey[i]; } tempKeySum = tempKeySum & 0xFF; ArraySlice data = new ArraySlice(byteData); for (int i = 0; i < drmCount; i++) { int verification = (int)data.getLong(i * 0x30); int size = (int)data.getLong(i * 0x30 + 4); int type = (int)data.getLong(i * 0x30 + 8); int chkSum = (int)data.getByte(i * 0x30 + 12) & 0xFF; byte[] cookie = data.byteSlice(i * 0x30 + 16, 32); if (chkSum == tempKeySum) { Debug.WriteLine("Cookie: " + bytesToHex(cookie) + " Found at DRMCount: " + i); Debug.WriteLine("Temp Key: " + bytesToHex(tempKey)); cookie = PK1Dec(cookie, tempKey, true); Debug.WriteLine("Decrypted Cookie: " + bytesToHex(cookie) + " Found at DRMCount: " + i); ArraySlice slice = new ArraySlice(cookie); int ver = (int)slice.getLong(); int flags = (int)slice.getLong(); int finalkey = (int)slice.getLong(); if (verification == ver && ((flags & 0x1F) > 0)) { Debug.WriteLine("W00000T"); } } } Debug.WriteLine("PID: " + Encoding.Default.GetString(pid)); Debug.WriteLine("HEX BIGPID: " + bytesToHex(bigpid)); Debug.WriteLine("Key Vec: " + bytesToHex(keyVec1)); Debug.WriteLine("Temp Key: " + bytesToHex(tempKey)); Debug.WriteLine("Dec Key: " + bytesToHex(PK1Dec(tempKey, keyVec1, false))); Debug.WriteLine("\n\n"); } }
public MobiHeader(ArraySlice headerSlice) { mMagic = System.Text.Encoding.Default.GetString(headerSlice.byteSlice(0x3C, 8)); if (!mMagic.Equals(BOOK_MOBI) && !mMagic.Equals(TEXT_READ)) { throw new Exception("Invalid File Format"); } mNumSections = headerSlice.getShort(76); }
public String getBookTitle() { Dictionary <Int32, Encoding> codecMap = new Dictionary <Int32, Encoding>(); codecMap[1252] = Encoding.GetEncoding(1252); codecMap[65001] = Encoding.UTF8; String title = null; if (mHeader.getMagicString().Equals(MobiHeader.BOOK_MOBI)) { if (mMetaMap.ContainsKey(503)) { title = Encoding.Default.GetString(mMetaMap[503]); } else { int o = (int)mSections[0].offset; int toff = (int)mEncMobiBook.getLong(o + 0x54); int tsize = (int)mEncMobiBook.getLong(); title = codecMap[mMobiCodepage].GetString(mEncMobiBook.byteSlice(toff + o, tsize)); } } if (title == null) { title = Encoding.Default.GetString(mEncMobiBook.byteSlice(0, 32)).Split('\0')[0]; } return(title); }
public MobiBook(String filename) { mEncMobiBook = getBookSlice(filename); mHeader = new MobiHeader(mEncMobiBook); mEncMobiBook.seek(MobiHeader.HEADER_SIZE); for (int i = 0; i < mHeader.getNumberSections(); i++) { mSections.Add(new Section(mEncMobiBook)); } int offset = (int)mSections[0].offset; mCompression = mEncMobiBook.getShort(offset); mRecords = mEncMobiBook.getShort(offset + 0x8); if (mHeader.getMagicString().Equals(MobiHeader.TEXT_READ)) { mExtraDataFlags = 0; mMobiLength = 0; mMobiCodepage = 0; mMobiVersion = -1; return; } mMobiLength = (int)mEncMobiBook.getLong(offset + 0x14); mMobiCodepage = (int)mEncMobiBook.getLong(offset + 0x1c); mMobiVersion = (int)mEncMobiBook.getLong(offset + 0x68); if ((mMobiLength >= 0xE4) && (mMobiVersion >= 5)) { mExtraDataFlags = mEncMobiBook.getShort(offset + 0xF2); } if (mCompression != 17480) { // multibyte utf8 data is included in the encryption for PalmDoc compression // so clear that byte so that we leave it to be decrypted. mExtraDataFlags &= 0xFFFE; } //if exth region exists parse it for metadata array int exthFlag = (int)mEncMobiBook.getLong(offset + 0x80); int exthOffset = 16 + mMobiLength; if ((exthFlag & 0x40) > 0) { if ((exthOffset + mEncMobiBook.size() >= 4) && System.Text.Encoding.Default.GetString(mEncMobiBook.byteSlice(exthOffset + offset, 4)).Equals("EXTH")) { int nItems = (int)mEncMobiBook.getLong(exthOffset + offset + 8); int pos = offset + exthOffset + 12; for (int i = 0; i < nItems - 1; i++) { int type = (int)mEncMobiBook.getLong(pos); int size = (int)mEncMobiBook.getLong(pos + 4); mMetaMap[type] = mEncMobiBook.byteSlice(pos + 8, size - 8); /* TODO: # reset the text to speech flag and clipping limit, if present # if type == 401 and size == 9: # set clipping limit to 100% # self.patchSection(0, "\144", 16 + self.mobi_length + pos + 8) # elif type == 404 and size == 9: # make sure text to speech is enabled # self.patchSection(0, "\0", 16 + self.mobi_length + pos + 8) */ pos += size; } } } Debug.WriteLine(mHeader); Debug.WriteLine("BookTitle: {0} \nMobiLength: {1} \nMobiCodePage {2}\nExtraDataFlags: {3} \nMobiVersion: {4}\n", getBookTitle(), mMobiLength, mMobiCodepage, mExtraDataFlags, mMobiVersion); List <byte[]> pidList = new List <byte[]>(); pidList.Add(Encoding.Default.GetBytes("DL3pB54YXE")); pidList.Add(Encoding.Default.GetBytes("DL3pB54Y")); pidList.Add(Encoding.Default.GetBytes("SSEVC1U7")); processBook(pidList); }