2015-04-16 66 views
3

我正在爲Windows系統實現SMBIOS讀取功能。由於API級別不同,有幾種方法可以支持:NtOpenSection(L「\ Device \ PhysicalMemory」)返回STATUS_OBJECT_NAME_NOT_FOUND

  1. 無故障GetSystemFirmwareTable('RSMB')可用於Windows Server 2003和更高版本;
  2. hardcore NtOpenSection(L"\\Device\\PhysicalMemory")適用於Windows XP之前和之後的傳統系統;
  3. L"Win32_ComputerSystemProduct"中重要的WMI數據通過繁瑣的COM自動化調用作爲後備路徑。

方法1和3都已經實現了,但我堅持\設備\ PhysicalMemory,爲NtOpenSection始終得到0xC0000034(STATUS_OBJECT_NAME_NOT_FOUND) - 絕對是ZwOpenSection文檔中的可能的結果代碼的一個也沒有。當然,我知道從Windows Server 2003sp1以及Windows XP-64開始,禁止訪問此部分,因此我在普通的Windows XP-32系統上嘗試了這一點 - 結果與第例如,Windows 7-64。我也知道即使在傳統系統上也可能需要管理員權限,但互聯網上遇到此問題的人員報告了此類情況的更多相關錯誤代碼,如0xC0000022(STATUS_ACCESS_DENIED)和0xC0000005(STATUS_ACCESS_VIOLATION)。

我的方法是基於戴爾的Libsmbios庫,我假定它正在工作。

UNICODE_STRING wsMemoryDevice; 
OBJECT_ATTRIBUTES oObjAttrs; 
HANDLE hMemory; 
NTSTATUS ordStatus; 

RtlInitUnicodeString(&wsMemoryDevice, L"\\Device\\PhysicalMemory"); 
InitializeObjectAttributes(&oObjAttrs, &wsMemoryDevice, 
    OBJ_CASE_INSENSITIVE, NULL, NULL); 

ordStatus = NtOpenSection(&hMemory, SECTION_MAP_READ, &oObjAttrs); 
if (!NT_SUCCESS(ordStatus)) goto Finish; 

我認爲這可能是可以調試這一點,但原生API似乎是透明的,像OllyDbg的調試器:執行立即返回一次SYSENTER指令接收控制。所以我不知道爲什麼Windows找不到這個對象。我還嘗試更改節名稱,因爲在線示例中有幾個變體,但總是生成0xC0000033(STATUS_OBJECT_NAME_INVALID)。

+1

如果要調試到內核模式,你需要一個內核調試器,如[WinDbg中或KD(https://msdn.microsoft.com/en-us/library/windows/hardware/ff551063.aspx )。 – IInspectable

+1

也許嘗試WinObj(可從Microsoft網站獲得)來仔細檢查該部分是否存在?並嘗試進程監視器(同上),看它是否將捕捉到的NtOpenSection請求,以防它被重定向出於某種原因。 –

+0

@HarryJohnston關於Sysinternals的好處,但是這個工具實際上什麼都沒有顯示:我用'Sleep(2000)'包圍了'NtOpenSection()',並且進程監視器僅記錄當時發生的4個配置文件事件;不排除來自* System *模塊的事件也沒有幫助。 –

回答

0

最後,我發現這樣一個奇怪的行爲的原因, - 多虧了你,人,證實了我的代碼段(這是一個實際的摘錄,而不是僞造的例子)確實有效。問題是,我沒有最初安裝的Windows DDK(我現在確實有,但仍不能的方式,Windows SDK的自動集成與Visual Studio它集成),所以有必要通過手工編寫的定義。特別是,當我意識到InitializeObjectAttributes實際上是預處理器宏而不是Win32函數時,我將RtlInitUnicodeString定義爲宏,因爲它的效果更簡單。然而,我不夠細心注意到UNICODE_STRING.Length.MaximumLength實際上意味着內容大小緩衝大小代替長度,我。即字節數而不是字符數。因此,我的宏上字段設置爲它們的預期值的一半,從而使視窗只看到L"\\Device\\PhysicalMemory"串的前半部分, - 具有明顯的效果。

+0

這是一個非常危險的建議,將'RtlInitUnicodeString'定義爲一個宏。這是一個非常有意的功能,如果你試着描述通過一個緩衝區而不是文字,它會炸燬你的臉。出於您描述的目的,有一個非常有用的'RTL_CONSTANT_STRING'宏,它完全符合您使用文字(並且還會導致緩衝區意外行爲)。另外,該對象只能從內核模式打開('OBJ_KERNEL_EXCLUSIVE')。 – 0xC0000022L