0xCAFEBABE与Hexspeak
如果将Java源码编译后的class文件以16进制方式打开,会发现前4个字节都是0xCAFEBABE
。
References:
- https://en.wikipedia.org/wiki/Java_class_file#Magic_Number
- https://stackoverflow.com/questions/2808646/why-are-the-first-four-bytes-of-the-java-class-file-format-cafebabe
- https://zh.wikipedia.org/wiki/Hexspeak
- https://zh.wikipedia.org/wiki/Leet
- http://radio-weblogs.com/0100490/2003/01/28.html
- https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html
文件必须以一些魔术数字(或字符串)开头,使其易于识别为有效的文件。例如zip(PKZip)固定以0x504b0304
开头,这样程序读取开头的4个字节就知道这个文件的类型能不能解析了,毕竟后缀名这种东西可有可无的没啥用。(很多CTF题会以zip文件做文章,感兴趣可以找一找)
那为什么class文件会选择这个字符呢?Java编程语言之父,詹姆斯•高斯林(James Gosling),曾这样说过:
在Java中使用
CAFEBABE
作为魔数(magic number)的过程, 说起来有些曲折:我和小伙伴们经常去一个叫
St Michael’s Alley
的地方吃午餐。根据当地传说, 在黑暗的过去,Grateful Dead
(感恩至死乐队)在出名前曾在此地表演。这绝对是一个因Grateful Dead Kinda Place
而闻名的地方(总感觉这句翻译的怪怪的)。Jerry
(乐队成员)去世时, 他们甚至建了一座佛教风格的小神龛。在我们过去常去那里的时候,把这个地方叫做Cafe Dead
。可以看到,这是一个十六进制数. 那时候我正好维护一些文件的编码格式,需要用到两个魔数(magic numbers): 一个用于对象持久化文件, 另一个用于类文件. 于是我就用
CAFEDEAD
作为对象持久化文件的魔数, 查找了一些适合放在CAFE
(似乎是一个不错的主题)后面的4位16进制的字符,最终我敲下BABE
并决定就是它了。当时, 这个魔数并没有什么特别的意义, 也看不出来有什么重要的, 或许很快就会消失在历史中。所以
CAFEBABE
成为class文件的魔数,CAFEDEAD
成为持久对象的魔数. 但没多久持久化对象(persistent object)技术真的消失了, 就如同魔数CAFEDEAD
的含义一样 -- 最终被RMI
技术代替了。
0xCAFEBABE
的十进制数是3405691582
,把每一位加起来得到的是43,恰好大于42——生命、宇宙以及任何事情的终极答案(出自道格拉斯·亚当斯所作的小说《银河系漫游指南》)。另外,43也是个质数,You see, magic everywhere. Even in the last sentence.
根据wiki的记载
Hexspeak最早是程序员用来清晰独特地标记内存和数据的一些魔术数字,使用以0-9与A-F构成的16进制数表示一些简单的英文单词。Hexspeak的转写规则为:数字“0”表示字母“O”,“1”表示“I”或“L”,“5”表示“S”,“7”表示“T”,“6”、“9”则各自表示“G”与“g”,其它的数字则可利用画谜和Leet的规则来借代字母,例如“defecate”就可用“DEFECA7E”或“DEFEC8”来表示。Hexspeak(16进制魔术数字)是一种类似Leet的英文单词转写形式。
而Leet的词条中:
Leet(英文中亦称 leetspeak 或 eleet。Leet拼写法:L337, 3L337, 31337或1337),又称黑客语,是指一种发源于西方国家的BBS、在线游戏和黑客社区所使用的文字书写方式。通常是把拉丁字母转变成数字或是特殊符号,例如E写成3、A写成@等。或是将单字写成同音的字母或数字,如to写成2、for写成4等等。
到这忽然想起LeetCode了,然后又想起了论坛里也经常发一些反和谐的字,比如河蟹(和谐)、反云力(反动)等等,果然大家都是如此的相似啊,哈哈。