博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

零宽字符隐写 - Zero-Width Steganography

Posted on 2025-09-07 16:36  steve.z  阅读(743)  评论(0)    收藏  举报

一、什么是零宽字符隐写?

这是一个非常有趣且隐蔽的信息隐藏技术,结合了“零宽字符”和“隐写术”两个领域。

  1. 隐写术 (Steganography)
    顾名思义,“隐写”就是将秘密信息隐藏起来书写。它不同于加密(Cryptography)。加密是将信息变成一堆乱码,让人一看就知道是秘密,但无法破译内容;而隐写术是试图将秘密信息的存在本身都隐藏起来,让它看起来像普通、无害的信息(如一段文字、一张图片、一个视频)。“藏木于林” 是对隐写术最形象的比喻。

  2. 零宽字符 (Zero-Width Characters)
    这是Unicode标准中一类特殊的控制字符。它们的特性是不可见(不占任何视觉空间),即在文本中显示时没有宽度,不会打断或改变文本的可见内容。但它们确实存在于文本的编码中。

    • 常见的零宽字符包括
      • 零宽空格 (Zero-Width Space, U+200B):用于在某些复杂的脚本中表示单词边界,但不可见。
      • 零宽非连接符 (Zero-Width Non-Joiner, U+200C):用于阻止两个字符之间的连笔(例如在阿拉伯语中)。
      • 零宽连接符 (Zero-Width Joiner, U+200D):用于鼓励两个字符之间的连笔(例如在阿拉伯语或emoji序列中,如 👨‍👩‍👧‍👦 家庭表情就是由多个emoji用ZWJ连接而成的)。
      • 左至右标记 (Left-to-Right Mark, U+200E) / 右至左标记 (Right-to-Left Mark, U+200F):用于控制文本方向,但本身不可见。
  3. 什么是零宽字符隐写?

零宽字符隐写就是利用这些不可见的零宽字符作为载体,将秘密信息编码并嵌入到一段普通的可见文本中的隐写技术。

简单来说,你看到的一段话(A),实际上里面还隐藏着另一段话(B),而B是用你看不见的字符写的。

二、工作原理(如何隐藏信息?)

  1. 编码秘密信息
    首先,需要将想要隐藏的秘密信息(如“secret”)转换成一种可以由0和1表示的二进制格式(例如,使用ASCII或Unicode编码)。s -> 01110011

  2. 用零宽字符表示二进制
    选择两种零宽字符来分别代表二进制的 01

    • 例如,规定:
      • U+200C (零宽非连接符) 代表 0
      • U+200D (零宽连接符) 代表 1
    • 那么,秘密信息“s”的二进制 01110011 就可以被编码成一串零宽字符序列:[U+200C, U+200D, U+200D, U+200C, U+200C, U+200C, U+200D, U+200D]
  3. 嵌入载体文本
    将这一长串代表秘密信息的零宽字符序列,插入到一段普通文本(称为“载体文本”)的任意位置。比如插入到句首、句尾、单词之间,甚至是某个单词的字母之间。

    • 载体文本“这是一条普通的问候信息,你好吗?”
    • 嵌入后“[零宽字符序列]这是一条普通的问候信息,你好吗?” 或者 “这[零宽字符序列]是一条普通的问候信息,你好吗?”

对于阅读这段文字的人来说,他们看到的仍然是:“这是一条普通的问候信息,你好吗?”,完全察觉不到隐藏信息的存在。只有知道编码规则的人,才能从文本中提取出这些零宽字符,并将其解码回原始的秘密信息。

三、实际应用与例子

  • 水印与溯源:公司可以在内部文档中嵌入隐藏的员工ID或时间戳。如果文档被泄露,可以通过提取这个隐藏信息来追踪泄密源头。
  • 绕过审查:在一些言论受限制的环境中,人们可以用这种方式在公开的社交媒体帖子中传递秘密信息,而审查系统可能无法检测到。
  • 社交工程与恶意攻击
    • 网络钓鱼:攻击者可能会在看似合法的URL(例如,模仿 www.apple.com)中插入零宽字符,使其在浏览器中显示为正确域名,但实际上指向恶意网站。虽然现代浏览器对此有防护,但仍是潜在威胁。
    • 混淆恶意代码:在某些支持Unicode的编程环境中,可能被用来隐藏恶意代码片段。

四、如何检测和防范?

  1. 文本编辑器:将可疑文本复制到代码编辑器(如VS Code、Sublime Text)或纯文本编辑器(如记事本++)中,这些编辑器有时会以特殊方式(如一个小点、一个高亮)显示零宽字符。
  2. 在线检测工具:有很多网站提供零宽字符检测和去除功能,只需将文本粘贴进去即可分析。
  3. 编程检测:可以写简单的脚本(如JavaScript、Python)来遍历字符串,检查是否包含Un码位在U+200BU+200F之间的字符。
  4. 保持警惕:不要随意复制粘贴来历不明的文本并直接执行(比如在命令行中),尤其是从社交媒体或即时通讯软件中收到的信息。

