二进制漏洞分析-20.TrustZone Task_Phone_Novelchd漏洞(上)
2023-12-10 11:1:40 Author: 安全狗的自我修养(查看原文) 阅读量:9 收藏

 

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

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

二进制漏洞分析-19.华为TrustZone TCIS漏洞

此通报包含有关以下漏洞的信息:

  • CVE-2021-46813 漏洞 GetOCSPResponse 中缺少长度检查

  • CVE-2021-46813 漏洞 NOVEL_CHDRM_Copyordecrypt中缺少长度和偏移检查

  • CVE-2021-46813 漏洞 NOVEL_CHDRM_SetDRMCertData中缺少长度检查

  • CVE-2021-40062 漏洞 缺少长度检查DRM_Secure_Store_Read

  • CVE-2021-40056 漏洞 getvaluewithtypeandindex 中缺少长度检查

  • CVE-2021-40057 漏洞 Secure_Store_EncryptWrite 和 Secure_Store_PlainWrite 中缺少长度检查

  • CVE-2021-40058 漏洞 NOVEL_CHDRM_SetRegisterResData中缺少长度检查

  • CVE-2021-40060 漏洞 调用NOVEL_CHDRMw_MemCompare时长度检查缺失/错误

  • CVE-2021-46813 漏洞 find_tlv_data中的整数下溢

  • CVE-2022-39003 漏洞 getvaluewithtypeandindex 中的 OOB 访问

  • HWPSIRT-2022-77114 未经检查的 Malloc 返回值

  • HWPSIRT-2021-84851 缺少长度检入pack_tlv_data

  • HWPSIRT-2021-40855 调用unpack_tlv_data后缺少长度检查

  • HWPSIRT-2021-36582 堆栈/堆/BSS 指针泄漏DRM_AES_Encrypt_xxx

  • HWPSIRT-2021-78954 unpack_tlv_data中的整数下溢

我们发现多个漏洞影响华为TASK_PHONE_NOVELCHD可信应用程序。为了使报告简明扼要,我们尝试对类似的漏洞进行重新组合。我们最终得到了下面给出的类别。

  • 缺少长度检查导致TEE_Param输出缓冲区的 39 个缓冲区溢出pack_tlv_data

  • 缺少长度检查导致 25 个缓冲区溢出(23 个堆栈分配,2 个堆分配)DRM_Secure_Store_Read

  • 缺少长度检查,导致 13 个堆栈缓冲区溢出getvaluewithtypeandindex

  • 缺少长度检查导致 14 个堆栈缓冲区溢出GetOCSPResponse

  • 缺少长度签入并导致 12 个堆栈缓冲区溢出Secure_Store_EncryptWriteSecure_Store_PlainWrite

  • 缺少长度和偏移检查,导致:NOVEL_CHDRM_Copyordecrypt

    • 1 堆栈缓冲区溢出

    • 6 次 ION 缓冲液 OOB 写入

    • 3 个 ION 缓冲液 OOB 读数

  • 缺少长度检查导致 2 个堆栈缓冲区溢出NOVEL_CHDRM_SetDRMCertData

  • 缺少长度检查导致:NOVEL_CHDRM_SetRegisterResData

    • 1 堆栈缓冲区溢出

    • 1 BSS 缓冲区溢出

  • 调用后缺少长度检查,导致 6 堆缓冲区溢出unpack_tlv_data

  • 堆栈/堆/bss 指针泄漏DRM_AES_Encrypt_xxx

  • 整数下溢导致 OOB 读取/缓冲区过度读取unpack_tlv_data

  • 整数下溢导致 OOB 读取/缓冲区过度读取find_tlv_data

  • 未经检查的 malloc 返回值导致 10 个空指针取消引用

缺少长度签入pack_tlv_data

该函数用于将 TLV 数据打包到输出缓冲区中。输出缓冲区的大小由用户控制,在写入之前从不检查,如果缓冲区不够大,无法写入其中的数据,则会导致缓冲区溢出。pack_tlv_data

