文本隐写不仅指在文本内容中隐写信息,还包括在常见文档文件中隐写信息,例如在Word和PDF文档中隐写消息。本节重点介绍文本的隐写方法,以及基于Word、PDF等文档文件的隐写套路。
在文本(即字符串)中隐写消息由来已久,英文中的大小写、正斜体,以及中文的“藏头诗”都属于这一范畴,如图2.4.1所示。这类题目的特点是“攻击力不大,伤害性极强”,如果不熟悉隐写套路,常常毫无头绪。第1章中讲的Base64信息隐藏也属于文本隐写,这一部分还可与古典密码相结合,例如猪圈密码、培根密码等也可以看作文本隐写的一种方式。总体而言,基于文字内容的隐写方式多样,更多的题目被归类于编码和密码学范畴,我们将会在密码学章节中加以详细阐述。
Word是Office套件中最为实用的工具,有doc和docx两种后缀。最简单的Word隐写方法是在文件属性信息中隐藏信息。由于Word本身是一个文本编辑器,通过写入白色文字、插入文本框或图形遮盖,以及利用Word自带的文字隐藏功能,均可实现信息隐藏。
图2.4.1 “藏头诗”隐写
【例题】basebase.zip
【题目描述】 找到文件中的flag。
【解题思路】 利用WinRAR查看文件,可以看到3个txt文件,需要用CRC碰撞获取txt的明文信息。解压密码是this_is_pass_word_。解压后有个Word文档,打开文档后,使用Ctrl+A组合键对文档进行全选,如图2.4.2所示。这时,注意到左上角似乎有东西,将其拖到文档中央,发现是个文本框,内容为OG5DRHEzNnNsU0g0RHljVlFvOVhoUjRhRjN1M3g4UGtQOGdrYjVydzVIdHBVZjNqSTJ0Mw==,经Base64解码后为8nCDq36slSH4DycVQo9XhR4aF3u3x8PkP8gkb5rw5HtpUf3jI2t3,猜测是Base62编码。但是,使用离线工具无法对其解码,于是搜索在线工具,使用http://decode-base62.nichabi.com/再次解码,得到flag{a5e17f319ca5f546e51e6d8b45ab555b}。
图2.4.2 使用“Ctrl+A”组合键全选后发现隐藏内容
如果文件后缀是doc,则其文件头是D0 CF 11 E0;如果后缀是docx,则文件头是50 4b 03 04,这与ZIP文件格式完全相同。无论Word文档是哪种后缀,都可以把后缀改为.zip,然后解压,就可以看到文档的组织格式以及各个配置文件,在这些文件中可能有隐写信息。
【例题】miscmisc.zip
【题目来源】 2019湖湘杯。
【题目描述】 找到文件中的flag。
【解题思路】 解压后有个PNG文件,用010 Editor打开文件,发现在这个PNG文件尾部插入了ZIP压缩包。提取出压缩包后解压,发现有两个文件chadiand.zip和chayidian.jpg。解压chadiand.zip需要密码,而我们并不知道其解压密码。通过查看压缩包,可以看到该压缩包中有两个文件,其中一个文件是flag.txt,另一个文件是flag.zip。
把chayidian.jpg拖入010 Editor,发现它以PNG格式开头,在图像尾部还有一个ZIP压缩包,提取出该压缩包后保存为ex.zip。ex.zip解压后得到一个flag.txt文件,想到chadiand.zip中也有个flag.txt文件,比较两个压缩包中flag.txt文件的CRC值,如图2.4.3和图2.4.4所示,很明显提示我们需要ZIP已知明文攻击,如图2.4.5所示(需要运行20分钟左右),得到chadiand_decrypted.zip。解压该文件后再解压flag.zip,得到3个文件:whoami.zip、world.doc和world1.png。先对world1.png使用“三板斧”,通过zsteg发现提示:pass:z^ea。
图2.4.3 明文文件
图2.4.4 查看加密压缩包
打开world.doc后没有看到有用的内容,下面介绍两种方法。
方法1 :修改文件后缀为world.zip,解压后在WordDocument中看到隐藏的信息,如图2.4.6所示,这是正常打开Word时没有显示的内容。
方法2 :双击打开文件world.doc,用<Ctrl+A>组合键全选文件,单击鼠标右键选择“字体”,取消勾选“隐藏”,可以看到隐藏的内容,如图2.4.7中的方框所示。
接下来的操作要大开脑洞。把“z^ea”和world.doc中隐藏内容的每行最后一个字符拼接起来,得到z^ea4zaa3azf8,把它当作解压whoami.zip的密码,解压后就得到flag{12sad7eaf46a84fe9q4fasf48e6q4f6as4f864q9e48f9q4fa6sf6f48}。
图2.4.5 已知明文攻击
图2.4.6 在WordDocument中找到关键信息
图2.4.7 在Word中显示隐藏的字体
【例题】CTF.docx
【题目描述】 找到文件中的flag。
【解题思路】 在文件属性信息中没有发现线索,打开Word文件也没有看到flag。于是,把文件后缀改为.zip并解压,解压后的文件较多,可以逐个打开查看。这里我们使用工具FileLocatorPro(官网地址为https://www.mythicsoft.com/)。该工具不仅能按文件名查找文件,还可以直接检索Word、PDF等文件中的内容。如图2.4.8所示,在theme.xml中有flag:a2fcb07f30e2ef22b7362eb55d366fbc。
图2.4.8 利用文本搜索工具快速查找flag
PDF(Portable Document Format,可携带文档格式)文件以PostScript语言图像模型为基础,无论在哪种打印机上都可保证精确的颜色和准确的打印效果,即PDF格式会忠实地再现原稿的字符、颜色以及图像。
一个PDF文件分为头部、文件体、交叉引用表和尾部4个部分。
❑ 头部 (Header):PDF文件的第一行由5个字符“%PDF-”后跟“1.N”的版本号组成。其中,N是0~7之间的数字,例如“%PDF-1.4”“%PDF-1.7”等。
❑ 文件体 (Body):由表示文件内容的一系列obj对象(也叫间接对象)组成,例如字体、页面和采样图像。从PDF 1.5开始,Body还可以包含对象流,每个对象流包含一系列obj对象。obj对象如下所示:
第一个数字称为对象号,用于唯一标识一个对象。第二个数字是产生号,用来表明它是被创建后的第几次修改,所有新创建的PDF文件的产生号都是0,即第一次被创建以后没有被修改过。上面的例子说明该对象的对象号是3,而且创建后没有被修改过。对象的内容包含在<<和>>之间,最后以关键字endobj结束。
❑ 交叉引用表 (Cross-Reference Table):交叉引用表包含文件中间接对象的信息,以便允许对这些对象进行随机访问,因此无须读取整个文件即可定位任何特定对象。交叉引用表以xref开始,紧接着是以空格隔开的两个数字,然后是一个对象信息,如下所示:
上例中有四个子部分,每个子部分的开头只包含两个数字。第二行有数字“01”,0表示下面的对象从0号对象开始,1表示对象的数量,即表示1个对象。接下来的每一行均表示一个对象的信息,其格式为nnnnnnnnnn ggggg x,其中:nnnnnnnnnn的长度为10个字节,表示对象在文件的偏移地址;ggggg的长度为5个字节,表示对象的生成号;x表示该对象是否被引用,n(in-use)表示对象被引用,f(free)表示对象未被引用。对于交叉引用表中的第一个编号为0的对象,其x始终是f(free),且生成号为65 535。
❑ 尾部 (Trailer):PDF阅读器是从PDF的尾部开始解析文件的,通过Trailer部分能够快速找到交叉引用表和某些特殊对象。尾部格式如下:
其中,trailer表示文件尾对象的开始;/Size 20说明该PDF文件的对象数目;/Root 30R说明根对象的对象号为3;/Info20R表示文件里的摘要所在对象的编号。
关键字startxref下面的数字表示交叉引用表的偏移地址,通过它可以找到PDF文档中所有对象的相对地址,进而访问对象。在本例中,文件480379(0x7547B)偏移处就是交叉引用表的开始,如图2.4.9所示。
%%EOF为文件结束标志。
图2.4.9 PDF交叉引用
针对PDF的隐写较为复杂,这里我们总结了三种常见套路,下面逐一介绍。
套路一 :PDF文件是可以编辑的,可以利用图片遮挡住要隐藏的内容,这样,打开PDF文件只能看到一张图片。
【例题】blue.pdf
【题目来源】 2020年中能融合杯全国第六届工控系统信息安全攻防竞赛。
【题目描述】 找到文件中的flag。
【解题思路】 使用WPS打开PDF文件,看到一张图片。选中图片,单击鼠标右键选择“编辑图片”,如图2.4.10所示,把图片缩小,即可看到flag{security_through_obscurity}。
图2.4.10 编辑PDF文件
注意: 一些严苛的出题人会用白色图片覆盖重要信息,我们有两种应对措施:①打开文件后,用<Ctrl+A>组合键全选文件,观察选中的内容是否有异常;②把PDF阅读器的默认背景颜色换成非白色,这样打开后就能直接看出内容是否有异常。
套路二 :在PDF文字中隐藏信息,此时需要我们利用Kali中自带的工具提取出PDF中的所有文本内容,查看里面的隐写信息。
【例题】evidence.zip
【题目来源】 MeePwn CTF 2018。
【题目描述】 找到文件中的flag。
【解题思路】 解压后得到一张JPG图片。使用“三板斧”,用010 Editor查看图片文件,JPG后有附加文件,是以50 4b 05 06开头的,而50 4b 05 06是ZIP压缩源文件目录结束标志,代表ZIP文件结束。把附加数据文件头改为50 4b 03 04,在010 Editor中使用ZIP模板解析,如图2.4.11所示,把提取的数据保存成ZIP压缩包,解压时报错。这是因为数据区和目录区的压缩方式不一致,把数据区的压缩方式改为8,如图2.4.12所示,压缩包就能正常解压。解压后得到message.pdf文件,打开文件后看到都是文本,没有图片遮挡。使用Kali中的命令pdftotext可以提取出所有的文本,提取出的内容保存在flag.txt(如图2.4.13所示),与PDF文字内容比较,拼接得到flag:MeeCTF{T3xt_Und3r_t3Xt!!!!}。
图2.4.11 发现附加ZIP压缩包
图2.4.12 修改压缩方式
图2.4.13 pdftotext转为纯文本
套路三 :利用obj对象隐写信息。obj对象中的数据经zlib算法压缩,可以在PDF文件中插入一个经过压缩的obj对象,并利用该对象隐藏信息。使用工具PDFStreamDumper(网站地址为https://github.com/dzzie/pdfstreamdumper)可以查看obj对象解压后的内容。
【例题】announcement.pdf
【题目来源】 CSAW CTF 2014。
【题目描述】 找到文件中的flag。
【解题思路】 用010 Editor打开文件,如图2.4.14所示,发现乱码,猜测有嵌入文件。利用PDFStreamDumper工具分析,查看对象8,如图2.4.15所示,Shellcode编码的字符串是:\x59\x4F\x55\x20\x44\x49\x44\x20\x49\x54\x21\x20\x43\x4F\x4E\x47\x52\x41\x54\x53\x21\x20\x66\x77\x69\x77\x2C\x20\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x20\x6F\x62\x66\x75\x73\x63\x61\x74\x69\x6F\x6E\x20\x69\x73\x20\x73\x6F\x66\x61\x20\x6B\x69\x6E\x67\x20\x64\x75\x6D\x62\x20\x20\x3A\x29\x20\x6B\x65\x79\x7B\x54\x68\x6F\x73\x65\x20\x46\x6C\x75\x66\x66\x79\x20\x42\x75\x6E\x6E\x69\x65\x73\x20\x4D\x61\x6B\x65\x20\x54\x75\x6D\x6D\x79\x20\x42\x75\x6D\x70\x79\x7D。
解码后为:YOU DID IT! CONGRATS! fwiw, javascript obfuscation is sofa king dumb :)key{Those Fluffy Bunnies Make Tummy Bumpy}。
图2.4.14 查看PDF文件发现异常
图2.4.15 使用PDFStreamDumper发现隐藏内容