那條走廊,他一進去就覺得是對的。
理由很充分。地上的灰被踩過,而且是最近踩的;牆邊有一道拖痕,像是有人搬過重的東西;走廊盡頭的光是暖的,不是外面那種天光。
這條廊有人在用。
O1 在入口站了一下,抬頭看了一眼門楣,然後走了進去。
那時候是晚上八點多。
走了大概四十步,他看到第一個記號。
牆上有一道新的刻痕,位置很低,像是蹲著刻的。他蹲下去看,刻痕是新的,邊緣還很銳。
證據。 他在冊子上記了一筆。
再走一段,他發現一扇半開的門。門後是一個空房間,什麼都沒有,但地上有一塊地方比較乾淨——有東西被搬走了,而且是最近搬的。
又一個證據。 他又記了一筆。
第三個小時,他在一個轉角找到一整箱東西。
是一批舊卷冊——這座城從前的副本,整整齊齊地捆著,連目錄都還在。
O1 蹲下去翻的時候,手是抖的。
那是真的。 真的副本,真的是這座城的,而且抄得很完整。他一冊一冊翻過去,翻了一個多小時。
然後他開始覺得不對勁。
卷冊上畫的格局,跟他剛才走過的走廊對不起來——圖上有一道牆,他來的路上沒看到。上面列的管事有七個人,而他這幾天在城裡聽到的名字,一個都不在上面。規矩那一節提到一種計時方式,那種方式早就沒有人在用了。
那是這座城的副本。只是那座城已經不在了。
城改建過,人換過,規矩也改過。這批卷冊真實、完整、抄得一絲不苟——而且每一個字,都在描述一個已經沒有了的地方。
第五個小時,他在一扇門上看到一個標記。
那個標記他認得——那是某一種舊式門鎖的記號,而那種鎖有名的毛病他讀過,導典上有一整節在講。
他花了快兩個小時去撬它。
撬不開。
他反覆確認了三次,記號沒有錯,鎖型也沒有錯。可是那道門就是不動。
後來他才知道原因:那道鎖早就被換過裡面的機關了。 換的人沒有改門上的記號,因為記號是刻在門板上的,換機關的時候沒有人去磨掉它。
外面看起來還是那把有名的爛鎖。裡面已經不是了。
第六個小時之後,走廊開始分岔。
他選了比較亮的那一邊,理由是「有光的地方比較可能通到上面」。走了一段沒路,他回頭,走另一邊。另一邊也沒路,他再回頭。
第七個小時的時候,他發現自己在做一件事,而且這件事他當下就知道不太對——
他不是在找路了。他是在找證據,證明自己選對了這條廊。
每看到一樣東西,他第一個念頭都是「你看,果然有人在用」,而不是「這代表什麼」。
他知道自己在做什麼。他站在岔路口,想了大概兩分鐘。
然後他走向第三條岔路。
因為他已經走了七個小時。
第八個小時,他停了下來。
不是因為想通了什麼。是因為他站在第三條岔路的盡頭,面前是一面實牆,而他已經沒有下一個念頭了。
他在那面牆前面站了一會兒,然後做了一個決定:
整條廊,不要了。
不是換一條岔路,是從頭來過。他沿著原路往回走,一路走回入口——把那八個小時整個丟掉。
那是他那天做的唯一一件正確的事。
走到入口的時候,他抬頭。
門楣上刻著一行字。
他進來的時候看過。他記得自己看過,因為他還在冊子第一行寫了「入口門楣有刻字」——那時候他正急著進去,只當它是裝飾。
現在他站在門楣底下,把那行字讀完了。
那行字寫的是這條廊的用途。
它是給送柴的人走的。
它通向柴房、通向後院、通向堆料的地方。它從一開始就不通樓上。
那些腳印是送柴的人的。那道拖痕是柴堆拖出來的。那箱舊卷冊是柴房的舊帳。每一樣東西都是真的,而且每一樣東西都跟他要去的地方沒有關係。
O1 站在那裡站了很久。
讓他難受的不是浪費了八個小時。
是他發現:那行字他第一眼就看過了。
他不是沒看。他看得很細——他甚至把「入口門楣有刻字」這件事記了下來。
問題是他當時已經決定要走這條廊了。
他走進去的時候,心裡已經有了結論。之後的八個小時,他看到的每一樣東西,都被他拿去證明那個結論。
那些證據全部是真的。
只是它們證明的是別的事情。
回去的路上,天已經亮到刺眼。
他走到一半的時候,忽然想起一個人。
他想起銓敘司窗口後面那個從來沒有看過他做的任何一件事的人。那個人也有一個結論,而那個結論之後,他聽到的每一句關於 O1 的話,都被拿去證明那個結論。
O1 一直以為,那是那個人特有的毛病。
那天早上他知道不是了。
那天他在導典第一頁寫下第五行。
那一頁現在是:
桌子是我的。
先做,再讀。
先看完,再動手。
換一座城,就要換一種讀法。
先有結論,就看不見證據。
他寫完之後,坐在那裡看了很久。
因為他發現這一行,跟叩門沒有關係。
這一篇談這條路上最貴的一種失敗——不是卡住,是走錯了還走得很認真。
很多人以為 rabbit hole 是「假線索」或「誘餌」。不是。
幻廊的特徵是:那些線索全部是真的,只是跟你的目標無關。
真的,所以你會相信。無關,所以你走不到。
如果線索是假的,你很快就會發現矛盾;但真的線索不會給你矛盾,它只會給你更多細節。
① 真的存在,但早就沒用了
我打過一台靶機,裡面有一個網站的備份檔。完整、可讀、看起來像大獎。
翻完之後,什麼都沒有。那是一份跟現行系統沒有關聯的舊東西,存在是真的,價值是零。
備份檔、舊版原始碼、歷史設定——這一類最會騙人,因為「找到別人沒找到的東西」的感覺太好了。
② 版本號說有洞,但洞已經被補了
這一種更陰險,而且我認為是所有幻廊裡最值得寫進筆記的一種:
某個服務的版本號對應到一個真實的 CVE,你查得到、PoC 也有——但目標其實已經上了修補程式,只是版本號沒有跟著變。
很多修補(尤其是發行版自己回移的安全更新)不會更動主要版本號。所以你看到的版本是 A,實際的程式碼已經是 A+修補。
從外面看,那個洞完好如初。你會很合理地認定「這就是入口」,然後花三小時證明一件不存在的事。
判斷方式:
(Day 7 談 jQuery 那一段是同一件事的 Web 版本:CVE 是真的,版本是真的,就是打不動。)
① 沉沒成本——走到第七小時,「回頭」的意思不是「換一條路」,是「承認前面七小時是白費的」。
② 確認偏誤——一旦你在心裡把某條路標成「對的」,之後看到的每一樣東西都會被解讀成支持它的證據。你不是在找路,你是在找證據。
③ 它真的一直在給你東西——每隔一段就有新發現,每個新發現都會刷新你的耐心。這在心理上跟拉霸機是同一個結構。
出現下面任何兩項,就該停下來重估:
最後一項最準。
我那次是怎麼出來的?我放棄了整條路,從頭來過。
不是換一條岔路,是把八個小時整個丟掉,回到最開始重新列舉。
這聽起來很浪費,但它其實是最省的做法。因為在幻廊裡「往前找出口」是不會有結果的——你是用那個錯誤的前提在找,找到的每一樣東西都會被同一個前提消化掉。
唯一能打斷它的是中斷連續性。 確認偏誤需要連貫的脈絡才維持得住,一旦你真的離開那個脈絡——回到入口、換一台機器、去睡覺——回來的時候你會用比較接近旁觀者的眼睛看它。
所以時間盒的真正用途不是「時間到就放棄」,是**「時間到就強制中斷」**。
① 強制輪替(最重要的一個)
一個方向太久沒有結果就換目標,而且是換另一台機器,不是換同一台的另一個方向。
這一項有雙重效果:它提醒你「你已經在這裡太久了」,同時換機器本身就是在轉換思緒。你在 B 機器上做別的事的時候,A 機器的那個錯誤前提會自己鬆掉。
考試的時候這一項會救你的命——Day 19、20 會講到。
② 計時器
用計時器,不要靠感覺。專注的時候時間感會壞掉,這是生理性的,跟意志力無關。
③ 未追查線索清單
每發現一個新東西就記下來,但不要立刻追。這樣換路的時候你不是從零開始,而是從一張清單開始。
至於「開始前先寫下預期會看到什麼」——這個方法常被推薦,但老實說我自己沒有這個習慣。開始追一條線索的時候,我通常也說不清楚自己預期看到什麼,只是希望多一點線索。
所以我靠的是前三項,尤其是輪替。如果你也是那種「開始之前講不出預期」的人,那就把重心放在強制中斷上——它不需要你事前判斷,只需要你事後認帳。
不是回到「上一步」,是回到最後一個你確定為真的事實。
翻回你的原始勘紋輸出(Day 4 說的那些存檔在這裡派上用場),重新讀一次,然後問:
我當初是根據哪一條,決定走這個方向的?那一條真的支持這個方向嗎?
我那次的答案是:門楣上有一行字,我記下了它存在,但我沒有讀它。
順帶一提,我也踩過一次一模一樣的錯——打一台 Tomcat 的機器,帳號密碼其實就寫在登入失敗的提示頁上,而我一直專注在試各種帳密組合,那一頁看了幾十次,沒有一次真的讀它。
你會看不見的東西,通常不是藏起來的,是你已經決定它不重要的。
Day 6 說九成的卡關是因為沒看完。這裡要補上另外一成:
有時候你看得夠仔細了,只是你在仔細看一個錯的地方。
| 勘得不夠 | 走進幻廊 | |
|---|---|---|
| 症狀 | 沒有東西可看 | 東西多到看不完 |
| 感覺 | 空、無從下手 | 忙、一直有進展 |
| 該做 | 回去補列舉 | 停下來,回入口重估 |
如果你覺得自己很忙、一直在發現東西、但目標沒有更近——那大概不是勘得不夠。
幻廊真正教我的,不是關於機器的。
是「先有結論,就看不見證據」這件事,發生在自己身上的時候,你一點感覺都沒有。
你不會覺得自己在偏執。你只會覺得自己在努力。
越走越像是對的,往往就是幻廊的定義。
因為那時候你不是在找路,你是在找證據。