二进制漏洞分析-16.华为TrustZone TEE_SERVICE_FACE_REC漏洞(四)
2023-12-4 09:45:56 Author: 安全狗的自我修养(查看原文) 阅读量:8 收藏

 

二进制漏洞分析-5.华为安全监控漏洞(SMC MNTN OOB 访问)

二进制漏洞分析-10.华为TrustZone TEE_SERVICE_VOICE_REC漏洞

ION 虚拟地址库功能中的泄漏STFaceidAlgo::loadCpuModel

函数中映射 ION 缓冲区的虚拟地址存在泄漏。STFaceidAlgo::loadCpuModel

int HiAiManager::loadModelFromBuffers(HiAiManager *this, FIIonBuf *ionBuffers, int ionCount) {
// ...
HiAiManager::cpuModelCheck(this, name, this->npuLoadMem.vaddr + offset, size);
// ...
}
int HiAiManager::cpuModelCheck(HiAiManager *this, char *name, void *addr, int size) {
// ...
this->cpu_manager->vtable + 2))(
this->cpu_manager,
addr,
size,
this->cpuModelMem.vaddr,
this->cpuModelMem.size);
// ...
}
int STFaceidAlgo::loadCpuModel(STFaceidAlgo *this, void *model, int size, void *modelMem, int modelMemSize) {
// ...
tee_print(
0,
"%s %d:[%s][%s]%s model:%p, size:%d, modelMem:%p, modelMemSize:%d\n",
"[info]",
0x88,
FILogTag,
"STAlgo",
"loadCpuModel",
model,
size,
modelMem,
modelMemSize);
// ...
}

磁带库功能中的 ION 虚拟地址和堆指针泄漏hw_face_quality_estimation

映射 ION 缓冲区的虚拟地址和函数中的堆指针存在泄漏。hw_face_quality_estimation

int HwQualityAlgo::init(HwQualityAlgo *this) {
// ...
data = MemoryManager::alloc(this->field_20, size, HwQualityAlgo::NAME);
img_quality_setMemory(this->handle, data, size);
// ...
}
unsigned int img_quality_setMemory(Img_Quality_t *handle, const void *memory, int size) {
// ...
handle->memory = memory;
// ...
}
int img_quality_estimation_register(Img_Quality_t *handle, ImageBuffer *image, int *a3, int a4) {
// ...
v13[3] = image->addr;
// ...
hw_face_quality_estimation(
v13,
&v9,
&handle->field_48,
handle->memory + handle->field_4,
a4);
// ...
}
int hw_face_quality_estimation(void *a1, void *a2, void *a3, uint8_t *a4, void *a5) {
// ...
tee_print(
0,
"%s %d:[%s][%s]%d,%d,%d,%d, %p, %p, %d\n",
"[info]",
0xDB,
(const char *)&FILogTag,
"FaceIdDefaultTag",
a2[2],
*a2,
a2[3],
a2[1],
a4,
a1[3],
*a1);
}
// ...
}

库函数中的堆指针泄漏buffered_free

函数中存在堆指针泄漏。buffered_free

int buffered_free(void *ptr) {
// ...
g_secOsCb(
0,
"%s(%d):Fatal: release %p which not belong to pool checksum does not match\n",
"buffered_free",
0x319,
ptr);
// ...
g_secOsCb(
0,
"%s(%d):Fatal: release memory %p not belong to largepool%d\n",
"release",
0xD1,
ptr,
largepool);
// ...
g_secOsCb(
0,
"%s(%d):Fatal: release %p which not belong to pool %d, checksum match\n",
"buffered_free",
0x328,
ptr,
pool);
// ...
}

磁带库功能中的ION虚拟内存地址泄漏st_tee_initialize

函数中映射 ION 缓冲区的虚拟地址泄漏。st_tee_initialize

int HiAiManager::loadModelFromBuffers(HiAiManager *this, FIIonBuf *ionBuffers, int ionCount) {
// ...
HiAiManager::cpuModelCheck(this, name, this->npuLoadMem.vaddr + offset, size);
// ...
}
int HiAiManager::cpuModelCheck(HiAiManager *this, char *name, void *addr, int size) {
// ...
this->cpu_manager->vtable + 2))(
this->cpu_manager,
addr,
size,
this->cpuModelMem.vaddr,
this->cpuModelMem.size);
// ...
}
unsigned int STHiAiCpuManager::loadModel(
STHiAiCpuManager *this,
void *model,
int size,
void *modelMem,
int modelMemSize) {
// ...
STFaceidAlgo::loadCpuModel(st_faceid_algo, model, size, modelMem, modelMemSize);
// ...
}
int STFaceidAlgo::loadCpuModel(STFaceidAlgo *this, void *model, int size, void *modelMem, int modelMemSize) {
// ...
st_tee_initialize(this->handle, model);
// ...
}
unsigned int st_tee_initialize(handle_t *handle, void *model) {
// ...
g_secOsCb(0, "%s(%d):handle: %p, modelptr: %p\n", "st_tee_initialize", 0x501, handle, model);
// ...
}