void pack_tlv_data(uint8_t type, uint8_t *value, uint32_t length, uint8_t *outbuf, uint32_t *outbuf_size) {
outbuf[0] = type;
*(uint32_t *)(outbuf + 1) = bswap32(length);
if (length)
NOVEL_CHDRMw_Memcpy(outbuf + 5, value, length);
*outbuf_size = length + 5;
}

例如,我们将查看对 in 的易受攻击的调用,这是命令 ID #0x1 的处理程序。pack_tlv_dataNOVEL_CHDRM_GetDeviceID

TEE_Result TA_InvokeCommandEntryPoint(
void *sessionContext,
uint32_t commandID,
uint32_t paramTypes,
TEE_Param params[4])
{
/* [...] */
if (commandID == 1) {
DRM_CheckParamType(paramTypes, 5, 6, 0, 0);
/* [...] */
NOVEL_CHDRM_GetDeviceID(params[1].memref.buffer, &params[1].memref.size);
}
/* [...] */
}

NOVEL_CHDRM_GetDeviceID传递输出缓冲区及其大小,而无需事先验证。无论其实际大小如何,这都会写入 0x20 个字节。例如,如果我们提供大小为 0x8 字节的输出缓冲区,则会导致 0x18 字节的缓冲区溢出。TEE_Paramobuf1_addrobuf1_sizepack_tlv_dataobuf1_addrTEE_Param

int NOVEL_CHDRM_GetDeviceID(uint8_t *obuf1_addr, uint32_t *obuf1_size) {
pack_tlv_data(END_OF_CONTENT, &OTPChipIDHex, 0x20, obuf1_addr, obuf1_size);
return 0;
}

在这个特定示例中,TA 不会崩溃。但是有些调用具有可控大小,然后能够跨越页面边界,导致崩溃。pack_tlv_data

我们确定了 39 个易受攻击的调用,所有调用都写入了输出缓冲区的 OOB:pack_tlv_dataTEE_Param

