Final lfh presentation (3)

3,764 views
3,616 views

Published on

Slides of the presentation about the Low Fragmentation Heap at RSSIL 2012.

Published in: Technology, Spiritual
1 Comment
2 Likes
Statistics
Notes
  • stephaineweah@live.com

    Hello dear,my name is stephaine weah i am so happy to read your profile at (www.slideshare.net),please i will like us to know each other and to establish a strong relationship.contact me on my email (stephaineweah@live.com) to enable me share my picture with you and for you to know me more in further comminication.have a nice day.

    miss stephaine.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
3,764
On SlideShare
0
From Embeds
0
Number of Embeds
24
Actions
Shares
0
Downloads
83
Comments
1
Likes
2
Embeds 0
No embeds

No notes for slide

Final lfh presentation (3)

  1. 1. RSSIL 2012Exploiting the Low Fragmentation Heap for fun and profit Jeremy Fetiveau @__x86
  2. 2. Introduction● Why talking about the LFH? ○ heap exploitation ■ what is interesting to overwrite? ■ what if you deallocate twice a chunk of memory? ○ avoiding pray-after-frees ■ because you want to know where your chunks of memory will be ○ a few references
  3. 3. Introduction● A few talks about the LFH ○ Chris Valasek, Understanding the Low Fragmentation Heap" (BlackHat USA 2010) ○ Steven Seeley, Ghost in the Seven allocator (HITB 2012) ○ Chris Valasek & Tarjei Mandt, Heaps of Doom (Syscan 2012)● A few related talks ○ Ben hawkes, Attacking the Vista heap (BlackHat USA 2008) ○ Richard Johnson, Windows Vista Exploitation Countermeasures (ToorCon 2006)● A few references ○ Dr Valasek s whitepaper ○ Steven Seeleys blog (net-ninja)
  4. 4. Roadmap● How does it work? ○ Different managers ○ Choosing a manager ○ Overview of the managers ○ Front-End Allocation ○ Front-End Deallocation ○ Back-End Allocation ○ Back-End Deallocation● How to exploit? ○ Heap Feng Shui ○ SegmentOffset overwrites ○ FreeEntryOffset overwrites ○ Block Zone and subsegment overwrites ○ Double Frees ○ FTH, mitigation and what changed with Windows 8
  5. 5. Three managers Front-EndAlloc/Free Back-End VirtualAlloc/VirtualFree
  6. 6. The managers● A front-end manager : ○ The LFH ○ High performance, low fragmentation ○ Thread safe ○ Manages blocks less than 16k ○ Interesting when doing a lot of (de)allocations● A back-end manager ○ Manages blocks up to the decommit threshold (0xFE00) ○ Uses HintLists and a global FreeList● Greater blocks managed using VirtualAlloc and VirtualFree
  7. 7. Memory Commitment● Reservation● Commitment● Releasing● Decommitting● Decommit Threshold● NtAllocateVirtualMemory/NtFreeVirtualMemory
  8. 8. Choosing the manager● Done within : ○ RtlAllocateHeap ○ RtlFreeHeap ○ Chooses whether to use back-end functions or front- end functions● Back-end: ○ RtlpAllocateHeap ○ RtlpFreeHeap● Front-end: ○ RtlpLowFragHeapAllocFromContext ○ RtlpLowFragHeapFree
  9. 9. Choosing the manager● Allocation: ○ The "blink" field of a ListHint entry must point to a _HEAP_BUCKET structure + 1 ○ So if blink & 1, we have to use the LFH● Deallocation: ○ If ChunkHeader.UnusedByte & 0x80: use the LFH ○ Otherwise use the back-end ○ If ChunkHeader.UnusedByte==5, we have to readjust the chunk
  10. 10. A little schema to illustrate that...ListHints _HEAP_BUCKET Flink +0 BlocksUnits Blink +1 BlocksUnits use LFH +2 SizeIndex Flink +3 UseAffinity Blink Flink Blink Flink Blink Flink Blink Counter. Ex: 0x10 use back-end Flink BlinkBack-End
  11. 11. Enabling the LFH● Not enabled at the beginning● Not enabled for every chunk size● Heap must support serialization: ○ Adds mutual exclusion ○ Prevents corruption when several threads try to alloc/free from the same heap● Heap must not be debugged (set _NO_DEBUG_HEAP=1)● Can be enabled using HeapSetInformation● HeapEnableTerminationOnCorruption set by default
  12. 12. Enabling the LFHLFH enabled for a chunk size when counter forthe corresponding ListHint entry is >0x20Allocations increment the counterDeallocations decrement the counter● 0x12 consecutive allocations when LFH has never been enabled● 0x11 when enabled for another bucket
  13. 13. Enabling the LFH● When counter > 0x20: ○ RtlpGetLFHContext ○ Returns : ■ NULL if LFH has not yet been activated ■ _LFH_HEAP.bucket[size] ○ If context is null : set heap.CompatibilityFlags ○ If context not null : save _HEAP_BUCKET+1 in blink
  14. 14. Front End structures
  15. 15. Back End structures
  16. 16. Front-End Allocation● RtlAllocateHeap :1. Get the heap2. Get the correct BlocksIndex3. Get the correct ListHints entry4. Look at blink5. If blink & 1, use LFH, otherwise use back- end
  17. 17. Front-End Allocation1. Get _HEAP_BUCKET.sizeIndex2. Get _LFH_HEAP3. Get _HEAP_LOCAL_DATA4. Get the correct _HEAP_SEGMENT_INFO using sizeIndex5. Get a _HEAP_SUBSEGMENT
  18. 18. Note: There can be actually severalLocalData. To choose it, well useLocalDataIndex
  19. 19. _HEAP_BUCKET+1 sizeIndexFlinkBLink _HEAP_LOCAL_DATA LowFragHeap SegmentInfo[128]
  20. 20. Heap subsegment● Look at the Hint first● If first is empty, look at the active subsegment● If both subsegment are empty, allocate a segment from the back-end manager _HEAP_SEGMENT_INFO Hint 1 ActiveSubsegment 2
  21. 21. Hint and active subsegments● Hint: ○ Already freed a chunk of that size● Otherwise use active subsegment● Subsegment empty : ○ subsegment.AggregateExchg.depth==0
  22. 22. Allocating from subsegment● A subsegment gives you : ○ An interlock sequence ○ A user block● User block : ○ Contains committed memory● Interlock sequence: ○ The number of free chunks ○ The offset in blocks of the first free chunk ○ 1 block = 8 bytes
  23. 23. Allocating A Subsegment● RtlpLowFragHeapAllocateFromZone : ○ initializes and creates a new _HEAP_SUBSEGMENT● RtlpSubSegmentInitlialize: ○ creates a new userblock
  24. 24. 16 bytes Allocation Example UserBlock Interlock Sequence header Depth=5 FreeEntryOffset=2 Freenext: 0x4 Free Size of the header : 16 bytesnext: 0x6 FreeEntryOffset=2 block * 8 bytes = 16 bytes Freenext: 0x8 Freenext: 0xA Note: under windows 8, the default Free FreeEntryOffset is randomizednext: 0xFF
  25. 25. 16 bytes Allocation Example UserBlock Interlock Sequence header Depth=4 FreeEntryOffset=4 Busy Free Size of the header : 16 bytesnext: 0x6 FreeEntryOffset=4 block * 8 bytes = 32 bytes Freenext: 0x8 Freenext: 0xA Freenext: 0xFF
  26. 26. 16 bytes Allocation Example UserBlock Interlock Sequence header Depth=3 FreeEntryOffset=6 Busy Busy Size of the header : 16 bytes FreeEntryOffset=6 block * 8 bytes = 48 bytes Freenext: 0x8 Freenext: 0xA Freenext: 0xFF
  27. 27. 16 bytes Allocation Example UserBlock Interlock Sequence header Depth=2 FreeEntryOffset=8 Busy Busy Size of the header : 16 bytes FreeEntryOffset=8 block * 8 bytes = 64 bytes Busy Freenext: 0xA Freenext: 0xFF
  28. 28. Front-End Deallocation● If chunkHeader.UnusedBytes == 0x5 : ○ header must be readjusted ○ SegmentOffset used for readjusting● If chunkHeader.UnusedBytes & 0x80 ○ RtlpLowFragHeapFree ○ Dont forget the chunk may have been readjusted!● Otherwise, use RtlpFreeHeap
  29. 29. Front-End Deallocation● RtlpLowFragHeapFree: ○ Readjustment : ■ ChunkHeader - 8 * SegmentOffset ■ What if you overwrote SegmentOffset? ○ Set UnusedBytes to 0x80 ○ Set SegmentOffset to 0 ○ If interlock.depth==subsegment.blockCount : ■ Userblock is full, you have to use another subsegment or allocate a user block
  30. 30. Front-End Deallocation● Depth incremented● FreeEntryOffset updated● Sequence is updated● If user block is full : ○ Sequence set to 3 ○ User block will be freed by the back-end ○ PerformSubgSegmentMaintenance() ○ RtlpFreeUserBlock
  31. 31. 16 bytes Deallocation Example UserBlock Interlock Sequence header Depth=2 FreeEntryOffset=8 Busy Busy Chunk we want to free Busy Freenext: 0xA Freenext: 0xFF
  32. 32. 16 bytes Deallocation Example UserBlock Interlock Sequence header Depth=3 FreeEntryOffset=2 Freenext: 0x8 Busy Size of the header : 16 bytes FreeEntryOffset=2 block * 8 bytes = 16 bytes Busy Freenext: 0xA Freenext: 0xFF
  33. 33. 16 bytes Deallocation Example UserBlock Interlock Sequence header Depth=3 FreeEntryOffset=2 Freenext: 0x8 Busy Chunk we want to free Busy Freenext: 0xA Freenext: 0xFF
  34. 34. 16 bytes Deallocation Example UserBlock Interlock Sequence header Depth=4 FreeEntryOffset=6 Freenext: 0x8 Busy Size of the header : 16 bytes FreeEntryOffset=6 block * 8 bytes = 48 bytes Freenext: 0x2 Freenext: 0xA Freenext: 0xFF
  35. 35. 16 bytes Deallocation Example UserBlock Interlock Sequence header Depth=4 FreeEntryOffset=6 Freenext: 0x8 Busy Chunk we want to free Freenext: 0x2 Freenext: 0xA Freenext: 0xFF
  36. 36. 16 bytes Deallocation Example UserBlock Interlock Sequence header Depth=5 FreeEntryOffset=4 Freenext: 0x8 Free Size of the header : 16 bytesnext: 0x6 FreeEntryOffset=6 block * 8 bytes = 48 bytes Freenext: 0x2 Freenext: 0xA Freenext: 0xFF
  37. 37. Now the Back-End! Everythings okay? Any questions before continuing?
  38. 38. Back-End Allocation : do you recall?
  39. 39. Back-End Allocation● Get the _HEAP● Get the BlocksIndex● Its a _HEAP_LIST_LOOKUP● Contains an extended lookup● Contains a ListHints
  40. 40. Back-End Allocation● Is chunkSize < ArraySize?● If so, use this ListHints● Otherwise if no extendedLookup: ○ use ListHints[ArraySize-1]● If there is an extendedLookup ○ is chunkSize < extended.ArraySize?● If so, use this ListHints● Otherwise, use extended.ListHints[ArraySize- 1]
  41. 41. ListsInUseUlong : The Bitmap● Now that we have the ListHints : ○ Find the correct sized entry ○ Check whether this entry is populated or not ○ ListsInUseUlong allows that● ListsInUseUlong: ○ 4 byte integer ○ Each bit corresponds to an entry ○ 1 = some free chunk available ○ 0 = no free chunk available
  42. 42. Back-End Allocation● If the entry corresponding to the requested size is populated ○ Safe unlink the first free chunk pointed to by flink● Otherwise navigate through FreeList ○ Safe unlink the first chunk that is large enough to fit the request● If no chunk can fit the request : ○ RtlpExtendHeap● Then the bitmap is updated
  43. 43. 24 bytes Allocation Example The user requested 16 bytes. 16 bytes + 8 bytes of header = 24 bytes 3*8=24 bytes.+0x00 Bitmap indicates that ListHints[3] contains free chunks+0x03 ... ListsInUseUlong :+0x7F 0 0 0 1 ... 0 0
  44. 44. 24 bytes Allocation Example+0x00+0x03 ... ListsInUseUlong :+0x7F 0 0 0 1 ... 0 0
  45. 45. 24 bytes Allocation Example+0x00+0x03 ... ListsInUseUlong :+0x7F 0 0 0 0 ... 0 0
  46. 46. Another 24 bytes Allocation Example Problem : No chunk available at ListHints[3]+0x00+0x03 ...+0x7F
  47. 47. Another 24 bytes Allocation Example _HEAP FreeList +0x00 +0x03 ... +0x7F
  48. 48. Another 24 bytes Allocation Example _HEAP FreeList +0x00 +0x03 ... +0x7F
  49. 49. Another 24 bytes Allocation Example _HEAP FreeList +0x00 +0x03 ... +0x7F
  50. 50. Another 24 bytes Allocation Example _HEAP FreeList +0x00 +0x03 ... +0x7F
  51. 51. Another 24 bytes Allocation Example _HEAP FreeList +0x00 +0x03 ... +0x7F
  52. 52. Another 24 bytes Allocation Example _HEAP FreeList +0x00 +0x03 ... +0x7F
  53. 53. Another 24 bytes Allocation Example _HEAP FreeList +0x00 +0x03 ... Large enough! +0x7F
  54. 54. Another 24 bytes Allocation Example _HEAP FreeList +0x00 +0x03 ... +0x7F
  55. 55. Its time for exploitation! Everythings okay? Any questions before continuing?
  56. 56. Exploiting heap determinism● Now that you understand the LFH, you can predict what is going to happen● Heap Feng Shui : making alloc/dealloc to reorganize the heap layout in the desired way● Useful if you want to overflow into a particular heap chunk
  57. 57. Fragmentation problems Depth: 5Busy Busy Free Busy FreeEntryOffset: 6 next=12Busy Free Busy Free ● 2 consecutive allocations wont give adjacent next=16 next=18 blocks! ● We need to defragment memory: ○ fill the holesFree Busy Busy Busy ○ fill the subsegment so that a new one isnext=30 created ○ now consecutive allocations will give adjacent blocksBusy Busy Free Busy next=0xFF
  58. 58. Fragmentation problems Enable the LFH The next alloc will return the address of array2[0], the second one will return the address of array2[4]. (LFH is kind of LIFO) Defragment and allocate a new subsegment Now, the object is after our "user controlled" buffer
  59. 59. More detailsnext: 16 Objective: ● 2 adjacent chunks ● first block user controlled A Steps:next: 30 ● alloc B ● allocnext: 0x22 next=16 next: 2 ● alloc ● alloc toOverflow ● free B ● alloc toBeOverflowednext=30 next: 0xFF Result: C Busy The green frame will contain the next: 10 next=0xFF chunk we chose it the correct order.
  60. 60. More detailsnext: 2 Objective: ● 2 adjacent chunks ● first block user controlled A Steps:next: 30 ● alloc B ● allocnext: 0x22 next=16 ● alloc ● alloc toOverflow ● free B ● alloc toBeOverflowednext=30 next: 0xFF Result: C Busy The green frame will contain the next: 10 next=0xFF chunk we chose it the correct order.
  61. 61. More detailsnext: 30 Objective: ● 2 adjacent chunks ● first block user controlled A Steps: ● alloc B ● allocnext: 0x22 next=16 ● alloc ● alloc toOverflow ● free B ● alloc toBeOverflowednext=30 next: 0xFF Result: C Busy The green frame will contain the next: 10 next=0xFF chunk we chose it the correct order.
  62. 62. More detailsnext: 10 Objective: ● 2 adjacent chunks ● first block user controlled A Steps: ● alloc B ● allocnext: 0x22 next=16 ● alloc ● alloc toOverflow ● free B ● alloc toBeOverflowednext=30 next: 0xFF Result: C Busy The green frame will contain the next=0xFF chunk we chose it the correct order.
  63. 63. More detailsnext: 22 Objective: ● 2 adjacent chunks ● first block user controlled A Steps: ● alloc B ● alloc next=16 ● alloc ● alloc toOverflow ● free B ● alloc toBeOverflowednext=30 next: 0xFF Result: C Busy The green frame will contain the next=0xFF chunk we chose it the correct order.
  64. 64. More detailsnext: 12 Objective: ● 2 adjacent chunks ● first block user controlled A Steps: ● alloc B ● alloc next: 22 next=16 ● alloc ● alloc toOverflow ● free B ● alloc toBeOverflowednext=30 next: 0xFF Result: C Busy The green frame will contain the next=0xFF chunk we chose it the correct order.
  65. 65. More detailsnext: 22 Objective: ● 2 adjacent chunks ● first block user controlled A Steps: ● alloc B ● alloc next=16 ● alloc ● alloc toOverflow ● free B ● alloc toBeOverflowednext=30 next: 0xFF Result: C Busy The green frame will contain the next=0xFF chunk we chose it the correct order.
  66. 66. Remarks● Be aware that new/delete and HeapAlloc/HeapFree dont use the same heap● Of course this example is very simple, but its purpose is only to show that you can manipulate the heap layout
  67. 67. SegmentOffset overwrites● Introduces user-after-frees or double-frees ○ You can overflow a chunk so as to put its UnusedBytes to 5 and set SegmentOffset so as to point to an interesting chunk ○ Thus we could free a C++ object for exemple ○ Then we allocate a chunk and get ... the C++ object ○ We can overwrite what we want: VPTR, variables etc.
  68. 68. SegmentOffset overwrites
  69. 69. FreeEntryOffset overwrites● During front-end allocation, FreeEntryOffset is updated : ○ Each chunk managed by a user block contains an offset stored within its first 2 bytes (part of the data) ○ If you overflow this so as to point to your desired object, youll end-up by modifying aggregateExchg. freeEntryOffset so as to points to it ○ The next allocated block will be at the desired address● Introduces use-after-frees or double-frees
  70. 70. FreeEntryOffset overwritesYou may have to reorganize the heap layout.Who tells you that the overflowed free chunk isthe next chunk to be allocated?
  71. 71. FreeEntryOffset overwrites We modified the FreeEntryOffset so that bazinga is the same as bla
  72. 72. Double Free1.free(foo)2.alloc(bar) // bar==foo3.free(foo) // == free(bar)4.alloc(dawg) // dawg==foo● Thus dawg=>foo and bar=>foo● ex: dawg is a c++ object and bar user controlled● using bar, we could change bars VPTR
  73. 73. Example
  74. 74. Calls virtual functionVPTR
  75. 75. Subsegment overwrite● If you overwrite Userblocks pointer of a _HEAP_SUBSEGMENT youve got a "write- what-where"
  76. 76. Block zones_LFH_BLOCK_ZONE _LFH_BLOCK_ZONE _LFH_BLOCK_ZONEListEntry ListEntry ListEntryLimit Limit LimitFreePointer FreePointer FreePointer_HEAP_SUBSEGMENT _HEAP_SUBSEGMENT _HEAP_SUBSEGMENT
  77. 77. Block zones overwritesWhat happened ? ● We filled the userblock ● We overwrote the block zone ● The next allocation cant be done using the userblock previouslyused ● So another one is allocated... ● ...from our overwritten block zone
  78. 78. _HEAP_UCR_DESCRIPTOR● UCR = "UnCommitted Range"● Static offset from the first allocation in a segment● Points to the next reserved region
  79. 79. _HEAP_UCR_DESCRIPTOR _HEAP_UCR_DESCRIPTOR ListEntry SegmentEntry Address Size_HEAP_UCR_DESCRIPTOR Overflowed buffer
  80. 80. Overwriting heap base● If you can control the heap base, youve won ○ functions pointers ○ pointers to LFH/back-end structures ○ canaries ○ etc
  81. 81. Fault Tolerant Heap● Monitors crashes● Part of the "Diagnostic Policy Service"● Enabled after a certain heuristic has occured● Prevents corruptions like double frees or heap overruns● HKLMSoftwareMicrosoftFTH : ○ CrashVelocity is the number of crashes that has to occur within CrashWindowInMinutes to enable the FT ○ Enabled ○ ExclusionList ○ MaximumTrackedApplications (128) ○ MaximumTrackedProcesses (4) ○ CheckPointPeriod ( 7 days)
  82. 82. Mitigations● Heap base randomization● Part of the chunk headers are encoded (size, flags and smallTagIndex)● Safe (un)link● Heap cookies● Encoding of function pointers present in the heap base● Termination on heap corruption● Algorithm variation
  83. 83. Whats new with Windows 8?● Blinks are no longer used to point to a _HEAP_BUCKET +1● Allocations from the LFH are now made in a random order● FreeEntryOffset is no longer used● BlockZones integrity is now checked● Guard pages between userblocks● Segment Offset protection● Fast failing with NtStopProfile
  84. 84. GreetingsSpecial thanks to Ivanlefou for helping me and reviewing mypresentation.And thanks a lot to Chris Valasek and Steven Seeley for theirwork.Thanks to 0verclok for his review.Thanks to Tetrane for his sponsor
  85. 85. Questions?Thank you for your attention!

×