二进制漏洞分析-5.华为安全监控漏洞(SMC MNTN OOB 访问)
二进制漏洞分析-10.华为TrustZone TEE_SERVICE_VOICE_REC漏洞
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);
// ...
}
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);
// ...
}
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);
// ...
}
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);
// ...
}
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_AloEnroll
EndEnroll
enrolled_face_id_p
FR_TA_EndEnroll
FR_AloEnroll
EndEnroll
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_feature
middle_feature
GetPlainDataWhenEnroll
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
¶在函数中,如果模板偏移量检查失败,则将记录错误,但无论如何该函数的执行仍将继续,并且下次调用 时可能会记录越界值。GetPlainDataWhenEnroll
tee_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-48479 | 2023 年 5 月 |
OOB 写入HiAiManager::loadModelFromBuffers | 危急 | CVE-2022-48478 漏洞-2022-48478 | 2023 年 5 月 |
整数溢出FR_TA_CoAuthSignImg | 高 | CVE-2022-48480 漏洞CVE-2022-48480 | 2023 年 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
恶意软件开发(更新中)
还有很多免费教程(限学员)
更多详细内容添加作者微信