之前研究 Runtime Service 提到了 Windows 下可以使用 GetFirmwareEnvironmentVariable 获得 Variable,最近请天杀帮忙研究 Windows 层面的具体实现。结论是:在hal.dll中有下面这样的代码
mov _HalEfiRuntimeServicesTable, offset _HalEfiRuntimeServicesBlock
结构体 _HalEfiRuntimeServicesBlock RuntimeTable <?> 成员如下
00000000 RuntimeTable struc ; (sizeof=0x24, align=0x4, mappedto_402)
00000000 GetTime dd ? ; XREF: HalEfiGetTime(x)+5C/r
00000004 SetTime dd ? ; XREF: HalEfiSetTime(x)+153/r
00000008 ResetSystem dd ? ; XREF: HalEfiResetSystem(x)+3F/r
0000000C GetVariable dd ? ; XREF: HalEnumerateEnvironmentVariablesEx(x,x,x)+252/r
00000010 GetNextVariableName dd ? ; XREF: HalEnumerateEnvironmentVariablesEx(x,x,x)+10C/r
00000014 SetVariable dd ? ; XREF: HalEfiSetEnvironmentVariable(x,x,x,x,x)+43/r
00000018 UpdateCapsule dd ? ; XREF: HalEfiUpdateCapsule(x,x,x,x)+40/r
0000001C QueryCapsuleCapabilities dd ? ; XREF: HalEfiQueryCapsuleCapabilities(x,x,x,x)+3C/r
00000020 QueryVariableInfo dd ? ; XREF: HalEfiQueryVariableInfo(x,x,x,x)+32/r
00000024 RuntimeTable ends
这次使用 WinDBG 进行调试实验。
实验的平台是 KBL-R ,USB3.0 调试。
1.查看当前系统中的模块
0: kd> lm
start end module name
00000001`c0000000 00000001`c000e000 kdcom_0 (pdb symbols) C:\ProgramData\Dbg\sym\kdcom.pdb\DDE6FDAD8C7544FEB91485DD8E1832511\kdcom.pdb
ffffa11b`77600000 ffffa11b`77994000 win32kfull (deferred)
ffffa11b`779a0000 ffffa11b`77bb2000 win32kbase (deferred)
ffffa11b`77bd0000 ffffa11b`77bda000 TSDDD (deferred)
ffffa11b`77be0000 ffffa11b`77c21000 cdd (deferred)
ffffa11b`780a0000 ffffa11b`78117000 win32k (deferred)
fffff803`b6c1d000 fffff803`b74ef000 nt (pdb symbols) C:\ProgramData\Dbg\sym\ntkrnlmp.pdb\83DB42404EFD4AB6AFB6FA864B700CB31\ntkrnlmp.pdb
fffff803`b74ef000 fffff803`b756e000 hal (deferred)
fffff803`b7600000 fffff803`b7613000 kdcom (pdb symbols) C:\ProgramData\Dbg\sym\kdusb.pdb\619D7C9237D81A5C017DD6813BE76D7F1\kdusb.pdb
fffff803`ca600000 fffff803`ca637000 ndiswan (deferred)
..............
我们要研究的是 HAL
2.检查 HAL 的 symbol
0: kd> !lmi hal
Loaded Module Info: [hal]
Module: hal
Base Address: fffff803b74ef000
Image Name: hal.dll
Machine Type: 34404 (X64)
Time Stamp: 869c055b (This is a reproducible build file hash, not a true timestamp)
Size: 7f000
CheckSum: 7cfc7
Characteristics: 2022
Debug Data Dirs: Type Size VA Pointer
CODEVIEW 20, 49db0, 475b0 RSDS - GUID: {B19D905A-E342-5D59-DE73-FDE2055F8636}
Age: 1, Pdb: hal.pdb
POGO 9f0, 49dd0, 475d0 [Data not mapped]
REPRO 0, 0, 0 [Debug data not mapped]
Symbol Type: DEFERRED - No error - symbol load deferred
Load Report: no symbols loaded
结论是 HAL 的 symbol 没有正常加载
3. 加载 symbol
0: kd> ld hal
Symbols loaded for hal
4.再次检查
0: kd> !lmi hal
Loaded Module Info: [hal]
Module: hal
Base Address: fffff803b74ef000
Image Name: hal.dll
Machine Type: 34404 (X64)
Time Stamp: 869c055b (This is a reproducible build file hash, not a true timestamp)
Size: 7f000
CheckSum: 7cfc7
Characteristics: 2022
Debug Data Dirs: Type Size VA Pointer
CODEVIEW 20, 49db0, 475b0 RSDS - GUID: {B19D905A-E342-5D59-DE73-FDE2055F8636}
Age: 1, Pdb: hal.pdb
POGO 9f0, 49dd0, 475d0 [Data not mapped]
REPRO 0, 0, 0 [Debug data not mapped]
Image Type: MEMORY - Image read successfully from loaded memory.
Symbol Type: PDB - Symbols loaded successfully from image header.
C:\ProgramData\Dbg\sym\hal.pdb\B19D905AE3425D59DE73FDE2055F86361\hal.pdb
Load Report: public symbols , not source indexed
C:\ProgramData\Dbg\sym\hal.pdb\B19D905AE3425D59DE73FDE2055F86361\hal.pdb
模块的 Symbol 已经正确加载了,下面可以继续
5.列出 hal 中的相关函数
0: kd> x hal!HalEfi*
fffff803`b751ab04 hal!HalEfiUpdateCapsule ()
fffff803`b751a774 hal!HalEfiQueryVariableInfo ()
fffff803`b751a864 hal!HalEfiSetEnvironmentVariable ()
fffff803`b751a50c hal!HalEfiGetEnvironmentVariable ()
fffff803`b7550000 hal!HalEfiRuntimeServicesTable =
fffff803`b7544240 hal!HalEfiMissedMappingsCount =
fffff803`b7544244 hal!HalEfiSetVirtualAddressMapStatus =
fffff803`b7535b10 hal!HalEfiToNtStatusMappings =
fffff803`b751a5a0 hal!HalEfiGetTime ()
fffff803`b7550010 hal!HalEfiRuntimeServicesBlock =
fffff803`b751a6f8 hal!HalEfiQueryCapsuleCapabilities ()
fffff803`b751a904 hal!HalEfiSetTime ()
fffff803`b751a7e0 hal!HalEfiResetSystem ()
6.对hal!HalEfiSetEnvironmentVariable 和 hal!HalEfiGetEnvironmentVariable下端点(bp)。然后在被测机上运行取得 Variable 的 application, Wndbg 会停下来:
0: kd> bl
0 e Disable Clear fffff803`b751a864 0001 (0001) hal!HalEfiSetEnvironmentVariable
1 e Disable Clear fffff803`b751a50c 0001 (0001) hal!HalEfiGetEnvironmentVariable
0: kd> g
Breakpoint 1 hit //这里会自动停下来
hal!HalEfiGetEnvironmentVariable:
fffff803`b751a50c 48895c2408 mov qword ptr [rsp+8],rbx
6: kd> g
Breakpoint 1 hit //这里会自动停下来
hal!HalEfiGetEnvironmentVariable:
fffff803`b751a50c 48895c2408 mov qword ptr [rsp+8],rbx
6: kd> g
因此,GetFirmwareEnvironmentVariable 这样的 API 最终会 call 到 HAL 中的 HalEfiGetEnvironmentVariable 来实现。
============================================================
2018年6月2日
补充两张 IDA 分析 HAL.DLL(X64 Windows) 的图片: