Áª·¢¿ÆÐ¾Æ¬Rootkit·ì϶·ÖÎö£¨CVE-2020-0069£©

°ä²¼¹¦·ò 2020-06-24

Ò»¡¢·ì϶²¼¾°


2020Äê3Ô £¬¹È¸è½¨²¹ÁËÒ»¸ö´æÔÚÓÚÁª·¢¿ÆÐ¾Æ¬Öеݲȫ·ì϶£¨CVE-2020-0069£© £¬·ì϶ӰÏì20Óà¿îÁª·¢¿ÆÐ¾Æ¬ºÍÊý°ÙÍòAndroidÉ豸¡£¸Ã·ì϶´æÔÚÓÚMediaTek Command QueueÇý¶¯£¨CMDQºÅÁî¶ÓÁÐÇý¶¯£© £¬ÔÊÐí±¾µØ¹¥»÷ÕßʵÏÖ¶ÔÎïÀíÄÚ´æµØÖ·µÄËÁÒâ¶Áд £¬´Ó¶øµ¼ÖÂȨÏÞÌáÉý¡£


¶þ¡¢ÊÜÓ°Ïì¹ú²úÊÖ»úÐͺÅ


Huawei GR3 TAG-L21

Huawei Y5II

Huawei Y6II MT6735 series

Lenovo A5

Lenovo C2 series

Lenovo Tab E7

Lenovo Tab E8

Lenovo Tab2 A10-70F

Meizu M5c

Meizu M6

Meizu Pro 7 Plus

Oppo A59 series

Oppo A5s

Oppo A7x -- up to Android 8.x

Oppo F5 series/A73 -- up to A.39

Oppo F7 series -- Android 8.x only

Oppo F9 series -- Android 8.x only

Oppo R9xm series

Xiaomi Redmi 6/6A series

ZTE Blade A530

ZTE Blade D6/V6

ZTE Quest 5 Z3351S


Èý¡¢CMDQÇý¶¯¼òÎö


DMA£¨Ö±½ÓÄÚ´æ½Ó¼û£©ÊÇÔÊÐíרÓÃÓ²¼þÖ±½Ó´ÓÖ÷´æ´¢Æ÷(RAM)·¢ËÍ»ò½Ó¹ÜÊý¾ÝµÄÒ»ÖÖ¸öÐÔ¡£ÆäÖ÷ÕÅÊÇͨ¹ýÔÊÐí´óÄÚ´æ½Ó¼û¶ø²»Íâ¶àÕ¼ÓÃCPUÀ´¼Ó¿ìϵͳ¡£MediaTek Command QueueÇý¶¯(CMDQºÅÁî¶ÓÁÐÇý¶¯)ÔÊÐí´ÓÓû§²ãÓëDMA½ÚÔìÆ÷ͨѶ £¬ÒÔʵÏÖýÌå»òÏÔʾÓйصŤ×÷¡£


»ùÓÚRedmi 6/6A Ô´´úÂë·ÖÎö £¬ÔÚcmdq_driver.hÍ·ÎļþÖÐ £¬ÉêÃ÷cmdqÇý¶¯µÄIOCTLŲÓÃÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


CMDQ_IOCTL_ALLOC_WRITE_ADDRESSÖ¸ÁîΪ·ÖÅäÒ»¸öDMA»º³åÇø¡£

CMDQ_IOCTL_FREE_WRITE_ADDRESSÖ¸ÁîΪ¿ªÊÍÒ»¸öDMA»º³åÇø¡£

CMDQ_IOCTL_READ_WRITE_ADDRESSÖ¸ÁîΪ¶Áȡһ¸öDMA»º³åÇøÖеÄÊý¾Ý¡£

CMDQ_IOCTL_EXEC_COMMANDÖ¸ÁîÔËÐз¢ËÍÆäËûºÅÁî¡£


1¡¢·ÖÅä¹ý³Ì


ͨ¹ýCMDQ_IOCTL_ALLOC_WRITE_ADDRESSŲÓÃcmdqCoreAllocWriteAddress ()º¯Êý £¬·ÖÅäÒ»¸öDMA»º³åÇø £¬¸Ãº¯Êý¹Ø¼ü´úÂëʵÏÖÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


¶øºó £¬Å²ÓÃcmdq_core_alloc_hw_buffer()º¯Êý·ÖÅäDMA»º³åÇø £¬pWriteAddr->vaÊÇÐé¹¹µØÖ· £¬pWriteAddr->paΪÎïÀíµØÖ· £¬Á½ÕßÖðÒ»¶ÔÓ¦¡£²¢ËãÕÊ»º³åÇø¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


×îºó £¬½«ÎïÀíµØÖ·¸³Öµµ½*paStart £¬²¢½«pWriteAddr½á¹¹ÌåÔö³¤µ½gCmdqContext.writeAddrListÁ´±íÖС£


2¡¢Ö´ÐкÅÁî¹ý³Ì


ÔÚCMDQ_IOCTL_EXEC_COMMANDŲÓÃÖÐ £¬Ñ¡È¡cmdqCommandStruct½á¹¹Ìå×÷Ϊ²ÎÊý £¬½á¹¹Ìå½ç˵ÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


