Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Windows 10 Nt Heap Exploitation (English version)

2,233 views

Published on

Windows 10 Nt Heap Exploitation (English version)

Published in: Technology
  • Be the first to comment

Windows 10 Nt Heap Exploitation (English version)

  1. 1. Windows Heap Exploitation Angelboy
  2. 2. Windows Heap Exploitation • Windows Memory Allocator • NT heap • BackEnd • Exploitation • FrontEnd • LowFragmentationHeap • Exploitation
  3. 3. Windows memory allocator • Memory allocator in Win10 is very complicated, there are mainly two kind of memory allocator. • Nt Heap • Default memory allocator • SegmentHeap • New memory allocator in Win10 • Some system process and UWP will use.
  4. 4. Windows memory allocator • Nt Heap can be divided into • Back-End • Front-End • LowFragmentationHeap • In order to prevent memory fragmentation problem, it will enable LFH after allocating a certain number of the same size of chunk. (e.g. Continuously allocate same size of chunks 18 times) • Size <= 0x4000
  5. 5. Windows memory allocator • The slide based on win10 (1809) • OS build - 17763.379 • Later versions may not be completely correct • 1903 is very smimilar • The structure of heap often change a lot. In the new release version, you need to trace the structure and workflow by yourself.
  6. 6. Windows memory allocator • Overview Kernel32.dll HeapAlloc HeapFree msvcrt140.dll malloc free ntdll.dll RtlAllocateHeap RtlFreeHeap ntdll.dll RtlpAllocateHeap RtlpFreeHeap ntdll.dll RtlpLowFragHeapAlloc RtlpLowFragHeapFree Kernel Front-End Back-End
  7. 7. Windows memory allocator • When we call malloc if LFH is disable. Kernel32.dll HeapAlloc HeapFree msvcrt140.dll malloc free ntdll.dll RtlAllocateHeap RtlFreeHeap ntdll.dll RtlpAllocateHeap RtlpFreeHeap Kernel Back-End
  8. 8. Windows memory allocator • When we call malloc at the first time or when 
 memory pool called userblock of LFH is used 
 up if LFH is enable. • It will use back-end allocator to allocate 
 userblock for LFH. Kernel32.dll HeapAlloc HeapFree msvcrt140.dll malloc free ntdll.dll RtlAllocateHeap RtlFreeHeap ntdll.dll RtlpAllocateHeap RtlpFreeHeap ntdll.dll RtlpLowFragHeapAlloc RtlpLowFragHeapFree Kernel Front-End Back-End
  9. 9. Windows memory allocator • When we allocate the same size after enabling LFH,
 it will use front-end allocator and use userblock in 
 LFH Kernel32.dll HeapAlloc HeapFree msvcrt140.dll malloc free ntdll.dll RtlAllocateHeap RtlFreeHeap ntdll.dll RtlpLowFragHeapAlloc RtlpLowFragHeapFree Front-End
  10. 10. Windows memory allocator • HEAP can be divide into • Process Heap • Default heap • The heap shared by the entire process, it will be used when you use windows API • Stored in _PEB • Used in CRT function • Stored in crt_heap
  11. 11. Windows memory allocator • HEAP can be divide into • Private heap • Create by HeapCreate
  12. 12. Windows memory allocator • Core data structure • _HEAP_ENTRY (chunk) • The basic structure of memory allocator • It is different in front-end and back-end, but it use same name.
  13. 13. Windows memory allocator • _HEAP_ENTRY (chunk) data chunk header chunk header data _HEAP chunk header . . . malloc return value
  14. 14. Windows memory allocator • Core data structure • _HEAP • The core structure of memory allocator, it is used to manage the heap. • Each heap correspond to a _HEAP structure, usually at the beginning of the heap
  15. 15. Windows memory allocator • _HEAP • EncodeFlagMask • It will be set to 0x100000 after heap initialization. It’s used to determine whether to encode the header of the chunk in the heap • Encoding (_HEAP_ENTRY) • It’s used to do xor with chunk header … EncodeFlagMask0x7c 0x80 0x138 Encoding … BlocksIndex … FreeList … FrontEndHeap … 0x150 0x198 FrontEndHeapUsageData0x1a8 …
  16. 16. Windows memory allocator • _HEAP • BlocksIndex (_HEAP_LIST_LOOKUP_) • The core structure in back-end allocator used to manage chunks. • FreeList (_HEAP_ENTRY) • A linked list used to collect all freed chunk in back-end • Similar as unsorted bin in libc • Sorted list … EncodeFlagMask0x7c 0x80 0x138 Encoding … BlocksIndex … FreeList … FrontEndHeap … 0x150 0x198 FrontEndHeapUsageData0x1a8 …
  17. 17. Windows memory allocator • _HEAP • FrontEndHeap • A pointer pointed to the structure of front-end heap • FrontEndHeapUsageData • Record the number of chunks used by various sizes. • When it reaches a certain level, it will enable the Front-End allocator of the corresponding chunk. … EncodeFlagMask0x7c 0x80 0x138 Encoding … BlocksIndex … FreeList … FrontEndHeap … 0x150 0x198 FrontEndHeapUsageData0x1a8 …
  18. 18. Windows memory allocator • Nt Heap • Back-End • Front-End
  19. 19. Nt heap • Nt Heap • Back-End • Data structure • Memory allocation mechanism
  20. 20. Windows memory allocator • _HEAP_ENTRY (chunk) • Divided into • Allocated chunk • Freed chunk • VirtualAlloc chunk
  21. 21. Nt heap • _HEAP_ENTRY (chunk) • PreviousBlockPrivateData • The data of the previous chunk, because chunk must be aligned to a multiple of 0x10 • Size • The size of chunk. • The value is right shift by 4 bits. User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  22. 22. Nt heap • _HEAP_ENTRY (chunk) • Flag • Indicates whether the chunk is busy • SmallTagIndex • Checksum is the xor of the first three bytes • It will be used to verify the header of chunk User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused xor
  23. 23. Nt heap • _HEAP_ENTRY (chunk) • PreviousSize • The size of previous chunk. • The value is right shift by 4 bits. User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  24. 24. Nt heap • _HEAP_ENTRY (chunk) • Unusedbyte • The remaining size of chunk after allocation • It can be used to determine the status of chunk (front-end or back-end) • User Data • The data used by user User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  25. 25. Nt heap • _HEAP_ENTRY (chunk) • Flink • Point to the next chunk in the linked list • Blink • Point to the previous chunk in the linked list • Unusedbyte • Must be zero User Data PreviousBlockPrivateData (8byte) Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) freed Flink Blink
  26. 26. Nt heap • _HEAP_VIRTUAL_ALLOC_ENTRY (mmap chunk) • Flink • Point to the next chunk of VirtualAlloc • Blink • Point to the previous chunk of VirtualAlloc User Data Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) inused Flink Blink …
  27. 27. Nt heap • _HEAP_VIRTUAL_ALLOC_ENTRY (mmap chunk) • Size • The size here refers to unused size without shifting • Unusedbyte • Must be 4 User Data Size (2byte) Flag (1byte) SmallTagIndex (1byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) inused Flink Blink …
  28. 28. Nt heap • FreeLists (_HEAP_ENTRY) • After free a chunk, it will be placed in FreeLists and will be inserted in FreeLists according to the size. Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData
  29. 29. Nt heap Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateDat … EncodeFlagMask0x7c 0x80 0x138 Encoding … BlocksIndex … FreeList … FrontEndHeap … 0x150 0x198 FrontEndHeapUsageData0x1a8 … Flink Blink _HEAP
  30. 30. Nt heap • Remark • About header encoding • Every chunk header will be xor with _HEAP->Encoding • It will be verified when it is decoded • The verification method is to check whether the checksum is correct. • The xor of the first three bytes and compare with fourth byte.
  31. 31. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • It is mainly used to manage freed chunks of various sizes, so that it can quickly find suitable chunks.
  32. 32. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • ExtendedLookup (_HEAP_LIST_LOOKUP) • Point to next ExtendedLookup • The next BlocksIndex will manage larger chunks • ArraySize • The max chunk size that will be managed by the BlocksIndex. • The first BlocksIndex ArraySize will by 0x80 (Actually is 0x800) BlocksIndex ExtendedLookup0x0 ArraySize0x8 … ItemCount (4 bytes) OutofRangeItems (4 bytes) 0x10 0x14 BaseIndex0x18 ListHead ListsInUseUlong ListHint 0x20 0x28 0x30
  33. 33. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • ItemCount • The number of chunks in the BlocksIndex • OutofRangeItems • The number of chunks that exceed the size managed by this BlocksIndex BlocksIndex ExtendedLookup0x0 ArraySize0x8 … ItemCount (4 bytes) OutofRangeItems (4 bytes) 0x10 0x14 BaseIndex0x18 ListHead ListsInUseUlong ListHint 0x20 0x28 0x30
  34. 34. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • BaseIndex • The starting index of the chunk in the Blocksindex. • It is used to find a suitable freed chunk in ListHint • The next BaseIndex of next BlocksIndex is the maximum value of current BaseIndex. • ListHead (_HEAP_ENTRY) • FreeList 的 Head BlocksIndex ExtendedLookup0x0 ArraySize0x8 … ItemCount (4 bytes) OutofRangeItems (4 bytes) 0x10 0x14 BaseIndex0x18 ListHead ListsInUseUlong ListHint 0x20 0x28 0x30
  35. 35. Nt heap • BlocksIndex (_HEAP_LIST_LOOKUP) • ListsInUseUlong • Used to determine whether there is a suitable chunk in ListHint, which is a bitmap • ListHint • Important structure in back-end. • A pointer array which point to the corresponding size of chunk array. • The goal is to find the suitable chunk faster. • The interval of chunk size is 0x10 BlocksIndex ExtendedLookup0x0 ArraySize0x8 … ItemCount (4 bytes) OutofRangeItems (4 bytes) 0x10 0x14 BaseIndex0x18 ListHead ListsInUseUlong ListHint 0x20 0x28 0x30
  36. 36. … EncodeFlagMask Encoding … BlocksIndex … FreeList … FrontEndHeap … FrontEndHeapUsageDat … _HEAP BlocksIndex ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Flink Blink Chunk header (0x110) PreviousBlockPrivate Flink Blink Chunk header(0x160) PreviousBlockPrivat ListHint Flink Flink Flink ListHint[7] ListHint[0x11] ListHint[0x16] 000001…1…1000000000 ListsInUseUlong
  37. 37. Nt heap • Nt Heap • Back-End • Data structure • Memory allocation mechanism
  38. 38. Nt heap • Allocate (RtlpAllocateHeap) • It can be divided into • Size <= 0x4000 • 0x4000 < size <= 0xff000 • Size > 0xff000
  39. 39. Nt heap • Allocate (RtlpAllocateHeap) • Size <= 0x4000 • The memory allocation is implemented in RtlpAllocateHeap • First, it will check whether FrontEndHeapStatusBitmap corresponds to the size is set (which indicates if LFH is enabled) • If not, add 0x21 to the corresponding FrontEndHeapUsageData • And check if the value exceeds 0xff00 or (& 0x1f) is larger than 0x10 • If true, it will enable LFH.
  40. 40. Nt heap • Allocate (RtlpAllocateHeap) • Size <= 0x4000 • Next, it will check whether ListHint corresponds to the size has a value. If true, it will take the chunk in ListHint first. • If there is a suitable chunk on the ListHint, remove the ListHint, and see whether the size of chunk's Flink is the same size. • If true, replace the ListHint with Flink • If not, clear the ListHint. • Finally, unlink the chunk to remove the chunk from the linked list and return it to user.
  41. 41. Nt heap • Allocate (RtlpAllocateHeap) • Size <= 0x4000 • If there is no suitable chunk • Search from the larger ListHint. If it finds a large one, remove it from the ListHint. • Then split the chunk and insert remaining chunk into freelist and put into ListHint.
  42. 42. Nt heap • Allocate (RtlpAllocateHeap) • Size <= 0x4000 • If there is no suitable chunk in FreeList • Try ExtendHeap to increase heap space, then take the chunk from it
  43. 43. Nt heap • Allocate (RtlpAllocateHeap) • 0x4000 < size <= 0xff000 • Everything is similar except without LFH-related operations
  44. 44. Nt heap • Allocate (RtlpAllocateHeap) • Size > 0xff000 (VirtualMemoryThreshold << 4) • Use ZwAllocateVirtualMemory directly • Similar to mmap, it will allocate large memory block , and will be inserted into _HEAP->VirtualAllocdBlocks • _HEAP->VirtualAllocdBlocks is linked list used to collect all VirtualAllocate chunk in back-end
  45. 45. Nt heap • Free (RtlpFreeHeap) • Divide into • Size <= 0xff000 • Size > 0xff000
  46. 46. Nt heap • Free (RtlpFreeHeap) • Size <= 0xff000 • It will check the alignment first and use the unused byte to determine the chunk state • If LFH is disable, decrease 1 to the corresponding FrontEndHeapUsageData • Then it will check whether the previous chunk or next chunk is freed. If it is freed, then coalesce them. • Unlink the coalesced chunk and remove from ListHint.
  47. 47. Nt heap • Free (RtlpFreeHeap) • Size <= 0xff000 • After the coalescence, update size & prevsize, and check whether it is the front or last of FreeList. If true, then insert into FreeList. If not, insert into ListHint and update it. • It will check the linked list integrity when inserting • But this check won’t terminate the process.
  48. 48. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Free(Q) Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7)
  49. 49. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find Prevchunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Prevchunk = Chunk address - (prevsize << 4)
  50. 50. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find Prevchunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Prevchunk = chunk addr - 0x70
  51. 51. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Decode prevchunk
 header Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7)
  52. 52. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check checksum Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) SmallTagInex ==
 (size & 0xff) xor (size >> 8) xor Flag
  53. 53. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check checksum Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) 7 ==
 0x7^0x0^0x0
  54. 54. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 linked list Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) P->Flink->Blink == 
 P->Blink->Flink == 
 P
  55. 55. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find 
 BlocksIndex Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7)
  56. 56. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find suitable 
 BlocksIndex Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Check P->size < ArraySize
  57. 57. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 ListHint Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Check ListHint[7] == Prevchunk
  58. 58. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 ListHint Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Check prevchunk->Flink == ListHead If true, update
 ListHint
  59. 59. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 ListHint[7]->Flink Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) decode prevchunk->Flink And check the checksum Because the previous slide is not true, it
 will check the size
 of Flink
  60. 60. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 ListHint[7]->Flink Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Size == 
 prevchunk->Flink->size If true, replace ListHint
 with Flink

  61. 61. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Update
 ListHint[7] Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) ListHint[7] =
 prevchunk->Flink
  62. 62. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Flink Blink Chunk header (0x70) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Unlink
 prevchunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x7) Flag (0x0) SmallTagIndex (0x7) Prevchunk->Blink->Flink
 = Prevchunk->Flink
 Prevchunk->Flink->Blink = Prevchunk->Blink
  63. 63. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Update
 prevchunk
 and next chunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Prevchunk->size =
 0x11 + Prevchunk->size(7) R->Prevsize = 0x18 P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  64. 64. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Check
 next chunk Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Check if next chunk
 is freed P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  65. 65. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Find suitable
 BlocksIndex
 For P Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Check
 P->Size < ArraySize P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  66. 66. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Search
 insert
 point Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Check
 P->size < ListHead->Blink->Size
 P->size < ListHead->Flink->Size P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  67. 67. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Insert
 linked list Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) Check
 S->Blink->Flink
 == S If not pass it will not 
 abort
 But it will not unlink P Flink Blink Chunk header (0x180) PreviousBlockPrivate
  68. 68. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Update
 ListHint Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x7) If LintHint[0x18] == NULL
 LintHint[0x18] = P P Flink Blink Chunk header (0x180) PreviousBlockPrivate FlinkListHint[0x18]
  69. 69. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Update
 header Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0x18) Flag (0x0) SmallTagIndex (0x18) SmallTagIndex = 
 (size >> 8) ^
 (size & 0xff) ^
 Flag P Flink Blink Chunk header (0x180) PreviousBlockPrivate FlinkListHint[0x18]
  70. 70. ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint Flink Blink Chunk header(0x110) PreviousBlockPrivat FlinkListHint[7] Flink Blink Chunk header(0x70) PreviousBlockPrivat merge chunk P Q R S Encode
 header Size (0x11) Flag (0x1) SmallTagIndex (0x10) Prevsize (0x7) Size (0xda) Flag (0xab) SmallTagIndex (0x41) P->header ^
 _HEAP->Encoding P Flink Blink Chunk header (0x180) PreviousBlockPrivate FlinkListHint[0x18]
  71. 71. Nt heap • Free (RtlpFreeHeap) • Size > 0xff000 • Check the linked list integrity and remove from _HEAP- >VirtualAllocdBlocks • Then use RtlpSecMemFreeVirtualMemory to munmap the chunk
  72. 72. Back-End Exploitation • Unlink • Similar bypass method in Linux. • In short, use the behavior of removing nodes from linked list. • It should be noted that the checksum must correct when decoding chunk. • The good thing is that Flink and Blink are directly point to UserData, that is, you don’t have to forge chunk header
  73. 73. Back-End Exploitation • Unlink • Q->Blink->Flink = Q->Flink • Q->Flink->Blink = Q->Blink Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData QP R
  74. 74. Back-End Exploitation • Unlink • Q->Blink->Flink = Q->Flink • Q->Flink->Blink = Q->Blink Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData QP R
  75. 75. Back-End Exploitation • Unlink • Q->Blink->Flink = Q->Flink • Q->Flink->Blink = Q->Blink Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x110) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData QP R
  76. 76. Back-End Exploitation • Unlink • Q->Blink->Flink = Q->Flink • Q->Flink->Blink = Q->Blink Flink Blink Chunk header (0x70) PreviousBlockPrivateData Flink Blink Chunk header (0x160) PreviousBlockPrivateData QP R
  77. 77. A A Chunk header (0x110) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint UAF T A
  78. 78. A A Chunk header (0x110) PreviousBlockPrivate Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint Free(Q) T A
  79. 79. Q A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A A ListHead QListHint[0x11] free(S) Update ListHint
  80. 80. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A A S SListHint[0x11] Q ListHead
  81. 81. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A A S SListHint[0x11] Q ListHead Let’s corrupt the heap !
  82. 82. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead free(P)
  83. 83. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Check next chunk 
 is free
  84. 84. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Decode 
 chunk Q
  85. 85. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead(&Q-8)->Blink == (&Q)->Flink == Q
  86. 86. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead(&Q-8)->Blink == (&Q)->Flink == Q Flink Blink
  87. 87. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead(&Q-8)->Blink == (&Q)->Flink == Q Flink Blink
  88. 88. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead*(&Q) == *(&Q) == Q
  89. 89. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead*(&Q) == *(&Q) == Q Pass the check !!
  90. 90. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Find 
 BlockIndex
  91. 91. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Check
 ListHint[0x11]
  92. 92. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHeadBecause S != Q
 it will not replace
 ListHint with Q
  93. 93. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex Data Pointer ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Unlink !! Q->Blink->Flink = Q->Flink Flink Blink
  94. 94. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P &Q - 8 R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHeadUnlink !! Q = &Q-8
  95. 95. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P &Q - 8 R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHead Unlink !! Q->Flink->Blink = Q->Blink Flink Blink
  96. 96. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHeadUnlink !! Q = &Q
  97. 97. S A Chunk header (0x110) PreviousBlockPrivate Q Chunk header (0x110) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat P Q R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A &Q - 8 &Q SListHint[0x11] Q ListHeadUpdate 
 chunk size
  98. 98. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHeadUpdate 
 chunk size P
  99. 99. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead Search insert point P
  100. 100. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHeadFind the last one And decode it P
  101. 101. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead P Find the first one And decode it
  102. 102. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHeadIt want to insert 
 in front of A P
  103. 103. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead Check
 A->Blink->Flink == A P
  104. 104. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead Check
 Q->Flink == A P
  105. 105. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHeadFailed
 but not aborting It will not insert P
  106. 106. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead Update 
 ListHint P
  107. 107. S A Chunk header (0x220) PreviousBlockPrivate Chunk header(0x50) PreviousBlockPrivat S Chunk header(0x110) PreviousBlockPrivat R S P &Q R S T ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint BlockIndex ListHint T A SListHint[0x11] Q ListHead P PListHint[0x22]
  108. 108. Back-End Exploitation • Edit Q • We can overwrite the pointer around Q • Finally, we can do arbitrary memory reading and writing. P &Q R S T
  109. 109. Back-End Exploitation • Edit Q • We can overwrite the pointer around Q • Finally, we can do arbitrary memory reading and writing. • We can overwrite Target 1 - 4 P Target 1 Target 2 Target 3 Target 4
  110. 110. Back-End Exploitation • After arbitrary memory reading and writing • Leak • ntdll.dll • PebLdr • binary address • Kernel32.dll
  111. 111. Back-End Exploitation • After arbitrary memory reading and writing • Leak • kernelbase • KERNELBASE!BasepFilterInfo • Stack address
  112. 112. Back-End Exploitation • After arbitrary memory reading and writing • Leak • ntdll.dll • _HEAP_LOCK • _HEAP->LockVariable.Lock • CriticalSection->DebugInfo • Point to ntdll
  113. 113. Back-End Exploitation • After arbitrary memory reading and writing • Leak • ntdll!PebLdr • _PEB_LDR_DATA • You can find all the location of dll • However the drawback is that the last two byte may be 0. • You can find the binary base first and find kernel32 from IAT
  114. 114. Back-End Exploitation • After arbitrary memory reading and writing • Leak • BinaryBase • Find kernel32 from IAT
  115. 115. Back-End Exploitation • After arbitrary memory reading and writing • Leak • Kernel32 • Important dll • Many useful function(CreateFile, ReadFile,WriteFile) • IAT • Find kernelbase.dll
  116. 116. Back-End Exploitation • After arbitrary memory reading and writing • Leak • kernelbase • KERNELBASE!BasepFilterInfo • Point to the structure on heap • You have high probability to find stack pointer in the structure • https://j00ru.vexillium.org/2016/07/disclosing-stack-data-from-the-default- heap-on-windows/
  117. 117. Back-End Exploitation • After arbitrary memory reading and writing • Leak • If there is no stack address in BasepFilterInfo • You can find stack address in TEB which usually locate one page before or after PEB
  118. 118. Back-End Exploitation • After arbitrary memory reading and writing • Write • Return address • Control RIP • ROP to VirtualProtect/VirtualAlloc • Jmp to shellcode
  119. 119. Windows memory allocator • Nt Heap • Back-End • Front-End
  120. 120. Windows memory allocator • Nt Heap • Front-End • Commonly use in win10 • LowFragmentationHeap • Only enable in non-debug mode • Size < 0x4000
  121. 121. Windows memory allocator • Nt Heap • Front-End • Data Structure • Memory allocation mechanism
  122. 122. Windows memory allocator • Nt Heap • Front-End • Data Structure • Memory allocation mechanism
  123. 123. LFH • FrontEndHeap (_LFH_HEAP) • HEAP (_HEAP) • Point to the corresponding _HEAP • Buckets (_HEAP_BUCKET) • An array to find the malloc size corresponding to the block size … Heap0x18 0x2a4 … Buckets SegmentInfoArray … … LocalData 0x4a8 0xcc0
  124. 124. LFH • FrontEndHeap (_LFH_HEAP) • SegmentInfoArray (_HEAP_LOCAL_SEGMENT_INFO) • _HEAP_LOCAL_SEGMENT_INFO array • Different sizes correspond to different Segment_info structures, to manage the information of the corresponding Subsegment. • LocalData (_HEAP_LOCAL_DATA) • One of the fields points to the LFH itself, which is usually used to retrieve the LFH. … Heap0x18 … Buckets SegmentInfoArray … … LocalData 0x2a4 0x4a8 0xcc0
  125. 125. LFH • Buckets (_HEAP_BUCKET) • BlockUnits • The block size >> 4 • SizeIndex • Required size >> 4 BlockUnits Buckets SizeIndex … BlockUnits SizeIndex … … … Buckets[0] Buckets[1]
  126. 126. LFH • SegmentInfoArray (_HEAP_LOCAL_SEGMENT_INFO) • LocalData (_HEAP_LOCAL_DATA) • Corresponding to _LFH_HEAP- >LocalData to retrieve _LFH_HEAP from SegmentInfo • BucketIndex • The index in Buckets[] LocalData SegmentInfoArray[x] ActiveSubsegment CachedItems … BucketIndex …
  127. 127. LFH • SegmentInfoArray (_HEAP_LOCAL_SEGMENT_INFO) • ActiveSubsegment (_HEAP_SUBSEGMENT) • Very important structure • Corresponding to the assigned Subsegment • To maintain Userblock • Record number of remaining chunk • The maximum number of chunk in Userblock SegmentInfoArray[x] LocalData ActiveSubsegment CachedItems … BucketIndex …
  128. 128. LFH • SegmentInfoArray (_HEAP_LOCAL_SEGMENT_INFO) • CachedItems (_HEAP_SUBSEGMENT) • _HEAP_SUBSEGMENT array • Stored the available Subsegment correspond to the SegmentInfo • When the ActiveSubsegment used up, it will reload from CachedItems. SegmentInfoArray[x] LocalData ActiveSubsegment CachedItems … BucketIndex …
  129. 129. LFH … Heap … … … LocalData 0x18 0x2a4 0x4a8 0xcc0 Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO … EncodeFlagMask Encoding … BlocksIndex … FreeList … FrontEndHeap … FrontEndHeapUsageData … _HEAP LocalData ActiveSubsegment CachedItems … BucketIndex …
  130. 130. LFH • ActiveSubsegment (_HEAP_SUBSEGMENT) • LocalInfo (_HEAP_LOCAL_SEGMENT_INFO) • Point back to corresponding _HEAP_LOCAL_SEGMENT_INFO LocalInfo ActiveSubsegment UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … 0x0 0x8 0x20 0x24 0x28 0x2a
  131. 131. LFH • ActiveSubsegment (_HEAP_SUBSEGMENT) • UserBlock (_HEAP_USERDATA_HEADER) • Memory pool of LFH • That is, the location of chunk (Block) • Some metadata will manage the chunks at the beginning of UserBlock • Important ! LocalInfo ActiveSubsegment UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … 0x0 0x8 0x20 0x24 0x28 0x2a
  132. 132. LFH • ActiveSubsegment (_HEAP_SUBSEGMENT) • AggregateExchg (_INTERLOCK_SEQ) • To indicate remaining amount of freed chunk in Userblock • LFH uses it to determine if it should allocate from this UserBlock LocalInfo ActiveSubsegment UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … 0x0 0x8 0x20 0x24 0x28 0x2a
  133. 133. LFH • ActiveSubsegment (_HEAP_SUBSEGMENT) • BlockSize • The size of each block (chunk) in the UserBlock • BlockCount • The number of blocks in the UserBlock • SizeIndex • The SizeIndex corresponding to the UserBlock LocalInfo ActiveSubsegment UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … 0x0 0x8 0x20 0x24 0x28 0x2a
  134. 134. LFH • AggregateExchg (_INTERLOCK_SEQ) • Depth • The remaining amount of freed chunk in UserBlock • Lock • Just a Lock AggregateExchg Depth0x0 Hint (15bit) Lock (1bit) 0x8
  135. 135. LFH • UserBlock (_HEAP_USERDATA_HEADER) • SubSegment • Point to corresponding Subsegment • EncodeOffsets • To verify chunk header integrity • BusyBitmap • Indicate which chunk is being used SubSegment UserBlock … EncodedOffsets BusyBitmap 0x8 0x18 0x20 chunk header chunk header chunk header
  136. 136. LFH • UserBlock (_HEAP_USERDATA_HEADER) • Block (chunk) • The allocated memory return to user. SubSegment UserBlock … EncodedOffsets BusyBitmap 0x8 0x18 0x20 chunk header chunk header chunk header
  137. 137. LFH • _HEAP_ENTRY (chunk) • SubSegmentCode • Encoded metadata to retrieve the location of UserBlock • PreviousSize • The index of the chunk in UserBlock User Data PreviousBlockPrivateData (8byte) SubSegmentCode (4byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  138. 138. LFH • _HEAP_ENTRY (chunk) • Unusedbyte • Unusedbyte & 0x80 must be true • To indicate it is LFH chunk User Data PreviousBlockPrivateData (8byte) SubSegmentCode (4byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Inused
  139. 139. LFH • _HEAP_ENTRY (chunk) • Unusedbytes • Must be 0x80 • To indicate it is LFH freed chunk User Data PreviousBlockPrivateData (8byte) SubSegmentCode (4byte) PreviousSize (2byte) SegmentOffset (1byte) Unusedbyte (1byte) Freed
  140. 140. LFH • Remark • About EncodedOffsets • EncodedOffsets is xor of the following values • (sizeof(userblock header) | (BlockUnit*0x10 << 16)) • LFHkey • Userblock address • _LFH_HEAP address
  141. 141. LFH • Remark • About LFH header encoding • The chunk header will xor with following values when initialization • _HEAP address • LFHkey • Chunk address >> 4 • ((chunk address) - (UserBlock address)) << 12
  142. 142. LFH … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex …
  143. 143. Windows memory allocator • Nt Heap • Front-End • Data Structure • Memory allocation mechanism
  144. 144. Windows memory allocator • Nt Heap • Front-End • Initialization • If FrontEndHeapUsageData[x] & 0x1f > 0x10, LFH will be initialized in next allocation • It will ExtendFrontEndUsageData and create new BlocksIndex (0x80-0x400) • Create FrontEndHeap • Initialize SegmentInfoArrays[idx] • It will start using front-end allocator from next allocation with same size
  145. 145. Windows memory allocator • LFH(Initialization) • malloc(0x40) * 16 FrontEndHeapUsageData … 0x210 The range of LFH is index from 0x0 to 0x80
  146. 146. Windows memory allocator • LFH(Initialization) • malloc(0x40) (17th) FrontEndHeapUsageData … 0x231 0x231 & 0x1f > 0x10
  147. 147. Windows memory allocator • LFH(Initialization) FrontEndHeapUsageData … 0x231 heap->CompatibilityFlag |= 0x20000000 After setting this flag, it will initialize
 LFH in the next allocation
  148. 148. Windows memory allocator … EncodeFlagMask Encoding … BlocksIndex … FreeList … FrontEndHeap … FrontEndHeapUsageData … _HEAP FrontEndHeapUsageData 0x231 BlocksIndex ExtendedLookup ArraySize … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex ListHead ListsInUseUlong ListHint
  149. 149. Windows memory allocator • LFH(Initialization) • malloc(0x40) (18th) • ExtendFrontEndUsageData and create new BlocksIndex (0x80-0x400) • The range of LFH is modified to index from 0x0 to 0x400 • Create and initialize FrontEndHeap (mmap) • initialize SegmentInfoArrays[idx] • Assign SegmentInfoArrays[BucketIndex] to segmentInfo FrontEndHeapUsageData … 0x4
  150. 150. Windows memory allocator … EncodeFlagMask Encoding … BlocksIndex … FreeList … FrontEndHeap … FrontEndHeapUsageData … _HEAP FrontEndHeapUsageData 0x251 0x4 BlocksIndex ExtendedLookup ArraySize(0x80) … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex (0x0) ListHead ListsInUseUlong ListHint BlocksIndex ExtendedLookup ArraySize (0x400) … ItemCount (4 bytes) OutofRangeItems (4 bytes) BaseIndex (0x80) ListHead ListsInUseUlong ListHint
  151. 151. Windows memory allocator … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalData ActiveSubsegment CachedItems … BucketIndex … … EncodeFlagMask Encoding … BlocksIndex … FreeList … FrontEndHeap … FrontEndHeapUsageData … _HEAP FrontEndHeapUsageData 0x251 0x4
  152. 152. Windows memory allocator • LFH(Initialization) • malloc(0x40) (19th) • Allocate Userblock and initialize every chunk. • Set the corresponding ActiveSubsegment to the UserBlock • Randomly return chunk to user Userblock metadata Chunk 00 Chunk 01 … Chunk MaxBlockCount
  153. 153. … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex …
  154. 154. Windows memory allocator • LFH • Allocate (RtlpLowFragHeapAllocFromContext) • It will check whether ActiveSubsegment has chunk available. • Check ActiveSubsegment->depth • If not, it will search from CachedItem, and replace ActiveSubsegment with CachedItem’s SubSegment if available.
  155. 155. … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex … Find SegementIfoArray by bucket->SizeIndex
  156. 156. … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex … Find SegementIfoArray by bucket->SizeIndex
  157. 157. … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex … Check ActiveSubsegment
  158. 158. … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex … Check ActiveSubsegment
  159. 159. … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex … Check ArgregateExchg.Depth not 0
  160. 160. … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex … Check ArgregateExchg.Depth not 0
  161. 161. … Heap … … … LocalData Buckets[x] SegmentInfoArray[x] BlockUnits SizeIndex … _LFH_HEAP _HEAP_BUCKET _HEAP_LOCAL_SEGMENT_INFO LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER LocalData ActiveSubsegment CachedItems … BucketIndex … Check Userblock
  162. 162. Windows memory allocator • LFH • Allocate (RtlpLowFragHeapAllocFromContext) • Retrieve RtlpLowFragHeapRandomData[x] • It will retrieve the value from RtlpLowFragHeapRandomData[x+1] next round. • x is 1 byte, x = rand() %256 after 256 rounds • RtlpLowFragHeapRandomData is a 256-byte array filled with random value • The range of random value is 0x0 - 0x7f
  163. 163. Windows memory allocator • LFH • Allocate (RtlpLowFragHeapAllocFromContext) • Finally, the index of chunk is • RtlpLowFragHeapRandomData[x]*maxidx >> 7 • Take the nearest chunk if collision • Check (unused byte & 0x3f) !=0 (indicate chunk is freed) • Modify index and unused byte in header and return to user
  164. 164. …. …. …. SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADER • Get an index • RtlpLowFragHeapRandomData[x]*maxidx >> 7 • Check if the BusyBitmap correspond to index is 0 • Return the chunk if true • Otherwise take the next nearest chunk chunk header
  165. 165. …. …. …. SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADER • If the index is inused • Take next nearest chunk • Set the bitmap to 1 chunk header
  166. 166. …. …. …. SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADER chunk header • If the index is inused • Take next nearest chunk • Set the bitmap to 1
  167. 167. Windows memory allocator • LFH • Free (RtlFreeHeap) • Update unused byte in chunk header • Find the index of the Chunk and reset Userblock->BusyBitmap • Update ActiveSubsegment->AggregateExchg • If the free chunk is not belong to ActiveSubsegment, it will try to put into cachedItems
  168. 168. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • Find UserBlock by chunk header
  169. 169. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • Find UserBlock by chunk header • Find corresponding SubSegment
  170. 170. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • Find UserBlock by chunk header • Find corresponding SubSegment • Assign unused byte to 0x80 • Clear the bitmap • Update AggregateExchg
  171. 171. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • Find UserBlock by chunk header • Find corresponding SubSegment • Assign unused byte to 0x80 • Clear the bitmap • Update AggregateExchg
  172. 172. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … Depth Hint (15bit) Lock (1bit) _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _INTERLOCK_SEQ _HEAP_USERDATA_HEADER • Free • Find UserBlock by chunk header • Find corresponding SubSegment • Assign unused byte to 0x80 • Clear the bitmap • Update AggregateExchg
  173. 173. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADERLocalData ActiveSubsegment CachedItems … BucketIndex … LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … _HEAP_SUBSEGMENT Depth (1) Hint (15bit) Lock (1bit) _INTERLOCK_SEQ CachedItems ActiveSubsegment 
 is not equivalent to
 SubSegment of free
 chunk
  174. 174. LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … _HEAP_SUBSEGMENT SubSegment … EncodedOffsets BusyBitmap chunk header chunk header chunk header _HEAP_USERDATA_HEADERLocalData ActiveSubsegment CachedItems … BucketIndex … LocalInfo UserBlock … AggregateExchg BlockSzie BlockCount … SizeIndex … _HEAP_SUBSEGMENT Depth (1) Hint (15bit) Lock (1bit) _INTERLOCK_SEQ CachedItems CachedItems[0]
  175. 175. LFH Exploitation • Reuse attack • If we have Use After Free • Because of randomness of LFH, we can not predict the next chunk. • We can fill up UserBlock and then free one of them, it will return same chunk in next allocation with same size.
  176. 176. LFH Exploitation • normal case • malloc(sizeof(A)) Userblock header
  177. 177. LFH Exploitation • normal case • malloc(sizeof(B)) Userblock header fptr
  178. 178. LFH Exploitation • normal case • free(A) Userblock header B fptr
  179. 179. LFH Exploitation • normal case • malloc(sizeof(A)) Userblock header B fptr
  180. 180. LFH Exploitation • normal case • malloc(sizeof(B)) Userblock header B fptr
  181. 181. LFH Exploitation • normal case • malloc(sizeof(B)) Userblock header B fptr Hard to use
  182. 182. LFH Exploitation • Reuse attack • malloc(sizeof(A)) Userblock header
  183. 183. LFH Exploitation • Reuse attack • malloc(sizeof(B)) x 6 Userblock header fptr
  184. 184. LFH Exploitation • Reuse attack • free(A) Userblock header B B B B fptr B B
  185. 185. LFH Exploitation • Reuse attack • malloc(sizeof(B)) Userblock header B B B B fptr B B
  186. 186. LFH Exploitation • Reuse attack • A->fptr Userblock header B B B B fptr B B
  187. 187. LFH Exploitation • Reuse attack • A->fptr Userblock header B B B B fptr B B Hijack the control flow !
  188. 188. Reference • https://github.com/saaramar/ 35C3_Modern_Windows_Userspace_Exploitation • http://illmatics.com/Understanding_the_LFH.pdf • https://github.com/saaramar/Deterministic_LFH
  189. 189. Thank you for listening angelboy@chroot.org @scwuaptx

×