<div><div align="center">İnsanlar İçin Yığın Taşmaları 102

Başlangıçta, okuyucuya bağlantı kaldırma işleminin nasıl çalıştığı ve saldırgana keyfi bir yazma sağlamak için serbest listeden [n] flink / blink?in nasıl kontrol edilebileceği konusunda pratik bir çalışma bilgisi vermek amacıyla Windows?un eski sürümlerindeki yığın taşmalarından yararlanma tekniklerini tartıştım. 4 ilkel.

Bu makalenin temel amacı, kendimi yeniden eğitmek (unutkanım) ve güvenlik uzmanlarının, yığın yöneticisinin pencerelerin eski sürümleri (NT v5 ve altı) altında nasıl çalıştığına ilişkin teknik anlayışları kavramaya devam etmelerine yardımcı olmaktır. Bu, yığın taşmalarından veya bellek bozulmaları güvenlik açıklarından yararlanmak ve genel ?yazma 4? ü önlemeyi amaçlayan belirli azaltıcı önlemleri atlamak için yapılır. Ayrıca, okuyucunun daha yeni Windows yığın uygulamalarına saldırmak için hiç şüphesiz ihtiyaç duyulacak bir bilgi ölçütü oluşturma amacına hizmet eder.

Bu öğreticide, Windows XP SP2 / SP3 yığın koruma mekanizmalarını atlamak için yalnızca iyi bilinen bir uygulamaya özel teknik ayrıntılı olarak tartışılacaktır. Bu nedenle, hiçbir şekilde kesin bir rehber değildir ve yığının her yönünü kapsamaz. Devam etmek için, Windows XP / Server 2003?te yığın yapılarının nasıl çalıştığına dair biraz sağlam bir anlayışa ihtiyaç vardır.

Yalnızca bu öğreticinin amaçları doğrultusunda ve İnsanlar için Yığın Taşması 101?den gelen geri bildirimlere dayanarak, yığın iç bileşenlerinin bu ortamda nasıl çalıştığının bazı yönlerini tartışacağım.

Yığın tabanlı arabellek taşmalarına aşina değilseniz, en azından temel düzeyde, o zaman önce bu alana odaklanmanız önerilir.

Takip etmek için ihtiyacınız olacaklar:
- Yalnızca SP1 yüklü Windows XP.
? Yalnızca SP2 / SP3 yüklü Windows XP.
? Bir hata ayıklayıcı (Olly Debugger, Immunity Debugger, ms sembol sunucusuna erişimli windbg vb.).
? Bir c / c ++ compilier (Dev C ++, lcc-32, MS visual C ++ 6.0 (hala alabiliyorsanız)). ? Kolay bir betik dili (python kullanıyorum, belki perl kullanabilirsiniz).
? Bir beyin (ve / veya sebat).
? Bir miktar Assembly, C bilgisi ve Olly için HideDbg (eklenti) veya bağışıklık hata ayıklayıcı altında!
? Zaman.

Bir kahve alın ve bu gizemli siyah sanatı inceleyelim.

Peki bir yığın ve blok tam olarak nedir?
Varsayılan olarak, Windows yığın için belirli bir yapıya sahiptir. PEB?deki uzaklık 0x90?da, sıralı bir dizi yapısında (kronolojik sırayla) verilen işlem için yığınların bir listesini görebilirsiniz. Bazı yığın yapılarına bakalım:

Windbg kullanarak mevcut PEB?yi! Peb kullanarak bulabiliriz. Bağışıklık Hata Ayıklayıcı kullanıcısıysanız, bu bilgileri! Peb kullanarak da görüntüleyebilirsiniz. ! Peb için sağlanan çok basit kod aşağıdadır.

Kod:
from immlib import *
def main(args):
imm = Debugger()
peb_address = imm.getPEBAddress()
info = 'PEB: 0x%08x' % peb_address
return info
PEB?ye girdikten sonra süreç yığınlarını görebiliriz:

Kod:
+0x090 ProcessHeaps : 0x7c97ffe0 -> 0x00240000 ****
0x7c97ffe0 işaretçi konumunda

Kod:
0:000> dd 7c97ffe0

