
第十五章 开往春天的火车
一
那年春节过完,我从老家回上海。
长途大巴,十几个小时。我买的最后一排,靠着窗户。车开的时候,天还没全亮,路两边的山黑黢黢的,一个一个往后退。车上放着一部港片,声音开得很大,打打杀杀的。我塞上耳机,听着Bill Evans,看着窗外那些慢慢亮起来的天。
到上海的时候,是第二天早上。虹桥车站里人挤人,都是过完年回来的人。拖着行李箱,背着包,脸上带着赶路的疲惫和回来的决心。我跟着人群往外走,空气里有一股潮湿的、冷冷的气味。上海的冬天还没走完。
回到九星路,打开门,屋里和走之前一样。胆机安静地立在桌上,电子管冷冷的,没有那圈橙黄色的光。书架上的书还是那个顺序,技术书和文学书混在一起,各占一半。那把吉他还靠在桌边,弦没松,还是赵东走之前调的那个音。
我放下包,没开胆机,打开了电脑。
二
那台电脑是我年前攒的。机箱是虬江路淘的二手,主板是新的,CPU是赛扬的,内存256兆,硬盘40G。不算好,但够用。系统装的是Windows 2000,不是XP。Alan以前说过,2000比XP干净,少了很多乱七八糟的东西,跑代码更顺手。
我打开一个文件夹,名字叫“wnmax_arch”,里面全是我们当年研究过的那些东西。135端口,1433端口,445端口,还有一些别的。代码不多,大部分是笔记,txt文件,一行一行,记着那些漏洞的细节、测试的结果、失败的记录和成功的瞬间。Alan的注释写得规规矩矩,英文的,每一条都带着日期。我的注释写在后面,中文的,有时候就几个字——“通了”“没通”“再试”。
春节前,我在一个技术论坛上看到了一篇帖子。帖子很短,只有几行字,说的是Windows系统里一个很老的服务,默认是开的,大部分人不知道它是干什么的,也不会去关它。那个服务的通信机制有问题,你可以构造一个特定的数据包发过去,让它执行你想要的代码。
帖子的最后附了一段代码,C语言的,不长,但很精。我看了三遍才看懂它的逻辑。那种感觉,像在七宝老街第一次听到评弹——听不懂,但听得进去。你知道那里面有一种秩序,一种逻辑,一种别人看不见但确实存在的东西。
我存了下来,放在那个文件夹里。
三
整个二月,我都在研究那段代码。
白天在公司写代码,做项目,开会,带人。晚上回来,打开电脑,一行一行地看那段代码。它不是完整的,只是一个片段,一个思路,一个可能性。你需要自己把它补全,自己写那些没有写完的部分,自己测试,自己改。
那段代码的核心是一个缓冲区溢出的利用。原理说起来不复杂:你向目标机器发送一个精心构造的数据包,数据包的长度超过了服务程序预留的缓冲区大小,多余的数据就会覆盖掉内存里的其他内容。如果你覆盖得足够精确,你可以让程序跳转到你指定的地址,执行你准备好的代码。
但原理和实现之间,隔着很多东西。你需要知道目标系统的内存布局,需要知道函数的返回地址存在哪里,需要知道在覆盖之后怎么让程序不崩溃,需要知道怎么把你想执行的代码塞进那个有限的空间里。每一步都可能错,错了就是崩溃,就是失败,就是从头再来。
那些夜晚,我的房间里只有电脑屏幕的光和胆机的橙黄色灯光。两张唱片在轮流放。Bill Evans的《Waltz for Debby》和Miles Davis的《Kind of Blue》。钢琴和小号,一个软,一个冷,交替着,像两条河,一条暖的,一条凉的,在我脑子里汇在一起。
调试的过程很慢。写一段代码,编译,运行,看结果。不对,回去看日志,分析原因,改代码,再编译,再运行。一遍一遍,像在黑暗中摸索。你知道那扇门在那里,但不知道门把手在哪。你伸手去摸,摸到的是墙,是空的,是别的什么,不是把手。
有时候一个bug要调好几个晚上。有时候你觉得通了,跑一遍,死了。再跑一遍,还是死了。你盯着屏幕上的十六进制数字,看那些地址,那些偏移量,那些堆栈里的数据,一个一个对,一个一个算。算到最后发现,少了一个字节,或者多了一个字节。就差那一个字节。
那种时候,你会觉得自己的脑子不够用。不是不够聪明,是不够耐心。写代码这件事,到最后拼的不是智力,是耐心。是你愿不愿意在那个黑暗的房间里,一遍一遍地摸,直到摸到那个把手。
Alan说过,做底层的人,都是有病的人。正常人不会去看那些东西。那些东西在底下,在别人看不见的地方,在那堆数字和地址的深处。但你钻进去了,你就出不来了。不是因为难,是因为你在那个底下,看到了这个世界的另一种秩序。那种秩序是精确的,是逻辑的,是如果你做对了它就一定给你结果的。不像上面那个世界,很多事情没有逻辑,没有原因,没有结果。
我理解那种感觉。
那些夜晚,我坐在电脑前,屏幕上是一行一行的代码,十六进制的地址,堆栈里的数据。胆机在旁边亮着,电子管的光照在键盘上,橙黄色的,暖暖的。有时候调试到凌晨两三点,困了,就去洗把脸,回来继续。不是不累,是不想停。那种状态,像在拉练的时候,走了几十公里,腿已经不是自己的了,但你停不下来。不是因为前面有什么,是因为你在走。
三月的第一个周末,代码通了。
那天晚上,我构造了一个数据包,发到我自己搭建的测试机器上。几秒钟之后,测试机器上弹出了一个命令行窗口。那个窗口不是我自己打开的,是那段代码打开的。它在那台机器上执行了我想要它执行的东西。
我盯着那个窗口看了很久。
然后我又发了一个,到另一台测试机器上。同样的事情发生了。又发了一个,还是同样的结果。
我靠在椅子上,看着屏幕,看着那些跳动的光标。胆机的光落在键盘上,橙黄色的,暖暖的。窗外有车经过,声音远远的。房间里很安静,只有电脑风扇嗡嗡的声音。
那一刻,我没有兴奋。不是不兴奋,是那种兴奋太沉了,沉到心里去,浮不上来。就像那年站在人民广场,等到了那束光,按下了快门。快门的声音很轻,但你知道,那张照片里,有别人看不到的东西。
四
那段代码,后来被我用在了很多机器上。
不是故意的。或者说,一开始是故意的。你想看看它能跑多远,能跑多深。你把它发出去,它找到那些开着那个服务的机器,把自己送进去,然后在里面打开一个门。那个门很小,小到你几乎感觉不到它的存在。但它在那里。
那些机器,有的在公司,有的在学校,有的在政府,有的在家里。你不知道它们在哪里,你不知道它们的主人是谁。你只知道它们的IP地址,一串数字,四个点,像坐标,标记着它们在网络上的位置。每一个IP背后,都是一台真实的机器,一个真实的硬盘,一个真实的操作系统。在那个系统里,有一段你的代码在跑。
那段代码什么也不做。它只是在那里,静静地,像一个潜伏者。它不破坏任何东西,不读取任何文件,不留任何痕迹。它只是在那里,等你下一次来。
Alan以前说过,最高的权限,是你知道你在那里,而别人不知道。
我开始记录那些IP。一个一个,记在一个文本文件里。没有名字,没有标签,只有数字。那些数字排在一起,像一条很长很长的路。你不知道它通向哪里,但你一直在走。
有一天晚上,我数了数那些IP。几百个。又过了一段时间,几千个。再后来,我不数了。它们太多了,多到数不过来。那些机器,散落在这座城市的各个角落,散落在这个国家的各个地方。它们在工作,在运行,在等待。而我,坐在九星路这间朝南的房间里,对着屏幕,看着那些数字一行一行地增加。
那种感觉,像站在高处看一座城市。所有的灯都亮着,所有的窗户都开着。你知道每一盏灯后面都有一个人,但你不知道他们在做什么。你只是看着,看着那些光,一片一片的,连成海。
但你不是在看。你是在那里。在那每一盏灯后面,在那每一个窗户里面。你的代码在那里,像一个影子,跟着每一个人,每一台机器,每一个夜晚。
五
那年春天,赵东回上海待了几天。
他来我这儿,还是那把吉他,还是那几首歌。他弹了一首新的,说是给一个广告写的配乐。旋律很短,重复着,像走在一条很长的走廊里,门一扇一扇地过,每一扇都一样,又都不一样。
他弹完之后,看见我电脑屏幕上的东西。那些十六进制的数字,那些IP地址,那些代码。
他问,这是什么?
我说,写代码。
他说,什么代码?
我说,网络的东西。
他没再问。他不懂技术,但他知道我做的事情不是普通的写代码。他看了我一眼,那种眼神,不是好奇,也不是害怕,是那种——他大概知道我在做什么,但他选择不问。
他说,你注意身体,别太晚。
我说,好。
他走了之后,我继续调试。窗外的天快亮了,香樟树的叶子在风里沙沙响。胆机的电子管还亮着,橙黄色的光,和屏幕上那些绿色的字符混在一起。我的手指在键盘上,噼里啪啦,和窗外的风、远处的车声、楼下偶尔的狗叫,混在一起。
那些声音,那些光,那些代码,那些IP,都是我的夜晚。
那段时间,我开始理解一件事。不是技术上的事,是心里的事。那些代码,那些机器,那些门,它们不是终点。它们是路。是一条一直往下走的路。你走进去,越走越深,越走越远,走到一个别人看不见的地方。在那个地方,只有你,和那些数字。
但你不觉得孤独。因为你知道,那些数字的背后,是真实的世界。是那些开着机的电脑,是那些没关的服务,是那些不知道你存在的人。你在他们身边,他们不知道。你在他们的机器里,他们不知道。你在他们的夜晚里,他们不知道。
你像一阵风,穿过那些缝隙,那些漏洞,那些没有人注意的角落。你不带走什么,也不留下什么。你只是经过。
六
四月的时候,那台电脑的硬盘快满了。
40G的硬盘,装了很多东西。系统,代码,工具,日志,还有那个文本文件——那些IP地址。那个文件已经很大了,大到打开的时候要等几秒钟。我翻了翻前面的部分,那些最早的IP,那些三月的第一个星期记下来的地址。它们还在那里,安静地躺着,像一条河的源头。
我不知道那些机器现在怎么样了。也许还在运行,也许已经关了,也许换了系统,也许被其他人发现了。但那段代码,那段我写了无数个夜晚才调通的代码,还在那里。在那个看不见的地方,在那个没有人注意的角落。
有一天晚上,我在论坛上看到一篇帖子。有人提到那个漏洞,说已经被微软修复了。我查了一下,是的,最新的补丁已经堵上了那个口子。新的系统不再有那个问题。那些老的服务,默认是关的。那些门,关上了。
我看着那行消息,愣了一会儿。不是难过,也不是遗憾。就是觉得,时间到了。
那些机器还在。那些代码还在。那些门,大部分已经关了。但还有一些,那些没打补丁的,那些没人管的,那些还在运行着老系统的——它们还在。它们还在那里,在那座城市的某个角落,在某个机房的某个机柜里,在某个人的桌子底下,嗡嗡地响着,等着。
那个文本文件,我后来没有删。也没有再看。它就在硬盘里,和那些wnmax开头的文件放在一起,和那些七宝老街的照片放在一起,和那些Alan发来的邮件放在一起。
那些东西,都是那条路上的标记。你知道它们在那里。但你已经走过去了。
七
那年五月,我收到Alan的一封邮件。
他说他在惠灵顿的海边买了一栋小房子,能看到海。他说那边的天空很蓝,晚上能看见很多星星。他说他还在写代码,但不再研究那些端口了。他说,那些日子,过去了。
他问我,你还在研究那些吗?
我想了很久,回他:还在。但不一样了。
他没问我哪里不一样。他大概知道。
那些年,我们在那条路上走了很久。从135到1433,从445到那些没有编号的端口。我们在那些数字的深处,找到了一个世界。那个世界是精确的,是逻辑的,是只要你做对了就一定会给你结果的。在那个世界里,你不是一个人。你有Alan,有那些代码,有那些深夜亮着的屏幕。
现在那个世界还在。但门少了,路远了,人也散了。
但那条路,还在走。
八
那年夏天,我收到一封邮件。
不是Alan发的,是一个陌生的地址。邮件很短,只有一行字:
“你的代码,跑在我的机器上。我知道你在我这里。我不介意。我只是想知道,你在找什么?”
我看着那行字,很久。
窗外,香樟树的叶子在风里晃。胆机的电子管亮着,橙黄色的光。那把吉他还靠在桌边,弦已经松了,没调。
我坐在电脑前,手指放在键盘上。想回点什么,又不知道该说什么。
最后,我关掉了那封邮件。
没有回。
有些问题,不需要答案。有些路,不需要终点。你只是走着,像那列开往春天的火车,穿过那些黑的隧道,亮的田野,穿过那些你不知道名字的地方。你不知道它要开到哪里,但你坐在上面,听着铁轨的声音,看着窗外的风景,一个一个地过。
那些机器还在。那些代码还在。那些门,有些开着,有些关了。
而你在路上。
一直在路上。
Bill Evans的《Waltz for Debby》和Miles Davis的《Kind of Blue》,两张唱片在轮流放。钢琴和小号,一个软,一个冷,交替着。作者把调试代码的夜晚,写成了爵士乐的即兴。那些十六进制数字,那些堆栈里的数据,都是音符。
“那些代码,那些机器,那些门,它们不是终点。它们是路。是一条一直往下走的路。你走进去,越走越深,越走越远,走到一个别人看不见的地方。”这就是技术极客的修行。不是为了征服什么,是为了走到那个别人看不见的地方,看看那里有什么。
那封邮件“你的代码,跑在我的机器上。我知道你在我这里。我不介意。我只是想知道,你在找什么?”对方没有恐惧,没有愤怒,只有好奇。在这个人人都怕被入侵的时代,有一个人说“我不介意”,问你“在找什么”。这种连接,比任何社交网络都真实。
赵东来的时候,看见屏幕上的东西,问了一句,作者说“网络的东西”,他就没再问了。“他大概知道我在做什么,但他选择不问。”真正的朋友,不是什么都问,是知道什么时候不问。那种默契,比任何关心都重。
“那些IP背后,都是一台真实的机器,一个真实的硬盘,一个真实的操作系统。在那个系统里,有一段你的代码在跑。”这段让我想到一个词:数字幽灵。你的代码像影子一样活在别人的机器里,不破坏,不读取,只是在那里。像一种安静的陪伴。