魚知道嗎?_風聞
code2Real-有人就有江湖,有code就有bug2021-08-15 12:13
(一)哲學家與魚
“子非魚”是《莊子》中一個非常有名的辯論,展示了莊子與惠施兩種截然不同的世界觀,出自《秋水》篇。原文如下:
“莊子與惠子游於濠梁之上。莊子曰:‘鯈魚出遊從容,是魚之樂也。’惠子曰:‘子非魚,安知魚之樂?’莊子曰:‘子非我, 安知我不知魚之樂?’惠子曰:‘我非子,固不知子矣;子固非魚也,子之不知魚之樂全矣!’莊子曰:‘請循其本。子曰‘汝安知魚樂’雲者,既已知吾知之而問我,我知之濠上也。’”
翻譯也很簡單:莊子和朋友惠施在濠水的一座橋樑上散步。莊子看着水裏的魚説:“魚在水裏悠然自得,這是魚的快樂啊。”
惠子説:“你不是魚,哪裏知道魚的快樂呢?”
莊子説:“你不是我,怎麼知道我不知道魚的快樂呢?”
惠子説:“我不是你,本來就不知道你;你本來就不是魚,你不知道魚兒的快樂,也是完全可以斷定的。”
莊子説:“請回到我們開頭的話題。你説:‘你哪裏知道魚的快樂’等等,就是已經知道了我知道魚的快樂而問我,我是在濠水河邊上知道的。”
作家王蒙卻指出莊子不過是在詭辯,他説:
“我越看越感覺莊子是太詭辯了,我是非常喜歡莊子的,莊子的文字好啊,但是這種詭辯這種訛,北京話叫訛攪,第一個他循環論證,‘子非我,安知我不知魚之樂’,惠子就説,我非子,安知我不知汝不知魚之樂’是不是?這個兩個人就一塊辯論一下,辯論到2005年也辯論不完,這是第一點。”
“第二點呢,你們看全文的話,這個莊子更不講道理,人家安知魚之樂,這個‘安’的意思是為什麼,你怎麼會知道魚之樂,為什麼和怎麼的意思,why和how是這個,但是莊子理解成了Where do you know the happiness of the fish?你問的是where,既然是where,就是你知道我已經知道魚之樂了,我告訴你我就是在濠上知道的,利用一個‘安’字,因為這個安字既可以當how講,也可以當why講,也可以當where講,是不是?這是訛的把戲。”
王蒙還感慨到:
“我就弄不懂了,為什麼古往今來那麼多人在這注釋啊……怎麼就沒有人指出來莊子在這兒詭辯呢?這一點啊他在訛攪,沒有人指出這個,類似的一些東西啊非常多。”
那麼莊子是在“訛攪”嗎?其實,如果真正把《莊子》讀上一遍,就會知道他不是在詭辯。他在“子非我,安知我不知魚之樂?”這一反問中,就已經指出了惠施“非魚”就不知魚之樂的邏輯錯誤之處。
如果惠施在這裏懂了,他也就不會再有下一問了,所以莊子只能無奈再把自己的層次拉低一些,用名家的套路來制服同屬名家的惠施罷了。
名家是什麼套路呢?“白馬非馬”,在概念名詞上下功夫,於是莊子就也玩了一把概念,不但把“哪裏”與“怎麼”混淆,而且更進一步:
你既然能問出“你哪裏知道魚的快樂”,那麼首先你就要知道“我知道魚的快樂”,然後才能問出“哪裏知道”這個問題。如果你並不知道“我知道魚的快樂”,那麼也就不會問我怎麼知道的,哪裏知道的,這個問題也就不存在了。
這説明了什麼呢?“不知道”也是一種“知道”。《莊子》中有過論述:能把自己病情説清楚的人,就不算是生了重病;自己都不知道自己生了什麼病,那才是真正的重病。
為了更好地説明這個問題,我們來做一個問答實驗:第一個問題,哪些東西是你知道的?第二個問題,哪些東西是你不知道的?第三個問題,哪些東西是你不知道自己不知道的?
第一個問題,我們很好回答;第二個問題,我們也能説出個一二三來;但第三個問題,就真的是沒法回答了。一旦回答,就與這個問題本身相違背了。
所以“不知”,也是一種“知”;真正的“無知”,是你並不知道自己不知道。因此在科學界,提出問題遠遠比解答問題要重要,一個問題被提出來,哪怕沒有答案,也已經是一種進步,一種“知”了。
(二)物理學家與魚
物理學家加來道雄寫過《一名物理學家的教育歷程》,摘錄如下。
記得那時我的父母不時帶我去舊金山遊覽著名的日本茶園。我蹲在那裏的一個小池邊,為慢慢暢遊在水底睡蓮之中五彩斑斕的鯉魚所陶醉。這是我最快樂的童年記憶之一。
在那靜靜的時刻,我充滿了無限的遐想。我常常給自己提一些只有小孩才問的問題,比如水池中鯉魚怎樣觀察它們周圍的世界。我想,它們的世界一定奇妙無比!
鯉魚們的一生就在這淺淺的水池中度過。它們相信它們的“宇宙”就由陰暗的池水和睡蓮構成。它們大部分時間在池底漫遊,因此它們只模糊地意識到在水面之上存在有另一個外部世界。我的世界的本質超過了它們的理解能力。我喜歡坐在距離鯉魚僅僅幾十釐米的地方,然而,我們之間卻如距深淵。鯉魚和我生活在兩個截然不同的宇宙之中,從來不進入對方的世界,我們之間被水面這一薄薄的“柵欄”分隔開來。
我曾想:在水底的魚羣中可能有一些鯉魚“科學家”。我想這個鯉魚“科學家”會對那些提出在睡蓮之外還存在有另外一個平行世界的魚冷嘲熱諷。他們認為,唯一真實存在的事物就是魚兒們看得見摸得着的。水池就是一切。水池之外看不見的世界沒有科學意義。
有一次,我遇到了一場暴雨。我注意到成千上萬的小雨滴轟擊在池水的表面。池水變得混亂,水中的睡蓮在洶湧不息的水波沖刷下搖擺不定。在躲避風雨之時,我想弄清楚周圍發生的一切將會以怎樣的形式呈現在鯉魚們的眼中。在它們看來,睡蓮似乎是自己在運動,沒有任何東西衝刷它們。因為就像我們看不見我們周圍的空氣和空間一樣,鯉魚們也看不見它們賴以生存的水,它們為睡蓮自己能夠運動而困惑不解。
我想,鯉魚“科學家們”將會聰明地杜撰某種虛構的東西——它被稱為“力”,來掩蓋自己的無知。由於不能理解在看不見的水面上存在的水波,它們將得出這樣一個結論:睡蓮之所以能夠不被觸摸而運動,是因為有一種看不見的神秘力在對它起作用。它們可能給這種錯覺起一個高深莫測的名稱(如超距作用,或沒有任何接觸睡蓮即會運動的能力)。
我曾想,如果在池水中抓出一個鯉魚“科學家”,事情將會怎麼樣呢?放回池水之前,它可能隨着我的查看而狂亂掙扎。那麼別的鯉魚又將怎樣看待這件事呢?對於它們而言,這確實是一件可怖的事情。它們第一次意識到有一位鯉魚“科學家”從它們的宇宙中消失了。就那麼簡簡單單,沒有留下任何蹤跡。不管在它們的宇宙中怎麼尋找,就是沒有這條丟失的鯉魚的蹤影。然而,就那麼幾秒鐘,當我把它放回池水之後,這位鯉魚“科學家”便突然冒了出來。對於別的鯉魚而言,這真是一個奇蹟。
待神智鎮定之後,這位鯉魚“科學家”就會講述一個真正令它們驚詫不已的傳奇故事。它説:“突然之間,不知怎的我就被拉出了咱們的宇宙(池水),投進了一個冥冥世界,那裏有令人目眩的強光和我從未見過的奇形怪狀的物體。最奇怪的是那個抓住我的生物竟然一點也不像魚。更使我震驚的是,無論如何也看不到它的鰭,但是沒有鰭它還是能夠運動。我感覺到熟悉的自然規律不再適合於這個冥冥世界。隨後,我發現自己突然又被扔回了咱們的世界。”(當然,這個到宇宙之外一遊的故事對於鯉魚是怪誕的,大多數魚都認為這完全是胡説八道。)
我常想,我們就像自鳴得意地在池中游動的鯉魚。我們的一生就在我們自己的“池子”裏度過,以為我們的宇宙只包含那些看得見摸得着的事物。就像鯉魚一樣。
(三)操作系統與虛擬機
目前虛擬機環境檢測有兩個“金標準”,分別是Al-khaser和Pafish。這兩個開源項目幾乎一網打盡了所有公開常見的VM檢測技術。下面簡要分析一下它們的技術原理。
3.1、硬件信息檢測
首先大概説説操作系統是怎麼知道這台計算機安了哪些設備的。計算機啓動的時候,主板固件會給OS傳兩個信息表,分別是ACPI和SMBIOS。ACPI表有很多部分,其中硬件信息主要集中在DSDT和SSDT這兩部分。
ACPI表的每個部分開頭都有一個OEM ID和OEM Table ID,這是第一個容易露餡的地方,例如QEMU默認將OEM ID寫為BOCHS,將OEM Table ID寫為BXPC + 部分名稱,如DSDT部分就寫成“BXPCDSDT”。
虛擬機的ACPI表中往往會存在一些現實中不存在的硬件,用於主客機間通訊,這是第二個容易露餡的地方,例如QEMU的DSDT表中會有DBUG和FWCF這兩個硬件。
計算機中大部分設備的信息並不寫在ACPI和SMBIOS表中。像顯卡、聲卡、網卡、USB這些都屬於PCI設備,與PCI控制器相連。PCI控制器本身提供一個接口,可以列出所有檢測到的PCI設備。每個PCI設備有四個用來亮明身份的代號,分別是Vendor ID, Device ID, Subsystem ID, Class ID。一般來説,OS檢測到PCI設備時,會首先根據Vendor ID和Device ID搜索驅動;如果搜不到驅動,則會根據Class ID查找是否有這一類設備的通用驅動。
虛擬機模擬出的PCI設備,其身份代號往往採用特定數字,這是第三個容易露餡的地方,例如QEMU模擬出的VirtIO設備,其Vendor ID多為0x1AF4。
相比於ACPI,SMBIOS對系統的正常運行沒有那麼重要。但是Windows的“系統信息”工具顯示的內容,多半都來自SMBIOS表,這是第四個容易露餡的地方,例如目前主流的虛擬機固件是OVMF,那麼虛擬機裏面“系統信息”就會顯示出OVMF的信息。
有些惡意軟件會通過檢測系統是否有風扇和熱區域(Thermal Zone)來判斷是否處於虛擬環境(一些安全系統會將軟件置於沙箱中試運行,以剔除惡意軟件,而惡意軟件需要識別出虛擬環境/沙箱,這是一種對抗)。目前所有版本的Windows,都是從SMBIOS表中讀取風扇信息,從ACPI表中讀取Thermal Zone信息。但是正常的商業軟件一般不使用此方法判定,因為很多正常的筆記本電腦也沒有在SMBIOS表中寫入風扇信息。
此外還有硬盤產品名、序列號、聲卡ID、網卡MAC地址等容易帶有虛擬機特徵的地方。
3.2、CPU信息檢測
x86 CPU本身有一條指令叫CPUID,用於探測該CPU所支持的功能,例如是否支持SSE指令集等。有些功能虛擬機無法模擬,就會屏蔽掉相關功能的信息,這是第五個容易露餡的地方。
早期虛擬化技術不完善的時候,虛擬機軟件需要挪動一些重要數據結構的位置,例如中斷表(IDT)等。著名的Red Pill程序就是靠讀取這些結構的地址來判定虛擬環境。但是後來有了Intel VT-x等硬件虛擬化技術,以及KVM以後,這些檢測方法就基本被淘汰了。
基於KVM的客機,如果將EAX寄存器置為0x40000000,並執行CPUID指令,會在EBX、ECX、EDX寄存器中讀取到字符串“KVMKVMKVM”,這是第六個容易露餡的地方。
3.3**、驅動信息檢測**
在有Linux KVM之前,各虛擬機軟件用的幾乎都是半虛擬化(Paravirtualization),也就是必須對客機軟件做一定修改才能在虛擬機中正常運行。例如VMWare虛擬機需要在客機中安裝一些驅動程序,這些驅動的信息中都帶有VMWare標識,這是第七個容易露餡的地方。
KVM實現的是全虛擬化,不需要對客機做任何修改,所以不必擔心這些問題。但是,按默認配置的QEMU虛擬機會帶有很多VirtIO接口的設備,這些設備的驅動也會留下虛擬機的痕跡,需要當心。
3.4、計時檢測
x86 CPU中有一個精度極高的計時器,稱為TSC計時器,可以精確到CPU時鐘週期數。那麼可以執行一段CPU指令,並將消耗的時間與正常CPU上消耗的時間進行對比,如果明顯高於正常值,就可判定處於虛擬機環境。
目前最常用的方法是,在兩次讀取TSC計時器之間,執行一次CPUID指令。前文説到,虛擬機軟件一般會特殊處理CPUID指令,屏蔽掉一些無法模擬的功能的信息,執行這些操作所需的時間遠多於正常CPU上執行一次CPUID所需的時間,這是第八個容易露餡的地方。
目前沒有簡單的辦法可以騙過計時檢測,所有已知方案都需要用特製的Linux內核和特製的QEMU軟件配合。
但是近幾年來,虛擬機環境檢測已經沒那麼重要了。這是因為微軟在Windows 10上大力推廣Hyper-V技術,有相當數量的用户自己都不知道自己處於虛擬機環境。例如,只要在Windows 10 Home的Windows Defender中開啓Memory Integrity或Core Isolation功能,就等同於開啓Hyper-V,並讓Windows運行在虛擬機環境下。
於是有很多網遊反作弊系統,只要檢測到開啓了Hyper-V,就放棄檢測虛擬機環境。於是在Linux界就有了一種神奇的操作,先用KVM開Windows虛擬機,然後在Windows中開啓Hyper-V,這樣就能愉快地玩各種3A鉅作了。
當然這種操作需要CPU和Hypervisor支持Nested Virtualization,然而Windows的Hyper-V長期以來不支持AMD的Nesting,會在啓動時卡死。直到2020年6月,微軟才宣佈Windows 10 Insider的Hyper-V開始支持嵌套虛擬化。
最近國外Reddit上有人報告使用5.11.6版本的Linux內核(無需打補丁),配合4.2版本的QEMU,可以在AMD系統上正常啓動Windows 10 20H2並開啓Hyper-V,可能是Linux KVM那邊做了改進。
(四)我們都是陰溝裏的蟲子
在科幻作家劉慈欣大名鼎鼎的作品《三體》裏,女主角葉文潔有一句台詞非常有震撼力,那就是:我們都是陰溝裏的蟲子,但是總還有人仰望星空。
陰溝裏的蟲子自然沒有魚在水中的那種靈活性。
越來越多的人開始懷疑我們的宇宙是一個虛擬系統。
既然操作系統有可能檢測出虛擬機,我們是不是可以比魚知道得更多?
《銀河系漫遊指南》(The Hitchhiker’s Guide to the Galaxy)是英國作家道格拉斯·亞當斯(Douglas Adams)的著名科幻小説系列的第一部。
這個系列一共5部,分別是:
1.銀河系漫遊指南 (The Hitchhiker’s Guide to the Galaxy)
2.宇宙盡頭的餐館 (The Restaurant at the End of the Universe)
3.生命,宇宙及一切 (Life The Universe and Everything)
4.再見,謝謝所有的魚 (So Long and thanks for all the Fish)
5.基本無害 (Mostly Harmless)