7c97ffe0 00240000 00340000 00350000 003e0000
7c97fff0 00480000 00000000 00000000 00000000
7c980000 00000000 00000000 00000000 00000000
7c980010 00000000 00000000 00000000 00000000
7c980020 02c402c2 00020498 00000001 7c9b2000
7c980030 7ffd2de6 00000000 00000005 00000001
7c980040 fffff89c 00000000 003a0043 0057005c
7c980050 004e0049 004f0044 00530057 0073005c
dword?lerin dökümünü alalım
Kalın yazılmış adresler, bu süreçte çalışan mevcut yığınlardır. Bu bilgi ayrıca windbg ve Immunity Debugger?da! Heap komutunu kullanarak bulunabilir.



Ek olarak, windbg?deki! Heap -stat komutunu kullanarak her bir yığınla ilgili istatistiksel bilgileri görüntüleyebilirsiniz. Aşağıda bunun örnek çıktısı verilmiştir:

Kod:
_HEAP 00030000
Segments 00000002
Reserved bytes 00110000
Committed bytes 00014000
VirtAllocBlocks 00000000
VirtAlloc bytes 00000000

Son olarak, Immunity Debugger?da -h ve -q bayrağını kullanarak yığınla ilgili bazı **** verileri dökebilirsiniz.



İlk yığın (0x00240000) varsayılan yığın iken, diğer yığınlar C bileşenlerinden veya yapılarından oluşturulur.

Çıktıdaki son yığın (0x00480000) uygulamamız tarafından oluşturuldu. Uygulama, ek öbek (ler) oluşturmak için HeapCreate () gibi bir çağrı kullanabilir ve işaretçileri PEB?de 0x90 ofsetinde saklayabilir. Aşağıda HeapCreate () için Windows API gösterilmektedir.

Kod:
HANDLE WINAPI HeapCreate(
__in DWORD flOptions,
__in SIZE_T dwInitialSize,
__in SIZE_T dwMaximumSize
);
HeapCreate () ?e doğru parametrelerle yapılan bir çağrı, EAX kaydında depolanan oluşturulan öbeğe bir işaretçi döndürecektir.

Argümanlar aşağıdaki gibidir:

Kod:
flOptions
+ HEAP_CREATE_ENABLE_EXECUTE: allow the execution of application code)
+ HEAP_GENERATE_EXCEPTIONS: An exception is raised when a call to HeapAlloc() or HeapReAlloc() is
called and can?t be fulfilled
+ HEAP_NO_SERIALIZE: Serialized access is not used when the heap functions access this heap

dwInitialSize
+ The initial size that is committed for the heap rounded up to the nearest page size (4k). If 0
is specified, then a single page size for the heap is set. The value must be smaller than
dwMaximumSize.

dwMaximumSize
+ The maximum size of the heap. If requests are made to HeapAlloc() or HeapReAlloc() that exceed
the dwinitialSize value, then the virtual memory manager will return page(s) of memory that will
fill the al******** request and the remainder of memory will be stored in the freelist. If
dwMaximumSize is 0, the heap can grow in size. The heap's size is limited only by the available
memory.
Bayraklar hakkında daha fazla bilgi msdn?de bulunabilir.
Aşağıda, önemli konumların vurgulanmış olduğu bir yığın yapısı tablosu verilmiştir.

Kod:
Address Value Description
0x00360000 0x00360000 Base Address
0x0036000C 0x00000002 Flags
0x00360010 0x00000000 ForceFlags
0x00360014 0x0000FE00 VirtualMemoryThreshold
0x00360050 0x00360050 VirtualAllocatedBlocks List
0x00360158 0x00000000 FreeList Bitmap
0x00360178 0x00361E90 FreeList[0]
0x00360180 0x00360180 FreeList[n]
0x00360578 0x00360608 HeapLockSection
0x0036057C 0x00000000 Commit Routine Pointer
0x00360580 0x00360688 FrontEndHeap
0x00360586 0x00000001 FrontEndHeapType
0x00360678 0x00361E88 Last Free Chunk
0x00360688 0x00000000 Lookaside[n]
Bu bilgiyi görüntülemek için windbg?de ?dt _heap? komutunu kullanabilirsiniz.

Yığın segmentleri

Daha önce bahsedildiği gibi, her yığın parçası bir yığın segmentinde saklanır. Bir bellek parçası serbest bırakılırsa, yığın segmentinde depolanmanın yanı sıra serbest listeye veya görünüm listesine eklenecektir.

