├── README.md ├── allocate_large_chunks_2.c ├── allocate_small_next_smallest.c ├── allocate_smallest.c ├── binmapsizeget.c ├── insmallbinrange.c ├── mallo_fast-nochunk4.c └── mallo_fast.c /README.md: -------------------------------------------------------------------------------- 1 | # painless_intro_ptmalloc2 2 | Proof of Concept files for SensePost's blog - Painless intro to the linux heap: 3 | * https://sensepost.com/blog/2017/painless-intro-to-the-linux-userland-heap/ 4 | -------------------------------------------------------------------------------- /allocate_large_chunks_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // This program allocate large chunks and then frees the odd ones to 5 | // cause fragmentation so we can inspect what happens to the 6 | // P->fd_nextsize and P->bk_nextsize pointers in memory 7 | 8 | // Javier Jimenez @ SensePost 2017 9 | 10 | int main(){ 11 | void *large1, *large2, *large3, *large4, *large5, *large6; 12 | 13 | printf("[info] allocating 2 large chunks (+1024 bytes each)\n"); 14 | large1 = malloc(20050); 15 | large2 = malloc(20025); 16 | large3 = malloc(20058); 17 | large4 = malloc(20060); 18 | large5 = malloc(20068); 19 | large6 = malloc(20075); 20 | printf("[+] large1 at %p\n", large1); 21 | printf("[+] \tdistance: %ld\n", large2-large1); 22 | printf("[+] large2 at %p\n", large2); 23 | printf("[+] \tdistance: %ld\n", large3-large2); 24 | printf("[+] large3 at %p\n", large3); 25 | printf("[+] \tdistance: %ld\n", large4-large3); 26 | printf("[+] large4 at %p\n", large4); 27 | printf("[+] \tdistance: %ld\n", large5-large4); 28 | printf("[+] large5 at %p\n", large5); 29 | printf("[+] \tdistance: %ld\n", large6-large5); 30 | printf("[+] large6 at %p\n", large6); 31 | printf("[info] freeing larges 1 3 5\n"); 32 | free(large1); 33 | free(large3); 34 | free(large5); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /allocate_small_next_smallest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // This program allocates the next smallest chunk possible to show that 4 | // memory will be padded to 16 bytes more, also due to the 5 | // chunk headers needing 8 byte addressess for fd and bk 6 | // (32 + 16 = 48) 7 | // Javier Jimenez @ SensePost 2017 8 | int main(){ 9 | void *smallestchunk1, *smallestchunk2; 10 | smallestchunk1 = malloc(25); 11 | smallestchunk2 = malloc(25); 12 | printf("Smallchunk1 at %p, Smallchunk2 at %p\n", smallestchunk1, smallestchunk2); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /allocate_smallest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // This program allocates the smallest chunk possible to show that 5 | // actually in memory will be a 32 bytes sized chunk due to the 6 | // chunk headers in 64 bit (8 byte addressess for fd and bk) 7 | // Javier Jimenez @ SensePost 2017 8 | int main(){ 9 | void *smallestchunk1, *smallestchunk2; 10 | smallestchunk1 = malloc(1); 11 | smallestchunk2 = malloc(1); 12 | printf("Smallchunk1 at %p, Smallchunk2 at %p\n", smallestchunk1, smallestchunk2); 13 | printf("Distance from 1 to 2 (ie size): %d\n", smallestchunk2-smallestchunk1); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /binmapsizeget.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define NBINS 128 4 | #define BINMAPSHIFT 5 5 | #define BITSPERMAP (1U << BINMAPSHIFT) 6 | #define BINMAPSIZE (NBINS / BITSPERMAP) 7 | 8 | // This program give us a visual representation of 9 | // the sizes used by the bins in malloc.c 10 | // Javier Jimenez @ SensePost 2017 11 | 12 | int main(){ 13 | printf("NBINS:%u BINMAPSHIFT:%u BITSPERMAP:%u BINMAPSIZE:%u\n",NBINS,BINMAPSHIFT,BITSPERMAP,BINMAPSIZE); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /insmallbinrange.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Taken from ptmalloc2 implementation 5 | #define MALLOC_ALIGNMENT 2 * sizeof(size_t) 6 | #define INTERNAL_SIZE_T size_t 7 | #define SIZE_SZ (sizeof (INTERNAL_SIZE_T)) 8 | #define MAX_FAST_SIZE (80 * SIZE_SZ / 4) 9 | #define NBINS 128 10 | #define NSMALLBINS 64 11 | #define SMALLBIN_WIDTH MALLOC_ALIGNMENT 12 | #define SMALLBIN_CORRECTION (MALLOC_ALIGNMENT > 2 * SIZE_SZ) 13 | #define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH) 14 | 15 | #define in_smallbin_range(sz) \ 16 | ((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE) 17 | 18 | 19 | int main(){ 20 | printf("MIN_LARGE_SIZE = %lu\n", MIN_LARGE_SIZE); 21 | printf("1023 is small: %d. 1025 is not: %d.\n", in_smallbin_range(1023), in_smallbin_range(1025)); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /mallo_fast-nochunk4.c: -------------------------------------------------------------------------------- 1 | // Malloc heap "fragmentation" example for SensePost's blog 2 | // Javier Jimenez @ SensePost 2017 3 | 4 | 5 | #include 6 | #include 7 | 8 | // Taken from ptmalloc2 implementation 9 | #define INTERNAL_SIZE_T size_t 10 | #define SIZE_SZ (sizeof (INTERNAL_SIZE_T)) 11 | #define MAX_FAST_SIZE (80 * SIZE_SZ / 4) 12 | 13 | int main(){ 14 | void *malloc1, *malloc2; 15 | printf("[info] MAX_FAST_SIZE == %zu\n", MAX_FAST_SIZE); 16 | printf("[info] Allocating 2 malloc of size greater than MAX_FAST_SIZE\n"); 17 | malloc1 = malloc(MAX_FAST_SIZE+16); 18 | malloc2 = malloc(MAX_FAST_SIZE+16); 19 | printf("[+]\t malloc1 at %p and malloc2 at %p\n", malloc1, malloc2); 20 | 21 | // Allocating 1 fast malloc and 1 malloc twice to cause fragmentation 22 | void *fastmalloc1, *malloc3, *fastmalloc2; 23 | printf("[info] Allocating 1 fast malloc and 1 malloc twice\n"); 24 | fastmalloc1 = malloc(20); 25 | malloc3 = malloc(MAX_FAST_SIZE+16); 26 | fastmalloc2 = malloc(20); 27 | printf("[+]\t %smalloc%d is at %p\n", "fast", 1, fastmalloc1); 28 | printf("[+]\t %smalloc%d is at %p\n", "", 3, malloc3); 29 | printf("[+]\t %smalloc%d is at %p\n", "fast", 2, fastmalloc2); 30 | printf("[info] The heap is now as follows\n"); 31 | printf("[info] %s\t%p\n", "malloc1 ", malloc1); 32 | printf("[info] \tdistance: %zu\n", malloc2-malloc1); 33 | printf("[info] %s\t%p\n", "malloc2 ", malloc2); 34 | printf("[info] \tdistance: %zu\n", fastmalloc1-malloc2); 35 | printf("[info] %s\t%p\n", "fastmalloc1", fastmalloc1); 36 | printf("[info] \tdistance: %zu\n", malloc3-fastmalloc1); 37 | printf("[info] %s\t%p\n", "malloc3 ", malloc3); 38 | printf("[info] \tdistance: %zu\n", fastmalloc2-malloc3); 39 | printf("[info] %s\t%p\n", "fastmalloc2", fastmalloc2); 40 | 41 | // Now we are going to cause fragmentation in the heap 42 | printf("\n[info] Now causing some fragmentation by freeing the two fastmallocs \n\t\ 43 | and the malloc3\n"); 44 | free(fastmalloc1); 45 | free(malloc3); 46 | free(fastmalloc2); 47 | 48 | void *malloc5, *malloc6; 49 | printf("[info] Allocating malloc5...\n"); 50 | malloc5 = malloc(MAX_FAST_SIZE+16); 51 | printf("[+] \tmalloc5 is at %p \n", malloc5); 52 | malloc6 = malloc(MAX_FAST_SIZE+16); 53 | printf("[+] \tmalloc6 is at %p \n", malloc6); 54 | printf("[info] We can check that the pointer used for malloc5(%p) was\n\t the old malloc3(%p)\n\ 55 | \tinstead of using the start of the big freed space starting \n\tat fastmalloc1(%p)\n", malloc5, malloc3, fastmalloc1); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /mallo_fast.c: -------------------------------------------------------------------------------- 1 | // Malloc heap "fragmentation" example for SensePost's blog 2 | // Javier Jimenez @ SensePost 2017 3 | 4 | #include 5 | #include 6 | 7 | // Taken from ptmalloc2 implementation 8 | #define INTERNAL_SIZE_T size_t 9 | #define SIZE_SZ (sizeof (INTERNAL_SIZE_T)) 10 | #define MAX_FAST_SIZE (80 * SIZE_SZ / 4) 11 | 12 | int main(){ 13 | void *malloc1, *malloc2; 14 | printf("[info] MAX_FAST_SIZE == %zu\n", MAX_FAST_SIZE); 15 | printf("[info] Allocating 2 malloc of size greater than MAX_FAST_SIZE\n"); 16 | malloc1 = malloc(MAX_FAST_SIZE+16); 17 | malloc2 = malloc(MAX_FAST_SIZE+16); 18 | printf("[+]\t malloc1 at %p and malloc2 at %p\n", malloc1, malloc2); 19 | 20 | // Allocating 1 fast malloc and 1 malloc twice to cause fragmentation 21 | void *fastmalloc1, *malloc3, *fastmalloc2, *malloc4; 22 | printf("[info] Allocating 1 fast malloc and 1 malloc twice\n"); 23 | fastmalloc1 = malloc(20); 24 | malloc3 = malloc(MAX_FAST_SIZE+16); 25 | fastmalloc2 = malloc(20); 26 | malloc4 = malloc(MAX_FAST_SIZE+16); 27 | printf("[+]\t %smalloc%d is at %p\n", "fast", 1, fastmalloc1); 28 | printf("[+]\t %smalloc%d is at %p\n", "", 3, malloc3); 29 | printf("[+]\t %smalloc%d is at %p\n", "fast", 2, fastmalloc2); 30 | printf("[+]\t %smalloc%d is at %p\n", "", 4, malloc4); 31 | printf("[info] The heap is now as follows\n"); 32 | printf("[info] %s\t%p\n", "malloc1 ", malloc1); 33 | printf("[info] \tdistance: %zu\n", malloc2-malloc1); 34 | printf("[info] %s\t%p\n", "malloc2 ", malloc2); 35 | printf("[info] \tdistance: %zu\n", fastmalloc1-malloc2); 36 | printf("[info] %s\t%p\n", "fastmalloc1", fastmalloc1); 37 | printf("[info] \tdistance: %zu\n", malloc3-fastmalloc1); 38 | printf("[info] %s\t%p\n", "malloc3 ", malloc3); 39 | printf("[info] \tdistance: %zu\n", fastmalloc2-malloc3); 40 | printf("[info] %s\t%p\n", "fastmalloc2", fastmalloc2); 41 | printf("[info] \tdistance: %zu\n", malloc4-fastmalloc2); 42 | printf("[info] %s\t%p\n", "malloc4 ", malloc4); 43 | 44 | // Now we are going to cause fragmentation in the heap 45 | printf("\n[info] Now causing some fragmentation by freeing the two fastmallocs \n\t\ 46 | and the malloc3\n"); 47 | free(fastmalloc1); 48 | free(malloc3); 49 | free(fastmalloc2); 50 | 51 | void *malloc5, *malloc6; 52 | printf("[info] Allocating malloc5...\n"); 53 | malloc5 = malloc(MAX_FAST_SIZE+16); 54 | printf("[+] \tmalloc5 is at %p \n", malloc5); 55 | malloc6 = malloc(MAX_FAST_SIZE+16); 56 | printf("[+] \tmalloc6 is at %p \n", malloc6); 57 | printf("[info] We can check that the pointer used for malloc5(%p) was\n\t the old malloc3(%p)\n\ 58 | \tinstead of using the start of the big freed space starting \n\tat fastmalloc1(%p)\n", malloc5, malloc3, fastmalloc1); 59 | return 0; 60 | } 61 | --------------------------------------------------------------------------------