【筆記】使用 PDB 符號檔案匯出 Windows 核心資料結構

CarterLi發表於2022-03-27

Windows 提供的基礎系統檔案(從上到下為依賴關係)

  • msvcrt.dll ucrtbase.dll 提供基礎 CRT (C語言執行時)庫,例如 fopen_sleep 等。前者 msvcrt 繫結 MSVC 版本號,不同的版本不完全相容(這也是安裝很多軟體時會讓你裝微軟執行時的緣故),後者是微軟新出的通用版本,所謂 Universal CRT
  • kernel32.dll kernelbase.dll 提供 Win32 相容 API 函式,例如基本的 CreateFileW (注意 CreateFile 是巨集而非函式)和 SleepEx 等,這些函式都是面向使用者端的
  • ntdll.dll 提供使用者端的 WinNT 核心函式入口,例如 NtCreateFileNtDelayExecution。這些以 Nt 打頭的函式是使用者端能接觸到的 Windows 系統最底層的函式。引數要求嚴苛(例如全部要求 wchar_t 編碼,路徑名要求奇葩的 NTFS 格式),實現都是些 syscall
  • ntoskrnl.exe WinNT 系統核心映象(NT Operating System KeRNeL)。這裡存放真正的核心程式碼,使用者端接觸不到,入口即為上面的 ntdll

維基百科:https://en.wikipedia.org/wiki...

微軟公開的 Windows API 都是繼承自 Windows 95 上古年代的 Win32 API,即 kernel* 提供的那些。MDSN 上有完整的文件,Windows SDK 有完整的標頭檔案。微軟(名義上)保證 API 和 ABI 的雙相容,這就是 WinXP 甚至某些 Win98 上執行的程式都可以直接在 Win11 上執行的原因。

但是 Windows NT 核心,WinNT API 才是精華。比如 Win32 API 中 Sleep(0) 的特殊行為,在 WinNT API 中可是明確的區分為 NtDelayExecutionNtYieldExecutionntdll 提供了大量貼近核心功能強大的函式,微軟一不提供文件說明和標頭檔案定義,二不保證不同版本間 AxI 相容(比如這次 IoRing ABI 不相容,讓我除錯了好久),想用有時還得手動 LoadLibrary (當然絕大多數情況連結 ntdll.lib 就夠了)

想用 WinNT API,首先要知道 WinNT 提供了哪些函式可以用。這裡最簡單的辦法,使用 PE Viewer(筆者這裡使用 XPEViewer) 開啟 ntdll.dll,檢視匯出函式表

image.png

這些函式都是很規範的 Pascal 命名,看名字就能把用途猜個大概,然後在網上搜尋即可。如果往下翻一翻還可以看到 ntdll 還定義了很多 CRT 中的函式。

通過 PE Viewer 只能看到函式名,如果要呼叫需要他們的精確宣告。一部分宣告可以在 ntoskrnl.exe 的符號檔案(PDB)中找到

PDB 是公開的,可以在微軟的符號伺服器下載。在 MSVC 中除錯系統 dll 時自動下載部分符號檔案(kernel32.pdbntdll.pdb 等),但絕不可能下載到 ntoskrnl.pdb。這裡可以用 PDBDownloader 手工下載。

下載之後的 pdb 檔案可以使用 PDBRipper 讀取

image.png

PDBRipper 現在有個 bug,不支援結構體中的匿名共用體。

也可以用 pdbex 直接匯出標頭檔案,而且沒有匿名共用體的 bug

PDB 檔案中能獲取到絕大多數函式中用到的資料結構(結構體和共用體),仍然沒有精確的函式宣告。函式宣告可以在網上找到一部分,剩下的我也不知道從哪搞 ;)

相關文章