Tahsis ederken, eğer yığın yöneticisi görünümde veya serbest listede herhangi bir kullanılabilir boş yığın bulamazsa, taahhüt edilmemiş alandan mevcut yığın segmentine daha fazla bellek ?işleyecektir?. Birçok ayırma nedeniyle çok fazla bellek işleniyorsa, bir yığın yapısı birçok segmente sahip olabilir.
Aşağıda, segment yığın yapısını gösteren bir tablo bulunmaktadır.

Kod:
Header Self Size (0x2) Prev Size (0x2) Segment index (0x1) Flag (0x1) Unused (0x1) Tag index (0x1)
Data
Yığın segmentlerini analiz ederken, windbg?de ?! Heap -a [heap address]? komutunu kullanırız.




Ek olarak, bağışıklık hata ayıklayıcısında ?! Heap -h [heap address] -c? komutunu kullanabilirsiniz (-c bayrağı yığınları gösterir)



Her segment kendi **** verilerini ve ardından segment içindeki veri yığınlarını içerir. Bu, segmentin kaydedilmiş hafızasıdır ve son olarak segment, kaydedilmemiş hafızanın bir bölümünü içerir. Artık analiz etmek istediğimiz segmenti bildiğimize göre, **** veri yapısını dökmek için ?dt _heap_segment [segment adresi]? komutunu kullanabiliriz.



Aşağıda, segment **** verilerinin yapısını içeren ayrıntılı bir tablo bulunmaktadır. Basit olması için, adres aralığını 0x00480000?den başlatacağız.

Kod:
Address Value Description
0x00480008 0xffeeffee Signature
0x0048000C 0x00000000 Flags
0x00480010 0x00480000 Heap
0x00480014 0x0003d000 LargeUncommitedRange
0x00480018 0x00480000 BaseAddress
0x0048001c 0x00000040 NumberOfPages
0x00480020 0x00480680 FirstEntry
0x00480024 0x004c0000 LastValidEntry
0x00480028 0x0000003d NumberOfUncommitedPages
0x0048002c 0x00000001 NumberOfUncommitedRanges
0x00480030 0x00480588 UnCommitedRanges
0x00480034 0x00000000 AllocatorBackTraceIndex
0x00480036 0x00000000 Reserved
0x00480038 0x00381eb8 LastEntryInSegment

Bir segmentteki önemli bilgiler ilk parçadır. Bu bilgi tek başına segmentte ?yürümek? için kullanılabilir, çünkü sadece boyutu ve ayrıntı düzeyini bilerek yığınları ve sonraki parçaları görüntüleyebilirsiniz.

Arka uç ayırıcı ? Freelist

Yığın yapısının 0x178 ofsetinde, FreeList [] dizisinin başlangıcını görebiliriz.
FreeList, çift bağlantılı bir yığın listesi içerir.
Hem flink hem de blink içerdikleri için çift bağlantılılar.




Yukarıdaki diyagram, serbest listenin 0-128 arasında değişen dizine alınmış yığın yığınları içerdiğini göstermektedir.

0 ile 1016 arasındaki herhangi bir yığın boyutu (maksimum boyut 1024 ? 8 bayt **** veri olduğundan 1016?dır), ayrılmış birim boyutuna göre depolanır * 8. Örneğin, serbest bırakılacak 40 baytlık bir parçam olduğunu söyleyin, sonra ben parçayı serbest listenin 4. Dizinine yerleştirir (40/8).

Bir yığın boyutu 1016 (127 * 8) baytın üzerindeyse, sayısal boyut sıralamasında serbest liste [0] girişinde depolanır.

Aşağıda, serbest liste parçasının bir açıklaması bulunmaktadır.

Kod:
Headers Self Size (0x2) Prev Size (0x2) Segment index (0x1) Flag (0x1) Unused (0x1) Tag index (0x1)
flink/blink Flink (0x4) Blink (0x4)
Data
Microsoft, serbest liste girişinin bağlantısının kaldırılmasına yönelik saldırıları önlemek için bazı azaltıcı önlemler yayınladı, aşağıda azaltıcı önlemlerin kısa bir açıklaması bulunmaktadır.

Serbest listenin güvenli bir şekilde ayrılması:

Güvenli bağlantı kesme, Microsoft tarafından Windows XP Sp2 ve sonraki sürümlerde uygulanan bir koruma mekanizmasıdır.

Temel olarak, İnsanlar için Yığın Taşması 101?de tartışıldığı gibi genel yazma 4 tekniğini engellemeye çalışan bir istismar azaltma işlemidir.

Bu kontrolde, önceki yığınlar ?flink? tahsis edilmiş parçamıza işaret eder ve bitişik parçalar yanıp söner.