地址访客冲击
0x1420NOVEL_CHDRM_GetDeviceID+200x20 字节缓冲区溢出params[1]
0x1540NOVEL_CHDRM_GetSerialNumber+10cn 字节缓冲区溢出params[1]
0x1638NOVEL_CHDRM_GetSecurityReqData+公元前0x10 字节缓冲区溢出params[1]
0x165cNOVEL_CHDRM_GetSecurityReqData+E00x20 字节缓冲区溢出params[1]
0x169cNOVEL_CHDRM_GetSecurityReqData+1204 字节缓冲区溢出params[1]
0x1740NOVEL_CHDRM_GetSecurityReqData+1C4n 字节缓冲区溢出params[1]
0x1774NOVEL_CHDRM_GetSecurityReqData+1F8n 字节缓冲区溢出params[1]
0x199cNOVEL_CHDRM_GetSecurityReqData+420n 字节缓冲区溢出params[1]
0x1a44NOVEL_CHDRM_GetSecurityReqData+4C8n 字节缓冲区溢出params[1]
0x1d30NOVEL_CHDRM_GetSignature+22cn 字节缓冲区溢出params[1]
0x2004NOVEL_CHDRM_GetAttestationSignature+244n 字节缓冲区溢出params[1]
0x2828NOVEL_CHDRM_GetDRMTime+404 字节缓冲区溢出params[1]
0x28d0NOVEL_CHDRM_GetTAVersion+90n 字节缓冲区溢出params[1]
0x2f90NOVEL_CHDRM_GetLicenseReqData+66 81 字节缓冲区溢出params[1]
0x30ecNOVEL_CHDRM_GetLicenseReqData+7C40x14 字节缓冲区溢出params[1]
0x3154NOVEL_CHDRM_GetLicenseReqData+82摄氏度0x10 字节缓冲区溢出params[1]
0x3184NOVEL_CHDRM_GetLicenseReqData+85摄氏度4 字节缓冲区溢出params[1]
0x31bcNOVEL_CHDRM_GetLicenseReqData+894n 字节缓冲区溢出params[1]
0x31e8NOVEL_CHDRM_GetLicenseReqData+8C00x20 字节缓冲区溢出params[1]
0x35acNOVEL_CHDRM_DelLicenseReqData+2801 字节缓冲区溢出params[1]
0x5134NOVEL_CHDRM_SetDRMDataLicenseResData+1ae01 字节缓冲区溢出params[1]
0x5ff8NOVEL_CHDRM_GetDRMCertData+234n 字节缓冲区溢出params[1]
0x6110NOVEL_CHDRM_GetDRMCertData+34Cn 字节缓冲区溢出params[1]
0x6220NOVEL_CHDRM_GetDRMCertData+45摄氏度n 字节缓冲区溢出params[1]
0x6348NOVEL_CHDRM_GetDRMCertData+584n 字节缓冲区溢出params[1]
0x644cNOVEL_CHDRM_GetDRMCertData+688n 字节缓冲区溢出params[1]
0x6554NOVEL_CHDRM_GetDRMCertData+790n 字节缓冲区溢出params[1]
0x6e30NOVEL_CHDRM_GetRegisterReqData+13c1 字节缓冲区溢出params[1]
0x6ebcNOVEL_CHDRM_GetRegisterReqData+1C8n 字节缓冲区溢出params[1]
0x7028NOVEL_CHDRM_GetRegisterReqData+3342 字节缓冲区溢出params[1]
0x70f8NOVEL_CHDRM_GetRegisterReqData+404n 字节缓冲区溢出params[1]
0x7154NOVEL_CHDRM_GetRegisterReqData+4602 字节缓冲区溢出params[1]
0x724cNOVEL_CHDRM_GetRegisterReqData+558n 字节缓冲区溢出params[1]
0x7274NOVEL_CHDRM_GetRegisterReqData+58020 字节缓冲区溢出params[1]
0x72d4NOVEL_CHDRM_GetRegisterReqData+5e0n 字节缓冲区溢出params[1]
0x7db4NOVEL_CHDRM_GetRegisterStatus+124n 字节缓冲区溢出params[1]
0x7df8NOVEL_CHDRM_GetRegisterStatus+1681 字节缓冲区溢出params[1]
0x7f0cNOVEL_CHDRM_GetRegisterStatus+27c1 字节缓冲区溢出params[1]
0x7fa8NOVEL_CHDRM_GetRegisterStatus+3181 字节缓冲区溢出params[1]

缺少长度签入DRM_Secure_Store_Read

DRM_Secure_Store_Read使用或 从安全存储中读取数据,具体取决于正在读取的文件。Secure_Store_PlainReadSecure_Store_EncryptRead

unsigned int DRM_Secure_Store_Read(void* data, uint32_t *data_len, uint32_t store_type)
{
if (store_type - 0x10 <= 0x4F) {
// drmCipherData
return Secure_Store_EncryptRead("64726D43697068657244617461.cli",
data, data_len, store_type, &version);
}

if (store_type - 0x60 <= 0x9F) {
// drmPlainData
return Secure_Store_PlainRead("64726D506C61696E44617461.cli",
data, data_len, store_type, &version);
}

if (store_type <= 0xF) {
// drmCipherData
ret1 = Secure_Store_EncryptRead("64726D43697068657244617461.cli",
data, &outsize, store_type, &version);
*data_len = outsize;
// drmPlainData
ret2 = Secure_Store_PlainRead("64726D506C61696E44617461.cli",
data + outsize, &outsize, store_type, &version);
*data_len += outsize;
return ret1 | ret2;
}

// [...]
}

这里将:Secure_Store_EncryptRead

  • 读取文件filename;

  • 解密其中的数据;

  • 根据值检索 TLV 对象store_type;

  • 将结果复制到输出缓冲区中。data