总结

特性 描述
本质 一种数字隐写术
载体 零宽字符(Unicode中不可见的控制字符)
原理 用零宽字符代表二进制0和1,将秘密信息编码后嵌入普通文本
优点 高度隐蔽,视觉上无法察觉,兼容性高
缺点 可通过专业工具或代码检测, payload(有效负载)相对较小
用途 水印、秘密通信、绕过审查(也可用于恶意目的)

五、回车CR 和 换行LF 是零宽字符吗?

不,回车(Carriage Return, CR)和换行(Line Feed, LF)符不属于零宽字符。 它们属于控制字符,但它们的“不可见”方式和零宽字符有本质区别。

下面我们来详细解释一下它们的区别:

核心区别:功能 vs. 空间

特性 零宽字符 (Zero-Width Characters) 回车(CR) / 换行(LF) 符
Unicode 类别 主要属于“格式字符”(Formatting Characters)范畴。 属于“控制字符”(Control Characters)范畴。
主要作用 修饰文本的格式、排序或连接方式,但不产生任何布局空间 控制文本的布局和格式,产生布局上的变化(换行)。
“不可见”的含义 本身不占据任何视觉空间,像一个“看不见的墨水标记”,插入在字符之间却不拉开距离。 没有具体的字形(glyph),所以不显示为一个可见符号,但它们的功能效果是可见的(即文本换到了新的一行)。
类比 像一种隐形墨水,写在纸上不会撑开其他字,但能用特殊方式读到。 像打字机的一个机械动作:回车(把打字头移回行首)和换行(把纸卷上一行)。你看不到这个动作,但能看到动作的结果。

详细解释

1. 回车(CR, \r, ASCII 13)和换行(LF, \n, ASCII 10)

这些是来自早期打字机和电传打字机的遗产。

  • 换行 (LF):命令打印机或显示器“将纸张向下移动一行”(换行)。
  • 回车 (CR):命令打印机或显示器“将打印头移回行首”(回车)。

在现代计算中,它们共同作用来表示一行的结束和下一行的开始(在Windows系统中是\r\n,在Unix/Linux/macOS中是\n)。

虽然你在屏幕上看不到CRLF这个符号本身,但它们执行了一个强大的、可见的格式功能——创建新行。因此,它们不是“零宽”的,而是“具有功能效应的不可见控制字符”。

2. 零宽字符 (如 U+200B, U+200C, U+200D)

这些字符是Unicode标准为了处理复杂文本排版(如阿拉伯语、天城文连字)而引入的。

  • 零宽空格 (U+200B):表示一个可以断字的词边界,但不像普通空格那样有宽度。
  • 零宽非连接符 (U+200C):阻止两个字符正常连接。
  • 零宽连接符 (U+200D):鼓励两个字符连接(如生成复杂的emoji序列)。

它们不执行任何像换行那样改变整体布局的命令。它们的作用范围仅限于其插入点的局部相邻字符,并且完全不影响文本的宏观流。这才是“零宽”的真正含义——不改变布局,不占用空间


一个很好的类比:文本编辑器视图

你可以在任何先进的文本编辑器(如VS Code、Sublime Text、Notepad++)中清晰地看到这种区别:

  1. 显示所有字符

    • 当你开启“显示所有字符”或“显示不可见字符”选项时。
    • 换行符 (LF \n):通常会显示为一个 (向下再向左的箭头) 或 (回车符号) 。它占据了一个视觉位置。
    • 零宽字符:可能会显示为一个非常特殊的、单独的符号(例如,VS Code中零宽空格显示为一个˽,零宽非连接符显示为一个,零宽连接符显示为)。关键点在于:即使它们被“显示”出来,编辑器也会明确告诉你这些符号本身是“零宽”的,并且它们不会导致后面的文本被“推開”。
  2. 选择文本

    • 当你用光标在文本中移动时,光标会跳过一个换行符(因为它占据了一个“位置”),但光标不会在零宽字符处停留(因为它们没有宽度,光标会直接滑过)。

总结

行为 换行符 (LF \n) 零宽空格 (U+200B)
在编辑器中可见化 显示为 显示为一个特殊的字符(如 ˽
光标导航 光标会在此停留 光标直接滑过,无法停留
主要效果 宏观布局:创建新行 微观修饰:定义单词边界而不占空间

所以,所有的零宽字符都是控制字符(或格式字符),但并非所有的控制字符(如回车换行)都是零宽字符。

判断的关键在于:这个字符是否会产生一个“布局上的效果”(如换行、制表符缩进)?如果是,它就不是零宽的。如果它只在局部修饰文本而不影响布局流,那它就是零宽的。