一、概述
之前反编译了iReader阅读的app,通过研读源码,获得了包括EBK2格式在内的文件格式。本文就EBK2的格式,将进行详细的分析。
感谢荒野无灯大神的《 逆向iReader解读ebk2电子书格式 》,为我EBK2格式分析提供了巨大的帮助。
EBK2文件中,所有数据的存储均是小端在前,即0x12345678存储顺序为:0x78 0x56 0x34 0x12。
二、文件头部分
文件头偏移地址0,结构如下:
struct Ebk2Head
{
DWORD bookid;// 一般为全0
WORD headSize;// ebk2文件信息头大小,104 Byte
WORD ebkVersion; // ebk文件版本
DWORD ebkSize;// ebk2文件大小
WCHAR bookName[32];// 书名,UTF-16LE编码,共64 Byte
DWORD fileSize;// 解压后txt文件大小(包括章节名和内容)
DWORD headCompressSize;// 章节信息索引表的大小(压缩后的)
DWORD firstCompressBlockSize;// 第一个压缩块的大小
WORD chapterCount;// 章节数量
WORD compressBlockCount;// 小说内容压缩块的数量
DWORD mediaCount;// 媒体数量
DWORD mediaLength;// 媒体数据长度
DWORD txtCompressSize;// 压缩后的小说正文内容大小
};
可以得到以下关系:ebkSize=headSize+headCompressSize+txtCompressSize;
其中约束ebkVersion <= 10,headCompressSize <= 32768,否则文件版本不正确。约束headSize <= 104,否则文件格式损坏。约束chapterCount > 0,否则章节数目出错。
三、章节索引表
文件头后面紧跟着的就是章节索引表,偏移地址Ebk2Head.headSize。章节索引表整体使用GZIP方式进行压缩,压缩后的大小为Ebk2Head.headCompressSize。对章节索引表进行GZIP解压后,数据结构如下:
struct Ebk2Chapter
{
WCHAR name[32];// 章节名,UTF-16LE编码,共64 Byte
WORD offset;// 章节在压缩块中的起始地址
WORD block;// 章节内容的第一个压缩块下标索引
DWORD size;// 章节(解压后的)大小
};
struct Ebk2Block
{
DWORD of