二进制漏洞分析-15.华为TrustZone TEE_SERVICE_FACE_REC漏洞(三)

二进制漏洞分析-15.华为TrustZone TEE_SERVICE_FACE_REC漏洞(三)

原创 haidragon 安全狗的自我修养 2023-12-02 11:18

二进制漏洞分析-1.华为Security Hypervisor漏洞

二进制漏洞分析-2.揭示华为安全管理程序(上)

二进制漏洞分析-3.揭示华为安全管理程序(下)

二进制漏洞分析-4.华为安全监控漏洞(SMC SE 工厂检查 OOB 访问)

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

二进制漏洞分析-6.Parallels Desktop Toolgate 漏洞

二进制漏洞分析-7.华为TrustZone Vsim_Sw漏洞

二进制漏洞分析-8.Huawei TrustZone VprTa漏洞

二进制漏洞分析-9.华为TrustZone TEE_Weaver漏洞

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

二进制漏洞分析-11.华为TrustZone TEE_SERVICE_MULTIDRM漏洞(上)

二进制漏洞分析-11.华为TrustZone TEE_SERVICE_MULTIDRM漏洞(上)

二进制漏洞分析-12.华为TrustZone TEE_SERVICE_MULTIDRM漏洞(下)

二进制漏洞分析-13.华为TrustZone TEE_SERVICE_FACE_REC漏洞(一)

二进制漏洞分析-14.华为TrustZone TEE_SERVICE_FACE_REC漏洞(二)

Trustlet 函数中的堆指针泄漏FR_FaceFeatureAdd¶

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

unsigned int HwRecognitionAlgo::processEnroll(HwRecognitionAlgo *this, CImageBuffer *a2) {
    // ...
    FeatureManager::writeFaceFeature(
             *((FeatureManager **)this + 7),
             (unsigned int *)this + 0x21, // <- faceIdPtr
             v19,
             v9,
             v14,
             v40);
    // ...
}

int STRecognitionAlgo::writeFaceFeature(int a1, void *a2, void *a3, unsigned int a4, unsigned int a5) {
    // ...
    FeatureManager::writeFaceFeature(
               *(FeatureManager **)(a1 + 0x1C),
               (unsigned int *)(a1 + 0x5C), // <- faceIdPtr
               a4,
               a5,
               *(const void **)(a1 + 0x78),
               *(_DWORD *)(a1 + 0x7C));
}

int FR_FaceFeatureAdd(uint32_t *faceIdPtr, unsigned int typeId, unsigned int poseId, int feat, int featLen) {
    // ...
    tee_print(
        0,
        "%s %10.10s: [db_v3] face feature add, param is invalid: feat = 0x%x, featLen = %u, faceIdPtr = %p \n",
        "[error]",
        "FR_FaceFeatureAdd",
        feat,
        featLen,
        faceIdPtr);
    // ...
}

Trustlet 函数中的参数指针泄漏FR_SetFidoParam¶

函数中存在 TEE 参数指针泄漏。FR_SetFidoParam

TEE_Result TA_InvokeCommandEntryPoint(
        void *sessionContext,
        uint32_t commandID,
        uint32_t paramTypes,
        TEE_Param params[4]) {
    // ...
    FR_SetHuksParam(
                params[0].memref.buffer,
                params[0].memref.size,
                params[1].memref.buffer,
                params[1].memref.size,
                *params[2].memref.size);
    // ...
}

int FR_SetHuksParam(
        void *ibuf0_addr,
        uint32_t ibuf0_size,
        void *ibuf1_addr,
        uint32_t ibuf1_size,
        uint32_t ibuf2_val) {
    // ...
    return FR_SetFidoParam(ibuf0_addr, ibuf0_size, ibuf1_addr, ibuf1_size, ibuf2_val);
    // ...
}

