searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

如何在高通平台通过驱动漏洞提升到ROOT权限

2024-08-21 09:43:15
40
0

概述

本文档主要是针对高通平台驱动fastrpc某个漏洞介绍以下内容:接上一篇文章,在绕过地址随机化的情况下,如何提权到ROOT的逻辑分析。

提权过程

绕过厂商防护

由于镜像攻击将内核代码段映射为读写,且用户态可直接访问(页表AP位为01)。我可以通过该映射直接修改内核代码逻辑,从而绕过厂商的防护措施。

比如某厂商实现的防护措施是在系统调用后检查进程相关信息。具体实现在某函数A:

1.png

该函数首先执行相应的系统调用(0xffffff800809aaac),之后检查进程的UID,如果进程相关信息非法,则调用回调函数B:

2.png

该函数看上去是通知用户daemon有恶意进程。还有一个函数是except回调逻辑C:
3.png

我没有具体分析该函数的功能,绕过方式是篡改上述函数的逻辑,避免进行相关检查。具体实现方式是通过自己构造的页表项(镜像攻击)直接修改指令:一是将0xffffff800809aa9c位置的指令改为mov x19, #0x0。意味着不会进行相关检查A;二是将0xffffff800809ab80处指令改为ret,意味着B直接返回;三是将0xffffff800809acfc处指令改为ret,意味着C直接返回。

构造读写原语

为了方便地读写内核内存,需要构造读写原语。我使用的方法是:在内核代码段写入shellcode,然后回收未实现的系统调用,将系统调用表中相应跳转地址指向shellcode。这样程序可以通过特定系统调用执行内核中的shellcode。

目前,为了对内核代码段进行block类型的映射,代码段size按照映射粒度圆整。所以,代码段有部分未使用的内存。我直接将以下shellcode写入该内存:

4.png

这两个shellcode实现读写原语:写原语第一个参数是值,第二个参数是地址;读原语第一个参数任意,第二个参数为地址,读取的值通过返回值返回给用户。下面需要解决的问题是如何执行该shellcode。我使用的方法是借助系统调用:选择任意两个未实现的系统调用,将其调用表中的地址改为shellcode的地址,这样通过系统调用即可执行shellcode。

提升进程权限

此时,我们需要将进程权限提升,主要手段是修改进程的UID和GID。修改之前,我需要找到进程的task_struct对象,然后确定cred位置,最后修改相关数据。

内核使用task_struct->tasks将所有进程组织到双向链表中。内核init_task是全局变量,绕过地址随机化后,我可以轻易地找到该对象,通过遍历链表,即可找到目标进程(根据进程名字,comm)。

找到之后,我可以轻易地找到cred,修改相关数据即可。

运行适配DEMO

确认内核驱动版本一致后,运行ksma程序,具体操作如下:

  1. 请先配置好NDK,该漏洞使用的是android-ndk-r21b-linux-x86_64,不同版本会对成功率造成一定程度的影响
  2. make(编译程序并将二进制文件push到手机/data/local/tmp/中)
  3. adb shell data/local/tmp/ksma(泄露内核地址)
  4. 通过将得到的seed传入给pwn中
  5. ./pwn [addr] (提权)

程序执行成功后会弹出ROOT的shell:
7.png

0条评论
0 / 1000
txyzj
4文章数
0粉丝数
txyzj
4 文章 | 0 粉丝
原创

如何在高通平台通过驱动漏洞提升到ROOT权限

2024-08-21 09:43:15
40
0

概述

本文档主要是针对高通平台驱动fastrpc某个漏洞介绍以下内容:接上一篇文章,在绕过地址随机化的情况下,如何提权到ROOT的逻辑分析。

提权过程

绕过厂商防护

由于镜像攻击将内核代码段映射为读写,且用户态可直接访问(页表AP位为01)。我可以通过该映射直接修改内核代码逻辑,从而绕过厂商的防护措施。

比如某厂商实现的防护措施是在系统调用后检查进程相关信息。具体实现在某函数A:

1.png

该函数首先执行相应的系统调用(0xffffff800809aaac),之后检查进程的UID,如果进程相关信息非法,则调用回调函数B:

2.png

该函数看上去是通知用户daemon有恶意进程。还有一个函数是except回调逻辑C:
3.png

我没有具体分析该函数的功能,绕过方式是篡改上述函数的逻辑,避免进行相关检查。具体实现方式是通过自己构造的页表项(镜像攻击)直接修改指令:一是将0xffffff800809aa9c位置的指令改为mov x19, #0x0。意味着不会进行相关检查A;二是将0xffffff800809ab80处指令改为ret,意味着B直接返回;三是将0xffffff800809acfc处指令改为ret,意味着C直接返回。

构造读写原语

为了方便地读写内核内存,需要构造读写原语。我使用的方法是:在内核代码段写入shellcode,然后回收未实现的系统调用,将系统调用表中相应跳转地址指向shellcode。这样程序可以通过特定系统调用执行内核中的shellcode。

目前,为了对内核代码段进行block类型的映射,代码段size按照映射粒度圆整。所以,代码段有部分未使用的内存。我直接将以下shellcode写入该内存:

4.png

这两个shellcode实现读写原语:写原语第一个参数是值,第二个参数是地址;读原语第一个参数任意,第二个参数为地址,读取的值通过返回值返回给用户。下面需要解决的问题是如何执行该shellcode。我使用的方法是借助系统调用:选择任意两个未实现的系统调用,将其调用表中的地址改为shellcode的地址,这样通过系统调用即可执行shellcode。

提升进程权限

此时,我们需要将进程权限提升,主要手段是修改进程的UID和GID。修改之前,我需要找到进程的task_struct对象,然后确定cred位置,最后修改相关数据。

内核使用task_struct->tasks将所有进程组织到双向链表中。内核init_task是全局变量,绕过地址随机化后,我可以轻易地找到该对象,通过遍历链表,即可找到目标进程(根据进程名字,comm)。

找到之后,我可以轻易地找到cred,修改相关数据即可。

运行适配DEMO

确认内核驱动版本一致后,运行ksma程序,具体操作如下:

  1. 请先配置好NDK,该漏洞使用的是android-ndk-r21b-linux-x86_64,不同版本会对成功率造成一定程度的影响
  2. make(编译程序并将二进制文件push到手机/data/local/tmp/中)
  3. adb shell data/local/tmp/ksma(泄露内核地址)
  4. 通过将得到的seed传入给pwn中
  5. ./pwn [addr] (提权)

程序执行成功后会弹出ROOT的shell:
7.png

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0