秦鹿那天被妈妈催了相亲。早上八点,手机震了一下,妈妈的微信:“周六有空吗?王阿姨介绍了一个,银行工作的,条件不错。”
她回了一个“加班”就把手机翻过去了。
这是这个月第三次了。她妈妈不知道她在查什么案子,只知道她又加班了。她妈妈说“你一个搞电脑的怎么天天加班”,她说“电脑不会自己修好的”。
她妈妈叹了口气,发了一个“注意身体”的表情包,一个卡通人物捂着口,旁边写着“心疼”。
秦鹿看着那个表情包想:我妈心疼我的方式,和推送关心我的方式,有什么区别?都是程序化的、定时的、不了解真实情况的,唯一的区别是,一个是亲情驱动,一个是算法驱动。
但亲情也好,算法也好,她此刻需要的是线索,不是关心。
秦鹿的工位上,三个屏幕同时亮着。她的手指在键盘上飞快地敲击,嘴里咬着棒棒糖的塑料棒,糖已经吃完了,但她需要嘴巴动。银灰色头发今天扎了个马尾,因为她已经三天没洗头了,散下来太邋遢。工位旁边放着一个快递盒,她前天买的零食,拆了一半就忘了,现在盒子里只有几包辣条和一堆废纸。
她的眼神在三个屏幕之间跳跃,像一只在网上的蜘蛛。左边是三年前的网络安全事件档案,中间是“ABYSS”签名的特征码,右边是搜索引擎,她在用各种关键词排列组合试图找到更多线索。
已经搜了四个小时了。咖啡喝了三杯,棒棒糖吃了两,搜索关键词换了二十七组。每次她觉得自己快到了,线索就断了,像一条被反复咬断的线头,每次接上又断在另一个地方。
突然她停了。
左边的屏幕上跳出了一条旧新闻。标题是“XX大厂数据泄露事件,内部组被调查”。期是三年前。她之前搜到过这条新闻,但那次只看了个标题就划过去了。这次她点进去了。
新闻的正文很简短,某大厂推荐算法组发生数据泄露,代码被完整复制到外部服务器。公司对外宣称是“黑客攻击”,已经报警处理,涉事组已暂停运营。
但她注意到评论区有一条被折叠的回复,“本不是黑客,是内鬼”。回复者的账号已注销。
秦鹿在暗网的一个技术论坛上找到了另一个版本。有人发帖说,那次泄露不是“被入侵”,而是“从内部泄露”,组的代码被完整复制到了外部服务器,复制的方式是内部权限,不是外部突破。也就是说,有钥匙的人开了门。
她调取了当时的内部调查报告,花了她三个小时和两个空咖啡杯。报告很长,大部分是格式化的模板内容,但有一行字被标注为“低优先级备注”,藏在第十七页的脚注里:
“不排除内部人员作。负责人:周牧原。事件后调离组,三个月后辞职。”
周牧原。
她把这个名字和之前那个邮箱地址对了一下——zhoumu****@*****。zhoumu后面被遮住了三个字符。如果名字是“周牧原”,那完整邮箱可能是“zhoumuyuan@*****”,“yuan”恰好四个字符。
她敲了几下键盘,在PM的注册系统中测试了这个地址,系统返回“该邮箱已注销”,而不是“该邮箱不存在”。“已注销”说明它曾经存在过,“不存在”说明从未注册过。两个是完全不同的响应。
zhoumuyuan@*****。周牧原。
她靠在椅背上,盯着屏幕上那个名字看了十秒。棒棒糖的塑料棒在嘴里从左边倒到了右边,这是她确认某个判断的信号。她确认了:这不是巧合。从ABYSS签名到泄露事件到邮箱地址,三条线在“周牧原”这个点上交叉了。
她立刻给沈夜发了消息。沈夜二十分钟内赶到了网安部门。
秦鹿把屏幕上的内容一条一条讲给他听。沈夜不太懂技术,但他听懂了最关键的一句:“同一个人写的。”
“对。”秦鹿说,“ABYSS的底层代码和三年前泄露的那套推荐算法是同一个程序员的手笔。变量命名、函数结构、加密模块,匹配度94.6%。94.6%意味着……”
“意味着什么?”
“意味着从‘让人多刷五分钟手机’到‘让人少活一天’,只需要改一个参数。底层架构完全一样。”
沈夜看着屏幕上周牧原的简历。大厂核心组,推荐算法工程师,年薪百万,前途无量。三年前辞职。
“他什么时候辞的?”
秦鹿翻了一下记录。“辞职期是……”她停了一下,手指在键盘上悬了一秒,“三年前的七月十八号。”
沈夜把这个期记在心里。七月十八号。他不知道这个期意味着什么,但他的经验告诉他,每一个精确的期背后都有一个精确的原因。
“辞职原因呢?”
“‘个人原因’。”秦鹿说,“就这四个字,没了。”
沈夜看着屏幕上周牧原的工牌照。那张脸上的表情很平静,但眼神是空的,不是没在看什么,是看过什么之后剩下的空。他见过这种眼神,在审讯室里,在受害者家属脸上。那种空不是天生的,是被什么东西挖走的。
“年薪百万,前途无量,然后‘个人原因’辞职。”沈夜说,“接着搬去了哪里?”
秦鹿查了十分钟。户籍系统显示周牧原三年前从大厂离职后,先后搬了四次家,每次房租更低,从月租三千五搬到月租一千二,再到月租七百,现在是……
“城中村。月租四百五。”
沈夜看着这个地址,没说话。年薪百万到月租四百五,不是一年一年地降,是断崖式的跌。像一个人在往下跳,每一次搬家都是一次着地,但着地之后又接着往下跳。
顾临渊不知什么时候也到了。他站在秦鹿身后,看着屏幕上的信息,说了一句:“他离职原因写的‘个人原因’。”
秦鹿转头看他。
顾临渊没解释,但沈夜听懂了,“个人原因”是个垃圾桶,什么都可以往里扔。但能让一个人从年薪百万搬到月租四百五的“个人原因”,垃圾桶装不下。
“你觉得是什么?”秦鹿问沈夜。
沈夜没回答。他看着周牧原的工牌照,表情平静,但眼神是空的。和江映柳的那种空不一样,江映柳的空是被倒的杯子,周牧原的空是被烧的锅,不是被拿走了什么,是被烧掉了什么。
燃料、氧气、热量,烧完之后只剩一层灰,灰是白的,看起来什么都没有,但你知道那里曾经有过火。
他不知道是什么烧掉了他,但那个“个人原因”四个字背后,一定藏着什么东西。大到足以让一个人从年薪百万跌进月租四百五。大到可能让他把大厂的核心代码带出来,写出了ABYSS。
三个人沉默了一会儿。城市的灯火在窗外铺开,像一块巨大的电路板,每一盏灯是一个节点,每一条路是一线路,每个人是一个电流。而“深渊”系统,就像一块看不见的芯片,在了这块电路板的某个位置,悄悄改变了电流的方向。
秦鹿打破了沉默:“我继续查他背景,看看三年前到底发生了什么。”
沈夜站起来,走到角落的饮水机前,接了三杯水,纸杯,最便宜的那种,一碰就软。他把水递给秦鹿和顾临渊,自己端着第三杯站回了窗边。三个人各端着一杯水,在这个深夜的办公室里,谁也没有喝。
纸杯里的水面很平,映着天花板上光灯管的白光,像三面小镜子。沈夜看到自己在水面里的倒影,模糊的、晃动的,像一个人站在记忆的边缘,随时要掉进去。
赵满仓这时候推门进来,手里拿着一份报告。他的白大褂还没脱,头发上沾了一点灰,解剖室的排风系统老化了,总有些细小的东西飘在空气里。
“尸检补充报告。”他把报告放在桌上,“江映柳的胃内容物分析出来了。最后进食时间大约在死亡前六小时,橘子。果肉已经消化了一部分,但果皮纤维还在。”
沈夜看着他。
“只有橘子吗?为什么只吃了橘子?”沈夜想到了照片上的那棵橘子树。
赵满仓想了一下。他摘下眼镜擦了擦,这个动作和顾临渊一模一样,但赵满仓擦的是老花镜,虽然他才三十五岁。三十五岁就戴老花镜,法医这行费眼。他年轻时视力很好,5.2,能看到五十米外车牌上的数字。现在他连手机上的字都要拿远了才看得清。
“可能不甜。也可能……她只是想尝一下味道,确认那个橘子还是橘子。你有没有过这种感觉?吃一口东西,不是饿了,就是想确认这个味道还是你记忆中的那个味道。如果不是,那就什么都不可信了。”
停了两秒,他补了一句:“我验了这么多年尸体,胃里什么都有。有人最后一顿吃的是佛跳墙,有人吃的是方便面,有人胃里是药。好像一个人最后的晚餐,吃的什么就不重要了。”
又停了两秒,他像是突然想到了什么,补了一句:“你知道死人最大的优点是什么吗?”
沈夜看着他。
“不会突然坐起来跟你说‘其实我还有一个问题’。”赵满仓把老花镜重新戴上,“活人会。活人总是会。他们总是在你以为结束了的时候又冒出一个问题,‘为什么是我’‘还有没有别的办法’‘我能再打一个电话吗’。死人不会。死人很配合。”
他看着自己的手,那双摸过两千多具尸体的手。“但配合不代表活人该做的就做对了。”
沈夜站起来,拿了外套。
“我去城中村。”
赵满仓沉默了一秒。“小心。”
“嗯。”
从局里到城中村开车要二十分钟。他把车窗摇下来一条缝,夜风吹进来,带着城市边缘特有的味道,泥土、柴油、方便面调料。他看着后视镜里渐渐远去的城区灯光,高楼大厦的光像一片倒映在地上的星河。星河在身后,前方是暗的。