詭異案例:系統服務無法啟動怎么辦?
上周二,我(@佘華煜)接到了一個很詭異的案例,表現為任務欄右下角網絡連接圖標始終為一個紅叉,已排除網卡硬件、鏈路和網卡驅動的問題。主板都新換了一塊,可是問題依舊,這無疑將問題的根源指向了操作系統。本想通過網絡疑難解答包先自動排錯,可是發現該疑難解答提示服務未能啟動因此不能進行自動排錯,經查證,Diagnostic Policy Service 服務處于起不來的狀態,報錯"錯誤5:拒絕訪問"。
經過我的排查,我發現系統的很多服務都未能啟動,尤其是網絡相關的很多服務,例如DHCP,防火墻,ICS,IPSec Policy Agent 等等。當我手動嘗試啟動這些服務時,除了有些報相關服務尚未啟動之外,無一例外地,都報了一個錯誤——錯誤5:拒絕訪問。(需要先啟動的相關服務都是該錯誤)
查看系統日志,將里面的更詳細的錯誤代碼拿去微軟搜索,發現沒有什么收獲。在一些社區解決方案中,也沒能找到行之有效的解決辦法,甚至微軟官方論壇有一個同樣的案例,一個錯誤的/不太相關的解答被標記為正解……
這顯然不是正解,我得找到一個解決該問題的辦法。于是經過各種嘗試,我最后通過 Process Monitor 的幫助,找到了服務無法啟動的直接原因和解決辦法。由于當時沒有截圖,所以今天我還原了一個當時的情景,以 Base Filtering Engine 服務的無法啟動為例,闡述當時我的解決思路。Base Filtering Engine 服務簡稱 BFE,相關的網絡安全服務(如 Windows 防火墻和 IPSec)依賴于它。
在打開 Process Monitor 的記錄以后,我立即點擊啟動服務,來嘗試啟動 BFE。它立即報錯"拒絕訪問",我同時也嘗試啟動了那些不能啟動的服務,都成功地重現了問題。停止 ProcMon 的記錄后,在已記錄下的log中,我可以看見當該問題重現時系統各進程所做的一些操作。通過粗略的快速瀏覽翻查和關鍵字"denied"搜索,引起我注意的是,很多注冊表的訪問遇到了 access denied 的錯誤。而在文件訪問中,尚未發現該錯誤。為了精細地驗證,我對當前記錄下的log進行了篩選器的應用。
應用篩選后,我們可以看見所有相關的 Access Denied 的條目。當時真實環境里的可以看見很多這樣的條目,因為很多服務都出現了無法啟動的故障,而撰寫本文時的實驗環境里,我只制造了 BFE 這一種服務的該問題。通過 Path 列,我們可以看見其具體的路徑為 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BFE\Parameters\Policy\Persistent . 右擊該條目,選擇 Jump To… ,注冊表編輯器便會被調用打開打開,并且自動定位到該鍵。我查看其權限設置,發現所有條目繼承于 Policy 鍵。
那我們就來看看該處的 Policy 鍵上的權限設置,與正常的計算機的同一位置的權限設置有何不同。
不難發現,服務不能啟動(尤其是提示拒絕訪問)的直接原因是因為,該服務無權訪問注冊表的這個鍵。(通過 Process Monitor 可以看出,它實際上要訪問的是 Policy 的子鍵"Persistent"卻遭到拒絕)
要嘗試恢復,那我們要做的就是至少在 Persistent 鍵及其子鍵/鍵值上授予 BFE 合適的訪問權限。為了一步到位,我做的是參照正常的系統,將正常的 ACE 項在權限傳播的起始處——Policy 鍵上設置,并往下傳播。設置時,除了還原應有的 BFE 的權限,還完全一致地將其他缺失權限補齊,將多余權限刪除,這樣可以避免一些額外的潛在問題。(例如權限仍過小或者過大)
值得注意的是,BFE 這個服務賬號不同于一般用戶賬號和組,所以直接鍵入 BFE 時間查不到名稱的。正確的做法是鍵入"NT Service\BFE"檢查名稱。
而默認地,BFE 在 BFE 服務的注冊表項上的訪問權限是特殊的。雖然我們可以直接授予完全控制權限來解決該問題,但是我們最好還是參照 LUA 原則,跟系統默認的一樣,將其設為特殊權限。特殊權限的具體項目如下圖所示:
好了,設置好并且應用權限之后,再次點擊啟動服務按鈕,就可以看到該服務正常啟動了。
最后,對于該詭異案例,有幾個說明:
1. 究竟是什么操作導致了系統出現這樣的問題,讓諸多系統服務注冊表鍵權限變成非默認值,至今尚不明確。據用戶稱,他就是出了個差,回來后就這樣了,其間沒有裝過什么軟件或者手動做過這種設置注冊表權限的危險操作。搜索互聯網,很多人都有遇到此問題的經歷,但是沒有哪個帖子能夠明確指出是什么操作引起了這個問題。如果您恰好有過此方面的研究,歡迎告訴我。
2. 事實上,該用戶最后重裝系統了,這也是我建議他做的。因為,該問題的發生,可能還伴有其他的一些未知的系統嚴重性更改,修復了注冊表權限,并且讓服務啟動后,不能確保他在該系統上,今后不會遇到其他的怪異問題。
3. 就像我遇到的這個真實案例一樣,該錯誤一旦發生,往往會伴有很多系統服務遇到此拒絕訪問的啟動問題。如果要應用此方法全面修復,那是非常耗費時間和精力的。這里給出一個能盡量加速解決此問題的思路:
話說當年 NT 5.0 時代,可以通過系統自帶的 secedit 命令重置所有安全設置和權限,但是現在已然不行了。鑒于目前尚未發現任何 fix 程序能夠自動重置系統服務的默認注冊表權限的,只能用以上4步進行修復。如果您所遇到的情形中只有一兩項服務有此問題,那么完全可以不采用腳本的方式,而是采用 GUI 的工具去看服務以及手動修復權限設置。等我今后有空的話,會寫一個重置系統自帶服務對應的注冊表權限的腳本。(貌似意義不太大)若您有高見,請不吝賜教。