二进制漏洞分析-4.华为安全监控漏洞(SMC SE 工厂检查 OOB 访问)
参数 OOB 访问FI_onExec
¶
在函数(如前所述)中,即使 TEE 参数类型正确,也不会检查输入缓冲区的大小。因此,如果缓冲区小于预期,则可以进行 OOB 访问。FI_onExec
params[1]
int FI_onExec(
unsigned int commandID,
void *buffer1,
unsigned int length1,
void *buffer2,
unsigned int length2,
uint32_t paramTypes) {
// ...
switch (commandID) {
case 0x80013:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80014:
// ...
image_info.width = ((uint32_t *)buffer1)[0x380];
// ...
case 0x80015:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80016u:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
}
// ...
例如,在代码处理命令0x80013中,将值从偏移0x4b004提取到此缓冲区中,如果缓冲区小于此偏移量,则会导致崩溃。可以使用概念验证代码来触发此 bug:
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1d00000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x7004e004, fault_code: 0x92000007
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[TEE_SERVICE_FAC] tid=40 is-idle=0 is-curr=0
[HM] state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM] aff[0]=ff
[HM] flags=1000 smc-switch=0 ca=7022 prefer-ca=7022
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <_Z9FI_onExecjPvjS_j+0x420/0x9e4>
[HM] <_Z9FI_onExecjPvjS_j>+0x4e4/0x9e4
[HM] <TA_InvokeCommandEntryPoint>+0x4a0/0x8e8
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
空指针取消引用MsgController::_sendMsg
¶
要与 trustlet 异步交互,CA 可以注册一个代理,该代理可以等待事件并发送响应。可以设置此通信通道:
在 NWd 端使用 ioctl
TC_NS_CLIENT_IOCTL_REGISTER_AGENT
;在 SWd 端使用命令 (#ID 0x17)。
HandlePrepareAgentCommand
如下图所示,最终从库中调用函数。HandlePrepareAgentCommand
FI_prepare4Agent
lib_faceidalgo
uint32_t HandlePrepareAgentCommand(uint32_t paramTypes, TEE_Param params[4]) {
// [...]
ret = FR_TA_PrepareAgent();
// [...]
}
uint32_t FR_TA_PrepareAgent() {
// [...]
g_algo_api->FI_prepare4Agent()
// [...]
}
FI_prepare4Agent
调用。然后,此函数调用该函数,该函数将启动一个线程循环,该循环可以根据对象中设置的消息代码接收和发送响应。FaceIdCore::prepare4Agent
MsgController::threadLoop
this->msgCode
MsgController
uint32_t FI_prepare4Agent() {
// [...]
FaceIdCore::prepare4Agent(g_faceid_core);
// [...]
}
int FI_onExec(
unsigned int commandID,
void *buffer1,
unsigned int length1,
void *buffer2,
unsigned int length2,
uint32_t paramTypes) {
// ...
switch (commandID) {
case 0x80013:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80014:
// ...
image_info.width = ((uint32_t *)buffer1)[0x380];
// ...
case 0x80015:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80016u:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
}
// ...
1
int FI_onExec(
unsigned int commandID,
void *buffer1,
unsigned int length1,
void *buffer2,
unsigned int length2,
uint32_t paramTypes) {
// ...
switch (commandID) {
case 0x80013:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80014:
// ...
image_info.width = ((uint32_t *)buffer1)[0x380];
// ...
case 0x80015:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80016u:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
}
// ...
3
在 NWd 端的初始化过程中,将提供通过共享内存分配的代理缓冲区。在调用 期间,将检索此缓冲区并将其映射到 SWd 中,该缓冲区使用函数 进行设置。MsgController::agentLock
this->agentBuffer
TEE_EXT_GetAgentBuffer
int FI_onExec(
unsigned int commandID,
void *buffer1,
unsigned int length1,
void *buffer2,
unsigned int length2,
uint32_t paramTypes) {
// ...
switch (commandID) {
case 0x80013:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80014:
// ...
image_info.width = ((uint32_t *)buffer1)[0x380];
// ...
case 0x80015:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80016u:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
}
// ...
5
相反,可以使用命令 (ID #0x11) 从对象中删除代理缓冲区。此处理程序将调用库中的函数,该函数最终调用 .MsgController
HandleDynamicUnloadCommand
FI_dynamicFini
lib_faceidalgo
MsgController::deInit
int FI_onExec(
unsigned int commandID,
void *buffer1,
unsigned int length1,
void *buffer2,
unsigned int length2,
uint32_t paramTypes) {
// ...
switch (commandID) {
case 0x80013:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80014:
// ...
image_info.width = ((uint32_t *)buffer1)[0x380];
// ...
case 0x80015:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80016u:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
}
// ...
7
int FI_onExec(
unsigned int commandID,
void *buffer1,
unsigned int length1,
void *buffer2,
unsigned int length2,
uint32_t paramTypes) {
// ...
switch (commandID) {
case 0x80013:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80014:
// ...
image_info.width = ((uint32_t *)buffer1)[0x380];
// ...
case 0x80015:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
case 0x80016u:
// ...
image_info.width = ((uint32_t *)buffer1)[0x12C01];
// ...
}
// ...
9
1
3
5
但是,可以设置为 0,然后让 trustlet 使用它而不进行任何检查。例如,我们可以拼出命令的执行流程 (#ID 0x10),并看到它即使在被删除后也使用代理缓冲区。this->agentBuffer
HandleDynamicInitCommand
HandleDynamicInitCommand
首先调用库中的函数,该函数使用 设置为 0x12 的函数向消息控制器发送消息。FI_dynamicInit
lib_faceidalgo
MsgController::send
msgCode
7
9
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1d00000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x7004e004, fault_code: 0x92000007
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[TEE_SERVICE_FAC] tid=40 is-idle=0 is-curr=0
[HM] state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM] aff[0]=ff
[HM] flags=1000 smc-switch=0 ca=7022 prefer-ca=7022
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <_Z9FI_onExecjPvjS_j+0x420/0x9e4>
[HM] <_Z9FI_onExecjPvjS_j>+0x4e4/0x9e4
[HM] <TA_InvokeCommandEntryPoint>+0x4a0/0x8e8
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
1
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1d00000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x7004e004, fault_code: 0x92000007
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[TEE_SERVICE_FAC] tid=40 is-idle=0 is-curr=0
[HM] state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM] aff[0]=ff
[HM] flags=1000 smc-switch=0 ca=7022 prefer-ca=7022
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <_Z9FI_onExecjPvjS_j+0x420/0x9e4>
[HM] <_Z9FI_onExecjPvjS_j>+0x4e4/0x9e4
[HM] <TA_InvokeCommandEntryPoint>+0x4a0/0x8e8
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
3
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1d00000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x7004e004, fault_code: 0x92000007
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[TEE_SERVICE_FAC] tid=40 is-idle=0 is-curr=0
[HM] state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM] aff[0]=ff
[HM] flags=1000 smc-switch=0 ca=7022 prefer-ca=7022
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <_Z9FI_onExecjPvjS_j+0x420/0x9e4>
[HM] <_Z9FI_onExecjPvjS_j>+0x4e4/0x9e4
[HM] <TA_InvokeCommandEntryPoint>+0x4a0/0x8e8
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
5
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1d00000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x7004e004, fault_code: 0x92000007
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[TEE_SERVICE_FAC] tid=40 is-idle=0 is-curr=0
[HM] state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM] aff[0]=ff
[HM] flags=1000 smc-switch=0 ca=7022 prefer-ca=7022
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <_Z9FI_onExecjPvjS_j+0x420/0x9e4>
[HM] <_Z9FI_onExecjPvjS_j>+0x4e4/0x9e4
[HM] <TA_InvokeCommandEntryPoint>+0x4a0/0x8e8
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
7
然后接收此消息,并且由于是0x12它将由在默认情况下调用的函数处理。MsgController::threadLoop
msgCode
MsgController::_sendMsg
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1d00000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x7004e004, fault_code: 0x92000007
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[TEE_SERVICE_FAC] tid=40 is-idle=0 is-curr=0
[HM] state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM] aff[0]=ff
[HM] flags=1000 smc-switch=0 ca=7022 prefer-ca=7022
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <_Z9FI_onExecjPvjS_j+0x420/0x9e4>
[HM] <_Z9FI_onExecjPvjS_j>+0x4e4/0x9e4
[HM] <TA_InvokeCommandEntryPoint>+0x4a0/0x8e8
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
9
但是,此函数将取消引用,该函数在调用之前设置为 0,并将导致 null 指针取消引用。this->agentBuffer
HandleDynamicInitCommand
1
此 bug 可以使用概念验证代码触发,并导致崩溃,因为地址为 0 写入:
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1e00000036 (tid: 54) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x0, fault_code: 0x92000046
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[TEE_SERVICE_FAC] tid=54 is-idle=0 is-curr=0
[HM] state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM] aff[0]=ff
[HM] flags=1000 smc-switch=0 ca=6744 prefer-ca=6744
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <_ZN13MsgController8_sendMsgEv+0x14/0x48>
[HM] <_ZN13MsgController10threadLoopEv>+0x1f0/0x248
[HM] <_ZN13MsgController10threadLoopEv>+0x1f0/0x248
[HM] <_ZN10FaceIdCore13prepare4AgentEv>+0x2c/0xa0
[HM] <_Z16FI_prepare4Agentv>+0x34/0x98
[HM] <TA_InvokeCommandEntryPoint>+0x738/0x8e8
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
Trustlet 函数中的物理地址泄漏FR_TA_CoAuthSignImg
¶
函数中存在静态物理地址泄漏。FR_TA_CoAuthSignImg
5
Trustlet 函数中的参数指针泄漏FR_GetHwAuthToken
¶
函数中存在 TEE 参数指针泄漏。FR_GetHwAuthToken
7
9
Trustlet 函数中的参数指针泄漏FR_ActiveUserSet
¶
函数中存在 TEE Param 指针泄漏。FR_ActiveUserSet
uint32_t HandlePrepareAgentCommand(uint32_t paramTypes, TEE_Param params[4]) {
// [...]
ret = FR_TA_PrepareAgent();
// [...]
}
1
uint32_t HandlePrepareAgentCommand(uint32_t paramTypes, TEE_Param params[4]) {
// [...]
ret = FR_TA_PrepareAgent();
// [...]
}
3
Trustlet 函数中的 ION 虚拟地址泄漏FR_HashCheck
¶
函数中映射 ION 缓冲区的虚拟地址泄漏。FR_HashCheck
uint32_t HandlePrepareAgentCommand(uint32_t paramTypes, TEE_Param params[4]) {
// [...]
ret = FR_TA_PrepareAgent();
// [...]
}
5
uint32_t HandlePrepareAgentCommand(uint32_t paramTypes, TEE_Param params[4]) {
// [...]
ret = FR_TA_PrepareAgent();
// [...]
}
7
uint32_t HandlePrepareAgentCommand(uint32_t paramTypes, TEE_Param params[4]) {
// [...]
ret = FR_TA_PrepareAgent();
// [...]
}
9
Trustlet 函数中的参数指针泄漏FR_GetResultAuthToken
¶
函数中存在指针泄漏。TEE_Param
FR_GetResultAuthToken
1
3
Trustlet 函数中的堆指针泄漏FR_LoadDataBase
¶
函数中存在堆指针泄漏。FR_LoadDataBase
5
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...