int FR_SetFidoParam(
        void *ibuf0_addr,
        uint32_t ibuf0_size,
        void *ibuf1_addr,
        uint32_t ibuf1_size,
        uint32_t ibuf2_val) {
    // ...
    tee_print(
        0,
        "%s %10.10s: param is invalid, aaid:0x%x, aaidLength:%u, nonce:0x%x, nonceLength:%u \n",
        "[error]",
        "FR_SetFidoParam",
        ibuf0_addr,
        ibuf0_size,
        ibuf1_addr,
        ibuf1_size);
    return 0x7A000003;
}

Trustlet 函数中的堆栈指针泄漏FidoWrapUvt¶

函数中存在堆栈指针泄漏。FidoWrapUvt

int HandleGetuvtCommand(uint32_t paramTypes, TEE_Param params[4]) {
    // ...
    uint32_t uvtLen;
    char uvt[4096];
    // ...
    FidoWrapUvt(uvt, &uvtLen);
    // ...
}

int FidoWrapUvt(char *wrappedUvt, uint32_t *wrappedUvtLen_p) {
    tee_print(
        0,
        "%s %10.10s: wrap failure, param is NULL.uvt=0x%x,uvtLen=%u,wrappedUvt=0x%x \n",
        "[error]",
        "FidoWrapUvt",
        g_uvt,
        g_uvtLen,
        wrappedUvt);
    // ...
}

Trustlet 函数中的堆指针泄漏FR_UnwrapFeatureData¶

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

int FR_LoadDataBase() {
    // ...
    FR_AllocMemToReadFile(v31, v32, &databuf, &datalen);
    FR_UnwrapFeatureData(databuf, datalen, &datalen);
    // ...
}

int FR_UnwrapFeatureData(void *buf, int size, int *outlen_p) {
    // ...
    tee_print(
        0,
        "%s %10.10s: buf: %p, size: 0x%x, outlen: 0x%x, isWrapped:%d \n",
        "[info]",
        "FR_UnwrapFeatureData",
        buf,
        size,
        *outlen_p,
        isWrapped);
    // ...
    sub_13F7C(buf, size, &oputbuf, &bufSize);
    // ...
    tee_print(0, "%s %10.10s: oputbuf: %p, bufSize:0x%x \n", "[info]", "FR_UnwrapFeatureData", oputbuf, bufSize);
}

库函数中的堆指针泄漏AlgoManager::createAlgo¶

函数中存在堆指针泄漏。AlgoManager::createAlgo

AlgoInterface *AlgoManager::createAlgo(
        AlgoManager *this,
        const char *name,
        FeatureManager *feature_manager,
        MemoryManager *memory_manager,
        MsgController *msg_controller)
{
    // [...]
    algo_fptrs = &g_algorithms;
    // [...]
    alloc_ptr = algo_fptr->newAlgo(feature_manager, memory_manager,
        msg_controller);
    // [...]
    tee_print(0, "%s %d:[%s][%s]%s, name %s, %p \n", "[info]", 0x3C,
        &FILogTag, "AlgoManager", "createAlgo", name, alloc_ptr);
    // [...]
}

HwDetectionAlgo *HwDetectionAlgo::newAlgo(...)
{
    HwDetectionAlgo *alloc = new HwDetectionAlgo;
    // [...]
    return alloc;
}

磁带库功能中的ION虚拟内存地址泄漏HiAiManager::loadModelFromBuffers¶

在函数中,trustlet 库处理模型缓冲区列表,其中包含有关用户提供的 trustlet 映射的 ION 缓冲区的信息。在上面突出显示的调用中,该函数泄漏了其中一个映射的 ION 缓冲区的虚拟地址。HiAiManager::loadModelFromBuffersmodel_listtee_print

uint32_t HiAiManager::loadModelFromBuffers(...) {
    // [...]
    tee_print(0, "%s %d:[%s][%s]%s : name:%s, addr = %d, size = %d, perf = %d\n",
        "[info]", 0x100, &FILogTag, "HiAiManager", "loadModelFromBuffers",
        path_data, model_list->buffers[0].addr, size, perf);
    // [...]
}

磁带库功能中的 ION 物理内存泄漏HiAiManager::runModelInMainThread¶

