Upgrade to Pro — share decks privately, control downloads, hide ads and more …

secretholder - HITCON 2016 writeup

Dhaval Kapil
November 29, 2017

secretholder - HITCON 2016 writeup

Dhaval Kapil

November 29, 2017
Tweet

More Decks by Dhaval Kapil

Other Decks in Education

Transcript

  1. secretholder HITCON 2016

  2. Challenge overview

  3. Challenge overview • Menu driven: ◦ Keep secret ◦ Wipe

    secret ◦ Renew secret
  4. Challenge overview Keep secret if (***_secret_flag == 0) { ***_secret

    = calloc(1, ***_SIZE); ***_secret_flag = 1; read(0, ***_secret, ***_SIZE); } SMALL_SIZE = 40 (fast chunk) BIG_SIZE = 4000 (large chunk) HUGE_SIZE = 400000
  5. Challenge overview Renew secret if (***_secret_flag == 1) { read(0,

    ***_secret, ***_SIZE); }
  6. Challenge overview Wipe secret free(***_secret); // Vulnerability - Double Free

    ***_secret_flag = 0;
  7. Problem • Chunk size for ‘huge_secret’ is too big •

    Memory will be allocated using mmap • Not adjacent to heap memory • Effectively we can control only 2 chunks - difficult to exploit
  8. Trick • ptr = malloc(400000); // allocated using mmap, some

    random address • free(ptr); • ptr = malloc(400000); // Memory allocated by extending top chunk!
  9. sysmalloc • When malloc cannot find an appropriate chunk in

    any bin and top chunk does not have enough size to service the request, malloc relies on sysmalloc • If the requested size is >= mmap_threshold, sysmalloc obtains memory using mmap. • If the requested size is < mmap_threshold, sysmalloc extends top chunk using sbrk. [Code]
  10. Freeing mmapped chunks • If (size of chunk > mmap_threshold)

    && (size of chunk <= DEFAULT_MMAP_THRESHOLD_MAX), set mmap_threshold to chunk size • munmap_chunk() Note: Initially, mmap_threshold = 128 * 1024 [Code]
  11. Trick • ptr = malloc(400000); // sysmalloc will rely on

    mmap since this is > mmap_threshold • free(ptr); // mmap_threshold will be updated to 401410 (chunk size) • ptr = malloc(400000); // sysmalloc will rely on sbrk and extend the top chunk
  12. Attack 1. Keep ‘small’ and wipe it -> fast chunk

    inserted in fastbin 2. Keep ‘big’ -> malloc_consolidate forces fast chunk to merge with top chunk, hence, same chunk is returned. Now small and big secrets point to the same chunk. 3. Wipe ‘small’ -> Frees the big chunk 4. Keep ‘small’ -> Again the same chunk is returned. But now, the top chunk starts from somewhere within the ‘big’ chunk. 5. Keep ‘huge’, free ‘huge’, keep ‘huge’ -> This trick forces the huge chunk be carved out of the top chunk.
  13. Attack Small secret Big secret Huge secret Top Chunk Can

    overwrite metadata of huge secret chunk
  14. Attack • Create a fake chunk in small secret with

    fd pointing to ‘small_secret - 3’ and bk pointing to ‘small_secret - 2’. • Adjust previous size and zero out PREV_IN_USE bit of ‘huge_secret’. • Free ‘huge_secret’ • ‘small_secret’ now points to a few bytes before ‘big_secret’ -> Arbitrary write
  15. Attack • Update read’s GOT with puts@plt and leak out

    libc address of say puts’ GOT • Calculate system’s libc address and update read’s GOT with it. • Free any chunk with ‘/bin/sh\x00’
  16. https://github.com/DhavalKapil/ctf-writeups/blob/master/hitcon-2016/secretholder/e xploit.py [Exploit]