kernel pwn 入门(四) ret2dir详细

介绍

ret2dir 是哥伦比亚大学网络安全实验室在 2014 年提出的一种辅助攻击手法,主要用来绕过 smep、smap、pxn 等用户空间与内核空间隔离的防护手段
原论文见此处: ret2dir原文论文

参考:kernel pwn入门到大神
ret2dir

ret2dir原理

在开启了smep/smap后,内核空间到用户空间的直接访问被禁止,也就是传统的ret2usr失效了,如下图(图片来源于论文)。
在这里插入图片描述
为饶过这种限制,原文作者找到了一段区域,可以隐式的访问到用户空间数据。在内核空间就能访问到用户空间的数据,该区域也被称为phsymap,是很大一段的虚拟内存,映射了整个物理内存
这片区域叫做:direct mapping of all physical memory
在这里插入图片描述

这个映射区其实就是内核空间会与物理地址空间进行线性的映射,我们可以在这段区域直接访问到物理地址对应的内容。

在这里插入图片描述
下图就是在论文中对ret2dir这种攻击的示例图,不和ret2usr一样,指针不是指向用户空间,而是指向直接映射区域,在用户空间构造的payload也会映射到物理地址,所以只要在phsymap区域找到用户空间的payload就能执行。在高版本内核中 direct mapping area没有可执行权限需要通过ROP利用

在这里插入图片描述
因此若能获得指向存在payload的用户空间对应的物理地址在phsymap位置,就能够直接执行用户空间的payload

  1. 通过读取/proc/pid/pagemap可获取映射地址,该文件中存放了物理地址与虚拟地址的映射关系,可是该文件需要root权限才能读取.
  2. 利用堆喷技术phsymap区域填充大量payload,提高命中概率。

在这里插入图片描述

ret2dir手法总结:

  • 利用mmap或者堆喷技术在用户空间喷射大量相同的payload
  • 随机挑选direct mapping area上的地址,大概率命中写入的payload

pt_regs

系统调用:用户态布置好相应的参数后执行 syscall 进入到内核中的 entry_SYSCALL_64,随后通过系统调用表跳转到对应的函数

entry_SYSCALL_64 :当程序进入到内核态时,该函数会将所有的寄存器压入内核栈上,形成一个 pt_regs 结构体,该结构体实质上位于内核栈底.

entry_SYSCALL_64定义在arch/x86/entry/entry_64.S

在这里插入图片描述
pt_regs定义在arch/x86/include/asm/ptrace.h

struct pt_regs {
   
   
/*
 * C ABI says these regs are callee-preserved. They aren't saved on kernel entry
 * unless syscall needs a complete, fully filled "struct pt_regs".
 */
	unsigned long r15;
	unsigned long r14;
	unsigned long r13;
	unsigned long r12;
	unsigned long rbp;
	unsigned long rbx;
/* These regs are callee-clobbered. Always saved on kernel entry. */
	unsigned long r11;
	unsigned long r10;
	unsigned long r9;
	unsigned long r8;
	unsigned long rax;
	unsigned long rcx;
	unsigned long rdx;
	unsigned long rsi;
	unsigned long rdi;
/*
 * On syscall entry, this is syscall#. On CPU exception, this is error code.
 * On hw interrupt, it's IRQ number:
 */
	unsigned long orig_rax;
/* Return frame for iretq */
	unsigned long rip;
	unsigned long cs;
	unsigned long eflags;
	unsigned long rsp;
	unsigned long ss;
/* top of stack page */
};

内核栈只有一个页面的大小,而pt_regs固定在内核栈底部,当可以劫持到rip的时候,需要通过rop来控制rsp可以使用到pt_regs来构造ROP。

注意:

  • 在内核版本 5.13 之前 pt_regs 结构体栈顶的偏移值基本是固定的(因为内核栈只有一个 page),通常可以借助 add rsp, val ; ret 的 gadget 劫持一处函数指针就能实现进一步 ROP 利用。

  • 但是,在 5.13 及之后do_syscall_64 函数入口处,新增了一行
    add_random_kstack_offset();来源于 2021 年 的一个 commit,效果是在栈底的 pt_regs
    之上放了一个不超过 0x3FF 的偏移,使得利用的稳定性大幅下降。

模板:

__asm__(
    "mov r15,   0xbeefdead;"
    "mov r14,   0x11111111;"
    "mov r13,   0x22222222;"
    "mov r12,   0x33333333;"
    "mov rbp,   0x44444444;"
    "mov rbx,   0x55555555;"
    "mov r11,   0x66666666;"
    "mov r10,   0x77777777;"
    "mov r9,    0x88888888;"
    "mov r8,    0x99999999;"
    "xor rax,   rax;"
    "mov rcx,   0xaaaaaaaa;"
    "mov rdx,   8;"
    "mov rsi,   rsp;"
    "mov rdi,   seq_fd;"        // 这里假定通过 seq_operations->stat 来触发
    "syscall"
);

系统调用

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

saulgoodman-q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值