unsigned int Secure_Store_EncryptRead(uint8_t *filename, void *data,
uint32_t *outsize, uint8_t store_type, uint32_t *version) {
/* [...] */
// Reads the file from the file
HiTEE_FlashRead(filename, &rpmb_data, 0x2000, &rpmb_data_size);
rpmb_data_size = _byteswap_ulong(rpmb_data.size);
/* [...] */
// In-place RPMB data decryption.
Secure_Store_DataDecrypt(rpmb_data.data, &rpmb_data_size);
/* [...] */
// Extracts data from the file according to the `store_type` argument.
unpack_tlv_data(store_type, rpmb_data.data, &rpmb_data_size,
&unpacked_tlv_buf_p, &unpacked_tlv_len);
/* [...] */
// Copies the result into the `data` output buffer provided to the function.
NOVEL_CHDRMw_Memcpy(data, unpacked_tlv_buf_p, unpacked_tlv_len);
/* [...] */
}

注意:除了解密过程外,执行相同的操作。Secure_Store_PlainRead

输出缓冲区首先作为参数传递给 ,然后传播到 和/或 。但是,从不检查其大小,这可能会导致在将数据复制到其中时缓冲区溢出。dataDRM_Secure_Store_ReadSecure_Store_PlainReadSecure_Store_EncryptRead

例如,我们将查看对 in 的易受攻击的调用,这是命令 ID #0x17 的处理程序。DRM_Secure_Store_ReadNOVEL_CHDRM_GetSerialNumber

TEE_Result TA_InvokeCommandEntryPoint(
void *sessionContext,
uint32_t commandID,
uint32_t paramTypes,
TEE_Param params[4])
{
/* [...] */
if (commandID == 0x17) {
DRM_CheckParamType(paramTypes, 5, 6, 0, 0);
/* [...] */
NOVEL_CHDRM_GetSerialNumber(params[1].memref.buffer,
&params[1].memref.size);
}
/* [...] */
}

NOVEL_CHDRM_GetSerialNumber从安全存储中读取类型为 0x60 的文件。读取的数据将写入大小为 2048 的堆栈分配缓冲区。DRM_Secure_Store_Read

int NOVEL_CHDRM_GetSerialNumber(uint8_t *obuf1_addr, uint32_t obuf1_size) {
/* [...] */
uint8_t cert[2048];
memset(cert, 0, sizeof(cert));
/* [...] */
DRM_Secure_Store_Read(cert, &cert_size, 0x60);
/* [...] */
}

但是,用户可以调用以将与类型 0x60 对应的值写入安全存储。文件数据和大小来自对输入缓冲区(由用户控制)进行操作的调用。因此,应该可以写入超过 2048 个字节,从而在使用 读取此数据时导致缓冲区溢出。NOVEL_CHDRM_SetDRMCertDataDRM_Secure_Store_Writeunpack_tlv_dataTEE_ParamDRM_Secure_Store_Read

int NOVEL_CHDRM_SetDRMCertData(uint8_t *ibuf0_addr, uint32_t ibuf0_size) {
/* [...] */
if (!unpack_tlv_data(0x16, ibuf0_addr, &ibuf0_size, &cert, &cert_size)) {
DRM_Secure_Store_Write(cert, cert_size, 0x60);
/* [...] */
}
/* [...] */
}

我们确定了 25 个易受攻击的调用,所有这些调用都可能导致缓冲区溢出:DRM_Secure_Store_Read

