Source Code: char buf[256]; int main(int argv,char **argc) { char *pbuf=(char*)malloc(256); // gets(buf); strcpy(buf,argc[1]); free(pbuf); } Memory Layout Diagram: +--------------+ <---0x08049680 |AAAAAAAAAAAAAA| \ |AAAAAAAAAAAAAA| | |AAAAAAAAAAAAAA| | |AAAAAAAAAAAAAA| |<--buf[256] (2440 Bytes?!?) |AAAAAAAAAAAAAA| | |AAAAAAAAAAAAAA| | |AAAAAAAAAAAAAA| / +--------------+ <---0x0804a008 | 0xFFFFFFFC | \ +--------------+ | | 0xFFFFFFFC | | +--------------+ |<---pbuf | AAAAAAAA | | +--------------+ | | .dtors - 12 | | +--------------+ | | shellcode | / +--------------+ Size is set to 0xfffffffc (so LSB is 0) Prev_Size is set to 0xfffffffc Previous chunk pointer is calculated like this: 0x0804a008 - (0xfffffffc) = 0x0804a00c (rather than 0x08049680) The "fake chunk" must be at 0x0804a00c -prev_size and size can be anything (use 0xfffffffc) -unlink() writes 8 bytes of garbage to 0x08049680, so put 8B of garbage before shellcode -unlink() writes 4 bytes to bk+8, so you need an \xeb\x0c after 8B to jump over it -fd points to .dtors - 12 -bk points to buf+8