pVABaseÖ¸ÏòÓû§²ã´æ·ÅºÅÁîµÄ»º³åÇø £¬»º³åÇø´óÓ×·ÅÔÚblockSizeÖС£ÆäÖÐcmdqReadAddressStruct½á¹¹Ìå½ç˵ÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


DmaAddressesÊÇÒª¶ÁÈ¡µÄÎïÀíµØÖ· £¬¶ÁÈ¡µÄÖµ´æ·ÅÔÚvaluesÖС£ÔÚCMDQ_IOCTL_EXEC_COMMANDºÅÁîµÄÖ´Ðйý³Ì £¬ÊµÏÖ´úÂëÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


º¯ÊýŲÓÃõè¾¶ÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


Cmdq_core_acquire_task()º¯Êý»á½«command°ó¶¨µ½taskÖÐÖ´ÐС£¾ßÌåʵÏÖÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


ŲÓÃcmdq_core_find_free_task()º¯Êý»ñȡһ¸ö¿ÕÏÐtask¡£Äõ½¿ÕÏÐtask²¢½øÐÐһЩ³õʼ»¯ÉèÖà £¬¶øºóÆðͷŲÓÃcmdq_core_insert_read_reg_command()º¯ÊýÖ´ÐкÅÁî¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


¸Ãº¯ÊýʵÏÖ·ÖÎö £¬ÏÈ¿½±´Óû§²ã´«ÈëµÄºÅÁîµ½DMA»º³åÇøÖС£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


pCommandDesc->pVABaseÊÇ´æ·ÅºÅÁîµÄÄÚ´æÕØÊ¼µØÖ·¡£¿½±´ÍêºÅÁîºó £¬ºóÃæ·Ö¼¸ÖÖ·½Ê½½áβ¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾

ÕâÀï²»×öÉ £¬×îºó¿½±´EOCºÍJUMPÖ¸Áî½áβ¡£ÕâÀïÒ²Êǽ«Óû§²ã´«ÈëµÄºÅÁ±´¹ýÀ´¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


´Ócmdq_core_acquire_task()º¯ÊýÖзµ»Øºó £¬ÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


ŲÓÃcmdq_core_consume_waiting_list()º¯ÊýÖ´ÐÐtask¡£ÏÈ´ÓÆÚ´ý¶ÓÁÐÖлñÈ¡task¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


¶øºó £¬»ñÈ¡¿ÕÏÐÄÚºËÏ̡߳£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


×îºó £¬½«task°ó¶¨µ½threadÖÐÈ¥Ö´ÐС£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


ËÄ¡¢¶ÁдºÅÁî·ÖÎö


ÒÔcmdq_test.c²âÊÔ´úÂëΪÀý £¬·ÖÎöÀí½âÒ»¸öÆëÈ«µÄ¶ÁдºÅÁî»ú¹Ø¡£cmdqÇý¶¯Öнç˵ÁËÁ½Àà¼Ä·ÅÆ÷ £¬Ò»ÀàÊǵØÖ·¼Ä·ÅÆ÷ÓÃÓÚ´æ·ÅµØÖ· £¬Ò»ÀàÊÇÊýÖµ¼Ä·ÅÆ÷ÓÃÓÚ´æ·Å¶ÁÈ¡»òдÈëµÄÊýÖµ¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


regResultsÊÇÐé¹¹µØÖ· £¬Å²ÓÃcmdq_core_alloc_hw_buffer()º¯Êý·ÖÅäÒ»¸ödmaµØÖ· £¬regResultsMVAÓëÖ®¶ÔÓ¦ £¬¶øºóÉèÖÃregResultsÖеÄÊý¾Ý¡£ÆðÍ·Æ´½Ó¶ÁÈ¡ºÍдÈëºÅÁ


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


½«regResults[0]µÄµØÖ·Ð´ÈëCMDQ_DATA_REG_DEBUG_DSTÀàÐ͵ĵØÖ·¼Ä·ÅÆ÷ÖС£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


¶øºó £¬´ÓCMDQ_DATA_REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷ÖжÁÈ¡Êý¾Ý²¢Ð´Èëµ½CMDQ_DATA_REG_DEBUGÊýÖµ¼Ä·ÅÆ÷ÖС£Õâʱ³½ £¬CMDQ_DATA_REG_DEBUGÊýÖµ¼Ä·ÅÆ÷ÖеÄÖµÓ¦¸ÃΪ0xdeaddead¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


½Ó×Å £¬½«regResults[1]µÄµØÖ·×ª´æµ½CMDQ_DATA_REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷ÖС£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


×îºó £¬½«CMDQ_DATA_REG_DEBUGÊýÖµ¼Ä·ÅÆ÷ÖеÄ0xdeaddeadдÈëµ½CMDQ_DATA_REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷Öб£ÁôµÄregResults[1]µÄµØÖ·ÖÐ £¬¼´regResults[1]=0xdeaddead¡£ÅжÏregResults[0]ºÍregResults[1]ÊÇ·ñÏà³Æ¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


