mirror of https://github.com/pwndbg/pwndbg.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
5.7 KiB
C
247 lines
5.7 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/* copy-paste from malloc.c */
|
|
# define INTERNAL_SIZE_T size_t
|
|
#define SIZE_SZ (sizeof (INTERNAL_SIZE_T))
|
|
#define MALLOC_ALIGNMENT (2 * SIZE_SZ < __alignof__ (long double) \
|
|
? __alignof__ (long double) : 2 * SIZE_SZ)
|
|
|
|
typedef struct malloc_chunk {
|
|
INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if P == 0). */
|
|
INTERNAL_SIZE_T size; /* Size in bytes, including overhead. 3LSB: N,M,P*/
|
|
/* A(NON_MAIN_ARENA), M(IS_MMAPPED), P(PREV_INUSE) */
|
|
|
|
struct malloc_chunk* fd; /* double links -- used only if free. */
|
|
struct malloc_chunk* bk;
|
|
|
|
/* Only used for large blocks: pointer to next larger size. */
|
|
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
|
|
struct malloc_chunk* bk_nextsize;
|
|
} malloc_chunk;
|
|
|
|
/* common heap setup */
|
|
#define setup_heap char *a = malloc(50); \
|
|
char *b = malloc(50); \
|
|
char *c = malloc(50); \
|
|
char *d = malloc(4000); \
|
|
char *e = malloc(4000); \
|
|
char *f = malloc(4000); \
|
|
char *g = malloc(4000); \
|
|
malloc_chunk *a_real = (malloc_chunk*)(a - 2*SIZE_SZ); \
|
|
malloc_chunk *b_real = (malloc_chunk*)(b - 2*SIZE_SZ); \
|
|
malloc_chunk *c_real = (malloc_chunk*)(c - 2*SIZE_SZ); \
|
|
malloc_chunk *d_real = (malloc_chunk*)(d - 2*SIZE_SZ); \
|
|
malloc_chunk *e_real = (malloc_chunk*)(e - 2*SIZE_SZ); \
|
|
malloc_chunk *f_real = (malloc_chunk*)(f - 2*SIZE_SZ); \
|
|
malloc_chunk *g_real = (malloc_chunk*)(g - 2*SIZE_SZ); \
|
|
int *tmp; \
|
|
int tmp2, tmp3; \
|
|
printf("a=%p\nb=%p\nc=%p\nd=%p\ne=%p\nf=%p\ng=%p\n", a, b, c, d, e, f, g);
|
|
|
|
/*
|
|
Every function MUST have two comments: "break1" and "break2"
|
|
One after setup, second just before line triggering the bug
|
|
*/
|
|
|
|
void invalid_pointer_overflow() {
|
|
// free(): invalid pointer
|
|
setup_heap
|
|
// break1
|
|
|
|
tmp2 = a_real->size;
|
|
a_real->size = 0xffffffffffffff00;
|
|
// break2
|
|
free(a);
|
|
a_real->size = tmp2;
|
|
}
|
|
|
|
void invalid_pointer_misaligned() {
|
|
// free(): invalid pointer
|
|
setup_heap
|
|
// break1
|
|
|
|
// break2
|
|
free(a+2);
|
|
}
|
|
|
|
void invalid_size_minsize() {
|
|
// free(): invalid size
|
|
setup_heap
|
|
// break1
|
|
|
|
tmp2 = a_real->size;
|
|
a_real->size = 8;
|
|
// break2
|
|
free(a);
|
|
a_real->size = tmp2;
|
|
}
|
|
|
|
void invalid_size_misaligned() {
|
|
// free(): invalid size
|
|
setup_heap
|
|
// break1
|
|
|
|
tmp2 = a_real->size;
|
|
a_real->size = 24;
|
|
// break2
|
|
free(a);
|
|
a_real->size = tmp2;
|
|
}
|
|
|
|
void invalid_next_size_fast() {
|
|
// free(): invalid next size (fast)
|
|
setup_heap
|
|
// break1
|
|
|
|
tmp2 = a_real->size;
|
|
tmp3 = a[32 - 2*SIZE_SZ + SIZE_SZ];
|
|
a_real->size = 32;
|
|
a[32 - 2*SIZE_SZ + SIZE_SZ] = (size_t*)3;
|
|
// break2
|
|
free(a);
|
|
a[32 - 2*SIZE_SZ + SIZE_SZ] = (size_t*)tmp3;
|
|
a_real->size = tmp2;
|
|
}
|
|
|
|
void double_free_tcache() {
|
|
// free(): double free detected in tcache 2
|
|
setup_heap
|
|
// break1
|
|
|
|
free(a);
|
|
// break2
|
|
free(a);
|
|
}
|
|
|
|
void double_free_fastbin() {
|
|
// double free or corruption (fasttop)
|
|
setup_heap
|
|
// break1
|
|
|
|
void *ptrs[10];
|
|
for (int i = 0; i < 10; ++i)
|
|
ptrs[i] = malloc(50);
|
|
for (int i = 0; i < 10; ++i)
|
|
free(ptrs[i]);
|
|
|
|
free(a);
|
|
// break2
|
|
free(a);
|
|
}
|
|
|
|
void invalid_fastbin_entry() {
|
|
// invalid fastbin entry (free)
|
|
// not working, dunno why
|
|
// maybe because of 'have_lock == 0'
|
|
setup_heap
|
|
// break1
|
|
|
|
void *ptrs[10];
|
|
for (int i = 0; i < 10; ++i)
|
|
ptrs[i] = malloc(50);
|
|
for (int i = 0; i < 10; ++i)
|
|
free(ptrs[i]);
|
|
|
|
free(a);
|
|
a_real->size = 88;
|
|
// break2
|
|
free(c);
|
|
}
|
|
|
|
void double_free_or_corruption_top() {
|
|
// double free or corruption (top)
|
|
setup_heap
|
|
// break1
|
|
|
|
malloc_chunk *top_chunk_real = (malloc_chunk*) (((size_t)c_real + c_real->size) & (~7));
|
|
char *top_chunk = (char*) ((size_t)top_chunk_real + 2*SIZE_SZ);
|
|
// break2
|
|
free(top_chunk);
|
|
}
|
|
|
|
void double_free_or_corruption_out() {
|
|
// double free or corruption (out)
|
|
setup_heap
|
|
// break1
|
|
|
|
d_real->size = 0xffffff00;
|
|
// break2
|
|
free(d);
|
|
}
|
|
|
|
void double_free_or_corruption_prev() {
|
|
// double free or corruption (!prev)
|
|
setup_heap
|
|
// break1
|
|
|
|
e_real->size &= ~1;
|
|
// break2
|
|
free(d);
|
|
}
|
|
|
|
void invalid_next_size_normal() {
|
|
// free(): invalid next size (normal)
|
|
setup_heap
|
|
// break1
|
|
|
|
e_real->size = 1;
|
|
// break2
|
|
free(d);
|
|
}
|
|
|
|
void corrupted_consolidate_backward() {
|
|
// corrupted size vs. prev_size while consolidating
|
|
setup_heap
|
|
// break1
|
|
|
|
free(d);
|
|
d_real->size = 0xaa;
|
|
// break2
|
|
free(e);
|
|
}
|
|
|
|
void corrupted_unsorted_chunks() {
|
|
// free(): corrupted unsorted chunks
|
|
setup_heap
|
|
// break1
|
|
|
|
free(d); // it goes to unsorted
|
|
d_real->bk = a_real;
|
|
// break2
|
|
free(f);
|
|
}
|
|
|
|
|
|
int main(int argc, char const *argv[]) {
|
|
setvbuf(stdout, NULL, _IONBF, 0);
|
|
|
|
if (argc < 2) {
|
|
printf("Usage: %s bug_to_trigger\n", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
int choice;
|
|
sscanf(argv[1], "%d", &choice);
|
|
switch(choice) {
|
|
case 1: invalid_pointer_overflow(); break;
|
|
case 2: invalid_pointer_misaligned(); break;
|
|
case 3: invalid_size_minsize(); break;
|
|
case 4: invalid_size_misaligned(); break;
|
|
case 5: double_free_tcache(); break;
|
|
case 6: invalid_next_size_fast(); break;
|
|
case 7: double_free_fastbin(); break;
|
|
case 8: invalid_fastbin_entry(); break;
|
|
case 9: double_free_or_corruption_top(); break;
|
|
case 10: double_free_or_corruption_out(); break;
|
|
case 11: double_free_or_corruption_prev(); break;
|
|
case 12: invalid_next_size_normal(); break;
|
|
case 13: corrupted_consolidate_backward(); break;
|
|
case 14: corrupted_unsorted_chunks(); break;
|
|
default: printf("Unknown\n");
|
|
}
|
|
|
|
puts("END");
|
|
return 0;
|
|
} |