> For the complete documentation index, see [llms.txt](https://lightc.gitbook.io/pwn-gitbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lightc.gitbook.io/pwn-gitbook/kpwn/kpwn-tricks/cve-2022-42703.md).

# CVE-2022-42703

[Exploiting CVE-2022-42703 - Bringing back the stack attack - Project Zero](https://projectzero.google/2022/12/exploiting-CVE-2022-42703-bringing-back-the-stack-attack.html)

## 栈控制

`CPU`处理特定中断和异常时（包含用户态和内核态的中断和异常）会切换到静态的虚拟地址处的栈，不同异常使用不同的栈

[23. Page Table Isolation (PTI) — The Linux Kernel documentation](https://docs.kernel.org/arch/x86/pti.html)

在处理中断和异常时会将一些通用寄存器压入栈中，处理完成后弹出栈用于恢复上下文

在这篇文章中，可以看见我们通过整数除零异常泄露了内核`text`段基址

[QEMU-nday](/pwn-gitbook/kpwn/kpwn-tricks/qemu-nday.md)

`#DB(Debug Exception)`调试异常也可以触发

[80386 Programmer's Reference Manual -- Section 12.2](https://pdos.csail.mit.edu/6.828/2004/readings/i386/s12_02.htm)

有六个`80386`寄存器只能在特权级`0`时可以通过`MOV`的变体指令进行访问

* `DR0\~DR3`：调试地址寄存器，保存与四个断点条件（由`DR7`控制）之一相关联的线性地址
* `DR7`：调试控制寄存器
* `DR6`：调试状态寄存器

可以通过`ptrace(2)`设置硬件断点，通过读取、写入、获取指令触发断点，**关键的是这些硬件断点也可以在内核模式触发**，例如`copy\_to/from\_user`，由此产生的异常将通过非随机化的异常栈保存和恢复内核上下文

`copy\_to/from\_user`处理硬件断点时，正在使用的任何寄存器都可能因为我们利用任意写覆盖异常栈中保存的寄存器值而被破坏，`rcx`寄存器控制着`copy\_to/from\_user`调用的大小，而触发硬件断点会让内核把`rcx`压入异常栈，通过任意地址写破坏这个保存的值，返回执行`copy\_to/from\_user`时恢复被破坏的`rcx`，可以导致内核在用户空间与内核空间之间非法复制过多字节

## 流程

1. 进程`X`通过`fork`分出进程`Y`
2. 进程`X`通过`ptrace`跟踪进程`Y`，在进程`Y`的已知虚拟地址`addr`设置硬件断点
3. 进程`Y`大量调用`uname(2)`系统调用，该调用通过`copy\_to\_user`将内核栈缓存区数值复制到`addr`地址，内核持续触发硬件监视并进入`DB`异常处理，使用`DB`异常栈保存和恢复`copy\_to\_user`的执行状态
4. 与此同时，在`DB`异常栈保存`rcx`值的已知位置进行大量任意写，控制`copy\_to\_user`执行的长度
5. 这样内核会将当前任务的大部分栈数据复制回用户空间，通过这些数值可以帮助我们绕过很多防护
6. 随后我们反向运用该技术，使用`prctl(2)`让内核从用户空间向内核任务栈复制大量数值，通过再次破坏`rcx`制造原本不存在的栈缓存区溢出
