
本文分析的样题提供了一个名为 EasyWord.zip 的压缩包。解压后,我们可以得到三个文件。

首先查看 hint.txt,其内容给出了关键提示:
The length of docm 's password is 6
The Regular Expression of the password is:
[a-z] [a-z] q [a-z] b [a-z]
由此我们得知 password.docm 文件的密码由6位全小写字母组成,且满足正则表达式 ??q?b? 的格式。面对这种已知模式的弱密码,使用工具进行爆破是高效的选择。
我们可以使用 john (John the Ripper) 这款强大的密码破解工具。首先,需要从文档中提取哈希值并保存。
office2john password.docm > word.hash
接着,利用掩码攻击模式,针对提取出的 word.hash 文件进行爆破。掩码 ?l?lq?lb?l 精确对应了 hint 给出的密码模式。
john --mask='?l?lq?lb?l' word.hash
# ?l 表示 小写字母(a-z)
# q 和 b 是固定字符

爆破成功,得到密码 ulqsbt。使用该密码打开 password.docm 文档后,我们发现这是一个启用了宏的文档(.docm),并且顶部出现了安全警告。

点击“启用内容”后,会弹出一个对话框要求输入口令。

什么是宏加密?
当你打开一个带有宏的 Microsoft Office 文件(如 .docm 或 .xlsm)并尝试进入 VBA 编辑器时,如果作者设置了“VBA 工程密码”,系统就会弹出一个密码输入窗口。
这常常让初学者产生一个误解:认为宏代码被彻底加密了,不知道密码就永远无法查看。
但事实并非如此:
- 宏代码大多仍然以原始形式保存在文件里。
- 这种密码保护的主要目的是“阻止你在 VBA 编辑器里直接查看或编辑代码”,而非将代码内容加密到不可读的状态。
我们可以做一个形象的比喻:
- 这就像给一个抽屉的门贴上了“禁止打开”的封条(提示你不要打开)。
- 但抽屉本身并没有被焊死,里面的东西也原封未动。只要你移除了封条,抽屉依然可以打开。
docm 文件解析
实际上,.docm 或 .xlsm 文件本质上是一个遵循 Open XML 格式的压缩包。你只需将其文件后缀改为 .zip,就能用压缩软件直接打开查看内部结构。

普通文件的宏位置
对于一个未加密的 .docm 文件,解压后通常可以看到如下目录结构:
word/
_rels/
[Content_Types].xml
其中的宏代码,就存储在以下路径:
word/vbaProject.bin
vbaProject.bin 解析
vbaProject.bin 并非普通的文本文件,它是一种 OLE 复合文档 格式。你可以将其理解为一个“容器文件”,里面嵌套存储了多个子文件和流,其中就包含了编译后的 VBA 宏代码。
加密宏格式
在许多 Office 版本中,VBA 工程是否设置了密码,会在 vbaProject.bin 文件的特定位置留下一个可读的文本标记,例如:
DPB="xxxxxx"
这里的 DPB 可以理解为“此 VBA 工程已受密码保护”的标识。当 Office 应用程序加载文件时,如果检测到这个标识格式正常,就会触发密码输入弹窗。
反之,如果这个标识被破坏、篡改或不存在,Office 就可能不再弹窗询问密码,从而实现所谓的“绕过”。由于 DPB 是 ASCII 文本,我们可以使用十六进制编辑器,通过搜索字符串 DPB 或其十六进制值 44 50 42 来快速定位它。
加密文件的宏位置
然而,在我们拿到的 password.docm 文件中,整个文档内容(包括宏)被整体加密了。解压后看到的不是通常的文件结构,而是加密相关的文件:
EncryptedPackage 被加密的 Word 内容整体压缩包
EncryptionInfo 加密说明书,存储了加密算法、模式、盐值等信息
DataSpaces Office 加密规范的一部分,描述数据保护空间
在这种情况下,vbaProject.bin 文件被包裹在 EncryptedPackage 内,我们无法直接访问。
绕过原理
1、解除Word文档的密码保护
由于加密文件中没有独立的 vbaProject.bin 文件,我们的第一步必须是用已知的密码 ulqsbt 解密 EncryptedPackage,将其还原成真实的文档压缩包。
我们可以使用 Python 库 msoffcrypto-tool,它是专门处理 Microsoft Office 文件加密的利器。
pip install msoffcrypto-tool
编写解密脚本如下:
import msoffcrypto
# Path:从pathlib模块导入,用于处理文件路径,提供跨平台的文件操作支持
from pathlib import Path
# 定义输入和输出文件的路径对象
# in_file:指向当前目录下名为“password.docm”的加密文件
in_file = Path(“password.docm”)
# out_file:输出文件,解密后保存为“decrypted.docm”
out_file = Path(“decrypted.docm”)
# 打开加密的输入文件(以二进制只读模式)
# 使用with语句确保文件正确打开和关闭
with in_file.open(“rb”) as f:
# 创建OfficeFile对象,表示要处理的Office文档
office = msoffcrypto.OfficeFile(f)
# 加载解密所需的密码
# 这里使用密码“ulqsbt”来解锁文档
office.load_key(password=“ulqsbt”)
# 打开输出文件(以二进制写入模式)
# 如果文件不存在则创建,存在则覆盖
with out_file.open(“wb”) as out:
# 执行解密操作,将解密后的内容写入输出文件
office.decrypt(out)
# 解密完成后,打印成功信息
# 显示输出文件的路径,确认解密完成
print(“OK ->”, out_file)
运行脚本后,我们得到了解密后的 decrypted.docm 文件。将其作为压缩包打开,现在可以看到标准的内部结构了,其中包含了关键的 word/vbaProject.bin 文件。