库函数中的堆指针泄漏st_tee_detect

函数中存在堆指针泄漏。st_tee_detect

unsigned int STFaceidAlgo::faceDetect(STFaceidAlgo *this, void *a2, int a3) {
// ...
st_tee_detect(this->handle, a3, ptr, buf1, buf2);
// ...
}
unsigned int st_tee_detect(void *handle, int a2, void *a3, int a4, void *a5) {
// ...
g_secOsCb(3, "%s(%d):invalid handle %p\n", "st_tee_detect", 0x6FD, handle);
// ...

库函数中的堆指针泄漏st_tee_extract

函数中存在堆指针泄漏。st_tee_extract

int STFaceidAlgo::extract(STFaceidAlgo *this, void *a2, int a3, int a4, int a5) {
// ...
st_tee_extract(this->handle, a3, a2, 0, buf1, buf2, a4, a5);
// ...
}
int st_tee_extract(void *handle, int a2, void *a3, int a4, void* a5, void *a6, uint32_t *a7, uint32_t *a8) {
// ...
g_secOsCb(3, "%s(%d):invalid handle %p\n", "st_tee_extract", 0xC55, handle);
// ...
}

库功能中的堆栈指针和 ION 虚拟地址泄漏st_tee_create_handle

堆栈地址和映射 ION 缓冲区的虚拟地址存在泄漏。st_tee_create_handle

int HiAiManager::cpuModelCheck(HiAiManager *this, char *name, void *addr, int size) {
// ...
this->cpu_manager->vtable + 2))(
this->cpu_manager,
addr,
size,
this->cpuModelMem.vaddr,
this->cpuModelMem.size);
// ...
}
unsigned int STHiAiCpuManager::loadModel(
STHiAiCpuManager *this,
void *model,
int size,
void *modelMem,
int modelMemSize) {
// ...
STFaceidAlgo::loadCpuModel(st_faceid_algo, model, size, modelMem, modelMemSize);
// ...
}
int STFaceidAlgo::loadCpuModel(STFaceidAlgo *this, void *model, int size, void *modelMem, int modelMemSize) {
// ...
STFaceidAlgo::init(this, modelMem, modelMemSize);
// ...
}
int STFaceidAlgo::init(STFaceidAlgo *this, void *modelMem, int modelMemSize) {
// ...
memory_config[0] = modelMem;
memory_config[1] = modelMemSize;
// ...
st_tee_create_handle(&this->handle, memory_config);
// ...
}
unsigned int st_tee_create_handle(handle_t **handle_p, const void **memory_config) {
// ...
g_secOsCb(0, "%s(%d):memory_config: %p\n", "st_tee_create_handle", 0x455, memory_config);
g_secOsCb(
0,
"%s(%d):memory_config->ptr_pool_mem: %p\n",
"st_tee_create_handle",
0x456,
*memory_config);
// ...
}

库函数中的堆指针泄漏gray16to8_hist

函数中存在堆指针泄漏。gray16to8_hist

char *gray16to8_hist(uint16_t *a1, uint8_t *a2, int a3, int a4) {
// ...
hist = buffered_malloc(0x40000);
g_secOsCb(0, "%s(%d):after buffered_malloc hist: %p\n", "gray16to8_hist", 0x5B4, hist);
// ...
hist_ptr = hist;
// ...
g_secOsCb(
0,
"%s(%d):min_val %d, max_val: %d, hist: %p, hist_ptr:%p\n",
"gray16to8_hist",
0x5D8,
min_val,
max_val,
hist,
hist_ptr);
// ...
}

库功能中的虚拟地址泄漏HIAI_TensorBuffer_createFromTensorDesc

函数中存在虚拟地址泄漏。HIAI_TensorBuffer_createFromTensorDesc

uint32_t *HIAI_TensorBuffer_createFromTensorDesc(uint32_t *a1) {
// ...
data = _SRE_MemAllocShared(0, size);
tee_print(0, "%s %d:%s:data is 0x%x, size %d\n", "[info]", 0xCC, "HIAIModelManager.cpp", data, size);
// ...
}

磁带库功能中的ION虚拟内存地址泄漏HIAI_ModelManager_loadFromModelBuffers

函数中映射 ION 缓冲区的虚拟地址泄漏。HIAI_ModelManager_loadFromModelBuffers