该函数会泄漏用户提供的 trustlet 映射的 ION 缓冲区的物理地址。HiAiManager::runModelInMainThread

uint32_t HiAiManager::runModelInMainThread(HiAiManager *this, char *a2) {
    // [...]
    paddr = this->npuRunMem.paddr;
    vaddr = this->npuRunMem.vaddr;
    // [...]
    tee_print(0,
        "%s %d:[%s][%s]%s(), output %d-%d: n:%d, c:%d, h:%d, w:%d, size:0x%x, allignedSize:0x%x, inout_phy_addr:%p",
        "[info]", 0x1C7, &FILogTag, "HiAiManager", "runModelInMainThread",
        o1, o2, n, c, h, w, size, alignedSize, paddr);
    // [...]
}

磁带库功能中的ION虚拟内存地址泄漏HiAiManager::loadModelFromBuffers¶

在函数中,trustlet 库使用用户提供的有关 trustlet 映射的 ION 缓冲区的信息来初始化对象。在上面突出显示的调用中,该函数会泄漏这些映射的 ION 缓冲区的虚拟地址。MemoryManager::initMemoryMemoryManagertee_print

uint32_t MemoryManager::initMemory(MemoryManager *this, FIIonBuf *buffers, int count) {
    // [...]
    for (int i = 0; i < count; i++) {
        // [...]
        tee_print(0, "%s %d:[%s][%s]%s index:%d, size:%d , addr:%p\n", "[info]", 0x21, &FILogTag,
        "MemoryManager", "initMemory", index, buffers->size, buffers->vaddr);
        // [...]
        buffers++;
    }
    // [...]
}

磁带库功能中的ION虚拟内存地址泄漏MemoryManager::alloc¶

该函数泄漏指向其中一个 trustlet 映射的 ION 缓冲区内的地址。这些指针是为 中的对象设置的。MemoryManager::allocMemoryManagerMemoryManager::initMemory

char *MemoryManager::alloc(MemoryManager *this, int size, const char *name) {
    idx = 0;
    // [...]
    obj_addr = &this->vtable + idx;
    ion_ptr = obj_addr[2] + *this->field_5C;
    // [...]
    tee_print(0, "%s %d:[%s][%s]%s size:%d, name:%s, addr:%p \n",
        "[info]", 0x33, &FILogTag, "MemoryManager", "alloc",
        size, name, fptr);
}

磁带库功能中的ION虚拟内存地址泄漏MemoryManager::free¶

与 中的漏洞类似,会泄露作为参数传递的地址。MemoryManager::allocMemoryManager::free

void MemoryManager::free(MemoryManager *this, void *addr, const char *name) {
    if ( FILog::mLogLevel > 2 )
        tee_print(0, "%s %d:[%s][%s]%s addr:%p, name %s \n", "[info]",
            0x3A, &FILogTag, "MemoryManager", "free", addr, name);
}

库函数中的指针泄漏MsgController::agentLock¶

该函数泄漏缓冲区的地址。MsgController::agentLockthis->agentBuffer

void MsgController::agentLock(MsgController *this)
{
    // [...]
    tee_print(0,
        "%s %d:[%s][%s]%s GetAgentBuffer success, agentBuffer=%p, agentBufsize=%d\n",
        "[info]", 0x4C, &FILogTag, "MsgController", "agentLock",
        this->agentBuffer, this->agentBufsize);
    // [...]
}

库函数中的堆指针泄漏CImageBufferAllocator::endAllocatation¶

该函数从链表中泄漏堆分配元素的地址。CImageBufferAllocator::endAllocatationthis->list

uint32_t CImageBufferAllocator::endAllocatation(CImageBufferAllocator *this) {
    // [...]
    prev = this->list.prev;
    // [...]
    next = prev->list.next;
    // [...]
    tee_print(0, "%s %d:[%s][%s]%s delete CImageBuffer %p\n", "[info]",
        0x32, &FILogTag, "CImageBufferAllocator", "endAllocatation",
        next);
    // [...]
}

