一、什么是零宽字符隐写?
这是一个非常有趣且隐蔽的信息隐藏技术,结合了“零宽字符”和“隐写术”两个领域。
-
隐写术 (Steganography):
顾名思义,“隐写”就是将秘密信息隐藏起来书写。它不同于加密(Cryptography)。加密是将信息变成一堆乱码,让人一看就知道是秘密,但无法破译内容;而隐写术是试图将秘密信息的存在本身都隐藏起来,让它看起来像普通、无害的信息(如一段文字、一张图片、一个视频)。“藏木于林” 是对隐写术最形象的比喻。 -
零宽字符 (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):用于控制文本方向,但本身不可见。
- 常见的零宽字符包括:
-
什么是零宽字符隐写?
零宽字符隐写就是利用这些不可见的零宽字符作为载体,将秘密信息编码并嵌入到一段普通的可见文本中的隐写技术。
简单来说,你看到的一段话(A),实际上里面还隐藏着另一段话(B),而B是用你看不见的字符写的。
二、工作原理(如何隐藏信息?)
-
编码秘密信息:
首先,需要将想要隐藏的秘密信息(如“secret”)转换成一种可以由0和1表示的二进制格式(例如,使用ASCII或Unicode编码)。s->01110011。 -
用零宽字符表示二进制:
选择两种零宽字符来分别代表二进制的 0 和 1。- 例如,规定:
U+200C(零宽非连接符) 代表 0U+200D(零宽连接符) 代表 1
- 那么,秘密信息“s”的二进制
01110011就可以被编码成一串零宽字符序列:[U+200C, U+200D, U+200D, U+200C, U+200C, U+200C, U+200D, U+200D]
- 例如,规定:
-
嵌入载体文本:
将这一长串代表秘密信息的零宽字符序列,插入到一段普通文本(称为“载体文本”)的任意位置。比如插入到句首、句尾、单词之间,甚至是某个单词的字母之间。- 载体文本:
“这是一条普通的问候信息,你好吗?” - 嵌入后:
“[零宽字符序列]这是一条普通的问候信息,你好吗?”或者“这[零宽字符序列]是一条普通的问候信息,你好吗?”
- 载体文本:
对于阅读这段文字的人来说,他们看到的仍然是:“这是一条普通的问候信息,你好吗?”,完全察觉不到隐藏信息的存在。只有知道编码规则的人,才能从文本中提取出这些零宽字符,并将其解码回原始的秘密信息。
三、实际应用与例子
- 水印与溯源:公司可以在内部文档中嵌入隐藏的员工ID或时间戳。如果文档被泄露,可以通过提取这个隐藏信息来追踪泄密源头。
- 绕过审查:在一些言论受限制的环境中,人们可以用这种方式在公开的社交媒体帖子中传递秘密信息,而审查系统可能无法检测到。
- 社交工程与恶意攻击:
- 网络钓鱼:攻击者可能会在看似合法的URL(例如,模仿
www.apple.com)中插入零宽字符,使其在浏览器中显示为正确域名,但实际上指向恶意网站。虽然现代浏览器对此有防护,但仍是潜在威胁。 - 混淆恶意代码:在某些支持Unicode的编程环境中,可能被用来隐藏恶意代码片段。
- 网络钓鱼:攻击者可能会在看似合法的URL(例如,模仿
四、如何检测和防范?
- 文本编辑器:将可疑文本复制到代码编辑器(如VS Code、Sublime Text)或纯文本编辑器(如记事本++)中,这些编辑器有时会以特殊方式(如一个小点、一个高亮)显示零宽字符。
- 在线检测工具:有很多网站提供零宽字符检测和去除功能,只需将文本粘贴进去即可分析。
- 编程检测:可以写简单的脚本(如JavaScript、Python)来遍历字符串,检查是否包含Un码位在
U+200B到U+200F之间的字符。 - 保持警惕:不要随意复制粘贴来历不明的文本并直接执行(比如在命令行中),尤其是从社交媒体或即时通讯软件中收到的信息。
总结
| 特性 | 描述 |
|---|---|
| 本质 | 一种数字隐写术 |
| 载体 | 零宽字符(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)。
虽然你在屏幕上看不到CR或LF这个符号本身,但它们执行了一个强大的、可见的格式功能——创建新行。因此,它们不是“零宽”的,而是“具有功能效应的不可见控制字符”。
2. 零宽字符 (如 U+200B, U+200C, U+200D)
这些字符是Unicode标准为了处理复杂文本排版(如阿拉伯语、天城文连字)而引入的。
- 零宽空格 (U+200B):表示一个可以断字的词边界,但不像普通空格那样有宽度。
- 零宽非连接符 (U+200C):阻止两个字符正常连接。
- 零宽连接符 (U+200D):鼓励两个字符连接(如生成复杂的emoji序列)。
它们不执行任何像换行那样改变整体布局的命令。它们的作用范围仅限于其插入点的局部相邻字符,并且完全不影响文本的宏观流。这才是“零宽”的真正含义——不改变布局,不占用空间。
一个很好的类比:文本编辑器视图
你可以在任何先进的文本编辑器(如VS Code、Sublime Text、Notepad++)中清晰地看到这种区别:
-
显示所有字符:
- 当你开启“显示所有字符”或“显示不可见字符”选项时。
- 换行符 (LF
\n):通常会显示为一个↵ (向下再向左的箭头) 或 ⏎ (回车符号) 。它占据了一个视觉位置。 - 零宽字符:可能会显示为一个非常特殊的、单独的符号(例如,VS Code中零宽空格显示为一个
˽,零宽非连接符显示为一个,零宽连接符显示为)。关键点在于:即使它们被“显示”出来,编辑器也会明确告诉你这些符号本身是“零宽”的,并且它们不会导致后面的文本被“推開”。
-
选择文本:
- 当你用光标在文本中移动时,光标会跳过一个换行符(因为它占据了一个“位置”),但光标不会在零宽字符处停留(因为它们没有宽度,光标会直接滑过)。
总结
| 行为 | 换行符 (LF \n) |
零宽空格 (U+200B) |
|---|---|---|
| 在编辑器中可见化 | 显示为 ↵ 或 ⏎ | 显示为一个特殊的字符(如 ˽) |
| 光标导航 | 光标会在此停留 | 光标直接滑过,无法停留 |
| 主要效果 | 宏观布局:创建新行 | 微观修饰:定义单词边界而不占空间 |
所以,所有的零宽字符都是控制字符(或格式字符),但并非所有的控制字符(如回车换行)都是零宽字符。
判断的关键在于:这个字符是否会产生一个“布局上的效果”(如换行、制表符缩进)?如果是,它就不是零宽的。如果它只在局部修饰文本而不影响布局流,那它就是零宽的。
浙公网安备 33010602011771号