int HIAI_ModelManager_loadFromModelBuffers(HIAI_ModelManager *this, ModelBuffer **buffers, int nBuffers) {
// ...
for (int i = 0; i < model_list.nBuffers; i++) {
tee_print(
0,
"%s %d:%s:addr[%d] = 0x%x.\n",
"[debug]",
0x1A2,
"HIAIModelManager.cpp",
index,
model_list.buffers[index].addr);
// ...
}
// ...
}

堆栈和堆指针泄漏FR_AloEnroll

命令 (ID #0x3) 中调用的函数打印的日志字符串中存在双堆指针泄漏和堆栈指针泄漏。指向堆栈变量的指针被传递给 ,从而被传递给 。FR_AloEnrollEndEnrollenrolled_face_id_pFR_TA_EndEnrollFR_AloEnrollEndEnroll

int EndEnroll(uint32_t paramTypes, TEE_Param params[4]) {
// ...
enrolled_face_id = 0;
params[3].value.b = FR_TA_EndEnroll(
ibuf0_addr,
params->memref.size,
ibuf1_addr,
params[1].memref.size,
&enrolled_face_id);
params[2].value.b = enrolled_face_id;
}
int FR_TA_EndEnroll(
template_t *templates_array,
uint32_t templates_len,
void *authtoken,
uint32_t authtoken_len,
int enrolled_face_id_p)
{
// ...
first_feature_len = 0;
first_feature = GetPlainDataWhenEnroll(
templates_array,
templates_len,
&templates_offset,
template_cpy,
&first_feature_len);
middle_feature_len = 0;
middle_feature = GetPlainDataWhenEnroll(
templates_array,
templates_len,
&templates_offset,
template_cpy,
&middle_feature_len);
FR_AloEnroll(
first_feature,
first_feature_len,
enrolled_face_id_p,
middle_feature,
middle_feature_len);
// ...
}
int FR_AloEnroll(
void *first_feature,
uint32_t first_feature_len,
int *enrolled_face_id_p,
void *middle_feature,
uint32_t middle_feature_len)
{
// ...
tee_print(
0,
"%s %10.10s: [db_v3] face template add:param is invalid.template:0x%x,templen:%u,faceid:0x%x,image:0x%x,imagelen:%u \n",
"[error]",
"FR_AloEnroll",
first_feature, /* heap-allocated buffer */
first_feature_len,
enrolled_face_id_p, /* stack variable pointer */
middle_feature, /* heap-allocated buffer */
middle_feature_len);
// ...
}

堆分配了缓冲区,并在 中分配。first_featuremiddle_featureGetPlainDataWhenEnroll

void *GetPlainDataWhenEnroll(
template_t *tmpl,
unsigned int tmpl_len,
int *tmpl_offset_p,
const void *iv_buf,
uint32_t *feature_len)
{
// ...
encrypted_len = *(uint32_t *)((char *)tmpl + *tmpl_offset_p);
// ...
decrypted_buf = TEE_Malloc(encrypted_len, 0);
// ...
return decrypted_buf;
}

这些指针最终将出现在 NWd 可访问的日志中,然后可以使用 等实用程序读取这些日志。logcat

签入错误GetPlainDataWhenEnroll

在函数中,如果模板偏移量检查失败,则将记录错误,但无论如何该函数的执行仍将继续,并且下次调用 时可能会记录越界值。GetPlainDataWhenEnrolltee_print

void *GetPlainDataWhenEnroll(
template_t *tmpl,
unsigned int tmpl_len,
int *tmpl_offset_p,
const void *iv_buf,
uint32_t *feature_len)
{
// ...
if (*tmpl_offset_p + 4 > tmpl_len)
tee_print(0, "%s %10.10s: Template length is invalid : %u \n", "[error]", "GetPlainDataWhenEnroll", tmpl_len);
encrypted_len = *(int *)((char *)&tmpl + *tmpl_offset_p);
tee_print(
0,
"%s %10.10s: Data length is %u \n",
"[info]",
"GetPlainDataWhenEnroll",
encrypted_len);
// ...
}

受影响的设备

我们验证了这些漏洞是否影响了以下设备:

  • 麒麟990:P40 专业版 (ELS)

请注意,其他型号可能已受到影响。

补丁

名字严厉CVE漏洞补丁
未经验证的参数类型FI_onExec危急CVE-2022-48479 漏洞CVE-2022-484792023 年 5 月
OOB 写入HiAiManager::loadModelFromBuffers危急CVE-2022-48478 漏洞-2022-484782023 年 5 月
整数溢出FR_TA_CoAuthSignImgCVE-2022-48480 漏洞CVE-2022-484802023 年 5 月
参数 OOB 访问FI_onExec不适用固定
空指针取消引用MsgController::_sendMsg不适用固定
Trustlet 函数中的物理地址泄漏FR_TA_CoAuthSignImg不适用固定
Trustlet 函数中的参数指针泄漏FR_GetHwAuthToken不适用固定
Trustlet 函数中的参数指针泄漏FR_ActiveUserSet不适用固定
Trustlet 函数中的 ION 虚拟地址泄漏FR_HashCheck不适用固定
Trustlet 函数中的参数指针泄漏FR_GetResultAuthToken不适用固定
Trustlet 函数中的堆指针泄漏FR_LoadDataBase不适用固定
Trustlet 函数中的堆指针泄漏FR_FaceFeatureAdd不适用固定
Trustlet 函数中的参数指针泄漏FR_SetFidoParam不适用固定
Trustlet 函数中的堆栈指针泄漏FidoWrapUvt不适用固定
Trustlet 函数中的堆指针泄漏FR_UnwrapFeatureData不适用固定
库函数中的堆指针泄漏AlgoManager::createAlgo不适用固定
磁带库功能中的ION虚拟内存地址泄漏HiAiManager::loadModelFromBuffers不适用固定
磁带库功能中的 ION 物理内存泄漏HiAiManager::runModelInMainThread不适用固定
磁带库功能中的ION虚拟内存地址泄漏HiAiManager::loadModelFromBuffers不适用固定
磁带库功能中的ION虚拟内存地址泄漏MemoryManager::alloc不适用固定
磁带库功能中的ION虚拟内存地址泄漏MemoryManager::free不适用固定
库函数中的指针泄漏MsgController::agentLock不适用固定
库函数中的堆指针泄漏CImageBufferAllocator::endAllocatation不适用固定
库函数中的堆指针泄漏CImageBufferAllocator::endAllocatation不适用固定
库函数中的堆指针泄漏CImageBufferAllocator::beginAllocatation不适用固定
库函数中的指针泄漏CImageBuffer::delStride不适用固定
库函数中的堆指针泄漏CImageBuffer::fillImage不适用固定
库函数中的指针泄漏CImageBuffer::attachBuffer不适用固定
库函数中的指针泄漏ImageSourceBase::clear不适用固定
库函数中的堆指针泄漏PipelineBuilder::createPipeline不适用固定
ION 虚拟地址库功能中的泄漏STFaceidAlgo::loadCpuModel不适用固定
磁带库功能中的 ION 虚拟地址和堆指针泄漏hw_face_quality_estimation不适用固定
库函数中的堆指针泄漏buffered_free不适用固定
磁带库功能中的ION虚拟内存地址泄漏st_tee_initialize不适用固定
库函数中的堆指针泄漏st_tee_detect不适用固定
库函数中的堆指针泄漏st_tee_extract不适用固定
库功能中的堆栈指针和 ION 虚拟地址泄漏st_tee_create_handle不适用固定
库函数中的堆指针泄漏gray16to8_hist不适用固定
库功能中的虚拟地址泄漏HIAI_TensorBuffer_createFromTensorDesc不适用固定
磁带库功能中的ION虚拟内存地址泄漏HIAI_ModelManager_loadFromModelBuffers不适用固定
堆栈和堆指针泄漏FR_AloEnroll不适用固定
签入错误GetPlainDataWhenEnroll不适用固定

时间线

  • 2021年12月21日,华为PSIRT收到第一份漏洞报告。

  • 2022年1月12日 - 华为PSIRT确认首份漏洞报告。

  • 2022年1月21日,华为PSIRT收到第二份漏洞报告。

  • 2022年2月24日 - 华为PSIRT确认发布第二份漏洞报告。

  • 2023年5月1日 - 华为PSIRT表示,这些问题已在2023年5月的更新中修复。

  • 从 2022 年 11 月 30 日至 2023 年 7 月 19 日 - 我们定期交换有关公告发布的信息。

  • 2023年7月03日 - 华为PSIRT通知我们,部分漏洞未修补,将在2023年8月更新中修复。

    二进制漏洞(更新中)

  • 其它课程

  • windows网络安全防火墙与虚拟网卡(更新完成)

  • windows文件过滤(更新完成)

  • USB过滤(更新完成)

  • 游戏安全(更新中)

  • ios逆向

  • windbg

  • 恶意软件开发(更新中)

  • 还有很多免费教程(限学员)

  • 更多详细内容添加作者微信


文章来源: http://mp.weixin.qq.com/s?__biz=MzkwOTE5MDY5NA==&mid=2247490298&idx=1&sn=216e6e83f0316efe1234a9f908d73870&chksm=c13f29b3f648a0a5be98dbacc0d91fbce78f4481cf859e565f239b038c612f09698ef0db8f19&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh