Heaps About Heaps

Document Sample
Heaps About Heaps Powered By Docstoc
					HEAPS ABOUT HEAPS
                       This Talk Covers

Windows 2003
: Windows 2003 SP2
: Still most widely used windows server OS
: Still not a lot of heap exploits released
: Still not a lot of heap research released
: Vista -> Ben Hawkes BHUS08

Heap Explotation
: How the heap works
: Freelists vs Lookaside
: Exploitation Techniques

Heap Exploit Walkthrough
: From start to finish
                        Windows Heap

Multiple Heaps
: Process has default heap
: Can create separate heaps for different uses
: Some loaded .dll create their own heap
: Some .dlls hold pointer to the heap they use

State Of The Heap
: Server restart
: Service restart
: First request
: Long time live, multiple previous requests

Things That Matter
 : Everything, IP address, server name, day of the week
                     Heap Exploit Difficulties

Safe Unlinking
: On unlink, coalesce, relink from freelist
: Causes the link/unlink to fail if addresses readable
: Raises a handled exception, execution proceeds
: Chunk address still returned to caller

Cookie Check
: Cookie checked on free
: Invalid cookie prevents relinking of chunk

HeapSetInformation()
: HeapEnableTerminateOnCorruption()
: Windows Vista and Windows Server 2008
            Need To Get Creative In Exploitation Methods
                     A Heap In Motion


  Initial Heap
Heap Management      The heap object initially starts as an empty
                           contiguous block of memory.
 Last Free Chunk
      Header          Two structures are written into the heap.
 Last Free Chunk
      Space           The Heap Management structure contains
                     information regarding the heap object, and
                              tracks the heap chunks.

                     There is always one Free Chunk in the heap
                   object and it points to the free space at the end
                                     of the heap.
                         The Heap In Motion


  Initial Heap      Allocated A,B,C
Heap Management    Heap Management

 Last Free Chunk    Chunk A Header
      Header        Chunk A Space
 Last Free Chunk                       After the allocation of three
      Space         Chunk B Header    memory chunks, the heap layout
                    Chunk B Space           now looks like this

                    Chunk C Header
                    Chunk C Space

                    Last Free Chunk
                         Header
                    Last Free Chunk
                         Space
                         The Heap In Motion


  Initial Heap      Allocated A,B,C        Free B
Heap Management    Heap Management    Heap Management

 Last Free Chunk    Chunk A Header     Chunk A Header
      Header                                                Freeing a
                    Chunk A Space      Chunk A Space
 Last Free Chunk                                             chunk in
      Space                                               between two
                    Chunk B Header    Free Chunk Header
                                                           busy chunks,
                    Chunk B Space     Free Chunk Space    creates a Free
                                                              Chunk
                    Chunk C Header     Chunk C Header
                    Chunk C Space       Chunk C Space

                    Last Free Chunk    Last Free Chunk
                         Header             Header
                    Last Free Chunk    Last Free Chunk
                         Space              Space
                         The Heap In Motion


  Initial Heap      Allocated A,B,C          Free B              Free A
Heap Management    Heap Management     Heap Management      Heap Management

 Last Free Chunk    Chunk A Header       Chunk A Header     Free Chunk Header
      Header        Chunk A Space         Chunk A Space     Free Chunk Space
 Last Free Chunk
      Space         Chunk B Header     Free Chunk Header
                    Chunk B Space       Free Chunk Space

                    Chunk C Header       Chunk C Header      Chunk C Header
                              Free
                    Chunk C Space chunks that sit next to
                                       Chunk C Space          Chunk C Space
                                  each other are joined
                                         Last together.
                                  (Coalesced) Free Chunk
                    Last Free Chunk                          Last Free Chunk
                        Header               Header               Header
                    Last Free Chunk      Last Free Chunk     Last Free Chunk
                         Space                Space               Space
                          Heap Management Structure
                                               Heap Management
                                  Address     Value             Description
                                  00360000              Base Address
   All offsets hold settings
  These Flagsare from the
                                  0036000C   00000002   Flags
such as isDebug, Exception
  base of the Heap Object
  The maximum size of an
   Raising, and Executable        00360010   00000000   ForceFlags
              before
 allocation Heap a Virtual        00360014   0000FE00   VirtualMemoryThreshold
      Linked list of blocks
     Memory allocation is
   A four DWORD bitmask
    allocated from Virtual        00360050   00360050   VirtualAllocatedBlocks List
           performed
    with to the first if the
Pointer each bit setchunk in
            Memory                00360158   00000000   FreeList Bitmap
corresponding FreeList[n] is
           FreeList[0]            00360178   00361E90   FreeList[0]
 Start of populated
 FreeList[0] is used to store
           double linked lists    00360180   00360180   FreeList[n]
     to store CriticalSectionis
  Pointer to Free Chunks
 Free Chunks > 1016 bytes
   that to Function() the
Pointeris used to lock that       00360578   00360608   HeapLockSection
   called when the heap
  Pointerduring changesis
     heap to the front end        0036057C   00000000   Commit Routine Ptr
 expanded and more pages
            allocator.            00360580   00360688   FrontEndHeap
    This iscommitted Free
              stores settings
  Flag that pointer to the
   Pointera the 48 byte
      Start of the Last
             to                   00360586   00000001   FrontEndHeapType
      about the front end
           Lookaside
       Chunk in the heap
    Lookaside list headers        00360678   00361E88   Last Free Chunk
            allocator
                                  00360688   00000000   Lookaside[n]
      Heap Management Structure - Virtual Memory Allocation
                                               Heap Management
                                  Address     Value           Description
  EBX is set to Base Address     00360014   0000FE00   VirtualMemoryThreshold
       Check threshold           00360050   00360050   VirtualAllocatedBlocks List

                                                        00360050        FLINK
7C82AE14 CMP EDI,DWORD PTR DS:[EBX+14]                  00360054        BLINK
7C82AE17 JBE ntdll.7C82A2FC
...
7C82AE8E LEA EAX,DWORD PTR DS:[EBX+50]                      Load BLINK
...
7C82AE97 MOV EDX,DWORD PTR DS:[EAX+4]
...                                                     ECX is @NewChunk
7C82AEA0 MOV DWORD PTR DS:[ECX],EAX
7C82AEA2 MOV DWORD PTR DS:[ECX+4],EDX
7C82AEA5 MOV DWORD PTR DS:[EDX],ECX                    Write @NewChunk to
7C82AEA7 MOV DWORD PTR DS:[EAX+4],ECX                       @BLINK+4

  If the VirtualAllocatedBlocks->BLINK can be overwritten then the address of
              the NewChunk can be written to an arbitrary location
                 Heap Management Structure - FreeList Bitmap
                                                          Heap Management
                                          Address         Value                Description
     Bitmap is populated when
                                          00360158   00000000           FreeList Bitmap
     chunk added to FreeList[n]

80     00   00   02   00   00   80   00    00   00   00    00      00    00   00   00

 0-7             24-31          48-55                              Bitmap is checked when
                                                                   looking for a FreeList[n]
7C82A291 LEA ESI,DWORD PTR DS:[EBX+EDX*4+158]                        that fits the request
...
7C82A2A8 AND EAX,DWORD PTR DS:[ESI]
...
7C82A2B8 JNZ ntdll.7C82CB46                                       If a match is found then the
7C82A2BE TEST EAX,EAX                                             corresponding FreeList[n] is
7C82A2C0 JNZ ntdll.7C82C8C9                                          used for the allocation.
7C82A2C6 MOV EAX,DWORD PTR DS:[ESI]

     If the Bitmap can be manipulated then a pointer to an empty FreeList[n] can
         be returned, allowing the overwrite of management structures. [nico]
                 Heap Management Structure - FreeList Bitmap
                                                           Heap Management
                                           Address         Value                 Description
           FreeList[7] is
            populated                      00360158   00000000          FreeList Bitmap


80    00    00
            01   02   00    00   80   00    00   00   00    00     00    00      00    00


                                                                         FreeLists
            FreeList[16] is
            Modify bitmap                             Address            Value          Description
               empty
                                                      003601B0 00364D78 FreeList[7]
                                                           ...            ...         ...
     Request for block 16 will
     Request for block 16 will                        003601F8      003601F8 Overwrite
                                                                    XXXXXXXX FreeList[16]
      create a new block and
         return 003601F8                                            XXXXXXXX Overwrite
             return it
                                                                    XXXXXXXX Overwrite
                                                                    XXXXXXXX Overwrite
                                                                    XXXXXXXX Overwrite
     If the Bitmap can be manipulated then a pointer to an empty FreeList[n] can
         be returned, allowing the overwrite of management structures. [nico]
          Heap Management Structure - FreeList Bitmap


                       Part Of The Bitmap Loading Code

7C82C8AB MOVZX EAX,AH
7C82C8AE MOVSX EAX,BYTE PTR DS:[EAX+7C82BAB8]
7C82C8B5 ADD EAX,8
7C82C8B8 JMP ntdll.7C82C830
7C82C8BD MOVSX EAX,BYTE PTR DS:[ECX+7C82BAB8]
7C82C8C4 JMP ntdll.7C82C830                               [ 7C82BAB8 ]
7C82C8C9 LEA EDX,DWORD PTR DS:[EBX+178]              A Static Pointer To A Bit
7C82C8CF JMP ntdll.7C82C808                          Mask Table That Can Be
7C82C8D4 SHR EAX,18
                                                     Modified To Manipulate
7C82C8D7 MOVSX EAX,BYTE PTR DS:[EAX+7C82BAB8]
                                                        The Bitmap Result
7C82C8DE ADD EAX,18
7C82C8E1 JMP ntdll.7C82C830



If the Bitmap can be manipulated then a pointer to an empty FreeList[n] can
    be returned, allowing the overwrite of management structures. [nico]
           Heap Management Structure – FreeList[n]
                                                       Heap Management
                                     Address       Value             Description
FreeList[0] is similar to
                                 00360178        00361e90     FreeList[0]
 FreeList[n] but holds
 chunks > 1016 bytes             00360180        00360180     FreeList[n]

                                                              00360180        FLINK
                                                              00360184        BLINK

                Free Chunk Header
Header       Self Size   Prev Size    CK   FL     UN     SI
 Links              FLINK                      BLINK


                Free Chunk Header                                   Double Linked List
                                                                      connects free
Header       Self Size   Prev Size    CK   FL     UN     SI
                                                                     chunks together
 Links              FLINK                      BLINK
        Heap Management Structure - Commit Routine Pointer
                                                  Heap Management
                                    Address      Value            Description
    Custom function() called
                                   0036057C    00000000    Commit Routine Ptr
    when committing more
     memory to the Heap

                                                          Initially set to nothing
7C833BF9 MOV ECX,DWORD PTR DS:[EAX+57C]
7C833BFF TEST ECX,ECX
7C833C01 JNZ ntdll.7C852C9E
...
7C852C9E PUSH EBX
7C852C9F LEA EDX,DWORD PTR SS:[EBP+14]
7C852CA2 PUSH EDX                                        Loaded into ECX and called
7C852CA3 PUSH EAX
7C852CA4 CALL ECX



     This is a static pointer that can be overwritten to gain execution control
                    Heap Management Structure – Lookaside[n]
                                                       Heap Management
                                       Address        Value               Description
            Lookaside[0] and           00360688     00000000     Lookaside[n]
        Lookaside[1] are not used      003606E8                  Lookaside[2]

                                        48 byte structure
        Lookaside List Header
Address           Description
 +00        Pointer To First Chunk                   Lookaside Chunk Header

 +04        Depth                      Header     Self Size   Prev Size   CK    FL      UN   SI

 +06        Max Depth                  Links             FLINK

 +08
 +0C         Allocation tracking for                 Lookaside Chunk Header
             automatic Lookaside
 +10              Fine Tuning          Header     Self Size   Prev Size   CK    FL      UN   SI
  ...                                  Links             FLINK
                                    Heap Chunks


                     A Used Chunk                              Chunk Flags
Header   Self Size     Prev Size    CK   FL   UN   SI   00   Free
 Data                                                   01   Busy
                                                        02   Extra Present
              Chunk On Lookaside                        04   Fill Pattern
Header   Self Size     Prev Size    CK   FL   UN   SI   08   Virtual Alloc
Links           FLINK                                   10   Last Entry
 Data                                                   20   FFU1
                                                        40   FFU2
               Chunk On FreeList                        80   No Coalesce
Header   Self Size     Prev Size    CK   FL   UN   SI
Links           FLINK                    BLINK
 Data
                             Lookaside Lists

       Lookaside Starts                 Lookaside[n]
           Empty                      FLINK    003620D0
                                               00000000
                                               00362100
                                               003620E8
                                               XXXXXXXX
                                                                 This Value Gets
  Chunk Removed From
   Lookaside[n]->FLINK
        Chunk Added To               Address     FLINK           Copied To Here
                                                                     Copied
       Top Lookaside
       is corrupted
     Top OfOf Lookaside             003620D0
                                    00362100
                                    003620E8   XXXXXXXX
                                               00000000
                                               003620E8
                                               003620D0

                                     Address     FLINK
                                    003620E8
                                    003620D0   00000000
                                               003620D0
Overwrite the FLINK of The
About To Allocate From the           Address     FLINK
        top chunk
       Lookaside[n]
                                    003620D0   00000000




         There is no Safe Unlinking or Cookie check for Lookaside Lists
 Well known attack is to overwrite the FLINK of a chunk on a Lookaside. This
 will populate the Lookaside[n]->FLINK with an arbitrary value to be returned
                                  at allocation.
                            Freelist[n] Lists

       Freelist Starts                        Freelist[n]
                                        Lookaside[n]
      Freelist Is Empty
           Empty                                FLINK
                                    Address 003620D0
                                     FLINK     00000000
                                               00362100
                                               003620E8     BLINK
                                            00362130 00362130
                                                     00362160
                                   00360190 00360190 00360190
      Chunk Added To
         Bottom                     Address     FLINK       BLINK
                                            00362160
                                   00362130 00360190 00360190
            Added To
      Chunk Removed
       From Bottom
          Bottom                    Address     FLINK       BLINK
                                   00362160 00360190 00362130




          Safe Unlinking and Cookie checks will prevent Unlinking

Overwriting the Freelist[n]->BLINK will cause the address of the Free’d Chunk
                    to be written to an arbitrary location
                        Freelist[n] Lists

Freelist Searching
 : If a freelist[n] of requested size not available
   bitmap is used to find larger populated freelist[n]

Chunk Size
: Size field of the chunk header used as offset to bitmap
: Bitmap is updated on allocate/free if needed
: Size field is used to calculate freelist[n] to free to

Manipulating Size Field
: Allocation can control bitmap flipping
: Free can have chunk free’d to different lookaside/freelist
                        Header   Self Size   Prev Size   CK   FL   UN   SI
                    Flipping Bitmap On Allocate

                                             Chunk On FreeList
   Size Is Overwritten       Header       ####      Prev Size   CK   FL   UN   SI
  FLINK / BLINK Can Be
                              Links              FLINK               BLINK
       Overwritten
                               Data

               7C82C8E6 MOVZX ECX,WORD PTR DS:[ESI]     ; Load Self Size
               7C82C8E9 MOV EDX,ECX
               ..
               7C82C902 8DBC1A 58010000 LEA EDI,DWORD PTR DS:[EDX+EBX+158]

If Last Chunk On Freelist Then Bitmap Updated
                                                                Calculate Bitmap
    If FLINK and BLINK Overwritten with
              Valid For Read and
               FLINK == BLINK
            Then Bitmap Updated

                     Bitmap Attack Explained Earlier
               Free To Arbitrary Lookaside[n]/FreeList[n]

                                                 Chunk To Be Freed
     Size Is Overwritten          Header     ####    Prev Size   CK   FL   UN   SI
     Cookie Is Left Intact
                                   Data


                  7C829F1B MOVZX EAX,WORD PTR DS:[ESI]              selfsize
                  7C82A84C MOVZX EAX,WORD PTR SS:[EBP-20] ; Load self size
                  7C82A850 LEA EBX,DWORD PTR DS:[EDI+EAX*8+178] ; Calculate
                  7C829F1E MOV DWORD PTR SS:[EBP-20],EAX
                  7C829F21 CMP EAX,80 PTR SS:[EBP-88],EBX
                  7C82A857 MOV DWORD
 Freeing To       7C82A85D CMP DWORD PTR DS:[EBX],EBX
                  7C829F26 JNB ntdll.7C82A7BC                ; Check Freelist
 Freelist[n]
Lookaside[n]      7C829F2C PUSH DWORD PTR SS:[EBP+10]
                  7C829F2F LEA EAX,DWORD PTR DS:[EAX+EAX*2] ; Calculate Lookaside
                  7C829F32 SHL EAX,4
                       Coalescing Is A Problem That Needs To Be Dealt With
                  7C829F35 ADD EAX,ECX
                  7C829F37 PUSH EAX
                  7C829F38 CALL ntdll.7C829F8F               ; Push to Lookaside




                   Could This Be Useful When Filling In Gaps?
                             FreeList[0] - Free

                        Freelist[0]
              Address     FLINK       BLINK
                                                        Load Freelist[0]->FLINK
              00360178 00361E90 00362B60

Populated     Address     FLINK       BLINK            Check Size Is Larger Than
Freelist[0]                                               Not Greater, Load
              00361E90 003622D0 00360178                 Chunk Been Free’d
                                                            Chunk->FLINK
              Address     FLINK       BLINK
                                                       Check Size Is Great Than
              003622D0 00362B60 00361E90                 If It Is Greater Then
                                                         Chunk Been Free’d
                                                              Insert Chunk
              Address     FLINK       BLINK
              00362B60 00360178 003622D0




                  Exploitable Condition On Freelist[0] Insert
                     Exploiting FreeList[0] - Free


   An Overwritten Chunk In Freelist[0] Can Be Exploited To Write The Address
              Of The Chunk Being Freed To An Arbitrary Location


7C82A982 CMP DX,WORD PTR DS:[EAX]          ; Compare chunk size
7C82A985 JA ntdll.7C82FDC4                 ; To large move to next

7C82A98B LEA EAX,DWORD PTR DS:[ESI+8]      ; Header of free’d chunk
7C82A98E MOV DWORD PTR SS:[EBP-7C],EAX
7C82A991 MOV EDX,DWORD PTR DS:[ECX+4]      ; Load BLINK of current chunk
7C82A994 MOV DWORD PTR SS:[EBP-84],EDX
7C82A99A MOV DWORD PTR DS:[EAX],ECX        ; Set free’d->FLINK == current
7C82A99C MOV DWORD PTR DS:[EAX+4],EDX      ; Set free’d->BLINK ==current->BLINK
7C82A99F MOV DWORD PTR DS:[EDX],EAX        ; Write @free’d to [current->BLINK]
7C82A9A1 MOV DWORD PTR DS:[ECX+4],EAX      ; Set current->BLINK == @free’d



                Exploitable Condition On Freelist[0] Insert
                        Exploiting FreeList[0] - Free
                                                    Chunk Is Inserted Before The
                                                        Overwritting Chunk.
   Chunk To Be Freed @003622D0
                                                      FLINK and BLINK updated
8400   Prev Size
       Prev Size   CK    FL
                         FL   UN
                              UN   SI
  00361E90              00360718                Overwritten Chunk @00361E90
                                             FFFF        ????    ??   02   ??      ??
                                                FFFFFFFF              00360718
                                                                      003622D0




                               Place Where We Want To Write 003622D0
                              Could Be A Function Table, This Is A Lookaside

   Overwritten Lookaside Now Populated
Three Requests And We Get Our Set Location


                   Exploitable Condition On Freelist[0] Insert
                           FreeList[0] - Allocate

                        Freelist[0]
              Address     FLINK       BLINK
                                                            Freelist[0]->FLINK
                                                       Load Freelist[0]->BLINK
              00360178 00361E90 00362B60

Populated     Address     FLINK       BLINK               Check Size Is Large
Freelist[0]   00361E90 003622D0 00360178                     Too Small,
                                                         Enough For Request
                                                         Load Chunk->FLINK
              Address     FLINK       BLINK
                                                          Check Size Is Large
              003622D0 00362B60 00361E90                    Large Enough,
                                                         Enough For Request
                                                            Return Chunk
              Address     FLINK       BLINK
                                                          Check Size Is Large
              00362B60 00360178 003622D0
                                                         Enough For Request




                 Exploitable Condition On Freelist[0] Allocate
                 Exploiting FreeList[0] - Searching

                                             Overwritten Chunk @003622C8
 Request Made For Size                    0100       ????    ??      ??   ??    ??
       0x0BF8                                00360188                ????????


                                                        FLINK Points To Fake
                                                               Chunk
                                                             Chunk+8
Chunk Returned To Caller
 This Address Is In The
       Freelists                                 Fake Chunk @00360180
                                         8001       3600     80   01      36    00
                                            00360188              00360188

                   = Requested Size
                      (+1 block)                        Must Be Readable


         Exploitable Condition On Freelist[0] Allocate - Searching
                            Allocation Relinking


                                   Chunk Header      Chunk Header
If Chunk Is Larger Than
Request It Will Get Split           Chunk Space      Chunk Space




                                                   New Chunk Header Chunk Header
                                                               New
                                                   New Chunk Space Chunk Space
                                                               New
              Chunk Returned To
                    Caller


                 New Header Is Written
                 Into The Existing Chunk
                          Space
                                    Chunk Inserted Into
                                        FreeLists
                  Exploiting FreeList[0] - Relinking
                                              Overwritten Chunk @003622C8
                                           0202         ????    ??     ??     ??    ??
  Request Made For Size                       0036057C                     READ
Smaller Than Our Overwrite
                                          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
                                              XXXXXXXXXXXXXXXXXXXXXX.....

                                                         FLINK Points To Fake
  Relink Chunk Address                                          Chunk
                                                              Chunk+8
  Written To 00360580

This Is The FrontEndHeap                          Fake Chunk @00360574
     (Lookaside Base)                     7005       3600      08     06     36    00
                                             ????????                00360688


                  > Relink Chunk Size
                                                         Must Be Read/Write

          Exploitable Condition On Freelist[0] Allocate - Relinking
                          Splitting / Resizing

When Allocated Chunk Is To Large
: Checked when allocation from other list
: Chunk is cut to size, New header is written
: Chunk is inserted to freelist[n] or freelist[0]
: Size manipulated to put new chunk into arbitrary Freelist
7C82A3DB CMP EBX,1                          ; Larger than one block difference
7C82A3DE JE ntdll.7C82E5A4
7C82A3E4 MOV EAX,DWORD PTR SS:[EBP-48]      ; Load requested size
7C82A3E7 LEA EDI,DWORD PTR DS:[ESI+EAX*8]   ; Move to create the new chunk
..
7C82A3F3 MOV BYTE PTR DS:[EDI+5],CL         ; Store new flag
7C82A3F6 MOV WORD PTR DS:[EDI+2],AX         ; Store Prev Size        Can Skip By
..                                                                  Setting As Last
7C82A400 MOV WORD PTR DS:[EDI],BX           ; Store new size            Chunk
7C82A403 TEST CL,10                         ; Is chunk new LAST CHUNK
7C82A406 JNZ ntdll.7C82A65E                 ; Jump if chunk is last chunk
7C82A40C LEA EAX,DWORD PTR DS:[EDI+EBX*8]   ; Move to NEXT chunk based on size
7C82A40F MOV DWORD PTR SS:[EBP-50],EAX      ; Will try and coalesce with next
                           Coalesced Chunks

When Chunk Is Free’d To Freelist
: Size field is used to locate previous and next chunk
: Requires valid FLINK/BLINK on chunks to colaesce
                                                                                  Test Flag Of
                                                                                   Previous
7C82A6F6 JE SHORT ntdll.7C82A702                 ; If prev size is 0 jump           Chunk
7C82A6F8 TEST BYTE PTR DS:[ESI+5],1              ; Is prev chunk BUSY?
7C82A6FC JE ntdll.7C82CA7A                       ; If not then coalesce
7C82A702 TEST BYTE PTR DS:[EDI+5],10             ; Is our chunk the last chunk?
7C82A706 JNZ ntdll.7C82A7B3                      ; If so can't coalesce
7C82A70C MOV EAX,DWORD PTR SS:[EBP+10]                                              Test Flag
7C82A70F MOV EAX,DWORD PTR DS:[EAX]              ; Load our block size               Of Next
7C82A711 LEA ESI,DWORD PTR DS:[EDI+EAX*8]        ; Move to next chunk                Chunk
7C82A714 TEST BYTE PTR DS:[ESI+5],1              ; Is next chunk BUSY?
7C82A718 JNZ ntdll.7C82A7B3                      ; Yup, so don't colaesce

 : An overflow can control all of this to prevent coalesce
                Header   Self Size   Prev Size     CK    FL    UN    SI
                    Preventing Coalesce

How To Prevent A Coalesce
: Set the chunk being freed prev size to ZERO
: Set the chunk being freed FLAG to last chunk
: Set the chunk being freed self size > 0xFE00
: Set the prev/next chunks flag to PASS the BUSY check
: Control the size to fake the prev/next chunks location

Why Prevent A Coalesce()
: Coalescing an overwritten chunk normally blows up
: Linking, resizing, and relinking is very complex
                          Coalesced Chunks

                   ????   ????      ??   ??   ??   ??
                                 DATA                         Chunk A
   BUSY                                                     Data Stored In
   Chunk


                   FFFF   FFFF      FF   FF
                                         01   FF   FF        Chunk B
                                 DATA                     We Overflowing
   BUSY
   Chunk




                                              Keep The Flag Set
Chunk A Will Be Free’d                            To BUSY
  And We Want To
 Prevent Coalescing
                          Coalesced Chunks

                   ????   ????      ??   ??   ??   ??
                                 DATA                         Chunk A
   BUSY                                                     Data Stored In
   Chunk           FFFF   FFFF      FF   01   FF   FF
                                 DATA
                   FFFF
                   0200   FFFF
                          0200      FF   FF   FF   FF         Chunk B
                                 DATA                      We Overflowing
   BUSY
   Chunk           FFFF   FFFF      FF   01   FF   FF
                                 DATA



                           Create Two Fake Chunks And
Chunk B Will Be Free’d     Set Size In Header Of Chunk B
  And We Want To            To Point To The Fake Chunks
 Prevent Coalescing               Flag Set To Busy
                          Coalesced Chunks

                   ????   ????      ??   ??   ??   ??
                                 DATA                         Chunk A
   BUSY                                                     Data Stored In
   Chunk


                   FFFF   FFFF
                          0000      FF   10
                                         FF   FF   FF         Chunk B
                                 DATA                      We Overflowing
   BUSY
   Chunk



                                                Set The Flag To
Chunk B Will Be Free’d                         Contain The Last
  And We Want To                                  Chunk Flag
 Prevent Coalescing
                      Preventing A Free

How To Prevent A Free
: Set the chunks flag to FAIL the BUSY check
                                                 Move To Chunk
                                                    Header

                                                 Load Flag and
                                                  Test If Busy

Why Prevent A Free()
: Remove chunk from Lookaside
              Can be overwritten before allocation
: Remove chunk from Freelist[]
              Flag gets reset on allocation
Bypass Cookie Check
: Will cause a heap exception, doesn’t stop execution
                    Example Removing Chunk From Lookaside


    Before Allocation


                                        Overwrite Flag
Self Size   Prev Size   CK   FL   UN   SI       Self Size   Prev Size   CK   FL   UN   SI
 0300        0300       06   01   0E   00        0101        0101       01   02   01   01



    After Allocation




        After Free()
                                  Clearing The Lookaside

   Top Chunk On A Lookaside Is Overwritten
    : Flags set to not BUSY, Flink set to 0x00000000

        Before Allocation



                                    Overwrite Flag And FLINK
Self Size   Prev Size   CK   FL    UN   SI       Self Size   Prev Size   CK   FL   UN   SI
 0300        0300       06   01    0E   00        0101         0101      01   02   01   01
     00362100                                         00000000


        After Overwrite


                    Allocation And Free Will Clear The Lookaside List
                    The Exploitation Process

The Steps
 : Exploit the heap
 : Overwrite a function pointer or other to gain execution
 : Flip the heap onto the stack to get ret-to-libc style control
 : Turn off Data Execution Protection (DEP)
 : Return to shellcode

Exploit The Heap
 : Application dependant

Overwrite A Function Pointer
: Application dependant?
                         Heap / Stack Flipping

What Is Heap/Stack Flipping
: Exploit data is on the heap
: For fine grained control, it needs to be on the stack

Requirements
: Pointer to exploit data; on stack, in a register, in [reg +/- n]
: Locate instructions to manipulate pointer and pop esp, ret
: Overwrite function pointer to return to instructions
Populate ESP With The Pointer To Exploit Data

  EBX -> DATA    EBP -> DATA       ECX -> DATA   EAX-> DATA
  PUSH EBX       LEAVE            MOV ESP,ECX    XCHG EAX,ESP
  POP ESP        RET              RET 8          RET
  POP EBP
  RET
            Heap / Stack Flipping




                  Exploit Data




                                    Stack
Registers


                                    Code Gets
                                    Executed
                 Flipping Code
                 Heap / Stack Flipping




                        Exploit Data




                                             New Stack
New Registers
                Code That We Returned Into
                        Bypassing DEP

Entirely Ret-to-Libc
 : Entire shellcode in ‘borrowed’ instructions
 : Inject into process that is not DEP enabled
 : Very difficult

HeapCreate()
: Create new heap with HEAP_CREATE_ENABLE_EXECUTE
: Allocate new chunk, memcpy shellcode across
: Doable, but sounds like a lot of work

Registry
: 'Image File Execution Options‘
: Would turn it off on a restart
: Not really very helpful
                      Bypassing DEP

SetProcessDEPPolicy()
: Not available on 2003

Copy Shellcode To RWE Memory Page
: Copy shellcode and then return to address




VirtualProtect()
: Use the PAGE_EXECUTE_READWRITE flag to reset heap
: Return to shellcode
                       Bypassing DEP

VirtualAlloc()
: Allocate new memory with PAGE_EXECUTE_READWRITE
: Address is returned in EAX
: Copy shellcode and return to it

NtSetInformationProcess()
: Skape and Skywing ret-to-libc to deactivate DEP
: Easier on windows 2003



                                NtSetInformationProcess(
                                         NtCurrentProcess(), // (HANDLE)-1
                                         ProcessExecuteFlags, // 0x22
                                         &ExecuteFlags, // ptr to 0x2
                                         sizeof(ExecuteFlags)); // 0x4
                             Bypassing DEP



                                                                 Perfect
                                                             Instruction Set



   BUT!




                                     NtSetInformationProcess(
                                              NtCurrentProcess(), // (HANDLE)-1
Requires [ESI+37] To Be Writable              ProcessExecuteFlags, // 0x22
                                              &ExecuteFlags, // ptr to 0x2
      Correctly Set Stack                     sizeof(ExecuteFlags)); // 0x4
                      Heap Exploitation

Step By Step
: The vulnerability
: Reproduction
: Understanding the bug
: Finding an overwrite
: Find a pointer
: Flipping the heap to stack
: Bypassing DEP
: The working
                     The Vulnerability




                                           Citrix
                                        ImaSrv.exe
Citrix                            TCP Port 2512 or 2513
                            User-supplied -> Memory Allocation
                                   Undersized Allocation
                                 Overflow The Heap Buffer




                                                  ImaSrv.exe
TCP Port 2512 or 2513               User-supplied -> Memory Allocation

         Overflow The Heap Buffer
                    Reproducing The Vulnerability

Usual Integer Overflow
: Usual ‘packet size bug’
  Length Of Data            DATA


Usual Basic Fuzz Test
while !crashed
{
       inc buffer length
       fill buffer with 0xFF
       send to TCP 2512
}
 \xFF\xFF\xFF\xFF   \xFF\xFF\xFF\xFF\xFF\xFF
                                                    I Am Listening
                                                     On TCP 2512
                Reproducing The Vulnerability

                 A RtlAllocateHeap
             ntdll! Crash




In the good ‘ol days, it would now be as easy as overwriting the UEF.
                        But those days are over.
                   Understanding The Bug

                                              WSARecv
