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

int main(void) {
        unsigned int *chunk;
        int i;
        unsigned int shellcode[10];
        unsigned int ret_addr_2_change = 9;

        /* Get some space */
        chunk = malloc(0x8);

        /* now setup the chunk to fool chunk_free()
           By making prev_size negative it will look
         _after_ this chunk in stead of in front of it
       */
        chunk[0] = -0x10;       /* prev_size */
        chunk[1] = 0x8;         /* size */
        chunk[2] = (int) shellcode;   /* fd */
        chunk[3] = (int) shellcode;   /* bk */

        /* set fd to the adres of the return address - 3
           the minus 3 is needed because fd[3] will become bk
           bk will be set to point to our shellcode. Remember that
           bk[2] will be changed to contain fd so that there should be
           a jmp or so in the shellcode to skip that value.
         */
        chunk[4+2] = (int) (&ret_addr_2_change - 3);
        chunk[4+3] = (int) (shellcode);

        /* set shellcode to 0 so that we can see the change */
        memset(shellcode, 0, sizeof(shellcode));

	i = ret_addr_2_change;

//	printf("ret before call: %x\n", ret_addr_2_change);
//	printf("address of ret: %x\n", &ret_addr_2_change);
//	printf("address of shellcode: %x\n", shellcode);
        /* remember we give mem to free which finds the chunk based on
         that */
        free(chunk+2);

//        printf("ret now: %x\n", ret_addr_2_change);

	if (ret_addr_2_change != i) {
		printf("FAIL\n"); /* Exploit succeeded */
		exit(1);
	}
		
        for (i = 0 ; i < 10; i++) {
		if (shellcode[i] != 0) {
			printf("FAIL\n"); /* Exploit succeeded */
			exit(1);
		}
        }
	return 0;
}
