二进制漏洞分析-5.华为安全监控漏洞(SMC MNTN OOB 访问)
二进制漏洞分析-10.华为TrustZone TEE_SERVICE_VOICE_REC漏洞
华为TrustZone TEE_EID漏洞
此通报包含有关以下漏洞的信息:
CVE-2021-40028 漏洞CVE-2021-40028 Encap_tlv_for_hash_zip 函数中的 OOB 访问
CVE-2021-40018 漏洞 get_sec_image_zip 函数中的 OOB 访问
CVE-2021-40021 漏洞 check_xxx_params函数中的参数指针信息泄漏
CVE-2021-40025 漏洞 堆指针 eid_malloc、eid_free、malloc_eid_buffer 和 free_eid_buffer 函数中的信息泄漏
get_sec_image_zip
¶函数中有一个 OOB 访问:get_sec_image_zip
int get_sec_image_zip(void *ibuf0_addr, unsigned int *ibuf0_20028, unsigned int *ibuf0_20038, void *obuf3_addr) {
// [...]
img_buf = g_img_buf;
// [...]
for (int x = ibuf0_20028[0]; x <= ibuf0_20028[1]; x++) {
for (int y = ibuf0_20028[2]; y <= ibuf0_20028[3]; y++) {
*(uint8_t *)(eid_buf.addr + ...) = *(uint8_t *)(img_buf + x * 0x1E0 + y);
}
}
// [...]
}
g_img_buf
存储在局部变量中,然后在许多循环中使用该变量,而无需检查它是否已被分配。如果确实未分配,则循环中的访问将是 OOB。img_buf
我们通过概念验证触发了此 bug,并获得了以下崩溃:
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1f00000028 (tid: 40) data abort:
[HM] [ERROR][2498]Bad memory access on address: 0x0, fault_code: 0x92000006
[HM]
[HM] Dump task states for tcb
[HM] ----------
[HM] name=[TEE_EID] 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=7253 prefer-ca=7253
[HM] Registers dump:
[HM] ----------
[HM] 32 bits userspace stack dump:
[HM] ----------
[HM] <get_sec_image_zip+0x200/0x360>
[HM] <?>+0x0/0x0
[HM] <proc_sec_zip_cmd>+0x34/0x48
[HM] <tee_task_entry>+0x398/0xcd4
[HM] Dump task states END
[HM]
[HM] [TRACE][1212]pid=48 exit_status=130
Encap_tlv_for_hash_zip
¶这是函数中的另一个 OOB 访问:Encap_tlv_for_hash_zip
int Encap_tlv_for_hash_zip(int hash, int hash_len, int zip, int zip_len, uint8_t *hash_tlv) {
// [...]
*(uint32_t *)(hash_tlv + 0) = 2;
SLog("%s: Tlv hash type = %u\n", "[Trace]", 2);
*(uint32_t *)(hash_tlv + 4) = hash_len;
SLog("%s: Tlv hash_len = %u\n", "[Trace]", hash_len);
if (memcpy_s(hash_tlv + 8, 0x1FFF8, hash, hash_len)) {
SLog("%s: memcpy_s err size is %d, len is %d\n", "[Error]", 0x1FFF8, hash_len);
return -1;
}
printHexWithTag("Sm3 hash", hash, hash_len); *(uint32_t *)(hash_tlv + hash_len + 8) = 1;
SLog("%s: Tlv zip type = %u\n", "[Trace]", 1);
*(uint32_t *)(hash_tlv + hash_len + 0xc) = zip_len;
SLog("%s: Tlv zip_len = %u\n", "[Trace]", zip_len);
if (memcpy_s(hash_tlv + hash_len + 0x10, 0x1FFF0 - hash_len, zip, zip_len)) {
SLog("%s: memcpy_s err size is %d, len is %d\n", "[Error]", 0x1FFF0 - hash_len, zip_len);
return -1;
}
return hash_len + 0x10 + zip_len;
}
的值上限为 0x1FFF8,因为第一个 。但对于介于 0x1FFF1 和 0x1FFF8 之间的值,可以观察到以下行为:hash_len
memcpy_s
hash_len
TLV 类型 (1) 在偏移处的写入可以是 OOBhash_len + 8
TLV 长度 () 在偏移处的写入可以是 OOBzip_len
hash_len + 0xC
at 偏移量的目标可以是 OOBmemcpy_s
hash_len + 0x10
()的大小可以下溢memcpy_s
0x1FFF0 - hash_len
该函数将检测负大小,因此无法利用此行为。TLV 类型和长度的 OOB 写入将发生越界,但它们不会使 trustlet/分配器崩溃。我们怀疑这是因为分配是 mmap 的,并且大小(包括元数据)是页面对齐的,导致分配后出现填充。memcpy_s
尽管如此,通过使用概念证明触发此错误,我们可以看到负大小 (-4),证明 TLV 类型和长度 OOB 写入访问:
[TEE_EID-1] [Trace]: ------ TA_InvokeCommandEntryPoint ------
[TEE_EID-1] [Trace]: Recived the commond, id is 9
[TEE_EID-1] [Trace]: Recived the unsec zip message
[TEE_EID-1] [Trace]: Into the proc_unsec_zip_cmd function
[TEE_EID-1] [Trace]: Malloc_eid_buffer, addr = 0x375f010, len = 131072
[TEE_EID-1] [Trace]: Tlv hash type = 2
[TEE_EID-1] [Trace]: Tlv hash_len = 131060
[TEE_EID-1] [Trace]: Tlv zip type = 1
[TEE_EID-1] [Trace]: Tlv zip_len = 4096
[TEE_EID-1] [Error]: memcpy_s err size is -4, len is 4096
[TEE_EID-1] [Error]: Encap_tlv_for_hash_zip failed!
[TEE_EID-1] [Trace]: Free_eid_buffer, addr = 0x375f010
check_xxx_params
¶检查每个命令的输入参数的函数中存在信息泄漏,包括函数(在 0x71A8 处):check_common_params
unsigned int check_common_params(int paramTypes, TEE_Param *params) {
// [...]
if (params[0].memref.size != 4 || !params[0].memref.buffer) {
SLog("%s: Invalid param[0], size is %u, buffer address is %p\n\n", "[Error]",
params[0].memref.size, params[0].memref.buffer);
return 0xFFFF0006;
}
// [...]
}
当参数缓冲区地址的大小不正确时,所有这些函数都会打印参数缓冲区地址。这将显示缓冲区始终映射在同一地址。下面是一个日志消息示例:
[TEE_EID-1] [Trace]: Recived the commond, id is 6
[TEE_EID-1] [Trace]: Recived the id info message
[TEE_EID-1] [Error]: Invalid param[3], size is 2056, buffer address is 0x70004000
eid_malloc
eid_free
malloc_eid_buffer
free_eid_buffer
¶分配和解除分配函数中存在信息泄漏,包括 、 、 和 :eid_malloc
eid_free
malloc_eid_buffer
free_eid_buffer
void *eid_malloc(int len, int hint) {
// [...]
addr = TEE_Malloc(len, hint);
SLog("%s: Eid_malloc, addr = %p, len = %u\n", "[Trace]", addr, len);
return addr;
}
void eid_free(void *addr) {
SLog("%s: Eid_free, addr = %p\n", "[Trace]", addr);
TEE_Free(addr);
}
int malloc_eid_buffer(eid_buffer_t *buf, int size) {
// [...]
buf->addr = TEE_Malloc(size, 0);
// [...]
buf->size = size;
SLog("%s: Malloc_eid_buffer, addr = %p, len = %u\n", "[Trace]", buf->addr, size);
return 0;
}
int free_eid_buffer(eid_buffer_t *buf) {
// [...]
buf->size = 0;
SLog("%s: Free_eid_buffer, addr = %p\n", "[Trace]", buf->addr);
return TEE_Free(buf->addr);
}
这些函数打印已分配/释放缓冲区的地址。在开发堆漏洞时,这可能是有用的信息。下面是一个日志消息示例:
[TEE_EID-1] [Trace]: Malloc_eid_buffer, addr = 0x375f010, len = 131072
...
[TEE_EID-1] [Trace]: Free_eid_buffer, addr = 0x375f010
我们验证了这些漏洞是否影响了以下设备:
麒麟990:P40 专业版 (ELS)
请注意,其他型号可能已受到影响。
名字 | 严厉 | CVE漏洞 | 补丁 |
---|---|---|---|
函数中的 OOB 访问Encap_tlv_for_hash_zip | 危急 | CVE-2021-40028 漏洞CVE-2021-40028 | 2022 年 1 月 |
函数中的 OOB 访问get_sec_image_zip | 高 | CVE-2021-40018 漏洞 | 2022 年 1 月 |
函数中的参数指针信息泄漏check_xxx_params | 中等 | CVE-2021-40021 漏洞 | 2022 年 1 月 |
堆指针 、 和 函数中的信息泄漏eid_malloc eid_free malloc_eid_buffer free_eid_buffer | 中等 | CVE-2021-40025 漏洞 | 2022 年 1 月 |
2021年11月05日,华为PSIRT收到漏洞报告。
2021年11月16日 - 华为PSIRT确认该漏洞报告。
2022年1月1日 - 华为PSIRT表示,这些问题已在2022年1月的更新中修复。
从 2022 年 11 月 30 日至 2023 年 7 月 19 日 - 我们定期交换有关公告发布的信息。
二进制漏洞(更新中)
其它课程
windows网络安全防火墙与虚拟网卡(更新完成)
windows文件过滤(更新完成)
USB过滤(更新完成)
游戏安全(更新中)
ios逆向
windbg
恶意软件开发(更新中)
还有很多免费教程(限学员)
更多详细内容添加作者微信