Need To Trace From Start To Finish
: bp WSARecv and send overflow again


                                                        Stack




     Buffer Size                   Buffer Address
                  Understanding The Bug

Need To Trace From Start To Finish
: After WSARecv our buffer is loaded
                   Understanding The Bug

Trace Through Code To Determine Paths
 : This code checks buffer sizes           Load First DWORD Of
                                             Packet Into EAX




                                           Compare Against Size
                                             Of Current Buffer
                                                  0x408
             Jump If Our Packet
           Specified A Size Larger
                Than 0x408
                 Understanding The Bug

Trace Through Code To Determine Paths
 : Eventually get to here                 ESI == First DWORD
                                              From Packet




                     EAX == ESI + 3C
                                            Is Going To
                                         Allocate A Buffer
                                            Of Size EAX
                  Understanding The Bug

But its not over yet
: Trace down to ntdll!RTLAllocateHeap




                                          Allocate From Heap
                                               00320000




                                           Allocate 3B Bytes
                   Understanding The Bug

Still Thats Just An Undersized Buffer
: Keep tracing the code
                                           EAX Points To The Newly
                                               Allocated Buffer




                                           Bunch Of Stuff Is Written
                                             Into The New Buffer

                                           This Is A Custom Header
                                            And Is 0x3C Bytes Long
                   Understanding The Bug

Finally....
 : A memmove instruction overflows the buffer




                                                  New Buffer+3C


                                                     Packet Data




               KABOOM!                     This Is The Size Of The
                                            Packet That We Sent
                   Understanding The Bug

The Result
 : We can cause the allocation of a size 0x01 – 0x03B
 : We can overflow the chunk with 0x408 bytes

The Limitations
 : Can only allocate chunk 2 through to 9
       That range is FFFFFFC5      == 0x01 == Chunk 2
       To             FFFFFFFF     == 0x3b == Chunk 9

: The first 0x3C bytes are not controlled by us due to the
  custom header
                     The Request LifeCycle



                       RTLAllocateHeap()




      WSARecv()                                memmove()




                         RTLFreeHeap()



So Now What?
: We know we can cause an allocation of a lower chunk
: Lets look at the Lookaside lists at the time of the allocation
                            The Lookaside Lists


                                                     0x0a871cc8 – 0x0a871c60
   0x0a871c38 – 0x0a871bd0                                   = 0x68
           = 0x68




                                                  0x0a871d00 – 0x0a871c98
                                                          = 0x68
 Lookaside[8] Has A Top Chunk That Sits
After Lookaside[7] Top Chunk On All Runs
                   AND
   The Difference Is Greater Than 0x3C
                            Lets Try It

First Request
 : Request Lookaside[7]
 : Overwrite Lookaside[8]
 : Free Request

Problem
: If we now had two allocations of Lookaside[8]
: But we only have one

Solution
: Set flag of top chunk of Lookaside[8] to be FREE
: Then when free() is called it will be skipped
                            Lets Try It

First Request
 : Request Lookaside[7]
 : Overwrite Lookaside[8]
 : Free Request

Second Request
: Request Lookaside[8]
: Top Chunk Is Popped
: Free Request

Third Request
 : Request Lookaside[8], Our Address Is Returned
                   What Address To Overwrite

Function Pointer
 : Trace code looking for pointer
 : None found before WSARecv()

    Lucky For Us That Winsock
       Uses Static Pointers                             EAX Points To
                                                           Stack




                                    0x71C14044 Is A Static Pointer
                                      That Can Be Overwritten
                      Winsock Structure

Winsock                                             Static Pointer
: Holds a structure                                   To Handle




: Structure holds pointer to function pointer table on the
  default heap
                                                Load Address Of
                                                  Pointer Table
                                              ‘Static Within Heap’




                                                 Call Function
                      Exploiting The Bug

Pointer Table Address
: 0x142360
Set Lookaside Address
: Need to account for header
: Set lookaside to 0x01431D0
                                           Heap/Stack Flip Local To
Overwrite The Pointer Table                      Citrix DLLS
: We now control execution
Set The Stack
: EAX points to the pointer table
: EAX points to our data
: Search for a heap/stack flip
Return Down The Stack
: Return to Anti-DEP
: Return to shellcode on pointer table
                                                           Da Greetz
     Acknowledgement to those who shared current
information, some of which was used in this presentation               Acknowledgement to those who have published
                                                                                  past heap research
                    Nico
                   Caddis                                                         0ded
                   mxatone                                                        Shok
                                                                                Sotirov
                                                                            Sandip Chaudhari
                                                                              A. Anisimov
                                                                               N. Falliere
                                                                                 Halvar
                                                                               Litchfield
                                                                              + All Others

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:1
posted:2/8/2012
language:
pages:66