如何生成/读取带有密码的Office Excel 2003(Biff8格式)(非破解)
2011-02-22 11:36
627 查看
前言
对于这篇文章有兴趣的朋友可以先下载三份文档,和一个小工具。文档名称为
[MS-XLS](
介绍
Biff8格式
)
[MS-OFFCRYPTO](
介绍
Office加密
)
以及
[Applied Cryptography]
by Bruce Schneier(介绍一些加密算法,这里主要用到第
17章的
RC4流加密算法)。小工具名为
BiffView++,功能是可以查看
Excel2003文档的
Biff8格式。
正文
看过微软公开的
office文档格式的人应该知道,
Excel 2003是使用
Biff8的格式来生成的文件(
Excel
2007是
OpenXML),这篇文章是介绍对于如何通过
Biff8格式生成以及如何读取一个带有密码的
Excel文档。有兴趣的朋友可以先简单浏览一下
Biff8,了解其格式内容(参考文档
[MS-XLS])。
目前比较知名的对于
Excel Biff8格式操作的软件有:
·
NPOI—读、写
·
Spread(
FarPoint)—读、写
·
ActiveReports —支持其报表的
Excel导出
·
……
但以上软件似乎都并未实现加密的
Excel文件的读取与生成
。我在工作中正好需要用到这一块,所以研究学习了一下,现在将得到的成果与大家分享一下。
一、FilePass记录
研究过
Biff8格式的人都知道,它是以一条一条记录
(record)的形式保存,一条记录包括
Header(record
ID与
record
length)与内容。假如需要生成一份带有打开密码的
Excel文档,需要添加一条名为
FilePass
的记录,该条记录的内容由以下字段组成:
wEncryptionType (2 bytes)
:Boolean类型,指定加密类型,0x0000为XOR混淆,0x0001为RC4加密。现在多用RC4加密。
encryptionInfo (可变长度):
加密信息,具体的内容取决于
wEncryptionType
的值。此处只讨论RC4加密。
RC4加密的具体内容可以参考文档[MS-OFFCRYPTO]
,可以使用的加密算法有两种:RC4标准加密与CryptoAPI RC4加密。具体应该使用哪一种加密算法呢?这里就可以用到前言中介绍的工具BiffView++,先使用Office Excel生成一个带有密码的文档,在保存时的Tools->General Options...->Password to open设置一个密码然后保存。使用BiffView++查看保存的文档,可以发现FilePass
记录,如下:
其中2Fh为FilePass的记录ID,54为长度,后面的一串16进制数据为内容,之前我们介绍FilePass的前两个byte表示加密类型,可以看到这里是01 00,代表RC4加密,接下来的两个byte同样是01 00,参考[MS-XLS]文档的FilePass记录可以发现,0x0001表示RC4标准加密,而CryptoAPI rc4加密则必须是0x0002或0x0003,所以我们可以知道,接下来要研究的是RC4标准加密。
二、RC4流加密算法
在介绍Office RC4加密信息之前,我们先要学习一下RC4加密算法,这是一个非常简单的流加密算法,参考
[Applied Cryptography]
,先简单介绍一下,然后给出算法的核心代码:
RC4算法包括初始化算法(KSA)和伪随机子密码生成算法(PRGA)两大部分。
初始化算法:
生成线性的S-BOX,生成256长度的由密钥重复填充的数组,计数器j重置为0然后
for i = 0 to 255:
j = (j + Si + Ki) mod 256
swap Si and Sj
伪随机子密码生成算法:
i = (i + 1) mod 256
j = (j + Si) mod 256
swap Si and Sj
t = (Si + Sj) mod 256
K = St
其中K是与明文异或后得到密文,或者与密文异或得到明文(对称算法,所以加密与解密可以为同一个函数)
以下为算法的核心代码(c#):
三、Office二进制文档RC4加密
现在我们可以看一下RC4标准加密信息由什么组成:
EncryptionVersionInfo (4 bytes):
加密版本信息,分为主要和次要,各占两个byte,这里必须为0x0001与0x0001(我也不知道为什么)。
Salt (16 bytes):
一个随机生成,长度为16的bytes数组,用于生成RC4加密算法的密钥。不能与EncryptedVerifier
字段相同
EncryptedVerifier (16 bytes):
密码验证器,生成方式与工作原理容后再叙。
EncryptedVerifierHash (16 bytes):
验证器MD5 Hash
,生成方式与工作原理容后再叙。
要进行RC4加密,我们首先需要有密钥,那么密钥是如何生成的呢?
将密码以Unicode编码转化成Byte数组,然后进行MD5 hash
随机生成一个长度为16的byte数组Salt(与RC4加密信息的Salt字段对应)
取第一步结果的前5位与Salt连接,生成一个长度为21的byte数组
将第三步21位的数组重复连接16次,得到一个336位的byte数组(21*16=336)
将第四步的结果进行MD5 Hash,并取前5位与block
*(4 bytes)连接成一个长度为9的byte数组
将第五步的结果进行MD5 Hash得到一个16位的数组,即为密钥。
*block
:32-bit的无符整型,在密码验证时与Verifier生成时皆为0x00000000,在进行Biff8流加密时,每加密1024个字节的流就自增1,同时重新获取密钥,重置RC4的i,j计数器。
密码验证器EncryptedVerifier的生成与工作原理:
一份带有FilePass记录的Excel文档是如何验证用户输入的密码是否正确的呢?知道这个问题的答案后,我们也可以了解如何生成FilePass记录了。
首先,在得到用户输入的密码以后,使用上面介绍的方法生成密钥(block为0x00000000)
使用RC4算法,解密EncryptedVerifier
与EncryptedVerifierHash
使用MD5 Hash计算解密后的EncryptedVerifier
第3步得到的结果,与解密后的EncryptedVerifierHash值进行比较,若完全一样,则密码正确,否则,密码验证失败。
知道了密码验证的工作原理以后,由于RC4加密的对称性(明文加密可以得到密文,密文再加密后就是明文),我们可以反向推导验证器的生成:
生成密钥(这一步是毫无疑问的)
随机生成一个16长度的byte数组,用RC4加密,得到的结果作为EncryptedVerifier
写入FilePass
中
第三步随机生成的16长度的数组(未加密时)进行MD5 Hash,再进行RC4加密,得到的结果作为EncryptedVerifierHash
写入FilePass
中
这样,一条FilePass记录就生成了,如果已经完成了Excel其他记录的生成,可以尝试导出一份带有密码的Excel文档,打开后如果FilePass正确生成,Excel应用程序会提示你输入密码。那么这个时候输入正确的密码以后,Excel会显示你导出内容吗,例如我导出了一张图片,这张图片会得到正确的显示吗?
自然Excel加密没有这么简单,那么接下来我们应该做的是什么:
在生成FilePass记录时的密钥我们需要保留下来。
将需要生成文件的流从Workbook的头开始,进行加密。
加密时有几点需要注意的地方
,1)
计数器count_i与count_j在每次加密时保留;2)block的值需要每1024个字节进行自增,自增的同时重置计数器count_i与
count_j为0。3)有些记录不需要加密
(BOF,FilePass,UsrExcl,FileLock,InterfaceHdr,RRDInfo,RRDHead,另外
BoundSheet8的lbPlyPos字段不需要加密),这里不需要加密是指不将加密后的密文,写入文件流,但是加密方法要执行,因为RC4加密算法
的结果与流的位置有关系。4)记录的ID与长度不需要加密,同3)。
将加密后的流写入文件,保存一下,如果代码正确的话,Excel文档就可以正确的显示了。
加密的Excel文档的读取:
首先要持有文档的密码(本文并不是破解加密)
根据密码与FilePass中的Salt生成密钥,block为0x00000000
逐条读取记录的文件流,并使用RC4解密
解密需要注意的地方与加密相同。
解密后得到的记录即为原始记录,可以自行根据标准文档进行解析。
结束语
文章到此就结束了,虽然标准文档中以上提到的内容都存在,但是有几个原因促使我写下这篇文章:
标准文档都是英文,理解会有误差
有些细节仅仅看文档还不能一次写成功,需要试验,所以将我的试验结果分享出来,方便有这方面兴趣的朋友少走弯路
希望帮助推广一下这类对Office文件操作的方法,优点:速度快、低依赖性、高可控制性;缺点:复杂的文档解析工作
出于各种原因,如果您对文章有疑问,或者发现我的bug,请告知,谢谢!
对于这篇文章有兴趣的朋友可以先下载三份文档,和一个小工具。文档名称为
[MS-XLS](
介绍
Biff8格式
)
[MS-OFFCRYPTO](
介绍
Office加密
)
以及
[Applied Cryptography]
by Bruce Schneier(介绍一些加密算法,这里主要用到第
17章的
RC4流加密算法)。小工具名为
BiffView++,功能是可以查看
Excel2003文档的
Biff8格式。
正文
看过微软公开的
office文档格式的人应该知道,
Excel 2003是使用
Biff8的格式来生成的文件(
Excel
2007是
OpenXML),这篇文章是介绍对于如何通过
Biff8格式生成以及如何读取一个带有密码的
Excel文档。有兴趣的朋友可以先简单浏览一下
Biff8,了解其格式内容(参考文档
[MS-XLS])。
目前比较知名的对于
Excel Biff8格式操作的软件有:
·
NPOI—读、写
·
Spread(
FarPoint)—读、写
·
ActiveReports —支持其报表的
Excel导出
·
……
但以上软件似乎都并未实现加密的
Excel文件的读取与生成
。我在工作中正好需要用到这一块,所以研究学习了一下,现在将得到的成果与大家分享一下。
一、FilePass记录
研究过
Biff8格式的人都知道,它是以一条一条记录
(record)的形式保存,一条记录包括
Header(record
ID与
record
length)与内容。假如需要生成一份带有打开密码的
Excel文档,需要添加一条名为
FilePass
的记录,该条记录的内容由以下字段组成:
wEncryptionType (2 bytes)
:Boolean类型,指定加密类型,0x0000为XOR混淆,0x0001为RC4加密。现在多用RC4加密。
encryptionInfo (可变长度):
加密信息,具体的内容取决于
wEncryptionType
的值。此处只讨论RC4加密。
RC4加密的具体内容可以参考文档[MS-OFFCRYPTO]
,可以使用的加密算法有两种:RC4标准加密与CryptoAPI RC4加密。具体应该使用哪一种加密算法呢?这里就可以用到前言中介绍的工具BiffView++,先使用Office Excel生成一个带有密码的文档,在保存时的Tools->General Options...->Password to open设置一个密码然后保存。使用BiffView++查看保存的文档,可以发现FilePass
记录,如下:
BIFF FILEPASS (2Fh) | 54 | 01 00 01 00 01 00 75 E1 D8 96 5A CC D0 96 F7 5E 1E 14 FC 93 2E 61 6B F3 C2 42 72 48 99 37 29 A8 21 28 B5 6D 84 CF A2 10 95 55 E5 3C 67 1A C6 9F DA F4 A4 19 35 6A |
二、RC4流加密算法
在介绍Office RC4加密信息之前,我们先要学习一下RC4加密算法,这是一个非常简单的流加密算法,参考
[Applied Cryptography]
,先简单介绍一下,然后给出算法的核心代码:
RC4算法包括初始化算法(KSA)和伪随机子密码生成算法(PRGA)两大部分。
初始化算法:
生成线性的S-BOX,生成256长度的由密钥重复填充的数组,计数器j重置为0然后
for i = 0 to 255:
j = (j + Si + Ki) mod 256
swap Si and Sj
伪随机子密码生成算法:
i = (i + 1) mod 256
j = (j + Si) mod 256
swap Si and Sj
t = (Si + Sj) mod 256
K = St
其中K是与明文异或后得到密文,或者与密文异或得到明文(对称算法,所以加密与解密可以为同一个函数)
以下为算法的核心代码(c#):
public class RC4 { private int count_i, count_j; private const int S_BOX_LENGTH = 256; private byte[] s_box = new byte[S_BOX_LENGTH]; public void SetKey(byte[] key) { count_i = 0; count_j = 0; byte[] k = new byte[S_BOX_LENGTH]; int key_len = key.Length; for (int i = 0; i < S_BOX_LENGTH; i++) { s_box[i] = (byte)i; k[i] = key[i % key_len]; } int j = 0; for (int i = 0; i < S_BOX_LENGTH; i++) { unchecked { j = (byte)(j + s_box[i] + k[i]) & 255; } byte t = s_box[i]; s_box[i] = s_box[j]; s_box[j] = t; } } public byte[] De_Encrypt(byte[] input) { if (input == null || input.Length <= 0) return null; int x = count_i; int y = count_j; byte[] output = new byte[input.Length]; for (int index = 0; index < input.Length; index++) { x = (x + 1) & 255; y = (y + s_box[x]) & 255; byte t = s_box[x]; s_box[x] = s_box[y]; s_box[y] = t; int tmp = (s_box[x] + s_box[y]) & 0xFF; output[index] = (byte)(input[index] ^ s_box[tmp]); } count_i = x; count_j = y; return output; } }
三、Office二进制文档RC4加密
现在我们可以看一下RC4标准加密信息由什么组成:
EncryptionVersionInfo (4 bytes):
加密版本信息,分为主要和次要,各占两个byte,这里必须为0x0001与0x0001(我也不知道为什么)。
Salt (16 bytes):
一个随机生成,长度为16的bytes数组,用于生成RC4加密算法的密钥。不能与EncryptedVerifier
字段相同
EncryptedVerifier (16 bytes):
密码验证器,生成方式与工作原理容后再叙。
EncryptedVerifierHash (16 bytes):
验证器MD5 Hash
,生成方式与工作原理容后再叙。
要进行RC4加密,我们首先需要有密钥,那么密钥是如何生成的呢?
将密码以Unicode编码转化成Byte数组,然后进行MD5 hash
随机生成一个长度为16的byte数组Salt(与RC4加密信息的Salt字段对应)
取第一步结果的前5位与Salt连接,生成一个长度为21的byte数组
将第三步21位的数组重复连接16次,得到一个336位的byte数组(21*16=336)
将第四步的结果进行MD5 Hash,并取前5位与block
*(4 bytes)连接成一个长度为9的byte数组
将第五步的结果进行MD5 Hash得到一个16位的数组,即为密钥。
*block
:32-bit的无符整型,在密码验证时与Verifier生成时皆为0x00000000,在进行Biff8流加密时,每加密1024个字节的流就自增1,同时重新获取密钥,重置RC4的i,j计数器。
密码验证器EncryptedVerifier的生成与工作原理:
一份带有FilePass记录的Excel文档是如何验证用户输入的密码是否正确的呢?知道这个问题的答案后,我们也可以了解如何生成FilePass记录了。
首先,在得到用户输入的密码以后,使用上面介绍的方法生成密钥(block为0x00000000)
使用RC4算法,解密EncryptedVerifier
与EncryptedVerifierHash
使用MD5 Hash计算解密后的EncryptedVerifier
第3步得到的结果,与解密后的EncryptedVerifierHash值进行比较,若完全一样,则密码正确,否则,密码验证失败。
知道了密码验证的工作原理以后,由于RC4加密的对称性(明文加密可以得到密文,密文再加密后就是明文),我们可以反向推导验证器的生成:
生成密钥(这一步是毫无疑问的)
随机生成一个16长度的byte数组,用RC4加密,得到的结果作为EncryptedVerifier
写入FilePass
中
第三步随机生成的16长度的数组(未加密时)进行MD5 Hash,再进行RC4加密,得到的结果作为EncryptedVerifierHash
写入FilePass
中
这样,一条FilePass记录就生成了,如果已经完成了Excel其他记录的生成,可以尝试导出一份带有密码的Excel文档,打开后如果FilePass正确生成,Excel应用程序会提示你输入密码。那么这个时候输入正确的密码以后,Excel会显示你导出内容吗,例如我导出了一张图片,这张图片会得到正确的显示吗?
自然Excel加密没有这么简单,那么接下来我们应该做的是什么:
在生成FilePass记录时的密钥我们需要保留下来。
将需要生成文件的流从Workbook的头开始,进行加密。
加密时有几点需要注意的地方
,1)
计数器count_i与count_j在每次加密时保留;2)block的值需要每1024个字节进行自增,自增的同时重置计数器count_i与
count_j为0。3)有些记录不需要加密
(BOF,FilePass,UsrExcl,FileLock,InterfaceHdr,RRDInfo,RRDHead,另外
BoundSheet8的lbPlyPos字段不需要加密),这里不需要加密是指不将加密后的密文,写入文件流,但是加密方法要执行,因为RC4加密算法
的结果与流的位置有关系。4)记录的ID与长度不需要加密,同3)。
将加密后的流写入文件,保存一下,如果代码正确的话,Excel文档就可以正确的显示了。
加密的Excel文档的读取:
首先要持有文档的密码(本文并不是破解加密)
根据密码与FilePass中的Salt生成密钥,block为0x00000000
逐条读取记录的文件流,并使用RC4解密
解密需要注意的地方与加密相同。
解密后得到的记录即为原始记录,可以自行根据标准文档进行解析。
结束语
文章到此就结束了,虽然标准文档中以上提到的内容都存在,但是有几个原因促使我写下这篇文章:
标准文档都是英文,理解会有误差
有些细节仅仅看文档还不能一次写成功,需要试验,所以将我的试验结果分享出来,方便有这方面兴趣的朋友少走弯路
希望帮助推广一下这类对Office文件操作的方法,优点:速度快、低依赖性、高可控制性;缺点:复杂的文档解析工作
出于各种原因,如果您对文章有疑问,或者发现我的bug,请告知,谢谢!
相关文章推荐
- NPOI 2.1.1 系列(1) 使用NPOI读取 Excel文档 ;NpoiExcelHelper 导入导出 2003格式 2007格式的 Excel; Npoi 导出 xlsx 格式
- Java POI 读取Office excel (2003,2007)及相关jar包
- Office Password Remover V1.0.0.6┊瞬间破解Word\Excel密码┊汉化绿色特别版
- WinServer2003 忘记密码了,如何破解找回
- ACCESS 如何用 Docmd.OutputTo 将查询导出为 Excel 97-2003 格式?
- Java POI 读取Office excel (2003,2007)及相关jar包
- 如何轻松的破解excel 2016工作表密码
- Excel保护密码破解-----只支持2003版本
- 服务器读取EXCEL不安装OFFICE如何实现
- 如何在后台运行模式生成Excel格式文件(收藏)
- ASP.NET Excel的生成,读取,和2003与2007兼容
- Excel 2003 中如何自定义 Number 格式
- 如何在后台运行模式生成Excel格式文件
- excel文件密码破解,office密码破解,excel密码破解方法
- 读取excel文件数据集,生成固定格式excel文件
- 如何读取以BIFF格式存储的 Excel 二进制文件
- 在C#编程中,如何将Excel保存为2003的格式
- 如何破解EXCEL工作表保护密码
- ASP.NET Excel的生成,读取,和2003与2007兼容
- 瞬间破解 Word、Excel和Access等office 文档密码(已亲测)