Aşağıda, güvenlik mekanizmasının bir açıklaması ve şeması bulunmaktadır.

Kod:
Freelist chunk 1[flink] == Freelist chunk 2 && Freelist chunk 3[blink] ==Freelist chunk 2


Kırmızı ile gösterilen çizgiler, kontrolün yapıldığı yerdir.



Denetimlerden herhangi biri başarısız olursa, ntdll.dll?ye 0x7c936934?e atlama yapılır.

Gördüğünüz gibi, flink / blink?i kontrol eden bir kod eklememiz dışında, geleneksel bağlantısız bağlantımızla hemen hemen aynı.

Serbest Liste Başlık Çerezleri

Windows XP SP2?nin tanıtımı, öbek başlıklarının içine 0x5 ofsetinde yerleştirilen rastgele bir yığın tanımlama bilgisini gördü.

Bu çerez kontrolleri yalnızca serbest liste parçalarına sahiptir.

Aşağıda, güvenlik tanımlama bilgisinin vurgulanmış olduğu bir yığın parçasının görüntüsü bulunmaktadır.

Bu rastgele bir tek bayt girişidir ve bu nedenle 256 olası değerden oluşan maksimum olası rasgeleleştirmeye sahiptir.

Bu değeri çok iş parçacıklı bir ortamda zorla uygulayabileceğinizi unutmayın.




Ön Uç Ayırıcı ? Lookaside Görünüm Listesi

1016 baytın (en fazla: 1016 + 8) altındaki yığın parçalarını depolamak için kullanılan tek bağlantılı bir listedir.

Göz atma listesinin arkasındaki fikir, hız ve hızlı arama süresi sağlamaktır.

Bunun nedeni, uygulamaların işlemlerin çalışma zamanı sırasında birden çok HeapAlloc () ve HeapFree () ?yi çalıştırmasıdır.

Hız ve verimlilik için tasarlandığından, liste girişi başına 3?ten fazla boş parçaya izin vermez.

HeapFree () bir yığın üzerinde çağrılırsa ve bu belirli parça boyutu için zaten 3 girdi varsa, o zaman Freelist [n] ?ye serbest bırakılır.

Yığın yığın boyutu her zaman ayırmanın gerçek boyutuna + başlığı nedeniyle ek 8 bayt olarak hesaplanır.

Dolayısıyla, tahsis 16 bayt için yapılırsa, görünüm listesi 24 baytlık yığın boyutları için taranır (16 + yığın başlığı).

Aşağıdaki diyagram durumunda, pencere yığın yöneticisi başarılı olur ve görünüm listesinin 2. Dizininde kullanılabilir bir yığın bulur.

Lookaside listesi yalnızca bir sonraki kullanılabilir parçayı (kullanıcı verileri) gösteren bir flink içerir.

Kod:
Headers Self Size (0x2) Prev Size (0x2) Cookie (0x1) Flags (0x1) Unused (0x1) Segment index (0x1)
flink/blink Flink (0x4)
Data


Windows yığın yöneticisi bir ayırma isteği aldığında, isteği yerine getirebilecek boş yığın bellek parçalarını arar.

Optimizasyon ve hız için, Windows yığın yöneticisi ilk olarak (tek bağlantılı liste yapısı nedeniyle) başlangıçta görünüm listesinde gezer ve boş bir yığın bulmaya çalışır.

Eğer yığın burada bulunmazsa, Windows yığın yöneticisi arka uç ayırıcıyı deneyecektir.

Yığın yöneticisinin serbest listede dolaşacağı yer burasıdır (serbest liste [1]-serbest liste [127] arasında).

Hiçbir parça bulunmazsa, daha büyük bir yığın için serbest listedeki [0] girişini yürütür ve ardından yığınları böler.

Bir kısım öbek yöneticisine iade edilecek ve geri kalanı serbest listeye [n] dönecektir (n, boyut olarak kalan baytlara dayalı dizindir).

Bu bizi bir sonraki bölüm olan yığın işlemlerine getiriyor.

Temel Yığın İşlemleri

Yığın bölme: Yığın bölme, oldukça büyük bir parça için serbest listeye [n] erişme ve onu daha küçük parçalara ayırma işlemidir.

Serbest listede istenen tahsis boyutundan daha büyük bir parçaya erişildiğinde, yığın, istenen tahsis boyutunu karşılamak için ikiye bölünecektir.