ÈôÊÇÏà³Æ £¬×¢Ã÷¶Áд³É¹¦¡£


Îå¡¢PoC·ÖÎöÓë²âÊÔ


£¨1£©PoC´úÂëÖÐ £¬Ö´ÐÐд²Ù×÷µÄ¹Ø¼ü´úÂëÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


дÈë¹ý³ÌÖÐ £¬ÏȽ«value[count]ÒÆ¶¯µ½CMDQ_DATA_REG_DEBUGÊýÖµ¼Ä·ÅÆ÷ÖÐ £¬¶øºó½«pa_address+offsetµØÖ·Òƶ¯µ½CMDQ_DATA_REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷ÖÐ £¬×îºó½«CMDQ_DATA_REG_DEBUGÊýÖµ¼Ä·ÅÆ÷ÖеÄvalueдÈëµ½CMDQ_DATA_REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷Öб£ÁôµÄpa_address+offsetµØÖ·ÖÐ £¬¼´*(pa_address+offset)= value[count]¡£


£¨2£©PoC´úÂëÖÐ £¬Ö´ÐжÁ²Ù×÷µÄ¹Ø¼ü´úÂëÈçÏ£º


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


¶ÁÈ¡¹ý³ÌÖÐ £¬µÚÒ»²½ÏȽ«pa_address+offsetµØÖ·Òƶ¯µ½CMDQ_DATA_REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷ÖÐ £¬¶øºó´ÓCMDQ_DATA__REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷Öд洢µÄµØÖ·pa_address+offsetÖжÁÈ¡Êý¾Ý·Åµ½CMDQ_DATA_REG_DEBUGÊý¾Ý¼Ä·ÅÆ÷ÖÐ £¬ÔÙ½«dma_address+offsetµØÖ·Òƶ¯µ½CMDQ_DATA_REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷ÖÐ £¬×îºó½«CMDQ_DATA_REG_DEBUGÊýÖµ¼Ä·ÅÆ÷Öб£ÁôµÄÊý¾ÝдÈëµ½CMDQ_DATA_REG_DEBUG_DSTµØÖ·¼Ä·ÅÆ÷Öд洢µÄdma_address+offsetµØÖ·ÖÐ £¬¼´*(dma_address+ offset) = *(pa_address + offset)¡£


£¨3£©ÔÚReami6²âÊÔ»úÖÐ £¬Ö´ÐÐPoC²âÊÔ £¬³É¹¦½«LinuxÅú¸Ä³Éminix¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾


²Î¿¼Á´½Ó£º

[1]https://github.com/MiCode/Xiaomi_Kernel_OpenSource/tree/cactus-p-oss/drivers/misc/mediatek/cmdq

[2]https://github.com/quarkslab/CVE-2020-0069_poc/blob/master/jni/kernel_rw.c

[3]https://blog.quarkslab.com/cve-2020-0069-autopsy-of-the-most-stable-mediatek-rootkit.html

[4]https://forum.xda-developers.com/android/development/amazing-temp-root-mediatek-armv8-t3922213

[5]https://source.android.com/security/bulletin/2020-03-01



±¦ÔËÀ³¹Ù·½ÍøÕ¾»ý¼«·ÀÓù³¢ÊÔÊÒ£¨ADLab£©


ADLab³ÉÁ¢ÓÚ1999Äê £¬ÊÇÖйú°²È«ÐÐÒµ×îÔç³ÉÁ¢µÄ¹¥·À¼¼Êõ×êÑг¢ÊÔÊÒÖ®Ò» £¬Î¢ÈíMAPP´òËãÖ÷Ìâ³ÉÔ± £¬¡°ºÚȸ¹¥»÷¡±¸ÅÏëÊ×ÍÆÕß¡£½ØÖ¹Ä¿Ç° £¬ADLabÒÑͨ¹ýCVEÀۼư䲼°²È«·ì϶1000Óà¸ö £¬Í¨¹ý CNVD/CNNVDÀۼư䲼°²È«·ì϶800Óà¸ö £¬³ÖÐøÎ¬³Ö¹ú¼ÊÍøÂ簲ȫÁìÓòÒ»Á÷Ë®×¼¡£³¢ÊÔÊÒ×êÑз½Ïòº­¸Ç²Ù×÷ϵͳÓëÀûÓÃϵͳ°²È«×êÑÓ×¢ÒÆ¶¯ÖÇÄÜÖն˰²È«×êÑÓ×¢ÎïÁªÍøÖÇÄÜÉ豸°²È«×êÑÓ×¢Web°²È«×êÑÓ×¢¹¤¿ØÏµÍ³°²È«×êÑÓ×¢ÔÆ°²È«×êÑС£×êÑгɾÍÀûÓÃÓÚ²úÆ·Ö÷Ìâ¼¼Êõ×êÑÓ×¢¹ú¶È³Áµã¿Æ¼¼ÏîÄ¿¹¥¹Ø¡¢×¨Òµ°²È«·þÎñµÈ¡£


±¦ÔËÀ³¡¤(ÖйúÇø)×îйٷ½ÍøÕ¾