## The Bug  & The Exploit
Contact is a struct that contains 2 pointers - One for the name and one for the bio.  
This is the function that creates a new contact:  
```Cvoid create_contact(char *name){    if (num_contacts == MAX_CONTACTS){        puts("Too many contacts! Delete one first!");        return;    }
    struct contact *contact = (struct contact *)malloc(sizeof(struct contact));    if (contact == NULL){        puts("Could not allocate new contact.");        exit(-1);    };
    /* make a copy of the name on the heap */    contact->name = strdup(name);    if (contact->name == NULL){        puts("Could not duplicate name.");        exit(-1);    }
    contacts[num_contacts++] = contact;}```
There is no initialization of the bio field, which means it will still have the value this heap chunk previously had. It was only after seeing the flag that I realized I should've used double free, which would make things easier for me.  
I used the combination of create_contact and delete_contact in order to control the bio pointer of new contacts.
```Cvoid delete_contact(struct contact *contact){    free(contact->name);
    /* if the bio is set, free it as well */    if (contact->bio != NULL){        free(contact->bio);    }
    free(contact);
    /* replace the corresponding index with the last contact and decrement num_contacts */    for (int i = 0; i < num_contacts; i++){        if (contacts[i] == contact){            contacts[i] = contacts[num_contacts - 1];            num_contacts--;            break;        }    }}```
Think about the following scenario:  
1. Create a new chunk with a name the size of contact struct (0x10) and set its second qword to an arbitrary pointer.  2. Set it's bio to a new chunk of the same size as the contact struct.  3. Delete it. Free order is name, bio, chunk.  4. Add a new chunk with a name the size of the contact struct.     ```new_chunk = previous_chunk, new_name = previous_name.```5. Add a new chunk.     ```new_chunk = previous_name.```  
As we said before, the bio field is not initialized, which means it will contain the value that was previously stored here - name's second qword (a pointer of our choice).  
We can now use print_contacts to print the value pointed by our pointer!!  
Let's use it to leak an address in libc (using the GOT_PLT table) and a heap address (using the contacts array).  
We can use our leaked heap address in order to allocate a fake chunk in the heap (forge a chunk header in the contents of one of the chunks we allocate) and perform a fastbin attack to hijack __malloc_hook.  
By the time we get the pointer to __malloc_hook-0x13 from malloc, it's over - We just need to overwrite it with one_gadget and enjoy our shell :)  