库函数中的堆指针泄漏CImageBufferAllocator::endAllocatation¶

该函数泄漏堆分配对象的地址。CImageBufferAllocator::endAllocatationcimg_buf

uint32_t CImageBufferAllocator::putBuffer(CImageBufferAllocator *this,
        CImageBuffer *cimg_buf, const char *a3)
{
    // [...]
    tee_print(0, "%s %d:[%s][%s]%s delete CImageBuffer %p, name %s\n",
        "[info]", 0x54, &FILogTag, "CImageBufferAllocator", "putBuffer",
        cimg_buf, cimg_buf);
    // [...]
}

库函数中的堆指针泄漏CImageBufferAllocator::beginAllocatation¶

该函数泄漏堆分配对象的地址。CImageBufferAllocator::beginAllocatationcimg_buf

uint32_t CImageBufferAllocator::beginAllocatation(
        CImageBufferAllocator *this,
        int width,
        int height,
        int stride,
        int size,
        int type,
        int count,
        int a8)
{
    cimg_buf = new CImageBuffer;
    // [...]
    tee_print(0, "%s %d:[%s][%s]%s new CImageBuffer %p\n",
        "[info]", 0x20, &FILogTag, "CImageBufferAllocator", "beginAllocatation",
        cimg_buf);
    // [...]
}

库函数中的指针泄漏CImageBuffer::delStride¶

该函数泄漏 和 对象的字段地址。CImageBuffer::delStrideaddrCImageBufferImageBuffer

uint32_t CImageBuffer::fillImage(CImageBuffer *this, ImageBuffer *image, int index)
{
    // [...]
    CImageBuffer::delStride(this, image->addr, image->width, image->height, image->stride,
        this->addr, 1);
    // [...]
}

uint32_t CImageBuffer::delStride(CImageBuffer *this, const void *src, int width,
        int height, int stride, void *dest, int a7)
{
    // [...]
    tee_print(0,
        "%s %d:[%s][%s]%s(), error, src=%p, dst=%p, width=%d, height=%d, stride=%d\n ",
        "[error]", 0xDC, &FILogTag, "CImageBuffer", "delStride",
        src, dest, width, height, stride);
    // [...]
}

该字段的设置如下:addr

uint32_t CImageBufferAllocator::beginAllocatation(
        CImageBufferAllocator *this, int width, int height, int stride,
        int size, int type, int count, int a8)
{
    // [...]
    addr = MemoryManager::alloc(this->memory_manager, size, "CImageBufferAllocator");
    // [...]
    HwImage::HwImage(hwimg, width, height, stride, type, addr, size, this);
    // [...]
}

void HwImage::HwImage(HwImage *this, int width, int height, int stride,
        int type, void *addr, unsigned int size,
        CImageBufferAllocator *buffer_allocator)
{
    CImageBuffer::CImageBuffer(&this->parent, width, height, stride, type, addr, size, buffer_allocator);
    // [...]
}

void CImageBuffer::CImageBuffer(CImageBuffer *this, int width, int height,
        int stride, int type, void *addr, unsigned int size,
        CImageBufferAllocator *buffer_allocator)
{
    // [...]
    this->addr = addr;
    // [...]
}

库函数中的堆指针泄漏CImageBuffer::fillImage¶

该函数泄漏堆分配对象的地址。CImageBuffer::fillImageimage

uint32_t CImageBuffer::fillImage(CImageBuffer *this,
        ImageBuffer *image, int index)
{
    // [...]
    tee_print(
        0,
        "%s %d:[%s][%s]%s(), img=%p, size=%d, %x %x %x %x %x %x %x %x %x\n",
        "[verb]", 0xD2, &FILogTag, "CImageBuffer", "fillImage",
        image, /* [...] */ );
    // [...]
}

库函数中的指针泄漏CImageBuffer::attachBuffer¶

该函数泄漏对象的地址。CImageBuffer::attachBufferImageBuffer

