Home avatar

PAWNYABLE kernel ebpf 笔记

这里 pwn ebpf 的逻辑是让 verifier 对数据的范围估算错误,从而越界访问或者有任意读写的效果。

eBPF Docs ebpf 的自己的文档

BPF数据传递的桥梁——BPF Map(一) – My X Files

ebpf 的 maps 创建之后返回一个 fd,因此可以在 user 和 kernel 的空间访问这个 map 里面的数据。

字节码可以参考 【译】eBPF 概述:第 2 部分:机器和字节码 | Head First eBPF

可以不用 c 来写一个 ebpf 程序,能直接用宏来写 ebpf 的机器码,比如 linux/samples/bpf/bpf_insn.h 里面定义的

PAWNYABLE kernel FUSE 笔记

userfaultfd 可以在驱动读写数据的时候,触发中断,切换到用户空间。此时可以将数据释放,释放的内存被其他结构体占有,然后就能进行 uaf_read 或者 uaf_write,。

自 Linux kernel 5.11 版本起,非特权用户被禁止使用 userfaultfd 系统调用,但是我们仍能通过 FUSE 达成同样的效果(在用户空间实现文件系统的机制,本身不是一个文件系统)。

fuse 的文件系统包括 CephFS、GlusterFS、ZFS、sshfs、mailfs。访问 FUSE 的文件系统,可以使用和内核文件系统相同的接口。

实现主要由三个部分组成

cve-2022-32250

学习了一段时间的 kernel pwn 之后,想去看看真实场景的 cve 是怎样的。看了一部分,有点太久了先咕咕咕,之后有时间再说…

分析这个 cve 的过程中遇到的比较大的阻碍是看分析源码比较晕,因为 nftables 不太熟悉。于是本文就从详细记录了一下利用命令行和 library 和 nftables 交互的方式,了解一个大致的结构和逻辑之后,看源码就轻松多了。

nft 是命令行工具,用于在用户空间与 nftables 交互,它的基本使用可以查看: How to Use nftables | Linode Docs。这是一个 Linux 数据包分类框架,有表、链、规则几个概念。

PAWNYABLE kernel userfaultfd 笔记

感觉这个是比较古老(2020 左右的)用法了,看看即可?

userfaultfd 可以类比成一个缺页异常的 handler,如果 handler 可以处理很久,那可能更好达到竞争的效果

参考 Kernel Pwn Syscall userfaultfd and Syscall setxattr - Wings 的博客

户通过userfaultfd系统调用接收文件描述符,并使用ioctl将处理程序和地址等设置应用于它。当设置了 userfaultfd 的页面(第一次访问)发生页面错误时,将调用设置的处理程序,用户可以指定返回哪种数据(映射)。

在 CTF 题中通常用来卡条件竞争. 当内核模块中有 copy from/to user 的时候, 内核模块会访问用户的空间. 如果我们传入的是一个被 uffd 监视的地址, 那么这个线程将会被挂起直到处理结束. 这样就能够控制内核中线程的执行顺序, 从而更好的达到想要的竞争效果.

大概是 linux-5.11 之后默认开启

对于没有 CAP_SYS_PTRACE 的用户以完全权限使用 userfaultfd ,必须将 unprivileged_userfaultfd 标志设置为 1。这个标志是 /proc/sys/vm/unprivileged_userfaultfd 可以通过 进行设置和查看,默认设置为0,但可以确认在LK04机器上设置为1。

先用 userfaultfd 系统调用获得一个 fd

Synology BC500 摄像头 rce | rwctf Lets-party-in-the-house

题目给了的附件有 player.cpio run.sh zImage 。原始固件可以从 Synology Archive Download Site - Index of /download/Firmware/Camera/BC500下载。

如果直接模拟固件,终端会被报错信息填满,可以在 /etc/init.d/rcS 使用 telnetd -p 23 -l /bin/sh 开启 telnet 服务,然后在脚本上加一个 hostfw 参数映射 telnet 到主机上进行操作。

shell

PAWNYABLE kernel double fetch 笔记

感觉就像是 toctou?先检查后使用?

c

static long module_ioctl(struct file *filp,
                         unsigned int cmd,
                         unsigned long arg) {
  if (verify_request((void*)arg))
    return -EINVAL;

  switch (cmd) {
    case CMD_GET: return copy_data_to_user(filp, (void*)arg);
    case CMD_SET: return copy_data_from_user(filp, (void*)arg);
    default: return -EINVAL;
  }
}

堆块的范围是 kmalloc-32,可以用 seq structure 获得 kernel base。

PAWNYABLE NULL Pointer Dereference 笔记

现在把基础的和 user mode 类似的部分看完了,该看内核独有的攻击咯。

  • 为了完成 null ptr dereference,需要先禁用 SMAP(内核从用户态读写数据)

  • 以及 cat /proc/sys/vm/mmap_min_addr 需要是 0。mmap 需要可以拿到地址为 0 的区域。

所以这么看起来,利用的条件还是比较原始的….

看 mondule_ioctl 的功能的话,这个模块可以基于 ctx->key 和 ctx->data 对数据进行亦或的加解密。

虽然 CMD_SETKEY 有检查 private_data 是否已经初始化。但是, CMD_GETDATACMD_ENCRYPTCMD_DECRYPT 没有此检查。就是说,如果 ctx 为 0 的话,也是可以进行 CMD_GETDATACMD_ENCRYPTCMD_DECRYPT 的,只不过是用了用户空间的数据。

mmap 的参数设置中:

  • MAP_FIXED 强制将映射的内存区域放置在指定的地址。

  • MAP_POPULATE : 在 mmap 调用中使用 MAP_POPULATE 标志主要是为了提前将映射的内存区域加载到物理内存中,而不是等到访问这些内存时才触发页面的加载。这对于一些需要确保快速访问内存的情况特别有用,尤其是当内存区域被映射为匿名内存 (MAP_ANONYMOUS) 时。

PAWNYABLE kernel heap overflow 笔记

slab 的结构虽然之前看过了好多,但是现在再看还是感觉有点迷糊。大概是 slab 上的块是没有 metadata 的,但是释放的时候和使用的时候状态不同,释放的时候会存指针。不过既然 kernel 修改链表指针的操作不像 ptmalloc 这么多,那就不太细看了(

本题的堆块申请大小是 0x400,和 tty structure 这个结构体申请的大小一样。大小一样的块物理地址可能相邻,所以溢出的时候可能可以复写到。