UefiCpuPkg\Universal\Acpi\S3Resume2Pei\S3Resume.c:
VOID
EFIAPI
S3ResumeBootOs (
IN ACPI_S3_CONTEXT *AcpiS3Context,
IN PEI_S3_RESUME_STATE *PeiS3ResumeState
)
{
...
DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
SwitchStack (
(SWITCH_STACK_ENTRY_POINT) (UINTN) Facs->XFirmwareWakingVector,
NULL,NULL,(VOID *)(UINTN)TempStackTop);
...
}
根据ACPI Spec,Facs->XFirmwareWakingVector是OS执行S3唤醒的函数:
UefiCpuPkg\Universal\Acpi\S3Resume2Pei\S3Resume.c:
VOID
EFIAPI
S3ResumeBootOs (
IN ACPI_S3_CONTEXT *AcpiS3Context,
IN PEI_S3_RESUME_STATE *PeiS3ResumeState
)
{
...
DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
SwitchStack (
(SWITCH_STACK_ENTRY_POINT) (UINTN) Facs->XFirmwareWakingVector,
NULL,NULL,(VOID *)(UINTN)TempStackTop);
...
}
根据ACPI Spec,Facs->XFirmwareWakingVector是OS执行S3唤醒的函数:
X Firmware Waking Vector
8
24
64-bit physical address of OSPM’s Waking Vector. Before transitioning the system into a global sleeping state, OSPM fills in this field and the OSPM Flags field to describe the waking vector. OSPM populates this field with the physical memory address of an OS-specific wake function. During POST, the platform firmware checks if the value of this field is non-zero and if so transfers control to OSPM by jumping to this address after creating the appropriate execution environment
表格摘自ACPI 6.2 "5.2.10 Firmware ACPI Control Structure (FACS)",FACS表用于firmware和OS传输数据,表格中提到的OSPM是指OS的ACPI.sys模块。如表格所述,Facs->XFirmwareWakingVector的值由Windows 负责填写。在Comet lake platform上Facs->XFirmwareWakingVector的物理地址值为:0x2000,所以,我决定在windows上查找具体设置的代码(既然OS能设置,驱动模块也能设置,这是挂Hook的绝佳选择)。
查看ACPI table当然少不了rw工具,不过很可惜,不知出于什么原因,在xp\win7\win10上Facs->XFirmwareWakingVector都不约而同的不可见(目前,我猜想:如ACPI spec如说,该值只有在进入S3 Sleep时才会被设置):
表格摘自ACPI 6.2 "5.2.10 Firmware ACPI Control Structure (FACS)",FACS表用于firmware和OS传输数据,表格中提到的OSPM是指OS的ACPI.sys模块。如表格所述,Facs->XFirmwareWakingVector的值由Windows 负责填写。在Comet lake platform上Facs->XFirmwareWakingVector的物理地址值为:0x2000,所以,我决定在windows上查找具体设置的代码(既然OS能设置,驱动模块也能设置,这是挂Hook的绝佳选择)。
查看ACPI table当然少不了rw工具,不过很可惜,不知出于什么原因,在xp\win7\win10上Facs->XFirmwareWakingVector都不约而同的不可见(目前,我猜想:如ACPI spec如说,该值只有在进入S3 Sleep时才会被设置):
虽然在RW中未见Facs->XFirmwareWakingVector的值,但也不能阻挡我搜索的步伐。查找ReactOS 3.15源码后,我选择用windbg搜索WakeVector相关的符号:
drivers\bus\acpi\acpica\hardware\hwsleep.c
ACPI_STATUS
AcpiSetFirmwareWakingVector64 (
UINT64 PhysicalAddress)
{
ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64);
/* Determine if the 64-bit vector actually exists */
if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1))
{
return_ACPI_STATUS (AE_NOT_EXIST);
}
/* Clear 32-bit vector, set the 64-bit X_ vector */
AcpiGbl_FACS->FirmwareWakingVector = 0;
AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress;
return_ACPI_STATUS (AE_OK);
}
(跟各位得瑟一把,由于工作缘故,我有部分Checked Build OS,所以我逆向的工作量会减轻不少),并最终在hal模块中找到对应的(变量)符号,然而该变量的值依然是空:
drivers\bus\acpi\acpica\hardware\hwsleep.c
ACPI_STATUS
AcpiSetFirmwareWakingVector64 (
UINT64 PhysicalAddress)
{
ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector64);
/* Determine if the 64-bit vector actually exists */
if ((AcpiGbl_FACS->Length <= 32) || (AcpiGbl_FACS->Version < 1))
{
return_ACPI_STATUS (AE_NOT_EXIST);
}
/* Clear 32-bit vector, set the 64-bit X_ vector */
AcpiGbl_FACS->FirmwareWakingVector = 0;
AcpiGbl_FACS->XFirmwareWakingVector = PhysicalAddress;
return_ACPI_STATUS (AE_OK);
}
(跟各位得瑟一把,由于工作缘故,我有部分Checked Build OS,所以我逆向的工作量会减轻不少),并最终在hal模块中找到对应的(变量)符号,然而该变量的值依然是空:
kd> x *!*WakeVector*
82a21c98 hal!HalpWakeVector = <no type information>
kd> dd hal!HalpWakeVector
82a21c98 00000000 00000000 00000000 00000000
很遗憾,Windows内核原理\Windows情景分析等经典书都不曾关注S3\S4的实现,而本文OS相关代码是在虚拟机上做的测试,虚拟机进入S3后系统被挂起,windbg也失去作用,因此,我对hal模块进行简单的逆向分析。
kd> x *!*WakeVector*
82a21c98 hal!HalpWakeVector = <no type information>
kd> dd hal!HalpWakeVector
82a21c98 00000000 00000000 00000000 00000000
很遗憾,Windows内核原理\Windows情景分析等经典书都不曾关注S3\S4的实现,而本文OS相关代码是在虚拟机上做的测试,虚拟机进入S3后系统被挂起,windbg也失去作用,因此,我对hal模块进行简单的逆向分析。
1.确定hal模块:
kd> lm m hal
Browse full module list
start end module name
82a04000 82a3d000 hal (pdb symbols) e:\symbols\win7x86sp1chk\halmacpi.pdb\0B89B9AEB8FB4822A25882B9A877C1031\halmacpi.pdb
kd> lmvm hal
Browse full module list
start end module name
82a04000 82a3d000 hal (pdb symbols) e:\symbols\win7x86sp1chk\halmacpi.pdb\0B89B9AEB8FB4822A25882B9A877C1031\halmacpi.pdb
Loaded symbol image file: halmacpi.dll
Image path: halmacpi.dll
Image name: halmacpi.dll
虚拟机上使用的hal模块对应c:\windows\system32\halmacpi.dll,用IDA加载该dll(附注,根据调试发现,下文将提到的hal函数在win7\win8.1\win10差别不大,因此对于这部分内容在各OS之间还是具有参考价值)。本文借助win10x64 TH2 Checked build的halmacpi.dll为参考,分析了win10 RS5 free build的halmacpi.dll流程(附注,微软提供的win10x64 TH2 Checked build无法正常安装使用,如果看官手头有该OS,需要用dism命令,从镜像中提取halmacpi.dll。此处要感谢我的同事lyly,告诉我dism提取镜像中模块的方法)
2.搜索对hal!HalpWakeVector的引用:
呵呵,很可惜,还真没找到。不过运气好,在"Strings window"中看到一串重要的字符串以及函数HalpAcpiGetFacsMapping对它的引用:
kd> lm m hal
Browse full module list
start end module name
82a04000 82a3d000 hal (pdb symbols) e:\symbols\win7x86sp1chk\halmacpi.pdb\0B89B9AEB8FB4822A25882B9A877C1031\halmacpi.pdb
kd> lmvm hal
Browse full module list
start end module name
82a04000 82a3d000 hal (pdb symbols) e:\symbols\win7x86sp1chk\halmacpi.pdb\0B89B9AEB8FB4822A25882B9A877C1031\halmacpi.pdb
Loaded symbol image file: halmacpi.dll
Image path: halmacpi.dll
Image name: halmacpi.dll
虚拟机上使用的hal模块对应c:\windows\system32\halmacpi.dll,用IDA加载该dll(附注,根据调试发现,下文将提到的hal函数在win7\win8.1\win10差别不大,因此对于这部分内容在各OS之间还是具有参考价值)。本文借助win10x64 TH2 Checked build的halmacpi.dll为参考,分析了win10 RS5 free build的halmacpi.dll流程(附注,微软提供的win10x64 TH2 Checked build无法正常安装使用,如果看官手头有该OS,需要用dism命令,从镜像中提取halmacpi.dll。此处要感谢我的同事lyly,告诉我dism提取镜像中模块的方法)
2.搜索对hal!HalpWakeVector的引用:
呵呵,很可惜,还真没找到。不过运气好,在"Strings window"中看到一串重要的字符串以及函数HalpAcpiGetFacsMapping对它的引用:
虚拟机上使用的hal模块对应c:\windows\system32\halmacpi.dll,用IDA加载该dll(附注,根据调试发现,下文将提到的hal函数在win7\win8.1\win10差别不大,因此对于这部分内容在各OS之间还是具有参考价值)。本文借助win10x64 TH2 Checked build的halmacpi.dll为参考,分析了win10 RS5 free build的halmacpi.dll流程(附注,微软提供的win10x64 TH2 Checked build无法正常安装使用,如果看官手头有该OS,需要用dism命令,从镜像中提取halmacpi.dll。此处要感谢我的同事lyly,告诉我dism提取镜像中模块的方法)
2.搜索对hal!HalpWakeVector的引用:
呵呵,很可惜,还真没找到。不过运气好,在"Strings window"中看到一串重要的字符串以及函数HalpAcpiGetFacsMapping对它的引用:
01C003D8C0 aHalpacpigetfac db '**** HalpAcpiGetFacsMapping: No FADT found.',0Ah,0
.text:00000001C003D8C0 ; DATA XREF: HalpAcpiGetFacsMapping+54↑o
01C003D8C0 aHalpacpigetfac db '**** HalpAcpiGetFacsMapping: No FADT found.',0Ah,0
.text:00000001C003D8C0 ; DATA XREF: HalpAcpiGetFacsMapping+54↑o
2.1.在HalpAcpiGetFacsMapping内部,有两段代码片:
01C0001E39 mov edx, 'PCAF'
.text:00000001C0001E3E call HalpAcpiGetTableWork
.text:00000001C0001E43 test rax, rax
.text:00000001C0001E46 jnz short loc_1C0001E83 ; Physical memory address of the FACS
这段代码是根据表的签名来查找Acpi table,Long字符数组'PCAF'其实就是FACP表的签名。HalpAcpiGetTableWork将返回FACP表的物理地址。然后再从FACP->FIRMWARE_CTRL和签名"SCAF"获得Facs地址:
01C0001E39 mov edx, 'PCAF'
.text:00000001C0001E3E call HalpAcpiGetTableWork
.text:00000001C0001E43 test rax, rax
.text:00000001C0001E46 jnz short loc_1C0001E83 ; Physical memory address of the FACS
这段代码是根据表的签名来查找Acpi table,Long字符数组'PCAF'其实就是FACP表的签名。HalpAcpiGetTableWork将返回FACP表的物理地址。然后再从FACP->FIRMWARE_CTRL和签名"SCAF"获得Facs地址:
01C0001E83 loc_1C0001E83: ; CODE XREF: HalpAcpiGetFacsMapping+52↑j
.text:00000001C0001E83 mov edx, [rax+FACP_20.FIRMWARE_CTRL] ; Facp->FIRMWARE_CTRL
.text:00000001C0001E86 mov r9d, 'SCAF' ; Physical memory address of the FACS
...
.text:00000001C0001EB2 call HalpAcpiCheckAndMapTable
.text:00000001C0001EB7 mov cs:HalpAcpiFacsMapping, rax ; cs:HalpAcpiFacsMapping: hold facs phyical address
...
.text:00000001C0001ED3 mov rax, cs:HalpAcpiFacsMapping ;返回Facs表di'zhi
FIRMWARE_CTRL
4
36
Physical memory address of the FACS, where OSPM and Firmware exchange control information. See Section 5.2.6, “Root System Description Table,” for a description of the FACS. If the X_FIRMWARE_CTRL field contains a non zero value which can be used by the OSPM, then this field must be ignored by the OSPM. If the HARDWARE_REDUCED_ACPI flag is set, and both this field and the X_FIRMWARE_CTRL field are zero, there is no FACS available.
01C0001E83 loc_1C0001E83: ; CODE XREF: HalpAcpiGetFacsMapping+52↑j
.text:00000001C0001E83 mov edx, [rax+FACP_20.FIRMWARE_CTRL] ; Facp->FIRMWARE_CTRL
.text:00000001C0001E86 mov r9d, 'SCAF' ; Physical memory address of the FACS
...
.text:00000001C0001EB2 call HalpAcpiCheckAndMapTable
.text:00000001C0001EB7 mov cs:HalpAcpiFacsMapping, rax ; cs:HalpAcpiFacsMapping: hold facs phyical address
...
.text:00000001C0001ED3 mov rax, cs:HalpAcpiFacsMapping ;返回Facs表di'zhi
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-4-14 23:50
被hyjxiaobia编辑
,原因: 修改部分内容