Serbest listede [0] bunun 2048 baytlık tek bir yığın olduğunu varsayalım.

İstenen ayırma boyutu 1024 bayt (başlık dahil) ise, yığın bölünür ve 1024 baytlık yığın boyutu, arayana yeni tahsis edilmiş 1024 baytlık yığın döndürülürken serbest listeye [0] geri konur.

Yığın Birleştirme: Yığın birleştirme, merkez öbek de serbest bırakıldığında serbest kalan iki bitişik yığın bellek parçasını bir araya getirme eylemidir.

Yığın yöneticisinin bunu yapmasının nedeni, segment belleğini etkin bir şekilde kullanmaktır.

Tabii ki, parçalar serbest bırakıldığında verimlilikte bir değiş tokuş var.

Yığın birleştirme çok önemli bir işlemdir, çünkü birden fazla parça bir araya getirilebilir (bir kez ücretsiz) ve daha sonra daha büyük boyutlu diğer tahsisler için kullanılabilir.

Bu işlem gerçekleşmediyse, yığın segmentinde boşa harcanan yığınlar oluşur ve parçalara ayrılır.

Windows XP SP2 / 3 Güvenlik Mekanizmalarını Atlamak İçin Teknikler

Bakış kenarının bir kısmının üzerine yazmak:

Bu teknik, yığın tanımlama bilgilerini ve güvenli bağlantı kaldırma kontrollerini atlamak için en yaygın tekniktir.

Bu, bir write 4 ilkelini elde etmek için uygulamaya özgü bir teknik olsa da, bazı uygulamalar, güvenilir kullanım için yeterince yığın düzenini belirlemenize izin verebilir.

Lookside listesinde güvenli bir bağlantı kesme veya tanımlama bilgisi kontrolü olmadığından, bir saldırgan bitişik bir lookaside girişinde bulunan ?flink? değerinin üzerine yazabilir ve bu işaretçiyi bir HeapAlloc () veya HeapFree () çağrısı yoluyla yalnızca daha sonra kötü amaçlı kod yazmak için geri döndürebilir.

Sonraki kullanılabilir yığın.

Bunun görsel olarak nasıl çalıştığını görelim, derin nefes alalım.



1. Mevcut segmentte parça (A) ayırarak başlıyoruz




2. Daha sonra aynı segmentte başka bir parça (B) ayırıyoruz



3. Şimdi görünüm listesine (B) parçasını serbest bırakıyoruz, böylece iki giriş var, biri segment için, diğeri de görünüm listesi için



4. Şimdi yığın (A) ?yı taşıyoruz (Bu daha sonra yığın B?ye taşacak ve flinkini güncelleyecektir). Bu, üzerine yazılacak **** verilerdir

https://i.hizliresim.com/EqDYg4.jpg

5. Şimdi (B) parçasını yeniden ayırıyoruz (2. Adımdaki B öbeği ile aynı büyüklükte bir öbek ayırarak). Bu, öbek (B) için göstericiyi döndürür ve geçerli yığın bölütündeki referansını günceller ve bir sonraki tahsisat için hazır olur. Artık flink, yığın (B) olarak saldırganın yığın (A) taşmasından kontrol ettiği keyfi bir adrese güncellenir.



6. Şimdi parça (C) ayırarak kontrolü ele alıyoruz. Bu, yığın (B) ?den sonraki mevcut yığın olacak ve bu nedenle, yığın (B)? nin kontrollü flinkiyle de gösterilecektir. Saldırgan, yığın (C) ?yi kabuk koduyla doldurur.



Bu işlem tamamlandığında, ideal olarak yazma kontrolümüzden sonra çağrılacak olan üzerine yazılmış bir işlev işaretçisinin kontrolüne sahibiz.

Aşağıda göstereceğimiz C kodu yer almaktadır.

<div style="margin:20px; margin-top:5px"> Kod:
/*
Overwriting a chunk on the lookaside example
*/
#include
#include
int main(int argc,char *argv[])
{
char *a,*b,*c;
long *hHeap;
char buf[10];

printf("----------------------------\n");
printf("Overwrite a chunk on the lookaside\n");
printf("Heap demonstration\n");
printf("----------------------------\n");

// create the heap
hHeap = HeapCreate(0x00040000,0,0);
printf("\n(+) Creating a heap at: 0x00%xh\n",hHeap);
printf("(+) Allocating chunk A\n");

// allocate the first chunk of size N (