2、绕过加密宏
虽然我们已经能访问 vbaProject.bin,但它可能仍受VBA工程密码保护。接下来我们探讨两种绕过方法。
2.1、手动绕过(修改DPB标记)
使用十六进制编辑器(如 010 Editor, HxD)打开 word/vbaProject.bin 文件。利用查找功能,搜索字符串 DPB。

找到后,将其中的 DPB 修改为任意其他值,例如 DPA。这样做的目的是破坏这个标识的合法性,让 Office 在加载时无法识别出有效的密码保护标记,从而不再弹窗。
修改完成后,需要将整个解压的文件夹重新打包成 ZIP 格式,再将后缀改回 .docm。

2.2、脚本绕过(直接提取与分析)
我们也可以使用专门分析 OLE 文件的工具来直接查看宏代码,而无需通过 Office 界面。
pip install oletools
olevba word/vbaProject.bin
通过分析提取出的 VBA 代码,我们找到了验证输入口令的关键逻辑分支:
t = ChrW(21152) & ChrW(27833) & ChrW(21543) & ChrW(65292) & ChrW(21516) & ChrW(23398) & ChrW(20204) & ChrW(65281)
‘ t = “加油吧,同学们!”
strusout = Encode(strusrinput, t)
If (strusout = “©È©Y¨¯q£ø~”) Then
strdec = Decode(Dialog.Label_ls.Caption, sinput)
ElseIf (strusout = “£ëGJE£ç£ñ”) Then
strdec = Decode(Dialog.Label_ls1.Caption, sinput)
ElseIf (strusout = “§À¦¯opz+”) Then
strdec = Decode(Dialog.Label_ls2.Caption, sinput) ‘ <-- 8位口令对应这条
ElseIf (strusout = “£ú¦ªjr§º¦Õ¦Å¤¢”) Then
strdec = Decode(Dialog.Label_ls4.Caption, sinput)
ElseIf (strusout = “¨¤¨µt£Õ£÷©Ë£è¨¨”) Then
strdec = Decode(Dialog.Label_ls3.Caption, sinput)
Else
strdec = “密码不正确,别泄气再来!”
End If
Label_CLUE.Caption = strdec
观察代码发现,用户输入 strusrinput 经过 Encode(strusrinput, t) 函数处理后的结果 strusout,在与5个常量字符串进行比较。
代码的逻辑结构简化如下:
If strusout = A Then
strdec = Decode(Label_ls.Caption, sinput)
ElseIf strusout = B Then
strdec = Decode(Label_ls1.Caption, sinput)
...
End If
Label_CLUE.Caption = strdec
我们并不需要完全理解 Encode() 函数的加密细节。我们的目标是获取 Decode() 函数解密后的明文线索,而这些线索就藏在各个 Label_lsX.Caption 属性中。
一个巧妙的思路是:直接修改VBA代码,让程序无论输入什么,都直接执行解密操作。例如,可以将 Label_CLUE.Caption = strdec 这行代码改为:
Label_CLUE.Caption = Decode(Dialog.Label_ls.Caption, t)
然后分别用 Dialog.Label_ls1.Caption、Dialog.Label_ls2.Caption 等替换上式中的参数,依次执行。
具体需要替换的五个参数为:
Dialog.Label_ls.Caption
Dialog.Label_ls1.Caption
Dialog.Label_ls2.Caption
Dialog.Label_ls3.Caption
Dialog.Label_ls4.Caption
修改代码后,在Word中运行宏(例如 AutoOpen),随意输入字符并点击确定,对应的Label控件中就会显示出 Decode 函数输出的明文。
依次尝试,我们得到了五条明文结果:
- 123456
- aaaaaa
- 000000
- 墙角数枝
- iloveyou
回到最初的密码输入对话框,用这些明文进行测试。发现输入“墙角数枝”后,程序回显了破解RAR的线索:“两只黄鹂鸣翠柳,一行白鹭上青天!”。
结合题面hint“密码为16位,由字母、数字和符号组成”,我们可以将这句诗转换为常见的CTF口令格式。通常采用拼音首字母缩写加标点符号的方式:
- “两只黄鹂鸣翠柳” →
2zhlmcl
- “一行白鹭上青天” →
1hblsqt
- 保留原诗的逗号和句号作为符号。
最终,我们得到16位的复杂口令:2zhlmcl,1hblsqt.。
使用此密码解压 flag.rar,即可得到最终的Flag。
Dest0g3{VBScr1pt_And_Hashc4t_1s_g00d}
希望这篇对Word加密宏技术的原理分析与实战绕过思路,能为你带来启发。更多精彩的技术讨论,欢迎访问云栈社区进行交流。