地址访客冲击
0x149cNOVEL_CHDRM_GetSerialNumber+68基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x16c8NOVEL_CHDRM_GetSecurityReqData+14c基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x16e4NOVEL_CHDRM_GetSecurityReqData+168基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x17b4NOVEL_CHDRM_GetSecurityReqData+238基于堆栈的缓冲区溢出(如果大小为 4>)
0x19e8NOVEL_CHDRM_GetSecurityReqData+46c基于堆栈的缓冲区溢出(如果大小为 8,则>)
0x1bb0NOVEL_CHDRM_GetSignature+交流基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x2344NOVEL_CHDRM_VerifySignature+2b8基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x2fe0NOVEL_CHDRM_GetLicenseReqData+6b8基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x303cNOVEL_CHDRM_GetLicenseReqData+714基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x3974NOVEL_CHDRM_SetDRMDataLicenseResData+320基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x53c4NOVEL_CHDRM_SetDRMCertData+1直流基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x546cNOVEL_CHDRM_SetDRMCertData+284基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x5f9cNOVEL_CHDRM_GetDRMCertData+1天8基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x60b0NOVEL_CHDRM_GetDRMCertData+2ec基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x61c0NOVEL_CHDRM_GetDRMCertData+3FC基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x62d4NOVEL_CHDRM_GetDRMCertData+510基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x63f4NOVEL_CHDRM_GetDRMCertData+630基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x64f8NOVEL_CHDRM_GetDRMCertData+734基于堆的缓冲区溢出(任何大小)
0x6d98NOVEL_CHDRM_GetRegisterReqData+A4基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x6e64NOVEL_CHDRM_GetRegisterReqData+170基于堆的缓冲区溢出(如果大小为 256,则>)
0x7cf4NOVEL_CHDRM_GetRegisterStatus+64基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x7d64NOVEL_CHDRM_GetRegisterStatus+D4基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x7e28NOVEL_CHDRM_GetRegisterStatus+198基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x7e90NOVEL_CHDRM_GetRegisterStatus+200基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x7f3cNOVEL_CHDRM_GetRegisterStatus+2交流基于堆栈的缓冲区溢出(如果大小为 2048,则>

缺少长度签入getvaluewithtypeandindex

getvaluewithtypeandindex分析输入缓冲区以提取具有给定类型和键类型的值。它首先在输入缓冲区内定位值,计算其偏移量和长度。然后,使用 将该值复制到输出缓冲区中。值长度受输入缓冲区大小的限制。从不检查输出缓冲区长度,从而导致潜在的缓冲区溢出。inbufNOVEL_CHDRMw_Memcpyinsize

uint32_t getvaluewithtypeandindex(
uint32_t type,
uint32_t key_type,
void *inbuf,
uint32_t insize,
void *outbuf,
uint32_t *outsize_p)
{
/* [...] */
/*
* Parses the input buffer `inbuf` to compute `value_size` and `value_offset`.
* A value is then extracted from `inbuf` and written into `outbuf`.
*/
if (insize >= value_size + value_offset) {
NOVEL_CHDRMw_Memcpy(outbuf, inbuf + value_offset, value_size);
*outsize_p = value_size;
return 0;
}
/* [...] */
}

例如,我们将查看对 in 的易受攻击的调用,这是命令 ID #0xE 的处理程序。getvaluewithtypeandindexNOVEL_CHDRM_SetDRMDataLicenseResData

在 中,首先从 中提取缓冲区(大小不受限制)并将其复制到 中。然后,此缓冲区用作对 的调用的输入。此调用的输出是大小为 4 的堆栈变量。如上所述,可以将其超过 4 个字节复制到其输出中,从而导致缓冲区溢出。NOVEL_CHDRM_SetDRMDataLicenseResDataibuf0_addrdata1_pgetvaluewithtypeandindexOutputProtectiongetvaluewithtypeandindex

unsigned int NOVEL_CHDRM_SetDRMDataLicenseResData(
uint8_t *ibuf0_addr,
uint32_t ibuf0_size,
uint8_t *obuf1_addr,
uint32_t *obuf1_size)
{
/* [...] */
unpack_tlv_data(0xD, ibuf0_addr, &ibuf0_size, &data1_p, &data1_size);
/* [...] */
OutputProtection = 0;
OutputProtection_size = 0;
getvaluewithtypeandindex(4, 6, data1_p, data1_size,
&OutputProtection, &OutputProtection_size);
/* [...] */

我们确定了 13 个易受攻击的调用,所有这些调用都可能导致堆栈缓冲区溢出:getvaluewithtypeandindex

地址访客冲击
0x3aa4NOVEL_CHDRM_SetDRMDataLicenseResData+450基于堆栈的缓冲区溢出(如果大小为 512,则>)
0x3b14NOVEL_CHDRM_SetDRMDataLicenseResData+4c0基于堆栈的缓冲区溢出(如果大小为 2048,则>
0x3b84NOVEL_CHDRM_SetDRMDataLicenseResData+530基于堆栈的缓冲区溢出(如果大小为 128,则>)
0x3c3cNOVEL_CHDRM_SetDRMDataLicenseResData+5e8基于堆栈的缓冲区溢出(如果大小为 128,则>)
0x3f74NOVEL_CHDRM_SetDRMDataLicenseResData+920基于堆栈的缓冲区溢出(如果大小为 > 256)
0x4188NOVEL_CHDRM_SetDRMDataLicenseResData+B34基于堆栈的缓冲区溢出(如果大小为 32,则>)
0x42c8NOVEL_CHDRM_SetDRMDataLicenseResData+C74基于堆栈的缓冲区溢出(如果大小为 32,则>)
0x443cNOVEL_CHDRM_SetDRMDataLicenseResData+DE8基于堆栈的缓冲区溢出(如果大小为 32,则>)
0x4570NOVEL_CHDRM_SetDRMDataLicenseResData+F1C基于堆栈的缓冲区溢出(如果大小为 32,则>)
0x48e0NOVEL_CHDRM_SetDRMDataLicenseResData+128C基于堆栈的缓冲区溢出(如果大小为 32,则>)
0x4a1cNOVEL_CHDRM_SetDRMDataLicenseResData+13C8基于堆栈的缓冲区溢出(如果大小为 4>)
0x4ad0NOVEL_CHDRM_SetDRMDataLicenseResData+147C基于堆栈的缓冲区溢出(如果大小为 > 256)
0x4be4NOVEL_CHDRM_SetDRMDataLicenseResData+1590基于堆栈的缓冲区溢出(如果大小为 16,则>)

缺少长度签入GetOCSPResponse

NOVEL_CHDRM_SetDRMCertData是命令 ID #0xF 的处理程序,该处理程序将输入缓冲区及其大小作为参数。它首先调用从输入缓冲区中提取一个值,该值由用户控制,然后再将其传递给函数。TEE_Paramunpack_tlv_dataGetOCSPResponse

int NOVEL_CHDRM_SetDRMCertData(uint8_t *ibuf0_addr, uint32_t ibuf0_size) {
/* [...] */
ibuf0_size_cpy = ibuf0_size;
rsp_status_t rsp_status;
/* [...] */
if (!unpack_tlv_data(0x1C, ibuf0_addr, &ibuf0_size_cpy, &data_p, &data_size)) {
GetOCSPResponse(data_p, data_size, &rsp_status);
/* [...] */
}
/* [...] */
}

GetOCSPResponse解析位于输入缓冲区中的 ASN.1 数据。在此函数中,有许多以下模式的实例:data_p

  • 一个调用,它递增数据指针并检索当前标记的长度(无界)asn1_get_tag

  • 调用 that 将标记数据从输入缓冲区复制到输出缓冲区NOVEL_CHDRMw_Memcpyrsp_status_p

int GetOCSPResponse(uint8_t *data_p, uint32_t data_size, rsp_status_t *rsp_status) {
/* [...] */
asn1_get_tag(&data_p, seq0_end, &length, OID);
/* [...] */
NOVEL_CHDRMw_Memcpy(&rsp_status->field_14, data_p, length);
data_p += length;
/* [...] */
}

由于标记的长度是在没有任何检查的情况下给出的,这将导致缓冲区溢出(这是堆栈分配的缓冲区)。我们确定了 14 个易受攻击的模式,所有这些模式都会导致堆栈缓冲区溢出:NOVEL_CHDRMw_Memcpyrsp_status_pGetOCSPResponsersp_status_p

地址访客冲击
0x3a7d0GetOCSP响应+1e0基于堆栈的缓冲区溢出
0x3a8ecGetOCSP响应+2fc基于堆栈的缓冲区溢出
0x3a994GetOCSP响应+3a4基于堆栈的缓冲区溢出
0x3abc4GetOCSP响应+5d4基于堆栈的缓冲区溢出
0x3ac84GetOCSP响应+694基于堆栈的缓冲区溢出
0x3acecGetOCSP响应+6fc基于堆栈的缓冲区溢出
0x3ad54GetOCSP响应+764基于堆栈的缓冲区溢出
0x3ae18GetOCSP响应+828基于堆栈的缓冲区溢出
0x3aee0GetOCSP响应+8f0基于堆栈的缓冲区溢出
0x3b084GetOCSP响应+a94基于堆栈的缓冲区溢出
0x3b138GetOCSP响应+b48基于堆栈的缓冲区溢出
0x3b1f8GetOCSPResponse+c08基于堆栈的缓冲区溢出
0x3b2bcGetOCSP响应+ccc基于堆栈的缓冲区溢出
0x3b338GetOCSP响应+d48基于堆栈的缓冲区溢出

缺少长度签入和Secure_Store_EncryptWriteSecure_Store_PlainWrite

Secure_Store_EncryptWrite,可以使用用户控制的 和 参数 via 调用,首先作为 TLV 对象打包到大小为 + 5 的堆分配缓冲区中。然后,它将文件的 0x2000 字节读入堆栈分配的结构中。然后,此函数多次表现出相同的易受攻击模式,即调用:DRM_Secure_Store_Writebufferbuffer_sizebufferbuffer_tlvbuffer_sizerpmb_dataNOVEL_CHDRMw_Memcpy

  • rpmb_data.data作为目的地;

  • buffer_tlv作为来源;

  • buffer_tlv_size作为长度。

TEE_Result Secure_Store_EncryptWrite(
char *filename,
void *buffer,
uint32_t buffer_size,
uint32_t store_type,
uint32_t a5)
{
/* [...] */
rpmb_data_t rpmb_data;
/* [...] */
buffer_tlv = NOVEL_CHDRMw_Malloc(buffer_size + 5);
pack_tlv_data(store_type, buffer, buffer_size, buffer_tlv, &buffer_tlv_size);
ret = HiTEE_FlashRead(filename, &rpmb_data, 0x2000, &rpmb_data_size);
if (ret == 0xFFFF7106) {
/* [...] */
NOVEL_CHDRMw_Memcpy(&rpmb_data.data[secure_store_len], buffer_tlv, buffer_tlv_size);
secure_store_len += buffer_tlv_size;
}
/* [...] */
}

由于大小为 0x2000,并且由用户控制,因此会发生堆栈缓冲区溢出。rpmb_databuffer_tlv_size

注意:包含与 相同的易受攻击的模式。这两个函数的调用方式与DRM_Secure_Store_Read中的缺失长度检查部分中所述相同。Secure_Store_PlainWriteSecure_Store_EncryptWrite

总而言之,我们确定了 12 个易受攻击的模式实例,这些实例会导致堆栈缓冲区溢出:

地址访客冲击
0x37e60Secure_Store_EncryptWrite+1cc基于堆栈的缓冲区溢出
0x38058Secure_Store_EncryptWrite+3C4基于堆栈的缓冲区溢出
0x380a0Secure_Store_EncryptWrite+40摄氏度基于堆栈的缓冲区溢出
0x380d8Secure_Store_EncryptWrite+444基于堆栈的缓冲区溢出
0x38120Secure_Store_EncryptWrite+48C基于堆栈的缓冲区溢出
0x38190Secure_Store_EncryptWrite+4FC基于堆栈的缓冲区溢出
地址访客冲击
0x385c4Secure_Store_PlainWrite+1C4基于堆栈的缓冲区溢出
0x38764Secure_Store_PlainWrite+364基于堆栈的缓冲区溢出
0x387acSecure_Store_PlainWrite+3交流基于堆栈的缓冲区溢出
0x387e4Secure_Store_PlainWrite+3e4基于堆栈的缓冲区溢出
0x3882cSecure_Store_PlainWrite+42摄氏度基于堆栈的缓冲区溢出
0x38878Secure_Store_PlainWrite+478基于堆栈的缓冲区溢出
  • 二进制漏洞(更新中)

  • 其它课程

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

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

  • USB过滤(更新完成)

  • 游戏安全(更新中)

  • ios逆向

  • windbg

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

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

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


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