## 第二十五章:他开始怀疑闻人屿的真实身份
周二早上闻人屿到公司的时候,走廊里的气氛和前几天不太一样。他说不上来具体是什么变了,但那种"变"体现在极细微的层面上——有人走路的步伐比平时轻,像在尽量避免制造不必要的声响。他在工位坐下来开机,处理完一条工单之后收到了内通系统的一条新消息。发送者是南宫珩,内容是一段文本,看起来像从某份技术日志里摘出来的。那段文本描述了"某未知用户对核心机房防御系统底层条件判断语句进行修改的操作记录",操作的时间戳、源地址、目标路径全部被模糊化处理过,但修改手法本身被保留了下来——一行将"双向开放"改为"单向可进不可出"的条件判断语句,备注栏写着"类似于已知ID'Silence'曾使用过的防御加固风格"。
他把这段文本从头到尾读了一遍。南宫珩用"类似于"这个措辞把最后半句嵌在了正文里,像在一篇正常的日志摘要里夹了一根灰色标记线。
他打字:"你从哪找到这段记录的。"
"从一份历史归档日志的备份里。那篇帖子的时间戳是三年前,发帖ID已经注销了,但发帖内容里的代码结构和你的修改方式高度重合。结构层面的重合度超过百分之九十。"
"你是在告诉我你三年前就已经看过那个ID的代码了。"
"我看过。当时没有把那组ID和任何人联系起来。但你改防御层那行判断语句的方式和那个ID三年前在暗网上公开过的一段示例代码之间的结构重合度高到不能忽略。"南宫珩回完这行之后停了几秒,又补了一行,"你当年用那个ID发布那段示例代码的时候,没有想过它会被拿来和今天的事做比对。"
闻人屿看着这行字。南宫珩用的是"你当年",不是"那个ID"或"那个人"。这个词的位置和时态极其明确——他已经完成了从"代码风格相似"到"同一个人"的推断,并且选择在对话框里用"你当年"三个字来宣告这个推断的完成状态。闻人屿没有否认,也没有承认。他回了一句:"那段示例代码当时发在哪个板块。"
"技术分享区,标题是一段关于系统防御层出口规则优化的讨论。帖子里写了三种不同的出口锁实现方式,第三种和你昨晚用的手法完全相同——把双向开放改成单向可进不可出,在出口端加一层对输出流量的静默拦截。"
闻人屿把手机放在桌面上。他端起杯子喝了口水,水温合适,经过喉咙的时候瘢痕的位置没什么反应。他看着杯壁内壁的水面在光照下映出一小片晃动的光斑,把杯子放下来。办公室里的键盘声和电话铃声照常响着,他坐在那层日常的噪声中维持着"正在处理工单"的姿态。但他的注意力没有完全从刚才那根灰色标记线上移开。南宫珩用"你当年"三个字把一条时间跨度长达三年的证据链串了起来,从那个注销ID的代码片段到昨晚那行条件判断语句的修改方式。这根线的两端被他在三分钟内完成了对接,像两条各自沉在海底的电缆被同时捞起,在同一个甲板上接通了端口。
他等了大约五分钟才重新拿起手机。对话框里南宫珩那边没有新消息发过来。那种"没有新消息"本身构成了一层信号:他在等闻人屿回答,但不是用"为什么没有回复"来催促,而是保持通道开放,等他自己走过来。
闻人屿打了一行字:"那段示例代码的第三种子方案,我在三年前发出来的时候没有想过它会被任何人记住。"
"有人记住了。"
"你现在怀疑我就是那个ID的运营者。"
"不是怀疑。"南宫珩的回复速度和措辞收束方式和平时一样干净,"我已经确认了。那段示例代码的第三种子方案的实现细节里有三处你特有的编码习惯——函数命名方式、缩进间距、以及注释行末尾的空格。这三处和你写在蜜罐容器里的代码完全一致。"
闻人屿的拇指在手机侧边上停了半秒。蜜罐容器是他在穿进来之后最早部署的工具之一,那把刀的核心模块,运行日志只有他自己能调阅。他从未在任何公开渠道亮出过那个容器的源码。但南宫珩说他看过"蜜罐容器里的代码",这意味着他在某个时间点获取了那把刀的完整源代码副本。
"你什么时候拿到蜜罐容器的源码的。"
"在你把那份加密日志存进外置硬盘的同一周。我的系统监控层在蜜罐容器生成归档日志的时候捕获了一组结构特征码。"南宫珩的回复在这里顿了一下,像在组织下一步的表达方式,但那种停顿在文字上只表现为一个逗号,"特征码和暗网上Silence以前使用过的工具包里的签名模型匹配。我反向追踪了那个签名模型的逻辑,然后重构了蜜罐容器的架构。"
闻人屿靠在椅背上。他之前一直以为蜜罐容器是完全独立的、只有他自己知道的离线部署,但南宫珩的系统监控层在他穿进来的第一周就捕获了结构特征码。那些特征码像指纹一样嵌在容器的日志生成机制里,不需要源码就能捕捉,但要把它们追溯到具体的架构层面,需要三周的逆向工程。南宫珩用了将近三周的时间完成了从"特征匹配"到"架构重构"的推断,然后等到昨天那行防御层修改的代码出现时,用编码习惯的交叉比对把两个信息点合并了。
他低头重新拿起手机,打了一行字发出去:"你从第一周就开始追踪那条特征码了。"
"对。第一周捕捉到,用了三周时间确认。到昨天那条防御层修改的代码出现时,确认链已经完整了。那些编码习惯不会在两套互不关联的代码里重复出现,除非它们来自同一个人的手。"
闻人屿把手机放下来。他没有回"是"或"不是",也没有做任何口头上的确认。他把手机屏幕按灭放进口袋,拿起杯子起身去茶水间接了水。走廊里的灯管在头顶发出持续的嗡鸣,他走了一段之后停下来,在茶水间的窗边站了一小会儿,看着窗外灰白色的天光铺在城市的上方,那种均匀的亮度像一整块毛玻璃。茶杯里的热气升起来又散开,在他脸前形成一小片模糊的暖雾。
他端着水杯往回走的时候,经过走廊中段那扇和机房相邻的窗,看到磨砂玻璃门里面的灯亮着。门没完全关严,留下了一道大概两指宽的缝。他没有放慢脚步,但视线从那条缝里掠过的时候捕捉到了一个侧影——南宫珩站在操作台前面,正对着屏幕。他的外套搭在椅背上,从缝里看出去他的身影被框成一道狭长的深色块,边缘被光勾出柔和的轮廓。那道光线从显示器屏幕的方向打过来,沿着他的肩线滑下去,消失在门缝截断的地方。
闻人屿走回了工位。
下午的工作照常推进。三点左右他收到一条南宫晚棠的消息,发来了一张新的绿植照片,叶尖上挂着水珠,背景是一扇他认得的窗户——十六楼茶水间的窗台。她已经把那盆植物放过去了。他没有回文字,发了一张竖大拇指的默认表情过去。那边回了一个笑脸,然后对话结束了。
下班前他收到今天最后一条内通消息。南宫珩的黑色方块头像旁弹出一行字:"那份权限表的流向已经确认完了。下一步的工作方向会根据你今天之前提供的全部信息来制定。你明天下午之前不需要再做任何新的修改动作。"
他回了一个"好"字,然后关掉对话框收拾东西。走出写字楼的时候天色还亮着,西面的天际线残余着一层浅橙色的光带,被低空的薄云揉散成一片均匀的渐变色。他在台阶上停了一步,站了一小会儿,看着那道光带慢慢收窄、变暗,然后走下台阶往地铁站方向去了。
回到出租屋之后他吃了饭洗了碗,坐在桌前没有开工作站。他把手机拿过来,把那行"不是怀疑。我已经确认了。"和那行"那些编码习惯不会在两套互不关联的代码里重复出现"一起看了两遍。这两行字今天下午在他记忆里回放了许多次。第一次读到"蜜罐容器"的时候他拇指停住的那半秒,现在回想起来像一个被延迟触发的开关,直到此刻才真正接通。
那层"确认"意味着什么,他暂时没有去深想。他站起来去洗漱,然后躺了下来。窗帘拉了大半,路灯的黄线在天花板上照例画了一道窄长的亮影。他侧躺着看着那道影子,在脑中把今天所有的对话重新走了一遍。南宫珩用三周时间从一条特征码追踪到一个身份确认,中间跨越了暗网匿名ID、蜜罐容器、防御层修改多个层面。他在今天下午把这条追踪链完整地呈现在对话框里,然后把"确认"这个结论放在最后,像一个已经走到门口的人把门推开了一条缝,没有迈进来,只是站在门槛上等着对面的人自己看到那条缝里透进来的光。
今天所有的对话都以句号或问号结束,唯独"那些编码习惯不会在两套互不关联的代码里重复出现"以句号收束,那种收束的方式像一根线在末端打了一个结,不多余,不拖沓,但拉不开了。
他从枕头边摸到那盒润喉糖,取了一颗含在嘴里。薄荷的凉意在舌尖展开的时候他微微眯了一下眼,然后把手放回被子外面。他想着明天下午之前什么都不用做,想着操作台前那道门缝框住的深色轮廓,想着他站在门槛上没有迈进来。那颗糖在舌下慢慢化开,凉意退下去之后留下一层薄薄的甜。他闭上眼睛,听到窗外偶尔驶过的车声被窗帘和墙壁层层削薄,最后变成一种几乎没有厚度的背景嗡鸣。
他慢慢睡着了。