uint32_t CImageBuffer::attachBuffer(CImageBuffer *this_1, ImageBuffer *img, int idx)
{
    // [...]
    if (this->mAttachedBuffer[idx]) {
        // [...]
        tee_print(0,
            "%s %d:[%s][%s]%s() fail, mAttachedBuffer[%d] exist %p\n ",
            "[error]", 0x1A0, &FILogTag, "CImageBuffer", "attachBuffer",
            idx, this->mAttachedBuffer[idx]);
        // [...]
    }
    // [...]
}

库函数中的指针泄漏ImageSourceBase::clear¶

该函数泄漏对象的地址。ImageSourceBase::clearCImageBuffer

void ImageSourceBase::clear(ImageSourceBase *this) {
    // [...]
    tee_print(
        0,
        "%s %d:[%s][%s]%s buffer %p\n",
        "[info]",
        0x32,
        (const char *)&FILogTag,
        "ImageSourceBase",
        "clear",
        prev->alg_img_buf[2]);
    // [...]
}

库函数中的堆指针泄漏PipelineBuilder::createPipeline¶

该函数泄漏多个堆指针。PipelineBuilder::createPipeline

uint32_t PipelineBuilder::createPipeline(
        int type,
        Pipeline **pipeline_p,
        AlgoManager *algo_manager,
        MemoryManager *memory_manager,
        MsgController *msg_controller,
        FeatureManager *feature_manager,
        FIAlgoConfig *fi_algo_config)
{
            // [...]
            *pipeline_p = &stpipeline_unlock->parent;
            tee_print(0, "%s %d:[%s][%s]%s FI_PIPELINE_MODE_UNLOCK %p\n",
                "[info]", 0x27, &FILogTag, "PipelineBuilder", "createPipeline",
                *pipeline_p);
            // [...]
            *pipeline_p = &stpipeline_enroll->parent;
            tee_print(0, "%s %d:[%s][%s]%s FI_PIPELINE_MODE_ENROLL %p\n",
                "[info]", 0x3B, &FILogTag, "PipelineBuilder", "createPipeline",
                *pipeline_p);
            // [...]
            *pipeline_p = &pipeline_unlock_test->parent;
            tee_print(0, "%s %d:[%s][%s]%s FI_PIPELINE_MODE_UNLOCK_TEST %p\n",
                "[info]", 0x30, &FILogTag, "PipelineBuilder", "createPipeline",
                *pipeline_p);
            // [...]
            *pipeline_p = &pipeline_liveliness_test->parent;
            tee_print(0, "%s %d:[%s][%s]%s FI_PIPELINE_MODE_LIVENESS_TEST %p\n",
                "[info]", 0x42, &FILogTag, "PipelineBuilder", "createPipeline",
                *pipeline_p);
            // [...]
            *pipeline_p = &stpipeline4_load_model->parent;
            tee_print(0, "%s %d:[%s][%s]%s FI_PIPELINE_MODE_LOADMODEL %p\n",
                "[info]", 0x4D, &FILogTag, "PipelineBuilder", "createPipeline",
                *pipeline_p);
            // [...]
            *pipeline_p = &stpipeline4_upgrade_model->parent;
            tee_print(0, "%s %d:[%s][%s]%s FI_PIPELINE_MODE_UPGRADE_MODEL %p\n",
                "[info]", 0x5C, &FILogTag, "PipelineBuilder", "createPipeline",
                *pipeline_p);
            // [...]
            *pipeline_p = &pipeline_gaze_test->parent;
            tee_print(0, "%s %d:[%s][%s]%s FI_PIPELINE_MODE_GAZE_UNLOCK_TEST %p\n",
                "[info]", 0x65, &FILogTag, "PipelineBuilder", "createPipeline",
                *pipeline_p);
            // [...]
}

二进制漏洞(更新中)

其它课程

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

windows文件过滤(更新完成)

USB过滤(更新完成)

游戏安全(更新中)

ios逆向

windbg

恶意软件开发(更新中)

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

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